diff --git a/controllers/dns.go b/controllers/dns.go index f9e7a3e5..07fbcc09 100644 --- a/controllers/dns.go +++ b/controllers/dns.go @@ -29,10 +29,10 @@ func dnsHandlers(r *mux.Router) { // // Gets node DNS entries associated with a network. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth func getNodeDNS(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") @@ -55,14 +55,13 @@ func getNodeDNS(w http.ResponseWriter, r *http.Request) { // // Gets all DNS entries. // -// Schemes: https +// Schemes: https // -// Security: -// oauth -// -// Responses: -// 200: dnsResponse +// Security: +// oauth // +// Responses: +// 200: dnsResponse func getAllDNS(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") dns, err := logic.GetAllDNS() @@ -79,14 +78,13 @@ func getAllDNS(w http.ResponseWriter, r *http.Request) { // // Gets custom DNS entries associated with a network. // -// Schemes: https +// Schemes: https // -// Security: -// oauth -// -// Responses: -// 200: dnsResponse +// Security: +// oauth // +// Responses: +// 200: dnsResponse func getCustomDNS(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") @@ -109,14 +107,13 @@ func getCustomDNS(w http.ResponseWriter, r *http.Request) { // // Gets all DNS entries associated with the network. // -// Schemes: https +// Schemes: https // -// Security: -// oauth -// -// Responses: -// 200: dnsResponse +// Security: +// oauth // +// Responses: +// 200: dnsResponse func getDNS(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") @@ -139,14 +136,13 @@ func getDNS(w http.ResponseWriter, r *http.Request) { // // Create a DNS entry. // -// Schemes: https +// Schemes: https // -// Security: -// oauth -// -// Responses: -// 200: dnsResponse +// Security: +// oauth // +// Responses: +// 200: dnsResponse func createDNS(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") @@ -180,16 +176,8 @@ func createDNS(w http.ResponseWriter, r *http.Request) { } logger.Log(1, "new DNS record added:", entry.Name) if servercfg.IsMessageQueueBackend() { - serverNode, err := logic.GetNetworkServerLocal(entry.Network) - if err != nil { - logger.Log(1, "failed to find server node after DNS update on", entry.Network) - } else { - if err = logic.ServerUpdate(&serverNode, false); err != nil { - logger.Log(1, "failed to update server node after DNS update on", entry.Network) - } - if err = mq.PublishPeerUpdate(&serverNode, false); err != nil { - logger.Log(0, "failed to publish peer update after ACL update on", entry.Network) - } + if err = mq.PublishPeerUpdate(entry.Network, false); err != nil { + logger.Log(0, "failed to publish peer update after ACL update on", entry.Network) } } logger.Log(2, r.Header.Get("user"), @@ -202,14 +190,14 @@ func createDNS(w http.ResponseWriter, r *http.Request) { // // Delete a DNS entry. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: stringJSONResponse -// *: stringJSONResponse +// Responses: +// 200: stringJSONResponse +// *: stringJSONResponse func deleteDNS(w http.ResponseWriter, r *http.Request) { // Set header w.Header().Set("Content-Type", "application/json") @@ -270,14 +258,14 @@ func GetDNSEntry(domain string, network string) (models.DNSEntry, error) { // // Push DNS entries to nameserver. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: dnsStringJSONResponse -// *: dnsStringJSONResponse +// Responses: +// 200: dnsStringJSONResponse +// *: dnsStringJSONResponse func pushDNS(w http.ResponseWriter, r *http.Request) { // Set header w.Header().Set("Content-Type", "application/json") diff --git a/controllers/docs.go b/controllers/docs.go index 96d943c8..ed1981d2 100644 --- a/controllers/docs.go +++ b/controllers/docs.go @@ -29,7 +29,6 @@ import ( serverconfigpkg "github.com/gravitl/netmaker/config" "github.com/gravitl/netmaker/logic/acls" "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/config" ) var _ = useUnused() // "use" the function to prevent "unused function" errors @@ -303,18 +302,18 @@ type nodeLastModifiedResponse struct { } // swagger:parameters register -type registerRequestBodyParam struct { - // Register Request - // in: body - RegisterRequest config.RegisterRequest `json:"register_request"` -} - -// swagger:response registerResponse -type registerResponse struct { - // Register Response - // in: body - RegisterResponse config.RegisterResponse `json:"register_response"` -} +//type registerRequestBodyParam struct { +// // Register Request +// // in: body +// RegisterRequest config.RegisterRequest `json:"register_request"` +//} +// +//// swagger:response registerResponse +//type registerResponse struct { +// // Register Response +// // in: body +// RegisterResponse config.RegisterResponse `json:"register_response"` +//} // swagger:response boolResponse type boolResponse struct { @@ -388,8 +387,8 @@ func useUnused() bool { _ = serverConfigResponse{} _ = nodeGetResponse{} _ = nodeLastModifiedResponse{} - _ = registerRequestBodyParam{} - _ = registerResponse{} + // _ = registerRequestBodyParam{} + // _ = registerResponse{} _ = boolResponse{} _ = userBodyParam{} _ = userBodyResponse{} diff --git a/controllers/ext_client.go b/controllers/ext_client.go index b1620dbc..d420b71a 100644 --- a/controllers/ext_client.go +++ b/controllers/ext_client.go @@ -35,7 +35,7 @@ func checkIngressExists(nodeID string) bool { if err != nil { return false } - return node.IsIngressGateway == "yes" + return node.IsIngressGateway } // swagger:route GET /api/extclients/{network} ext_client getNetworkExtClients @@ -184,6 +184,13 @@ func getExtClientConf(w http.ResponseWriter, r *http.Request) { logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) return } + host, err := logic.GetHost(gwnode.HostID.String()) + if err != nil { + logger.Log(0, r.Header.Get("user"), + fmt.Sprintf("failed to get host for ingress gateway node [%s] info: %v", client.IngressGatewayID, err)) + logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) + return + } network, err := logic.GetParentNetwork(client.Network) if err != nil { @@ -207,7 +214,7 @@ func getExtClientConf(w http.ResponseWriter, r *http.Request) { if network.DefaultKeepalive != 0 { keepalive = "PersistentKeepalive = " + strconv.Itoa(int(network.DefaultKeepalive)) } - gwendpoint := gwnode.Endpoint + ":" + strconv.Itoa(int(gwnode.ListenPort)) + gwendpoint := gwnode.EndpointIP.String() + ":" + strconv.Itoa(host.ListenPort) newAllowedIPs := network.AddressRange if newAllowedIPs != "" && network.AddressRange6 != "" { newAllowedIPs += "," @@ -226,8 +233,8 @@ func getExtClientConf(w http.ResponseWriter, r *http.Request) { } defaultMTU := 1420 - if gwnode.MTU != 0 { - defaultMTU = int(gwnode.MTU) + if host.MTU != 0 { + defaultMTU = host.MTU } config := fmt.Sprintf(`[Interface] Address = %s @@ -245,7 +252,7 @@ Endpoint = %s client.PrivateKey, defaultMTU, defaultDNS, - gwnode.PublicKey, + host.PublicKey, newAllowedIPs, gwendpoint, keepalive) @@ -327,11 +334,16 @@ func createExtClient(w http.ResponseWriter, r *http.Request) { logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) return } - listenPort := node.LocalListenPort + host, err := logic.GetHost(node.HostID.String()) + logger.Log(0, r.Header.Get("user"), + fmt.Sprintf("failed to get ingress gateway host for node [%s] info: %v", nodeid, err)) + logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) + return + listenPort := host.LocalListenPort if node.Proxy { - listenPort = node.ProxyListenPort + listenPort = host.ProxyListenPort } - extclient.IngressGatewayEndpoint = node.Endpoint + ":" + strconv.FormatInt(int64(listenPort), 10) + extclient.IngressGatewayEndpoint = node.EndpointIP.String() + ":" + strconv.FormatInt(int64(listenPort), 10) extclient.Enabled = true parentNetwork, err := logic.GetNetwork(networkName) @@ -462,7 +474,7 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) { if changedEnabled { // need to send a peer update to the ingress node as enablement of one of it's clients has changed if ingressNode, err := logic.GetNodeByID(newclient.IngressGatewayID); err == nil { if err = mq.PublishExtPeerUpdate(&ingressNode); err != nil { - logger.Log(1, "error setting ext peers on", ingressNode.ID, ":", err.Error()) + logger.Log(1, "error setting ext peers on", ingressNode.ID.String(), ":", err.Error()) } } } @@ -534,7 +546,7 @@ func deleteExtClient(w http.ResponseWriter, r *http.Request) { err = mq.PublishExtPeerUpdate(&ingressnode) if err != nil { - logger.Log(1, "error setting ext peers on "+ingressnode.ID+": "+err.Error()) + logger.Log(1, "error setting ext peers on "+ingressnode.ID.String()+": "+err.Error()) } logger.Log(0, r.Header.Get("user"), diff --git a/controllers/network.go b/controllers/network.go index 608afb70..844559d5 100644 --- a/controllers/network.go +++ b/controllers/network.go @@ -36,13 +36,13 @@ func networkHandlers(r *mux.Router) { // // Lists all networks. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: getNetworksSliceResponse +// Responses: +// 200: getNetworksSliceResponse func getNetworks(w http.ResponseWriter, r *http.Request) { headerNetworks := r.Header.Get("networks") @@ -87,13 +87,13 @@ func getNetworks(w http.ResponseWriter, r *http.Request) { // // Get a network. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: networkBodyResponse +// Responses: +// 200: networkBodyResponse func getNetwork(w http.ResponseWriter, r *http.Request) { // set header. w.Header().Set("Content-Type", "application/json") @@ -118,13 +118,13 @@ func getNetwork(w http.ResponseWriter, r *http.Request) { // // Update keys for a network. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: networkBodyResponse +// Responses: +// 200: networkBodyResponse func keyUpdate(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var params = mux.Vars(r) @@ -145,11 +145,9 @@ func keyUpdate(w http.ResponseWriter, r *http.Request) { return } for _, node := range nodes { - logger.Log(2, "updating node ", node.Name, " for a key update") - if node.IsServer != "yes" { - if err = mq.NodeUpdate(&node); err != nil { - logger.Log(1, "failed to send update to node during a network wide key update", node.Name, node.ID, err.Error()) - } + logger.Log(2, "updating node ", node.ID.String(), " for a key update") + if err = mq.NodeUpdate(&node); err != nil { + logger.Log(1, "failed to send update to node during a network wide key update", node.ID.String(), err.Error()) } } } @@ -158,13 +156,13 @@ func keyUpdate(w http.ResponseWriter, r *http.Request) { // // Update a network. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: networkBodyResponse +// Responses: +// 200: networkBodyResponse func updateNetwork(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var params = mux.Vars(r) @@ -248,16 +246,6 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) { return } } - if holepunchupdate { - err = logic.UpdateNetworkHolePunching(network.NetID, newNetwork.DefaultUDPHolePunch) - if err != nil { - logger.Log(0, r.Header.Get("user"), - fmt.Sprintf("failed to update network [%s] hole punching: %v", - network.NetID, err.Error())) - logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) - return - } - } if rangeupdate4 || rangeupdate6 || localrangeupdate || holepunchupdate { nodes, err := logic.GetNetworkNodes(network.NetID) if err != nil { @@ -281,13 +269,13 @@ func updateNetwork(w http.ResponseWriter, r *http.Request) { // // Update a network ACL (Access Control List). // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: aclContainerResponse +// Responses: +// 200: aclContainerResponse func updateNetworkACL(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var params = mux.Vars(r) @@ -318,19 +306,10 @@ func updateNetworkACL(w http.ResponseWriter, r *http.Request) { // send peer updates if servercfg.IsMessageQueueBackend() { - serverNode, err := logic.GetNetworkServerLocal(netname) - if err != nil { - logger.Log(1, "failed to find server node after ACL update on", netname) - } else { - if err = logic.ServerUpdate(&serverNode, false); err != nil { - logger.Log(1, "failed to update server node after ACL update on", netname) - } - if err = mq.PublishPeerUpdate(&serverNode, false); err != nil { - logger.Log(0, "failed to publish peer update after ACL update on", netname) - } + if err = mq.PublishPeerUpdate(netname, false); err != nil { + logger.Log(0, "failed to publish peer update after ACL update on", netname) } } - w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(newNetACL) } @@ -339,13 +318,13 @@ func updateNetworkACL(w http.ResponseWriter, r *http.Request) { // // Get a network ACL (Access Control List). // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: aclContainerResponse +// Responses: +// 200: aclContainerResponse func getNetworkACL(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var params = mux.Vars(r) @@ -367,13 +346,13 @@ func getNetworkACL(w http.ResponseWriter, r *http.Request) { // // Delete a network. Will not delete if there are any nodes that belong to the network. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: stringJSONResponse +// Responses: +// 200: stringJSONResponse func deleteNetwork(w http.ResponseWriter, r *http.Request) { // Set header w.Header().Set("Content-Type", "application/json") @@ -414,13 +393,13 @@ func deleteNetwork(w http.ResponseWriter, r *http.Request) { // // Create a network. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: networkBodyResponse +// Responses: +// 200: networkBodyResponse func createNetwork(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") @@ -468,20 +447,6 @@ func createNetwork(w http.ResponseWriter, r *http.Request) { event.Commands, err.Error())) } - if servercfg.IsClientMode() != "off" { - _, err := logic.ServerJoin(&network) - if err != nil { - logic.DeleteNetwork(network.NetID) - if err == nil { - err = errors.New("Failed to add server to network " + network.NetID) - } - logger.Log(0, r.Header.Get("user"), "failed to create network: ", - err.Error()) - logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) - return - } - } - logger.Log(1, r.Header.Get("user"), "created network", network.NetID) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(network) @@ -491,13 +456,13 @@ func createNetwork(w http.ResponseWriter, r *http.Request) { // // Create a network access key. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: accessKeyBodyResponse +// Responses: +// 200: accessKeyBodyResponse // // BEGIN KEY MANAGEMENT SECTION func createAccessKey(w http.ResponseWriter, r *http.Request) { @@ -545,13 +510,13 @@ func createAccessKey(w http.ResponseWriter, r *http.Request) { // // Get network access keys for a network. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: accessKeySliceBodyResponse +// Responses: +// 200: accessKeySliceBodyResponse func getAccessKeys(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var params = mux.Vars(r) @@ -575,14 +540,14 @@ func getAccessKeys(w http.ResponseWriter, r *http.Request) { // // Delete a network access key. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: -// *: stringJSONResponse +// Responses: +// 200: +// *: stringJSONResponse // // delete key. Has to do a little funky logic since it's not a collection item func deleteAccessKey(w http.ResponseWriter, r *http.Request) { diff --git a/controllers/node.go b/controllers/node.go index f0cc34db..e58b174b 100644 --- a/controllers/node.go +++ b/controllers/node.go @@ -33,7 +33,6 @@ func nodeHandlers(r *mux.Router) { r.HandleFunc("/api/nodes/{network}/{nodeid}/deletegateway", authorize(false, true, "user", http.HandlerFunc(deleteEgressGateway))).Methods("DELETE") r.HandleFunc("/api/nodes/{network}/{nodeid}/createingress", logic.SecurityCheck(false, http.HandlerFunc(createIngressGateway))).Methods("POST") r.HandleFunc("/api/nodes/{network}/{nodeid}/deleteingress", logic.SecurityCheck(false, http.HandlerFunc(deleteIngressGateway))).Methods("DELETE") - r.HandleFunc("/api/nodes/{network}/{nodeid}/approve", authorize(false, true, "user", http.HandlerFunc(uncordonNode))).Methods("POST") r.HandleFunc("/api/nodes/{network}/{nodeid}", authorize(true, true, "node", http.HandlerFunc(updateNode))).Methods("POST") r.HandleFunc("/api/nodes/{network}", nodeauth(checkFreeTierLimits(node_l, http.HandlerFunc(createNode)))).Methods("POST") r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods("POST") @@ -53,7 +52,7 @@ func nodeHandlers(r *mux.Router) { func authenticate(response http.ResponseWriter, request *http.Request) { var authRequest models.AuthParams - var result models.LegacyNode + var result models.Node var errorResponse = models.ErrorResponse{ Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.", } @@ -95,8 +94,9 @@ func authenticate(response http.ResponseWriter, request *http.Request) { return } } + host, err := logic.GetHost(result.HostID.String()) - err = bcrypt.CompareHashAndPassword([]byte(result.Password), []byte(authRequest.Password)) + err = bcrypt.CompareHashAndPassword([]byte(host.HostPass), []byte(authRequest.Password)) if err != nil { errorResponse.Code = http.StatusBadRequest errorResponse.Message = err.Error() @@ -117,9 +117,9 @@ func authenticate(response http.ResponseWriter, request *http.Request) { }, { Command: mq.CreateClientCmd, - Username: result.HostID, + Username: result.HostID.String(), Password: authRequest.Password, - Textname: result.Name, + Textname: host.Name, Roles: []mq.MqDynSecRole{ { Rolename: mq.NodeRole, @@ -354,13 +354,9 @@ func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Ha // Responses: // 200: nodeSliceResponse func getNetworkNodes(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - - var nodes []models.LegacyNode var params = mux.Vars(r) networkName := params["network"] - nodes, err := logic.GetNetworkNodes(networkName) if err != nil { logger.Log(0, r.Header.Get("user"), @@ -369,12 +365,6 @@ func getNetworkNodes(w http.ResponseWriter, r *http.Request) { return } - for _, node := range nodes { - if len(node.NetworkSettings.AccessKeys) > 0 { - node.NetworkSettings.AccessKeys = []models.AccessKey{} // not to be sent back to client; client already knows how to join the network - } - } - //Returns all the nodes in JSON format logger.Log(2, r.Header.Get("user"), "fetched nodes on network", networkName) w.WriteHeader(http.StatusOK) @@ -403,7 +393,7 @@ func getAllNodes(w http.ResponseWriter, r *http.Request) { logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) return } - var nodes []models.LegacyNode + var nodes []models.Node if user.IsAdmin || r.Header.Get("ismasterkey") == "yes" { nodes, err = logic.GetAllNodes() if err != nil { @@ -426,8 +416,8 @@ func getAllNodes(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(nodes) } -func getUsersNodes(user models.User) ([]models.LegacyNode, error) { - var nodes []models.LegacyNode +func getUsersNodes(user models.User) ([]models.Node, error) { + var nodes []models.Node var err error for _, networkName := range user.Networks { tmpNodes, err := logic.GetNetworkNodes(networkName) @@ -473,15 +463,26 @@ func getNode(w http.ResponseWriter, r *http.Request) { logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) return } - - if len(node.NetworkSettings.AccessKeys) > 0 { - node.NetworkSettings.AccessKeys = []models.AccessKey{} // not to be sent back to client; client already knows how to join the network + host, err := logic.GetHost(node.HostID.String()) + if err != nil { + logger.Log(0, r.Header.Get("user"), + fmt.Sprintf("error fetching host for node [ %s ] info: %v", nodeid, err)) + logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) + return } - + server := servercfg.GetServerInfo() + network, err := logic.GetNetwork(node.Network) + if err != nil { + logger.Log(0, r.Header.Get("user"), + fmt.Sprintf("error fetching network for node [ %s ] info: %v", nodeid, err)) + logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) + return + } + legacy := node.Legacy(host, &server, &network) response := models.NodeGet{ - Node: node, - //Peers: peerUpdate.Peers, - ServerConfig: servercfg.GetServerInfo(), + Node: *legacy, + Peers: peerUpdate.Peers, + ServerConfig: server, PeerIDs: peerUpdate.PeerIDs, } if node.Proxy { @@ -494,8 +495,8 @@ func getNode(w http.ResponseWriter, r *http.Request) { } if servercfg.Is_EE && nodeRequest { - if err = logic.EnterpriseResetAllPeersFailovers(node.ID, node.Network); err != nil { - logger.Log(1, "failed to reset failover list during node config pull", node.Name, node.Network) + if err = logic.EnterpriseResetAllPeersFailovers(node.ID.String(), node.Network); err != nil { + logger.Log(1, "failed to reset failover list during node config pull", node.ID.String(), node.Network) } } @@ -633,7 +634,6 @@ func createNode(w http.ResponseWriter, r *http.Request) { return } } - peerUpdate, err := logic.GetPeerUpdate(&data.Node) if err != nil && !database.IsEmptyRecord(err) { logger.Log(0, r.Header.Get("user"), @@ -681,61 +681,30 @@ func createNode(w http.ResponseWriter, r *http.Request) { event.Commands, err.Error())) } - response := models.NodeGet{ - Node: data.Node, - //Peers: peerUpdate.Peers, + response := models.NodeJoinResponse{ + Node: data.Node, ServerConfig: server, PeerIDs: peerUpdate.PeerIDs, } //host, newNode := node.ConvertToNewNode() - logic.SaveHost(data.Host) - logic.SaveNode(data.Node) + + logic.UpsertHost(&data.Host) + //logic.CreateNode() + //logic.SaveNode(data.Node) logger.Log(1, r.Header.Get("user"), "created new node", data.Host.Name, "on network", networkName) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(response) go func() { - if err := mq.PublishPeerUpdate(data.Node, true); err != nil { + if err := mq.PublishPeerUpdate(data.Node.Network, true); err != nil { logger.Log(1, "failed a peer update after creation of node", data.Host.Name) } }() //runForceServerUpdate(&data.Node, true) } -// swagger:route POST /api/nodes/{network}/{nodeid}/approve nodes uncordonNode -// -// Takes a node out of pending state. -// -// Schemes: https -// -// Security: -// oauth -// -// Responses: -// 200: nodeResponse -// -// Takes node out of pending state -// TODO: May want to use cordon/uncordon terminology instead of "ispending". -func uncordonNode(w http.ResponseWriter, r *http.Request) { - var params = mux.Vars(r) - w.Header().Set("Content-Type", "application/json") - var nodeid = params["nodeid"] - node, err := logic.UncordonNode(nodeid) - if err != nil { - logger.Log(0, r.Header.Get("user"), - fmt.Sprintf("failed to uncordon node [%s]: %v", node.Name, err)) - logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) - return - } - logger.Log(1, r.Header.Get("user"), "uncordoned node", node.Name) - w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode("SUCCESS") - - runUpdates(&node, false) -} - // == EGRESS == // swagger:route POST /api/nodes/{network}/{nodeid}/creategateway nodes createEgressGateway @@ -844,7 +813,7 @@ func createIngressGateway(w http.ResponseWriter, r *http.Request) { if servercfg.Is_EE && failoverReqBody.Failover { if err = logic.EnterpriseResetFailoverFunc(node.Network); err != nil { - logger.Log(1, "failed to reset failover list during failover create", node.Name, node.Network) + logger.Log(1, "failed to reset failover list during failover create", node.ID.String(), node.Network) } } @@ -882,7 +851,7 @@ func deleteIngressGateway(w http.ResponseWriter, r *http.Request) { if servercfg.Is_EE && wasFailover { if err = logic.EnterpriseResetFailoverFunc(node.Network); err != nil { - logger.Log(1, "failed to reset failover list during failover create", node.Name, node.Network) + logger.Log(1, "failed to reset failover list during failover create", node.ID.String(), node.Network) } } @@ -909,7 +878,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) { var params = mux.Vars(r) - var node models.LegacyNode + var node models.Node //start here nodeid := params["nodeid"] node, err := logic.GetNodeByID(nodeid) @@ -920,7 +889,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) { return } - var newNode models.LegacyNode + var newNode models.Node // we decode our body request params err = json.NewDecoder(r.Body).Decode(&newNode) if err != nil { @@ -929,7 +898,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) { return } relayupdate := false - if node.IsRelay == "yes" && len(newNode.RelayAddrs) > 0 { + if node.IsRelay && len(newNode.RelayAddrs) > 0 { if len(newNode.RelayAddrs) != len(node.RelayAddrs) { relayupdate = true } else { @@ -941,7 +910,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) { } } relayedUpdate := false - if node.IsRelayed == "yes" && (node.Address != newNode.Address || node.Address6 != newNode.Address6) { + if node.IsRelayed && (node.Address.String() != newNode.Address.String() || node.Address6.String() != newNode.Address6.String()) { relayedUpdate = true } @@ -949,29 +918,11 @@ func updateNode(w http.ResponseWriter, r *http.Request) { newNode.PostDown = node.PostDown newNode.PostUp = node.PostUp } - ifaceDelta := logic.IfaceDelta(&node, &newNode) - // for a hub change also need to update the existing hub - if newNode.IsHub == "yes" && node.IsHub != "yes" { - nodeToUpdate, err := logic.UnsetHub(newNode.Network) - if err != nil { - logger.Log(2, "failed to unset hubs", err.Error()) - } - if err := mq.NodeUpdate(nodeToUpdate); err != nil { - logger.Log(2, "failed to update hub node", nodeToUpdate.Name, err.Error()) - } - if nodeToUpdate.IsServer == "yes" { - // set ifacdelta true to force server to update peeers - if err := logic.ServerUpdate(nodeToUpdate, true); err != nil { - logger.Log(2, "failed to update server node on hub change", err.Error()) - } - - } - } if ifaceDelta && servercfg.Is_EE { - if err = logic.EnterpriseResetAllPeersFailovers(node.ID, node.Network); err != nil { - logger.Log(0, "failed to reset failover lists during node update for node", node.Name, node.Network) + if err = logic.EnterpriseResetAllPeersFailovers(node.ID.String(), node.Network); err != nil { + logger.Log(0, "failed to reset failover lists during node update for node", node.ID.String(), node.Network) } } @@ -996,7 +947,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) { if servercfg.IsDNSMode() { logic.SetDNS() } - logger.Log(1, r.Header.Get("user"), "updated node", node.ID, "on network", node.Network) + logger.Log(1, r.Header.Get("user"), "updated node", node.ID.String(), "on network", node.Network) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(newNode) @@ -1028,13 +979,6 @@ func deleteNode(w http.ResponseWriter, r *http.Request) { logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) return } - if isServer(&node) { - err := fmt.Errorf("cannot delete server node") - logger.Log(0, r.Header.Get("user"), - fmt.Sprintf("failed to delete node [ %s ]: %v", nodeid, err)) - logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) - return - } if r.Header.Get("ismaster") != "yes" { username := r.Header.Get("user") if username != "" && !doesUserOwnNode(username, params["network"], nodeid) { @@ -1069,7 +1013,7 @@ func deleteNode(w http.ResponseWriter, r *http.Request) { Commands: []mq.MqDynSecCmd{ { Command: mq.DeleteClientCmd, - Username: node.HostID, + Username: node.HostID.String(), }, }, } @@ -1082,84 +1026,35 @@ func deleteNode(w http.ResponseWriter, r *http.Request) { logic.ReturnSuccessResponse(w, r, nodeid+" deleted.") logger.Log(1, r.Header.Get("user"), "Deleted node", nodeid, "from network", params["network"]) runUpdates(&node, false) - runForceServerUpdate(&node, false) } -func runUpdates(node *models.LegacyNode, ifaceDelta bool) { +func runUpdates(node *models.Node, ifaceDelta bool) { go func() { // don't block http response // publish node update if not server if err := mq.NodeUpdate(node); err != nil { - logger.Log(1, "error publishing node update to node", node.Name, node.ID, err.Error()) - } - - if err := runServerUpdate(node, ifaceDelta); err != nil { - logger.Log(1, "error running server update", err.Error()) - } - - }() -} - -// updates local peers for a server on a given node's network -func runServerUpdate(node *models.LegacyNode, ifaceDelta bool) error { - if servercfg.IsClientMode() != "on" || !isServer(node) { - return nil - } - - currentServerNode, err := logic.GetNetworkServerLocal(node.Network) - if err != nil { - return err - } - - if ifaceDelta && logic.IsLeader(¤tServerNode) { - if err := mq.PublishPeerUpdate(¤tServerNode, false); err != nil { - logger.Log(1, "failed to publish peer update "+err.Error()) - } - } - - if err := logic.ServerUpdate(¤tServerNode, ifaceDelta); err != nil { - logger.Log(1, "server node:", currentServerNode.ID, "failed update") - return err - } - return nil -} - -func runForceServerUpdate(node *models.LegacyNode, publishPeerUpdateToNode bool) { - go func() { - if err := mq.PublishPeerUpdate(node, publishPeerUpdateToNode); err != nil { - logger.Log(1, "failed a peer update after creation of node", node.Name) - } - - var currentServerNode, getErr = logic.GetNetworkServerLeader(node.Network) - if getErr == nil { - if err := logic.ServerUpdate(¤tServerNode, false); err != nil { - logger.Log(1, "server node:", currentServerNode.ID, "failed update") - } + logger.Log(1, "error publishing node update to node", node.ID.String(), err.Error()) } }() } -func isServer(node *models.LegacyNode) bool { - return node.IsServer == "yes" -} - -func updateRelay(oldnode, newnode *models.LegacyNode) { +func updateRelay(oldnode, newnode *models.Node) { relay := logic.FindRelay(oldnode) newrelay := relay //check if node's address has been updated and if so, update the relayAddrs of the relay node with the updated address of the relayed node - if oldnode.Address != newnode.Address { + if oldnode.Address.String() != newnode.Address.String() { for i, ip := range newrelay.RelayAddrs { - if ip == oldnode.Address { + if ip == oldnode.Address.IP.String() { newrelay.RelayAddrs = append(newrelay.RelayAddrs[:i], relay.RelayAddrs[i+1:]...) - newrelay.RelayAddrs = append(newrelay.RelayAddrs, newnode.Address) + newrelay.RelayAddrs = append(newrelay.RelayAddrs, newnode.Address.IP.String()) } } } //check if node's address(v6) has been updated and if so, update the relayAddrs of the relay node with the updated address(v6) of the relayed node - if oldnode.Address6 != newnode.Address6 { + if oldnode.Address6.String() != newnode.Address6.String() { for i, ip := range newrelay.RelayAddrs { - if ip == oldnode.Address { + if ip == oldnode.Address.IP.String() { newrelay.RelayAddrs = append(newrelay.RelayAddrs[:i], newrelay.RelayAddrs[i+1:]...) - newrelay.RelayAddrs = append(newrelay.RelayAddrs, newnode.Address6) + newrelay.RelayAddrs = append(newrelay.RelayAddrs, newnode.Address6.IP.String()) } } } diff --git a/controllers/relay.go b/controllers/relay.go index 45d82653..df939f8c 100644 --- a/controllers/relay.go +++ b/controllers/relay.go @@ -16,13 +16,13 @@ import ( // // Create a relay. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: nodeResponse +// Responses: +// 200: nodeResponse func createRelay(w http.ResponseWriter, r *http.Request) { var relay models.RelayRequest var params = mux.Vars(r) @@ -48,7 +48,7 @@ func createRelay(w http.ResponseWriter, r *http.Request) { err = mq.NodeUpdate(&relayedNode) if err != nil { - logger.Log(1, "error sending update to relayed node ", relayedNode.Name, "on network", relay.NetID, ": ", err.Error()) + logger.Log(1, "error sending update to relayed node ", relayedNode.ID.String(), "on network", relay.NetID, ": ", err.Error()) } } @@ -61,13 +61,13 @@ func createRelay(w http.ResponseWriter, r *http.Request) { // // Remove a relay. // -// Schemes: https +// Schemes: https // -// Security: -// oauth +// Security: +// oauth // -// Responses: -// 200: nodeResponse +// Responses: +// 200: nodeResponse func deleteRelay(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var params = mux.Vars(r) @@ -83,7 +83,7 @@ func deleteRelay(w http.ResponseWriter, r *http.Request) { for _, relayedNode := range updatenodes { err = mq.NodeUpdate(&relayedNode) if err != nil { - logger.Log(1, "error sending update to relayed node ", relayedNode.Name, "on network", netid, ": ", err.Error()) + logger.Log(1, "error sending update to relayed node ", relayedNode.ID.String(), "on network", netid, ": ", err.Error()) } } w.WriteHeader(http.StatusOK) diff --git a/database/database.go b/database/database.go index da6ad4ad..156d18a2 100644 --- a/database/database.go +++ b/database/database.go @@ -142,7 +142,7 @@ func createTable(tableName string) error { // IsJSONString - checks if valid json func IsJSONString(value string) bool { var jsonInt interface{} - var nodeInt models.LegacyNode + var nodeInt models.Node return json.Unmarshal([]byte(value), &jsonInt) == nil || json.Unmarshal([]byte(value), &nodeInt) == nil } diff --git a/ee/ee_controllers/metrics.go b/ee/ee_controllers/metrics.go index 862351a7..f14b5c02 100644 --- a/ee/ee_controllers/metrics.go +++ b/ee/ee_controllers/metrics.go @@ -60,12 +60,12 @@ func getNetworkNodesMetrics(w http.ResponseWriter, r *http.Request) { for i := range networkNodes { id := networkNodes[i].ID - metrics, err := logic.GetMetrics(id) + metrics, err := logic.GetMetrics(id.String()) if err != nil { - logger.Log(1, r.Header.Get("user"), "failed to append metrics of node", id, "during network metrics fetch", err.Error()) + logger.Log(1, r.Header.Get("user"), "failed to append metrics of node", id.String(), "during network metrics fetch", err.Error()) continue } - networkMetrics.Nodes[id] = *metrics + networkMetrics.Nodes[id.String()] = *metrics } logger.Log(1, r.Header.Get("user"), "fetched metrics for network", network) @@ -101,9 +101,9 @@ func getNetworkExtMetrics(w http.ResponseWriter, r *http.Request) { for i := range ingresses { id := ingresses[i].ID - ingressMetrics, err := logic.GetMetrics(id) + ingressMetrics, err := logic.GetMetrics(id.String()) if err != nil { - logger.Log(1, r.Header.Get("user"), "failed to append external client metrics from ingress node", id, err.Error()) + logger.Log(1, r.Header.Get("user"), "failed to append external client metrics from ingress node", id.String(), err.Error()) continue } if ingressMetrics.Connectivity == nil { @@ -142,12 +142,12 @@ func getAllMetrics(w http.ResponseWriter, r *http.Request) { for i := range allNodes { id := allNodes[i].ID - metrics, err := logic.GetMetrics(id) + metrics, err := logic.GetMetrics(id.String()) if err != nil { - logger.Log(1, r.Header.Get("user"), "failed to append metrics of node", id, "during all nodes metrics fetch", err.Error()) + logger.Log(1, r.Header.Get("user"), "failed to append metrics of node", id.String(), "during all nodes metrics fetch", err.Error()) continue } - networkMetrics.Nodes[id] = *metrics + networkMetrics.Nodes[id.String()] = *metrics } logger.Log(1, r.Header.Get("user"), "fetched metrics for all nodes on server") diff --git a/ee/ee_controllers/networkusers.go b/ee/ee_controllers/networkusers.go index 60c16c81..d1ef260b 100644 --- a/ee/ee_controllers/networkusers.go +++ b/ee/ee_controllers/networkusers.go @@ -34,9 +34,9 @@ type NetworkUserDataMap map[NetworkName]NetworkUserData // NetworkUserData - data struct for network users type NetworkUserData struct { - Nodes []models.LegacyNode `json:"nodes" bson:"nodes" yaml:"nodes"` + Nodes []models.Node `json:"nodes" bson:"nodes" yaml:"nodes"` Clients []models.ExtClient `json:"clients" bson:"clients" yaml:"clients"` - Vpn []models.LegacyNode `json:"vpns" bson:"vpns" yaml:"vpns"` + Vpn []models.Node `json:"vpns" bson:"vpns" yaml:"vpns"` Networks []models.Network `json:"networks" bson:"networks" yaml:"networks"` User promodels.NetworkUser `json:"user" bson:"user" yaml:"user"` } @@ -80,9 +80,9 @@ func getNetworkUserData(w http.ResponseWriter, r *http.Request) { netID := networks[i].NetID newData := NetworkUserData{ - Nodes: []models.LegacyNode{}, + Nodes: []models.Node{}, Clients: []models.ExtClient{}, - Vpn: []models.LegacyNode{}, + Vpn: []models.Node{}, Networks: []models.Network{}, } netUser, err := pro.GetNetworkUser(netID, promodels.NetworkUserID(networkUserName)) @@ -110,16 +110,16 @@ func getNetworkUserData(w http.ResponseWriter, r *http.Request) { // if access level is NODE_ACCESS, filter nodes if netUser.AccessLevel == pro.NODE_ACCESS { for i := range netNodes { - if logic.StringSliceContains(netUser.Nodes, netNodes[i].ID) { + if logic.StringSliceContains(netUser.Nodes, netNodes[i].ID.String()) { newData.Nodes = append(newData.Nodes, netNodes[i]) } } } else { // net admin so, get all nodes and ext clients on network... newData.Nodes = netNodes for i := range netNodes { - if netNodes[i].IsIngressGateway == "yes" { + if netNodes[i].IsIngressGateway { newData.Vpn = append(newData.Vpn, netNodes[i]) - if clients, err := logic.GetExtClientsByID(netNodes[i].ID, netID); err == nil { + if clients, err := logic.GetExtClientsByID(netNodes[i].ID.String(), netID); err == nil { newData.Clients = append(newData.Clients, clients...) } } @@ -134,7 +134,7 @@ func getNetworkUserData(w http.ResponseWriter, r *http.Request) { } } for i := range netNodes { - if netNodes[i].IsIngressGateway == "yes" { + if netNodes[i].IsIngressGateway { newData.Vpn = append(newData.Vpn, netNodes[i]) } } diff --git a/ee/logic/failover.go b/ee/logic/failover.go index c27fbba0..527c35cf 100644 --- a/ee/logic/failover.go +++ b/ee/logic/failover.go @@ -1,13 +1,14 @@ package logic import ( + "github.com/google/uuid" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" ) // SetFailover - finds a suitable failover candidate and sets it -func SetFailover(node *models.LegacyNode) error { +func SetFailover(node *models.Node) error { failoverNode := determineFailoverCandidate(node) if failoverNode != nil { return setFailoverNode(failoverNode, node) @@ -24,11 +25,11 @@ func ResetFailover(network string) error { for _, node := range nodes { err = SetFailover(&node) if err != nil { - logger.Log(2, "error setting failover for node", node.Name, ":", err.Error()) + logger.Log(2, "error setting failover for node", node.ID.String(), ":", err.Error()) } - err = WipeFailover(node.ID) + err = WipeFailover(node.ID.String()) if err != nil { - logger.Log(2, "error wiping failover for node", node.Name, ":", err.Error()) + logger.Log(2, "error wiping failover for node", node.ID.String(), ":", err.Error()) } } return nil @@ -36,29 +37,29 @@ func ResetFailover(network string) error { // determineFailoverCandidate - returns a list of nodes that // are suitable for relaying a given node -func determineFailoverCandidate(nodeToBeRelayed *models.LegacyNode) *models.LegacyNode { +func determineFailoverCandidate(nodeToBeRelayed *models.Node) *models.Node { currentNetworkNodes, err := logic.GetNetworkNodes(nodeToBeRelayed.Network) if err != nil { return nil } - currentMetrics, err := logic.GetMetrics(nodeToBeRelayed.ID) + currentMetrics, err := logic.GetMetrics(nodeToBeRelayed.ID.String()) if err != nil || currentMetrics == nil || currentMetrics.Connectivity == nil { return nil } minLatency := int64(9223372036854775807) // max signed int64 value - var fastestCandidate *models.LegacyNode + var fastestCandidate *models.Node for i := range currentNetworkNodes { if currentNetworkNodes[i].ID == nodeToBeRelayed.ID { continue } - if currentMetrics.Connectivity[currentNetworkNodes[i].ID].Connected && (currentNetworkNodes[i].Failover == "yes") { - if currentMetrics.Connectivity[currentNetworkNodes[i].ID].Latency < int64(minLatency) { + if currentMetrics.Connectivity[currentNetworkNodes[i].ID.String()].Connected && (currentNetworkNodes[i].Failover) { + if currentMetrics.Connectivity[currentNetworkNodes[i].ID.String()].Latency < int64(minLatency) { fastestCandidate = ¤tNetworkNodes[i] - minLatency = currentMetrics.Connectivity[currentNetworkNodes[i].ID].Latency + minLatency = currentMetrics.Connectivity[currentNetworkNodes[i].ID.String()].Latency } } } @@ -67,10 +68,10 @@ func determineFailoverCandidate(nodeToBeRelayed *models.LegacyNode) *models.Lega } // setFailoverNode - changes node's failover node -func setFailoverNode(failoverNode, node *models.LegacyNode) error { +func setFailoverNode(failoverNode, node *models.Node) error { node.FailoverNode = failoverNode.ID - nodeToUpdate, err := logic.GetNodeByID(node.ID) + nodeToUpdate, err := logic.GetNodeByID(node.ID.String()) if err != nil { return err } @@ -95,25 +96,25 @@ func WipeFailover(nodeid string) error { // WipeAffectedFailoversOnly - wipes failovers for nodes that have given node (ID) // in their respective failover lists -func WipeAffectedFailoversOnly(nodeid, network string) error { +func WipeAffectedFailoversOnly(nodeid uuid.UUID, network string) error { currentNetworkNodes, err := logic.GetNetworkNodes(network) if err != nil { return nil } - WipeFailover(nodeid) + WipeFailover(nodeid.String()) for i := range currentNetworkNodes { currNodeID := currentNetworkNodes[i].ID if currNodeID == nodeid { continue } - currMetrics, err := logic.GetMetrics(currNodeID) + currMetrics, err := logic.GetMetrics(currNodeID.String()) if err != nil || currMetrics == nil { continue } if currMetrics.FailoverPeers != nil { - if len(currMetrics.FailoverPeers[nodeid]) > 0 { - WipeFailover(currNodeID) + if len(currMetrics.FailoverPeers[nodeid.String()]) > 0 { + WipeFailover(currNodeID.String()) } } } diff --git a/ee/util.go b/ee/util.go index d61a9f83..a45bc1a4 100644 --- a/ee/util.go +++ b/ee/util.go @@ -45,6 +45,5 @@ func getCurrentServerLimit() (limits LicenseLimits) { if err == nil { limits.Users = len(users) } - limits.Servers = logic.GetServerCount() return } diff --git a/logic/dns.go b/logic/dns.go index b0701227..c40d24c3 100644 --- a/logic/dns.go +++ b/logic/dns.go @@ -75,7 +75,7 @@ func GetNodeDNS(network string) ([]models.DNSEntry, error) { for _, value := range collection { var entry models.DNSEntry - var node models.LegacyNode + var node models.Node if err = json.Unmarshal([]byte(value), &node); err != nil { continue } diff --git a/logic/extpeers.go b/logic/extpeers.go index 0bdd44b7..41360ed7 100644 --- a/logic/extpeers.go +++ b/logic/extpeers.go @@ -11,7 +11,7 @@ import ( ) // GetExtPeersList - gets the ext peers lists -func GetExtPeersList(node *models.LegacyNode) ([]models.ExtPeersResponse, error) { +func GetExtPeersList(node *models.Node) ([]models.ExtPeersResponse, error) { var peers []models.ExtPeersResponse records, err := database.FetchRecords(database.EXT_CLIENT_TABLE_NAME) @@ -34,7 +34,7 @@ func GetExtPeersList(node *models.LegacyNode) ([]models.ExtPeersResponse, error) continue } - if extClient.Enabled && extClient.Network == node.Network && extClient.IngressGatewayID == node.ID { + if extClient.Enabled && extClient.Network == node.Network && extClient.IngressGatewayID == node.ID.String() { peers = append(peers, peer) } } @@ -50,14 +50,14 @@ func GetEgressRangesOnNetwork(client *models.ExtClient) ([]string, error) { return []string{}, err } for _, nodeData := range nodesData { - var currentNode models.LegacyNode + var currentNode models.Node if err = json.Unmarshal([]byte(nodeData), ¤tNode); err != nil { continue } if currentNode.Network != client.Network { continue } - if currentNode.IsEgressGateway == "yes" { // add the egress gateway range(s) to the result + if currentNode.IsEgressGateway { // add the egress gateway range(s) to the result if len(currentNode.EgressGatewayRanges) > 0 { result = append(result, currentNode.EgressGatewayRanges...) } @@ -137,13 +137,13 @@ func CreateExtClient(extclient *models.ExtClient) error { if err != nil { return err } - extclient.Address = newAddress + extclient.Address = newAddress.String() extclientInternalAddr, err := UniqueAddress(extclient.Network, true) if err != nil { return err } - extclient.InternalIPAddr = extclientInternalAddr + extclient.InternalIPAddr = extclientInternalAddr.String() } } @@ -153,12 +153,12 @@ func CreateExtClient(extclient *models.ExtClient) error { if err != nil { return err } - extclient.Address6 = addr6 + extclient.Address6 = addr6.String() extclientInternalAddr6, err := UniqueAddress6(extclient.Network, true) if err != nil { return err } - extclient.InternalIPAddr6 = extclientInternalAddr6 + extclient.InternalIPAddr6 = extclientInternalAddr6.String() } } diff --git a/logic/gateway.go b/logic/gateway.go index 450c61e4..354fac8a 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -14,46 +14,47 @@ import ( ) // CreateEgressGateway - creates an egress gateway -func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.LegacyNode, error) { +func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, error) { + node, err := GetNodeByID(gateway.NodeID) + if err != nil { + return models.Node{}, err + } + host, err := GetHost(node.HostID.String()) + if err != nil { + return models.Node{}, err + } for i, cidr := range gateway.Ranges { normalized, err := NormalizeCIDR(cidr) if err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } gateway.Ranges[i] = normalized } - node, err := GetNodeByID(gateway.NodeID) - if err != nil { - return models.LegacyNode{}, err + if host.OS != "linux" && host.OS != "freebsd" { // add in darwin later + return models.Node{}, errors.New(host.OS + " is unsupported for egress gateways") } - if node.OS != "linux" && node.OS != "freebsd" { // add in darwin later - return models.LegacyNode{}, errors.New(node.OS + " is unsupported for egress gateways") - } - if node.OS == "linux" && node.FirewallInUse == models.FIREWALL_NONE { - return models.LegacyNode{}, errors.New("firewall is not supported for egress gateways") + if host.OS == "linux" && host.FirewallInUse == models.FIREWALL_NONE { + return models.Node{}, errors.New("firewall is not supported for egress gateways") } if gateway.NatEnabled == "" { gateway.NatEnabled = "yes" } err = ValidateEgressGateway(gateway) if err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } - node.IsEgressGateway = "yes" + node.IsEgressGateway = true node.EgressGatewayRanges = gateway.Ranges node.EgressGatewayNatEnabled = gateway.NatEnabled node.EgressGatewayRequest = gateway // store entire request for use when preserving the egress gateway postUpCmd := "" postDownCmd := "" ipv4, ipv6 := getNetworkProtocols(gateway.Ranges) - //no support for ipv6 and ip6tables in netmaker container - if node.IsServer == "yes" { - ipv6 = false - } - logger.Log(3, "creating egress gateway firewall in use is '", node.FirewallInUse, "'") - if node.OS == "linux" { - switch node.FirewallInUse { + logger.Log(3, "creating egress gateway firewall in use is '", host.FirewallInUse, "'") + iface := "netmaker" + if host.OS == "linux" { + switch host.FirewallInUse { case models.FIREWALL_NFTABLES: // nftables only supported on Linux // assumes chains eg FORWARD and postrouting already exist @@ -62,14 +63,14 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.LegacyNode // removing the chain with rules in it would remove all rules in that section (not safe // if there are remaining rules on the host that need to stay). In practice the chain is removed // when non-empty even though the removal of a non-empty chain should not be possible per nftables wiki. - postUpCmd, postDownCmd = firewallNFTCommandsCreateEgress(node.Interface, gateway.Interface, gateway.Ranges, node.EgressGatewayNatEnabled, ipv4, ipv6) + postUpCmd, postDownCmd = firewallNFTCommandsCreateEgress(iface, gateway.Interface, gateway.Ranges, node.EgressGatewayNatEnabled, ipv4, ipv6) default: // iptables assumed logger.Log(3, "creating egress gateway nftables is not present") - postUpCmd, postDownCmd = firewallIPTablesCommandsCreateEgress(node.Interface, gateway.Interface, node.EgressGatewayNatEnabled, ipv4, ipv6) + postUpCmd, postDownCmd = firewallIPTablesCommandsCreateEgress(iface, gateway.Interface, node.EgressGatewayNatEnabled, ipv4, ipv6) } } - if node.OS == "freebsd" { + if host.OS == "freebsd" { // spacing around ; is important for later parsing of postup/postdown in wireguard/common.go postUpCmd = "kldload ipfw ipfw_nat ; " postUpCmd += "ipfw disable one_pass ; " @@ -108,8 +109,8 @@ func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.LegacyNode if err != nil { return node, err } - if err = database.Insert(node.ID, string(nodeData), database.NODES_TABLE_NAME); err != nil { - return models.LegacyNode{}, err + if err = database.Insert(node.ID.String(), string(nodeData), database.NODES_TABLE_NAME); err != nil { + return models.Node{}, err } return node, nil } @@ -130,14 +131,17 @@ func ValidateEgressGateway(gateway models.EgressGatewayRequest) error { } // DeleteEgressGateway - deletes egress from node -func DeleteEgressGateway(network, nodeid string) (models.LegacyNode, error) { - +func DeleteEgressGateway(network, nodeid string) (models.Node, error) { node, err := GetNodeByID(nodeid) if err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } + host, err := GetHost(node.HostID.String()) + if err != nil { + return models.Node{}, err - node.IsEgressGateway = "no" + } + node.IsEgressGateway = false node.EgressGatewayRanges = []string{} node.EgressGatewayRequest = models.EgressGatewayRequest{} // remove preserved request as the egress gateway is gone // needed in case we don't preserve a gateway (i.e., no ingress to preserve) @@ -147,19 +151,20 @@ func DeleteEgressGateway(network, nodeid string) (models.LegacyNode, error) { cidrs = append(cidrs, node.IngressGatewayRange) cidrs = append(cidrs, node.IngressGatewayRange6) ipv4, ipv6 := getNetworkProtocols(cidrs) - logger.Log(3, "deleting egress gateway firewall in use is '", node.FirewallInUse, "'") - if node.IsIngressGateway == "yes" { // check if node is still an ingress gateway before completely deleting postdown/up rules + logger.Log(3, "deleting egress gateway firewall in use is '", host.FirewallInUse, "'") + if node.IsIngressGateway { // check if node is still an ingress gateway before completely deleting postdown/up rules // still have an ingress gateway so preserve it - if node.OS == "linux" { - switch node.FirewallInUse { + iface := "netmaker" + if host.OS == "linux" { + switch host.FirewallInUse { case models.FIREWALL_NFTABLES: // nftables only supported on Linux // assumes chains eg FORWARD and postrouting already exist logger.Log(3, "deleting egress gateway nftables is present") - node.PostUp, node.PostDown = firewallNFTCommandsCreateIngress(node.Interface) + node.PostUp, node.PostDown = firewallNFTCommandsCreateIngress(iface) default: logger.Log(3, "deleting egress gateway nftables is not present") - node.PostUp, node.PostDown = firewallIPTablesCommandsCreateIngress(node.Interface, ipv4, ipv6) + node.PostUp, node.PostDown = firewallIPTablesCommandsCreateIngress(iface, ipv4, ipv6) } } // no need to preserve ingress gateway on FreeBSD as ingress is not supported on that OS @@ -168,53 +173,52 @@ func DeleteEgressGateway(network, nodeid string) (models.LegacyNode, error) { data, err := json.Marshal(&node) if err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } - if err = database.Insert(node.ID, string(data), database.NODES_TABLE_NAME); err != nil { - return models.LegacyNode{}, err + if err = database.Insert(node.ID.String(), string(data), database.NODES_TABLE_NAME); err != nil { + return models.Node{}, err } return node, nil } // CreateIngressGateway - creates an ingress gateway -func CreateIngressGateway(netid string, nodeid string, failover bool) (models.LegacyNode, error) { +func CreateIngressGateway(netid string, nodeid string, failover bool) (models.Node, error) { var postUpCmd, postDownCmd string node, err := GetNodeByID(nodeid) - - if node.FirewallInUse == models.FIREWALL_NONE { - return models.LegacyNode{}, errors.New("firewall is not supported for ingress gateways") - } - if err != nil { - return models.LegacyNode{}, err + return models.Node{}, err + } + host, err := GetHost(node.HostID.String()) + if err != nil { + return models.Node{}, err + } + if host.FirewallInUse == models.FIREWALL_NONE { + return models.Node{}, errors.New("firewall is not supported for ingress gateways") } network, err := GetParentNetwork(netid) if err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } - node.IsIngressGateway = "yes" + node.IsIngressGateway = true cidrs := []string{} cidrs = append(cidrs, network.AddressRange) cidrs = append(cidrs, network.AddressRange6) node.IngressGatewayRange = network.AddressRange node.IngressGatewayRange6 = network.AddressRange6 ipv4, ipv6 := getNetworkProtocols(cidrs) - //no support for ipv6 and ip6tables in netmaker container - if node.IsServer == "yes" { - ipv6 = false - } - logger.Log(3, "creating ingress gateway firewall in use is '", node.FirewallInUse, "'") - switch node.FirewallInUse { + logger.Log(3, "creating ingress gateway firewall in use is '", host.FirewallInUse, "'") + iface := "netmaker" + switch host.FirewallInUse { case models.FIREWALL_NFTABLES: // nftables only supported on Linux // assumes chains eg FORWARD and postrouting already exist logger.Log(3, "creating ingress gateway nftables is present") - postUpCmd, postDownCmd = firewallNFTCommandsCreateIngress(node.Interface) + postUpCmd, postDownCmd = firewallNFTCommandsCreateIngress(iface) default: logger.Log(3, "creating ingress gateway using nftables is not present") - postUpCmd, postDownCmd = firewallIPTablesCommandsCreateIngress(node.Interface, ipv4, ipv6) + postUpCmd, postDownCmd = firewallIPTablesCommandsCreateIngress(iface, ipv4, ipv6) } if node.PostUp != "" { @@ -230,52 +234,51 @@ func CreateIngressGateway(netid string, nodeid string, failover bool) (models.Le node.SetLastModified() node.PostUp = postUpCmd node.PostDown = postDownCmd - node.UDPHolePunch = "no" if failover && servercfg.Is_EE { - node.Failover = "yes" + node.Failover = true } data, err := json.Marshal(&node) if err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } - err = database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) + err = database.Insert(node.ID.String(), string(data), database.NODES_TABLE_NAME) if err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } err = SetNetworkNodesLastModified(netid) return node, err } // DeleteIngressGateway - deletes an ingress gateway -func DeleteIngressGateway(networkName string, nodeid string) (models.LegacyNode, bool, error) { - +func DeleteIngressGateway(networkName string, nodeid string) (models.Node, bool, error) { node, err := GetNodeByID(nodeid) if err != nil { - return models.LegacyNode{}, false, err + return models.Node{}, false, err } - network, err := GetParentNetwork(networkName) + //host, err := GetHost(node.ID.String()) + //if err != nil { + //return models.Node{}, false, err + //} + //network, err := GetParentNetwork(networkName) if err != nil { - return models.LegacyNode{}, false, err + return models.Node{}, false, err } // delete ext clients belonging to ingress gateway - if err = DeleteGatewayExtClients(node.ID, networkName); err != nil { - return models.LegacyNode{}, false, err + if err = DeleteGatewayExtClients(node.ID.String(), networkName); err != nil { + return models.Node{}, false, err } logger.Log(3, "deleting ingress gateway") - wasFailover := node.Failover == "yes" - if node.IsServer != "yes" { - node.UDPHolePunch = network.DefaultUDPHolePunch - } - node.LastModified = time.Now().Unix() - node.IsIngressGateway = "no" + wasFailover := node.Failover == true + node.LastModified = time.Now() + node.IsIngressGateway = false node.IngressGatewayRange = "" - node.Failover = "no" + node.Failover = false // default to removing postup and postdown node.PostUp = "" node.PostDown = "" - logger.Log(3, "deleting ingress gateway firewall in use is '", node.FirewallInUse, "' and isEgressGateway is", node.IsEgressGateway) + //logger.Log(3, "deleting ingress gateway firewall in use is '", host.FirewallInUse, "' and isEgressGateway is", node.IsEgressGateway) if node.EgressGatewayRequest.NodeID != "" { _, err := CreateEgressGateway(node.EgressGatewayRequest) if err != nil { @@ -286,11 +289,11 @@ func DeleteIngressGateway(networkName string, nodeid string) (models.LegacyNode, data, err := json.Marshal(&node) if err != nil { - return models.LegacyNode{}, false, err + return models.Node{}, false, err } - err = database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) + err = database.Insert(node.ID.String(), string(data), database.NODES_TABLE_NAME) if err != nil { - return models.LegacyNode{}, wasFailover, err + return models.Node{}, wasFailover, err } err = SetNetworkNodesLastModified(networkName) return node, wasFailover, err diff --git a/logic/hosts.go b/logic/hosts.go index 1627f3e6..25f28491 100644 --- a/logic/hosts.go +++ b/logic/hosts.go @@ -74,7 +74,6 @@ func UpdateHost(newHost, currentHost *models.Host) { newHost.OS = currentHost.OS newHost.IPForwarding = currentHost.IPForwarding newHost.HostPass = currentHost.HostPass - newHost.NodePassword = currentHost.NodePassword newHost.MacAddress = currentHost.MacAddress newHost.Debug = currentHost.Debug newHost.Nodes = currentHost.Nodes diff --git a/logic/metrics.go b/logic/metrics.go index fef68941..9c9816a3 100644 --- a/logic/metrics.go +++ b/logic/metrics.go @@ -5,7 +5,6 @@ import ( "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/wireguard" ) // GetMetrics - gets the metrics @@ -38,69 +37,3 @@ func UpdateMetrics(nodeid string, metrics *models.Metrics) error { func DeleteMetrics(nodeid string) error { return database.DeleteRecord(database.METRICS_TABLE_NAME, nodeid) } - -// CollectServerMetrics - collects metrics for given server node -func CollectServerMetrics(serverID string, networkNodes []models.LegacyNode) *models.Metrics { - newServerMetrics := models.Metrics{} - newServerMetrics.Connectivity = make(map[string]models.Metric) - var serverNode models.LegacyNode - for i := range networkNodes { - currNodeID := networkNodes[i].ID - if currNodeID == serverID { - serverNode = networkNodes[i] - continue - } - if currMetrics, err := GetMetrics(currNodeID); err == nil { - if currMetrics.Connectivity != nil && currMetrics.Connectivity[serverID].Connected { - metrics := currMetrics.Connectivity[serverID] - metrics.NodeName = networkNodes[i].Name - metrics.IsServer = "no" - newServerMetrics.Connectivity[currNodeID] = metrics - } - } else { - newServerMetrics.Connectivity[currNodeID] = models.Metric{ - Connected: false, - Latency: 999, - } - } - } - - if serverNode.IsIngressGateway == "yes" { - clients, err := GetExtClientsByID(serverID, serverNode.Network) - if err == nil { - peers, err := wireguard.GetDevicePeers(serverNode.Interface) - if err == nil { - for i := range clients { - for j := range peers { - if clients[i].PublicKey == peers[j].PublicKey.String() { - if peers[j].ReceiveBytes > 0 && - peers[j].TransmitBytes > 0 { - newServerMetrics.Connectivity[clients[i].ClientID] = models.Metric{ - NodeName: clients[i].ClientID, - TotalTime: 5, - Uptime: 5, - IsServer: "no", - TotalReceived: peers[j].ReceiveBytes, - TotalSent: peers[j].TransmitBytes, - Connected: true, - Latency: -1, // can not determine latency on server currently - } - } else { - newServerMetrics.Connectivity[clients[i].ClientID] = models.Metric{ - NodeName: clients[i].ClientID, - TotalTime: 5, - Uptime: 0, - IsServer: "no", - Connected: false, - Latency: 999, - } - } - } - } - } - } - } - } - - return &newServerMetrics -} diff --git a/logic/metrics/metrics.go b/logic/metrics/metrics.go index e521f233..3e5e731c 100644 --- a/logic/metrics/metrics.go +++ b/logic/metrics/metrics.go @@ -90,7 +90,7 @@ func Collect(iface, network string, proxy bool, peerMap models.PeerMap) (*models } // GetExchangedBytesForNode - get exchanged bytes for current node peers -func GetExchangedBytesForNode(node *models.LegacyNode, metrics *models.Metrics) error { +func GetExchangedBytesForNode(node *models.Node, metrics *models.Metrics) error { peers, err := logic.GetPeerUpdate(node) if err != nil { @@ -102,7 +102,7 @@ func GetExchangedBytesForNode(node *models.LegacyNode, metrics *models.Metrics) return err } defer wgclient.Close() - device, err := wgclient.Device(node.Interface) + device, err := wgclient.Device("netmaker") if err != nil { return err } diff --git a/logic/networks.go b/logic/networks.go index 273f221e..34163e68 100644 --- a/logic/networks.go +++ b/logic/networks.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "net" - "os/exec" "strings" "github.com/c-robinson/iplib" @@ -15,7 +14,6 @@ import ( "github.com/gravitl/netmaker/logic/acls/nodeacls" "github.com/gravitl/netmaker/logic/pro" "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/validation" ) @@ -51,18 +49,6 @@ func DeleteNetwork(network string) error { nodeCount, err := GetNetworkNonServerNodeCount(network) if nodeCount == 0 || database.IsEmptyRecord(err) { // delete server nodes first then db records - servers, err := GetSortedNetworkServerNodes(network) - if err == nil { - for _, s := range servers { - if err = DeleteNode(&s, true); err != nil { - logger.Log(2, "could not removed server", s.Name, "before deleting network", network) - } else { - logger.Log(2, "removed server", s.Name, "before deleting network", network) - } - } - } else { - logger.Log(1, "could not remove servers before deleting network", network) - } if err = pro.RemoveAllNetworkUsers(network); err != nil { logger.Log(0, "failed to remove network users on network delete for network", network, err.Error()) } @@ -135,11 +121,11 @@ func GetNetworkNonServerNodeCount(networkName string) (int, error) { return count, err } for _, value := range collection { - var node models.LegacyNode + var node models.Node if err = json.Unmarshal([]byte(value), &node); err != nil { return count, err } else { - if node.Network == networkName && node.IsServer != "yes" { + if node.Network == networkName { count++ } } @@ -178,22 +164,22 @@ func GetNetworkSettings(networkname string) (models.Network, error) { } // UniqueAddress - see if address is unique -func UniqueAddress(networkName string, reverse bool) (string, error) { - +func UniqueAddress(networkName string, reverse bool) (net.IP, error) { + add := net.IP{} var network models.Network network, err := GetParentNetwork(networkName) if err != nil { logger.Log(0, "UniqueAddressServer encountered an error") - return "666", err + return add, err } if network.IsIPv4 == "no" { - return "", fmt.Errorf("IPv4 not active on network " + networkName) + return add, fmt.Errorf("IPv4 not active on network " + networkName) } //ensure AddressRange is valid if _, _, err := net.ParseCIDR(network.AddressRange); err != nil { logger.Log(0, "UniqueAddress encountered an error") - return "666", err + return add, err } net4 := iplib.Net4FromStr(network.AddressRange) newAddrs := net4.FirstAddress() @@ -205,7 +191,7 @@ func UniqueAddress(networkName string, reverse bool) (string, error) { for { if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, false) && IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, false) { - return newAddrs.String(), nil + return newAddrs, nil } if reverse { newAddrs, err = net4.PreviousIP(newAddrs) @@ -217,7 +203,7 @@ func UniqueAddress(networkName string, reverse bool) (string, error) { } } - return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", errors.New("ERROR: No unique addresses available. Check network subnet") + return add, errors.New("ERROR: No unique addresses available. Check network subnet") } // IsIPUnique - checks if an IP is unique @@ -231,16 +217,16 @@ func IsIPUnique(network string, ip string, tableName string, isIpv6 bool) bool { } for _, value := range collection { // filter - var node models.LegacyNode + var node models.Node if err = json.Unmarshal([]byte(value), &node); err != nil { continue } if isIpv6 { - if node.Address6 == ip && node.Network == network { + if node.Address6.String() == ip && node.Network == network { return false } } else { - if node.Address == ip && node.Network == network { + if node.Address.String() == ip && node.Network == network { return false } } @@ -250,21 +236,21 @@ func IsIPUnique(network string, ip string, tableName string, isIpv6 bool) bool { } // UniqueAddress6 - see if ipv6 address is unique -func UniqueAddress6(networkName string, reverse bool) (string, error) { - +func UniqueAddress6(networkName string, reverse bool) (net.IP, error) { + add := net.IP{} var network models.Network network, err := GetParentNetwork(networkName) if err != nil { fmt.Println("Network Not Found") - return "", err + return add, err } if network.IsIPv6 == "no" { - return "", fmt.Errorf("IPv6 not active on network " + networkName) + return add, fmt.Errorf("IPv6 not active on network " + networkName) } //ensure AddressRange is valid if _, _, err := net.ParseCIDR(network.AddressRange6); err != nil { - return "666", err + return add, err } net6 := iplib.Net6FromStr(network.AddressRange6) @@ -273,13 +259,13 @@ func UniqueAddress6(networkName string, reverse bool) (string, error) { newAddrs, err = net6.PreviousIP(net6.LastAddress()) } if err != nil { - return "", err + return add, err } for { if IsIPUnique(networkName, newAddrs.String(), database.NODES_TABLE_NAME, true) && IsIPUnique(networkName, newAddrs.String(), database.EXT_CLIENT_TABLE_NAME, true) { - return newAddrs.String(), nil + return newAddrs, nil } if reverse { newAddrs, err = net6.PreviousIP(newAddrs) @@ -291,23 +277,21 @@ func UniqueAddress6(networkName string, reverse bool) (string, error) { } } - return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", errors.New("ERROR: No unique IPv6 addresses available. Check network subnet") + return add, errors.New("ERROR: No unique IPv6 addresses available. Check network subnet") } // GetLocalIP - gets the local ip -func GetLocalIP(node models.LegacyNode) string { - +func GetLocalIP(node models.Node) string { var local string - ifaces, err := net.Interfaces() if err != nil { return local } - _, localrange, err := net.ParseCIDR(node.LocalRange) + host, err := GetHost(node.HostID.String()) if err != nil { return local } - + localrange := host.LocalRange found := false for _, i := range ifaces { if i.Flags&net.FlagUp == 0 { @@ -327,7 +311,7 @@ func GetLocalIP(node models.LegacyNode) string { if !found { ip = v.IP local = ip.String() - if node.IsLocal == "yes" { + if node.IsLocal { found = localrange.Contains(ip) } else { found = true @@ -337,7 +321,7 @@ func GetLocalIP(node models.LegacyNode) string { if !found { ip = v.IP local = ip.String() - if node.IsLocal == "yes" { + if node.IsLocal { found = localrange.Contains(ip) } else { @@ -361,7 +345,7 @@ func UpdateNetworkLocalAddresses(networkName string) error { for _, value := range collection { - var node models.LegacyNode + var node models.Node err := json.Unmarshal([]byte(value), &node) if err != nil { @@ -369,53 +353,27 @@ func UpdateNetworkLocalAddresses(networkName string) error { return err } if node.Network == networkName { - var ipaddr string + var ipaddr net.IP var iperr error - if node.IsServer == "yes" { - ipaddr, iperr = UniqueAddress(networkName, true) - } else { - ipaddr, iperr = UniqueAddress(networkName, false) - } + ipaddr, iperr = UniqueAddress(networkName, false) if iperr != nil { fmt.Println("error in node address assignment!") return iperr } - node.Address = ipaddr + node.Address.IP = ipaddr newNodeData, err := json.Marshal(&node) if err != nil { logger.Log(1, "error in node address assignment!") return err } - database.Insert(node.ID, string(newNodeData), database.NODES_TABLE_NAME) + database.Insert(node.ID.String(), string(newNodeData), database.NODES_TABLE_NAME) } } return nil } -// UpdateNetworkLocalAddresses - updates network localaddresses -func UpdateNetworkHolePunching(networkName string, holepunch string) error { - - nodes, err := GetNetworkNodes(networkName) - if err != nil { - return err - } - - for _, node := range nodes { - if node.IsServer != "yes" { - node.UDPHolePunch = holepunch - newNodeData, err := json.Marshal(&node) - if err != nil { - logger.Log(1, "error in node hole punch assignment") - return err - } - database.Insert(node.ID, string(newNodeData), database.NODES_TABLE_NAME) - } - } - return nil -} - // RemoveNetworkNodeIPv6Addresses - removes network node IPv6 addresses func RemoveNetworkNodeIPv6Addresses(networkName string) error { @@ -426,19 +384,19 @@ func RemoveNetworkNodeIPv6Addresses(networkName string) error { for _, value := range collections { - var node models.LegacyNode + var node models.Node err := json.Unmarshal([]byte(value), &node) if err != nil { fmt.Println("error in node address assignment!") return err } if node.Network == networkName { - node.Address6 = "" + node.Address6.IP = nil data, err := json.Marshal(&node) if err != nil { return err } - database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) + database.Insert(node.ID.String(), string(data), database.NODES_TABLE_NAME) } } @@ -455,31 +413,27 @@ func UpdateNetworkNodeAddresses(networkName string) error { for _, value := range collections { - var node models.LegacyNode + var node models.Node err := json.Unmarshal([]byte(value), &node) if err != nil { logger.Log(1, "error in node ipv4 address assignment!") return err } if node.Network == networkName { - var ipaddr string + var ipaddr net.IP var iperr error - if node.IsServer == "yes" { - ipaddr, iperr = UniqueAddress(networkName, true) - } else { - ipaddr, iperr = UniqueAddress(networkName, false) - } + ipaddr, iperr = UniqueAddress(networkName, false) if iperr != nil { logger.Log(1, "error in node ipv4 address assignment!") return iperr } - node.Address = ipaddr + node.Address.IP = ipaddr data, err := json.Marshal(&node) if err != nil { return err } - database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) + database.Insert(node.ID.String(), string(data), database.NODES_TABLE_NAME) } } @@ -496,31 +450,27 @@ func UpdateNetworkNodeAddresses6(networkName string) error { for _, value := range collections { - var node models.LegacyNode + var node models.Node err := json.Unmarshal([]byte(value), &node) if err != nil { logger.Log(1, "error in node ipv6 address assignment!") return err } if node.Network == networkName { - var ipaddr string + var ipaddr net.IP var iperr error - if node.IsServer == "yes" { - ipaddr, iperr = UniqueAddress6(networkName, true) - } else { - ipaddr, iperr = UniqueAddress6(networkName, false) - } + ipaddr, iperr = UniqueAddress6(networkName, false) if iperr != nil { logger.Log(1, "error in node ipv6 address assignment!") return iperr } - node.Address6 = ipaddr + node.Address6.IP = ipaddr data, err := json.Marshal(&node) if err != nil { return err } - database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) + database.Insert(node.ID.String(), string(data), database.NODES_TABLE_NAME) } } @@ -687,7 +637,7 @@ func networkNodesUpdateAction(networkName string, action string) error { } for _, value := range collections { - var node models.LegacyNode + var node models.Node err := json.Unmarshal([]byte(value), &node) if err != nil { fmt.Println("error in node address assignment!") @@ -702,55 +652,8 @@ func networkNodesUpdateAction(networkName string, action string) error { if err != nil { return err } - database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) + database.Insert(node.ID.String(), string(data), database.NODES_TABLE_NAME) } } return nil } - -func deleteInterface(ifacename string, postdown string) error { - var err error - if !ncutils.IsKernel() { - err = RemoveConf(ifacename, true) - } else { - ipExec, errN := exec.LookPath("ip") - err = errN - if err != nil { - logger.Log(1, err.Error()) - } - _, err = ncutils.RunCmd(ipExec+" link del "+ifacename, false) - if postdown != "" { - _, err = ncutils.RunCmd(postdown, false) - } - } - return err -} - -func isInterfacePresent(iface string, address string) (string, bool) { - var interfaces []net.Interface - var err error - interfaces, err = net.Interfaces() - if err != nil { - logger.Log(0, "ERROR: could not read interfaces") - return "", true - } - for _, currIface := range interfaces { - var currAddrs []net.Addr - currAddrs, err = currIface.Addrs() - if err != nil || len(currAddrs) == 0 { - continue - } - for _, addr := range currAddrs { - if strings.Contains(addr.String(), address) && currIface.Name != iface { - // logger.Log(2, "found iface", addr.String(), currIface.Name) - interfaces = nil - currAddrs = nil - return currIface.Name, false - } - } - currAddrs = nil - } - interfaces = nil - // logger.Log(2, "failed to find iface", iface) - return "", true -} diff --git a/logic/nodes.go b/logic/nodes.go index 530974ed..bb240487 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -5,7 +5,7 @@ import ( "encoding/json" "errors" "fmt" - "sort" + "net" "time" validator "github.com/go-playground/validator/v10" @@ -19,7 +19,6 @@ import ( "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/servercfg" - "github.com/gravitl/netmaker/validation" "golang.org/x/crypto/bcrypt" ) @@ -33,11 +32,11 @@ const ( ) // GetNetworkNodes - gets the nodes of a network -func GetNetworkNodes(network string) ([]models.LegacyNode, error) { - var nodes []models.LegacyNode +func GetNetworkNodes(network string) ([]models.Node, error) { + var nodes []models.Node allnodes, err := GetAllNodes() if err != nil { - return []models.LegacyNode{}, err + return []models.Node{}, err } for _, node := range allnodes { if node.Network == network { @@ -47,92 +46,11 @@ func GetNetworkNodes(network string) ([]models.LegacyNode, error) { return nodes, nil } -// GetSortedNetworkServerNodes - gets nodes of a network, except sorted by update time -func GetSortedNetworkServerNodes(network string) ([]models.LegacyNode, error) { - var nodes []models.LegacyNode - collection, err := database.FetchRecords(database.NODES_TABLE_NAME) - if err != nil { - if database.IsEmptyRecord(err) { - return []models.LegacyNode{}, nil - } - return nodes, err - } - for _, value := range collection { - - var node models.LegacyNode - err := json.Unmarshal([]byte(value), &node) - if err != nil { - continue - } - if node.Network == network && node.IsServer == "yes" { - nodes = append(nodes, node) - } - } - sort.Sort(models.NodesArray(nodes)) - return nodes, nil -} - -// GetServerNodes - gets the server nodes of a network -func GetServerNodes(network string) []models.LegacyNode { - var serverNodes = make([]models.LegacyNode, 0) - var nodes, err = GetNetworkNodes(network) - if err != nil { - return serverNodes - } - for _, node := range nodes { - if node.IsServer == "yes" { - serverNodes = append(serverNodes, node) - } - } - return serverNodes -} - -// UncordonNode - approves a node to join a network -func UncordonNode(nodeid string) (models.LegacyNode, error) { - node, err := GetNodeByID(nodeid) - if err != nil { - return models.LegacyNode{}, err - } - node.SetLastModified() - node.IsPending = "no" - data, err := json.Marshal(&node) - if err != nil { - return node, err - } - - err = database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) - return node, err -} - -// SetIfLeader - gets the peers of a given server node -func SetPeersIfLeader(node *models.LegacyNode) { - if IsLeader(node) { - setNetworkServerPeers(node) - } -} - -// IsLeader - determines if a given server node is a leader -func IsLeader(node *models.LegacyNode) bool { - nodes, err := GetSortedNetworkServerNodes(node.Network) - if err != nil { - logger.Log(0, "ERROR: COULD NOT RETRIEVE SERVER NODES. THIS WILL BREAK HOLE PUNCHING.") - return false - } - for _, n := range nodes { - if n.LastModified > time.Now().Add(-1*time.Minute).Unix() { - return n.Address == node.Address - } - } - return len(nodes) <= 1 || nodes[1].Address == node.Address -} - -// == DB related functions == - // UpdateNode - takes a node and updates another node with it's values -func UpdateNode(currentNode *models.LegacyNode, newNode *models.LegacyNode) error { - if newNode.Address != currentNode.Address { +func UpdateNode(currentNode *models.Node, newNode *models.Node) error { + if newNode.Address.String() != currentNode.Address.String() { if network, err := GetParentNetwork(newNode.Network); err == nil { - if !IsAddressInCIDR(newNode.Address, network.AddressRange) { + if !IsAddressInCIDR(newNode.Address.String(), network.AddressRange) { return fmt.Errorf("invalid address provided; out of network range for node %s", newNode.ID) } } @@ -140,9 +58,6 @@ func UpdateNode(currentNode *models.LegacyNode, newNode *models.LegacyNode) erro nodeACLDelta := currentNode.DefaultACL != newNode.DefaultACL newNode.Fill(currentNode) - if currentNode.IsServer == "yes" && !validateServer(currentNode, newNode) { - return fmt.Errorf("this operation is not supported on server nodes") - } // check for un-settable server values if err := ValidateNode(newNode, true); err != nil { return err @@ -151,7 +66,7 @@ func UpdateNode(currentNode *models.LegacyNode, newNode *models.LegacyNode) erro if newNode.ID == currentNode.ID { if nodeACLDelta { if err := updateProNodeACLS(newNode); err != nil { - logger.Log(1, "failed to apply node level ACLs during creation of node", newNode.ID, "-", err.Error()) + logger.Log(1, "failed to apply node level ACLs during creation of node", newNode.ID.String(), "-", err.Error()) return err } } @@ -160,15 +75,15 @@ func UpdateNode(currentNode *models.LegacyNode, newNode *models.LegacyNode) erro if data, err := json.Marshal(newNode); err != nil { return err } else { - return database.Insert(newNode.ID, string(data), database.NODES_TABLE_NAME) + return database.Insert(newNode.ID.String(), string(data), database.NODES_TABLE_NAME) } } - return fmt.Errorf("failed to update node " + currentNode.ID + ", cannot change ID.") + return fmt.Errorf("failed to update node " + currentNode.ID.String() + ", cannot change ID.") } // DeleteNode - marks node for deletion if called by UI or deletes node if called by node -func DeleteNode(node *models.LegacyNode, purge bool) error { +func DeleteNode(node *models.Node, purge bool) error { if !purge { newnode := node newnode.PendingDelete = true @@ -182,8 +97,9 @@ func DeleteNode(node *models.LegacyNode, purge bool) error { return err } if servercfg.Is_EE { - if err := EnterpriseResetAllPeersFailovers(node.ID, node.Network); err != nil { - logger.Log(0, "failed to reset failover lists during node delete for node", node.Name, node.Network) + host, _ := GetHost(node.HostID.String()) + if err := EnterpriseResetAllPeersFailovers(node.ID.String(), node.Network); err != nil { + logger.Log(0, "failed to reset failover lists during node delete for node", host.Name, node.Network) } } @@ -191,12 +107,12 @@ func DeleteNode(node *models.LegacyNode, purge bool) error { } // DeleteNodeByID - deletes a node from database -func DeleteNodeByID(node *models.LegacyNode) error { +func DeleteNodeByID(node *models.Node) error { var err error - var key = node.ID + var key = node.ID.String() //delete any ext clients as required - if node.IsIngressGateway == "yes" { - if err := DeleteGatewayExtClients(node.ID, node.Network); err != nil { + if node.IsIngressGateway { + if err := DeleteGatewayExtClients(node.ID.String(), node.Network); err != nil { logger.Log(0, "failed to deleted ext clients", err.Error()) } } @@ -209,34 +125,31 @@ func DeleteNodeByID(node *models.LegacyNode) error { SetDNS() } if node.OwnerID != "" { - err = pro.DissociateNetworkUserNode(node.OwnerID, node.Network, node.ID) + err = pro.DissociateNetworkUserNode(node.OwnerID, node.Network, node.ID.String()) if err != nil { - logger.Log(0, "failed to dissasociate", node.OwnerID, "from node", node.ID, ":", err.Error()) + logger.Log(0, "failed to dissasociate", node.OwnerID, "from node", node.ID.String(), ":", err.Error()) } } - _, err = nodeacls.RemoveNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID)) + _, err = nodeacls.RemoveNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String())) if err != nil { // ignoring for now, could hit a nil pointer if delete called twice - logger.Log(2, "attempted to remove node ACL for node", node.Name, node.ID) + logger.Log(2, "attempted to remove node ACL for node", node.ID.String()) } // removeZombie <- node.ID - if err = DeleteMetrics(node.ID); err != nil { - logger.Log(1, "unable to remove metrics from DB for node", node.ID, err.Error()) - } - if node.IsServer == "yes" { - return removeLocalServer(node) + if err = DeleteMetrics(node.ID.String()); err != nil { + logger.Log(1, "unable to remove metrics from DB for node", node.ID.String(), err.Error()) } return nil } // IsNodeIDUnique - checks if node id is unique -func IsNodeIDUnique(node *models.LegacyNode) (bool, error) { - _, err := database.FetchRecord(database.NODES_TABLE_NAME, node.ID) +func IsNodeIDUnique(node *models.Node) (bool, error) { + _, err := database.FetchRecord(database.NODES_TABLE_NAME, node.ID.String()) return database.IsEmptyRecord(err), err } // ValidateNode - validates node values -func ValidateNode(node *models.LegacyNode, isUpdate bool) error { +func ValidateNode(node *models.Node, isUpdate bool) error { v := validator.New() _ = v.RegisterValidation("id_unique", func(fl validator.FieldLevel) bool { if isUpdate { @@ -249,18 +162,7 @@ func ValidateNode(node *models.LegacyNode, isUpdate bool) error { _, err := GetNetworkByNode(node) return err == nil }) - _ = v.RegisterValidation("in_charset", func(fl validator.FieldLevel) bool { - isgood := node.NameInNodeCharSet() - return isgood - }) - _ = v.RegisterValidation("checkyesorno", func(fl validator.FieldLevel) bool { - return validation.CheckYesOrNo(fl) - }) - _ = v.RegisterValidation("checkyesornoorunset", func(fl validator.FieldLevel) bool { - return validation.CheckYesOrNoOrUnset(fl) - }) err := v.Struct(node) - return err } @@ -271,7 +173,7 @@ func IsFailoverPresent(network string) bool { return false } for i := range netNodes { - if netNodes[i].Failover == "yes" { + if netNodes[i].Failover { return true } } @@ -279,23 +181,24 @@ func IsFailoverPresent(network string) bool { } // CreateNode - creates a node in database -func CreateNode(node *models.LegacyNode) error { +func CreateNode(node *models.Node) error { + host, err := GetHost(node.HostID.String()) + if err != nil { + return err + } //encrypt that password so we never see it - hash, err := bcrypt.GenerateFromPassword([]byte(node.Password), 5) + hash, err := bcrypt.GenerateFromPassword([]byte(host.HostPass), 5) if err != nil { return err } //set password to encrypted password - node.Password = string(hash) - if node.Name == models.NODE_SERVER_NAME { - node.IsServer = "yes" - } - if node.DNSOn == "" { + host.HostPass = string(hash) + if !node.DNSOn { if servercfg.IsDNSMode() { - node.DNSOn = "yes" + node.DNSOn = true } else { - node.DNSOn = "no" + node.DNSOn = false } } @@ -313,34 +216,29 @@ func CreateNode(node *models.LegacyNode) error { node.DefaultACL = "unset" } - reverse := node.IsServer == "yes" - if node.Address == "" { + if node.Address.IP == nil { if parentNetwork.IsIPv4 == "yes" { - if node.Address, err = UniqueAddress(node.Network, reverse); err != nil { + if node.Address.IP, err = UniqueAddress(node.Network, false); err != nil { return err } } - } else if !IsIPUnique(node.Network, node.Address, database.NODES_TABLE_NAME, false) { - return fmt.Errorf("invalid address: ipv4 " + node.Address + " is not unique") + } else if !IsIPUnique(node.Network, node.Address.String(), database.NODES_TABLE_NAME, false) { + return fmt.Errorf("invalid address: ipv4 " + node.Address.String() + " is not unique") } - if node.Address6 == "" { + if node.Address6.IP == nil { if parentNetwork.IsIPv6 == "yes" { - if node.Address6, err = UniqueAddress6(node.Network, reverse); err != nil { + if node.Address6.IP, err = UniqueAddress6(node.Network, false); err != nil { return err } } - } else if !IsIPUnique(node.Network, node.Address6, database.NODES_TABLE_NAME, true) { - return fmt.Errorf("invalid address: ipv6 " + node.Address6 + " is not unique") - } - - node.ID = uuid.NewString() - if node.IsServer == "yes" { - node.HostID = uuid.NewString() + } else if !IsIPUnique(node.Network, node.Address6.String(), database.NODES_TABLE_NAME, true) { + return fmt.Errorf("invalid address: ipv6 " + node.Address6.String() + " is not unique") } + node.ID = uuid.New() //Create a JWT for the node - tokenString, _ := CreateJWT(node.ID, node.MacAddress, node.Network) + tokenString, _ := CreateJWT(node.ID.String(), host.MacAddress.String(), node.Network) if tokenString == "" { //logic.ReturnErrorResponse(w, r, errorResponse) return err @@ -349,34 +247,30 @@ func CreateNode(node *models.LegacyNode) error { if err != nil { return err } - CheckZombies(node) + CheckZombies(node, host.MacAddress) nodebytes, err := json.Marshal(&node) if err != nil { return err } - err = database.Insert(node.ID, string(nodebytes), database.NODES_TABLE_NAME) + err = database.Insert(node.ID.String(), string(nodebytes), database.NODES_TABLE_NAME) if err != nil { return err } - _, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID), defaultACLVal) + _, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), defaultACLVal) if err != nil { - logger.Log(1, "failed to create node ACL for node,", node.ID, "err:", err.Error()) + logger.Log(1, "failed to create node ACL for node,", node.ID.String(), "err:", err.Error()) return err } if err = updateProNodeACLS(node); err != nil { - logger.Log(1, "failed to apply node level ACLs during creation of node", node.ID, "-", err.Error()) + logger.Log(1, "failed to apply node level ACLs during creation of node", node.ID.String(), "-", err.Error()) return err } - if node.IsPending != "yes" { - DecrimentKey(node.Network, node.AccessKey) - } - - if err = UpdateMetrics(node.ID, &models.Metrics{Connectivity: make(map[string]models.Metric)}); err != nil { - logger.Log(1, "failed to initialize metrics for node", node.Name, node.ID, err.Error()) + if err = UpdateMetrics(node.ID.String(), &models.Metrics{Connectivity: make(map[string]models.Metric)}); err != nil { + logger.Log(1, "failed to initialize metrics for node", node.ID.String(), err.Error()) } SetNetworkNodesLastModified(node.Network) @@ -387,21 +281,21 @@ func CreateNode(node *models.LegacyNode) error { } // GetAllNodes - returns all nodes in the DB -func GetAllNodes() ([]models.LegacyNode, error) { - var nodes []models.LegacyNode +func GetAllNodes() ([]models.Node, error) { + var nodes []models.Node collection, err := database.FetchRecords(database.NODES_TABLE_NAME) if err != nil { if database.IsEmptyRecord(err) { - return []models.LegacyNode{}, nil + return []models.Node{}, nil } - return []models.LegacyNode{}, err + return []models.Node{}, err } for _, value := range collection { - var node models.LegacyNode + var node models.Node if err := json.Unmarshal([]byte(value), &node); err != nil { - return []models.LegacyNode{}, err + return []models.Node{}, err } // add node to our array nodes = append(nodes, node) @@ -410,24 +304,6 @@ func GetAllNodes() ([]models.LegacyNode, error) { return nodes, nil } -// CheckIsServer - check if a node is the server node -func CheckIsServer(node *models.LegacyNode) bool { - nodeData, err := database.FetchRecords(database.NODES_TABLE_NAME) - if err != nil && !database.IsEmptyRecord(err) { - return false - } - for _, value := range nodeData { - var tmpNode models.LegacyNode - if err := json.Unmarshal([]byte(value), &tmpNode); err != nil { - continue - } - if tmpNode.Network == node.Network && tmpNode.MacAddress != node.MacAddress { - return false - } - } - return true -} - // GetNetworkByNode - gets the network model from a node func GetNetworkByNode(node *models.Node) (models.Network, error) { @@ -443,28 +319,21 @@ func GetNetworkByNode(node *models.Node) (models.Network, error) { } // SetNodeDefaults - sets the defaults of a node to avoid empty fields -func SetNodeDefaults(node *models.LegacyNode) { +func SetNodeDefaults(node *models.Node) { - //TODO: Maybe I should make Network a part of the node struct. Then we can just query the Network object for stuff. parentNetwork, _ := GetNetworkByNode(node) - node.NetworkSettings = parentNetwork - node.NetworkSettings.AccessKeys = []models.AccessKey{} + _, cidr, _ := net.ParseCIDR(parentNetwork.AddressRange) + node.NetworkRange = *cidr + _, cidr, _ = net.ParseCIDR(parentNetwork.AddressRange6) + node.NetworkRange6 = *cidr + node.ExpirationDateTime = time.Now().Add(models.TEN_YEARS_IN_SECONDS) - node.ExpirationDateTime = time.Now().Unix() + models.TEN_YEARS_IN_SECONDS - - if node.DefaultACL == "" && node.IsServer != "yes" { + if node.DefaultACL == "" { node.DefaultACL = parentNetwork.DefaultACL } - if node.ListenPort == 0 { - node.ListenPort = parentNetwork.DefaultListenPort - } - - if node.Interface == "" { - node.Interface = parentNetwork.DefaultInterface - } if node.PersistentKeepalive == 0 { - node.PersistentKeepalive = parentNetwork.DefaultKeepalive + node.PersistentKeepalive = int(parentNetwork.DefaultKeepalive) } if node.PostUp == "" { postup := parentNetwork.DefaultPostUp @@ -474,44 +343,41 @@ func SetNodeDefaults(node *models.LegacyNode) { postdown := parentNetwork.DefaultPostDown node.PostDown = postdown } - if node.IsStatic == "" { - node.IsStatic = "no" - } - if node.UDPHolePunch == "" { - node.UDPHolePunch = parentNetwork.DefaultUDPHolePunch - if node.UDPHolePunch == "" { - node.UDPHolePunch = "yes" - } - } // == Parent Network settings == - if node.MTU == 0 { - node.MTU = parentNetwork.DefaultMTU - } // == node defaults if not set by parent == - node.SetIPForwardingDefault() - node.SetDNSOnDefault() - node.SetIsLocalDefault() - node.SetLastModified() - node.SetDefaultName() - node.SetLastCheckIn() - node.SetLastPeerUpdate() - node.SetDefaultAction() - node.SetIsServerDefault() - node.SetIsStaticDefault() - node.SetDefaultEgressGateway() - node.SetDefaultIngressGateway() - node.SetDefaulIsPending() - node.SetDefaultMTU() - node.SetDefaultNFTablesPresent() - node.SetDefaultIsRelayed() - node.SetDefaultIsRelay() - node.SetDefaultIsDocker() - node.SetDefaultIsK8S() - node.SetDefaultIsHub() - node.SetDefaultConnected() - node.SetDefaultACL() - node.SetDefaultFailover() + ///TODO ___ REVISIT ------ + ///TODO ___ REVISIT ------ + ///TODO ___ REVISIT ------ + ///TODO ___ REVISIT ------ + ///TODO ___ REVISIT ------ + //node.SetIPForwardingDefault() + //node.SetDNSOnDefault() + //node.SetIsLocalDefault() + //node.SetLastModified() + //node.SetDefaultName() + //node.SetLastCheckIn() + //node.SetLastPeerUpdate() + //node.SetDefaultAction() + //node.SetIsServerDefault() + //node.SetIsStaticDefault() + //node.SetDefaultEgressGateway() + //node.SetDefaultIngressGateway() + //node.SetDefaulIsPending() + //node.SetDefaultMTU() + //node.SetDefaultNFTablesPresent() + //node.SetDefaultIsRelayed() + //node.SetDefaultIsRelay() + //node.SetDefaultIsDocker() + //node.SetDefaultIsK8S() + //node.SetDefaultIsHub() + //node.SetDefaultConnected() + //node.SetDefaultACL() + //node.SetDefaultFailover() + ///TODO ___ REVISIT ------ + ///TODO ___ REVISIT ------ + ///TODO ___ REVISIT ------ + ///TODO ___ REVISIT ------ } // GetRecordKey - get record key @@ -524,9 +390,9 @@ func GetRecordKey(id string, network string) (string, error) { } // GetNodeByMacAddress - gets a node by mac address -func GetNodeByMacAddress(network string, macaddress string) (models.LegacyNode, error) { +func GetNodeByMacAddress(network string, macaddress string) (models.Node, error) { - var node models.LegacyNode + var node models.Node key, err := GetRecordKey(macaddress, network) if err != nil { @@ -535,11 +401,11 @@ func GetNodeByMacAddress(network string, macaddress string) (models.LegacyNode, record, err := database.FetchRecord(database.NODES_TABLE_NAME, key) if err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } if err = json.Unmarshal([]byte(record), &node); err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } SetNodeDefaults(&node) @@ -548,14 +414,14 @@ func GetNodeByMacAddress(network string, macaddress string) (models.LegacyNode, } // GetNodesByAddress - gets a node by mac address -func GetNodesByAddress(network string, addresses []string) ([]models.LegacyNode, error) { - var nodes []models.LegacyNode +func GetNodesByAddress(network string, addresses []string) ([]models.Node, error) { + var nodes []models.Node allnodes, err := GetAllNodes() if err != nil { - return []models.LegacyNode{}, err + return []models.Node{}, err } for _, node := range allnodes { - if node.Network == network && ncutils.StringSliceContains(addresses, node.Address) { + if node.Network == network && ncutils.StringSliceContains(addresses, node.Address.String()) { nodes = append(nodes, node) } } @@ -563,9 +429,9 @@ func GetNodesByAddress(network string, addresses []string) ([]models.LegacyNode, } // GetDeletedNodeByMacAddress - get a deleted node -func GetDeletedNodeByMacAddress(network string, macaddress string) (models.LegacyNode, error) { +func GetDeletedNodeByMacAddress(network string, macaddress string) (models.Node, error) { - var node models.LegacyNode + var node models.Node key, err := GetRecordKey(macaddress, network) if err != nil { @@ -574,11 +440,11 @@ func GetDeletedNodeByMacAddress(network string, macaddress string) (models.Legac record, err := database.FetchRecord(database.DELETED_NODES_TABLE_NAME, key) if err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } if err = json.Unmarshal([]byte(record), &node); err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } SetNodeDefaults(&node) @@ -587,9 +453,9 @@ func GetDeletedNodeByMacAddress(network string, macaddress string) (models.Legac } // GetNodeRelay - gets the relay node of a given network -func GetNodeRelay(network string, relayedNodeAddr string) (models.LegacyNode, error) { +func GetNodeRelay(network string, relayedNodeAddr string) (models.Node, error) { collection, err := database.FetchRecords(database.NODES_TABLE_NAME) - var relay models.LegacyNode + var relay models.Node if err != nil { if database.IsEmptyRecord(err) { return relay, nil @@ -603,7 +469,7 @@ func GetNodeRelay(network string, relayedNodeAddr string) (models.LegacyNode, er logger.Log(2, err.Error()) continue } - if relay.IsRelay == "yes" { + if relay.IsRelay { for _, addr := range relay.RelayAddrs { if addr == relayedNodeAddr { return relay, nil @@ -614,30 +480,30 @@ func GetNodeRelay(network string, relayedNodeAddr string) (models.LegacyNode, er return relay, errors.New(RELAY_NODE_ERR + " " + relayedNodeAddr) } -func GetNodeByID(uuid string) (models.LegacyNode, error) { +func GetNodeByID(uuid string) (models.Node, error) { var record, err = database.FetchRecord(database.NODES_TABLE_NAME, uuid) if err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } - var node models.LegacyNode + var node models.Node if err = json.Unmarshal([]byte(record), &node); err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } return node, nil } // GetDeletedNodeByID - get a deleted node -func GetDeletedNodeByID(uuid string) (models.LegacyNode, error) { +func GetDeletedNodeByID(uuid string) (models.Node, error) { - var node models.LegacyNode + var node models.Node record, err := database.FetchRecord(database.DELETED_NODES_TABLE_NAME, uuid) if err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } if err = json.Unmarshal([]byte(record), &node); err != nil { - return models.LegacyNode{}, err + return models.Node{}, err } SetNodeDefaults(&node) @@ -645,81 +511,9 @@ func GetDeletedNodeByID(uuid string) (models.LegacyNode, error) { return node, nil } -// GetNetworkServerNodeID - get network server node ID if exists -func GetNetworkServerLeader(network string) (models.LegacyNode, error) { - nodes, err := GetSortedNetworkServerNodes(network) - if err != nil { - return models.LegacyNode{}, err - } - for _, node := range nodes { - if IsLeader(&node) { - return node, nil - } - } - return models.LegacyNode{}, errors.New("could not find server leader") -} - -// GetNetworkServerNodeID - get network server node ID if exists -func GetNetworkServerLocal(network string) (models.LegacyNode, error) { - nodes, err := GetSortedNetworkServerNodes(network) - if err != nil { - return models.LegacyNode{}, err - } - mac := servercfg.GetNodeID() - if mac == "" { - return models.LegacyNode{}, fmt.Errorf("error retrieving local server node: server node ID is unset") - } - for _, node := range nodes { - if mac == node.MacAddress { - return node, nil - } - } - return models.LegacyNode{}, errors.New("could not find node for local server") -} - -// IsLocalServer - get network server node ID if exists -func IsLocalServer(node *models.LegacyNode) bool { - var islocal bool - local, err := GetNetworkServerLocal(node.Network) - if err != nil { - return islocal - } - return node.ID != "" && local.ID == node.ID -} - -// validateServer - make sure servers dont change port or address -func validateServer(currentNode, newNode *models.LegacyNode) bool { - return (newNode.Address == currentNode.Address && - newNode.ListenPort == currentNode.ListenPort && - newNode.IsServer == "yes") -} - -// unsetHub - unset hub on network nodes -func UnsetHub(networkName string) (*models.LegacyNode, error) { - var nodesToUpdate models.LegacyNode - nodes, err := GetNetworkNodes(networkName) - if err != nil { - return &nodesToUpdate, err - } - - for i := range nodes { - if nodes[i].IsHub == "yes" { - nodes[i].IsHub = "no" - nodesToUpdate = nodes[i] - newNodeData, err := json.Marshal(&nodes[i]) - if err != nil { - logger.Log(1, "error on node during hub update") - return &nodesToUpdate, err - } - database.Insert(nodes[i].ID, string(newNodeData), database.NODES_TABLE_NAME) - } - } - return &nodesToUpdate, nil -} - // FindRelay - returns the node that is the relay for a relayed node -func FindRelay(node *models.LegacyNode) *models.LegacyNode { - if node.IsRelayed == "no" { +func FindRelay(node *models.Node) *models.Node { + if !node.IsRelayed { return nil } peers, err := GetNetworkNodes(node.Network) @@ -727,11 +521,11 @@ func FindRelay(node *models.LegacyNode) *models.LegacyNode { return nil } for _, peer := range peers { - if peer.IsRelay == "no" { + if !peer.IsRelay { continue } for _, ip := range peer.RelayAddrs { - if ip == node.Address || ip == node.Address6 { + if ip == node.Address.IP.String() || ip == node.Address6.IP.String() { return &peer } } @@ -739,16 +533,16 @@ func FindRelay(node *models.LegacyNode) *models.LegacyNode { return nil } -func findNode(ip string) (*models.LegacyNode, error) { +func findNode(ip string) (*models.Node, error) { nodes, err := GetAllNodes() if err != nil { return nil, err } for _, node := range nodes { - if node.Address == ip { + if node.Address.IP.String() == ip { return &node, nil } - if node.Address6 == ip { + if node.Address6.IP.String() == ip { return &node, nil } } @@ -756,14 +550,14 @@ func findNode(ip string) (*models.LegacyNode, error) { } // GetNetworkIngresses - gets the gateways of a network -func GetNetworkIngresses(network string) ([]models.LegacyNode, error) { - var ingresses []models.LegacyNode +func GetNetworkIngresses(network string) ([]models.Node, error) { + var ingresses []models.Node netNodes, err := GetNetworkNodes(network) if err != nil { - return []models.LegacyNode{}, err + return []models.Node{}, err } for i := range netNodes { - if netNodes[i].IsIngressGateway == "yes" { + if netNodes[i].IsIngressGateway { ingresses = append(ingresses, netNodes[i]) } } @@ -772,7 +566,7 @@ func GetNetworkIngresses(network string) ([]models.LegacyNode, error) { // == PRO == -func updateProNodeACLS(node *models.LegacyNode) error { +func updateProNodeACLS(node *models.Node) error { // == PRO node ACLs == networkNodes, err := GetNetworkNodes(node.Network) if err != nil { @@ -799,12 +593,12 @@ func PurgePendingNodes(ctx context.Context) { } for _, node := range nodes { if node.PendingDelete { - modified := time.Unix(node.LastModified, 0) + modified := node.LastModified if time.Since(modified) > NodePurgeTime { if err := DeleteNode(&node, true); err != nil { - logger.Log(0, "failed to purge node", node.ID, err.Error()) + logger.Log(0, "failed to purge node", node.ID.String(), err.Error()) } else { - logger.Log(0, "purged node ", node.ID) + logger.Log(0, "purged node ", node.ID.String()) } } diff --git a/logic/peers.go b/logic/peers.go index eab7c616..72cfe79c 100644 --- a/logic/peers.go +++ b/logic/peers.go @@ -21,7 +21,14 @@ import ( "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) -func GetPeersForProxy(node *models.LegacyNode, onlyPeers bool) (manager.ProxyManagerPayload, error) { +// GetPeersforProxy calculates the peers for a proxy +// TODO ========================== +// TODO ========================== +// TODO ========================== +// TODO ========================== +// TODO ========================== +// revisit this logic with new host/node models. +func GetPeersForProxy(node *models.Node, onlyPeers bool) (manager.ProxyManagerPayload, error) { proxyPayload := manager.ProxyManagerPayload{} var peers []wgtypes.PeerConfig peerConfMap := make(map[string]proxy_models.PeerConf) @@ -31,36 +38,47 @@ func GetPeersForProxy(node *models.LegacyNode, onlyPeers bool) (manager.ProxyMan return proxyPayload, err } if !onlyPeers { - if node.IsRelayed == "yes" { + if node.IsRelayed { relayNode := FindRelay(node) if relayNode != nil { - relayEndpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayNode.Endpoint, relayNode.LocalListenPort)) + host, err := GetHost(relayNode.HostID.String()) + if err != nil { + logger.Log(0, "error retrieving host for relay node", relayNode.HostID.String(), err.Error()) + } + relayEndpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayNode.EndpointIP, host.LocalListenPort)) if err != nil { logger.Log(1, "failed to resolve relay node endpoint: ", err.Error()) } proxyPayload.IsRelayed = true proxyPayload.RelayedTo = relayEndpoint } else { - logger.Log(0, "couldn't find relay node for: ", node.ID, node.PublicKey) + logger.Log(0, "couldn't find relay node for: ", node.ID.String()) } } - if node.IsRelay == "yes" { + if node.IsRelay { + host, err := GetHost(node.HostID.String()) + if err != nil { + logger.Log(0, "error retrieving host for relay node", node.ID.String(), err.Error()) + } relayedNodes, err := GetRelayedNodes(node) if err != nil { - logger.Log(1, "failed to relayed nodes: ", node.Name, err.Error()) + logger.Log(1, "failed to relayed nodes: ", node.ID.String(), err.Error()) proxyPayload.IsRelay = false } else { - relayPeersMap := make(map[string]proxy_models.RelayedConf) for _, relayedNode := range relayedNodes { payload, err := GetPeersForProxy(&relayedNode, true) if err == nil { - relayedEndpoint, udpErr := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayedNode.Endpoint, relayedNode.LocalListenPort)) + relayedHost, err := GetHost(relayedNode.HostID.String()) + if err != nil { + logger.Log(0, "error retrieving host for relayNode", relayedNode.ID.String(), err.Error()) + } + relayedEndpoint, udpErr := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayedNode.EndpointIP, host.LocalListenPort)) if udpErr == nil { - relayPeersMap[relayedNode.PublicKey] = proxy_models.RelayedConf{ + relayPeersMap[host.PublicKey.String()] = proxy_models.RelayedConf{ RelayedPeerEndpoint: relayedEndpoint, - RelayedPeerPubKey: relayedNode.PublicKey, + RelayedPeerPubKey: relayedHost.PublicKey.String(), Peers: payload.Peers, } } @@ -79,26 +97,25 @@ func GetPeersForProxy(node *models.LegacyNode, onlyPeers bool) (manager.ProxyMan //skip yourself continue } - pubkey, err := wgtypes.ParseKey(peer.PublicKey) + host, err := GetHost(peer.HostID.String()) if err != nil { - logger.Log(1, "failed to parse node pub key: ", peer.ID) continue } proxyStatus := peer.Proxy - listenPort := peer.LocalListenPort + listenPort := host.LocalListenPort if proxyStatus { - listenPort = peer.ProxyListenPort + listenPort = host.ProxyListenPort if listenPort == 0 { listenPort = proxy_models.NmProxyPort } } else if listenPort == 0 { - listenPort = peer.ListenPort + listenPort = host.ListenPort } - endpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", peer.Endpoint, listenPort)) + endpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", peer.EndpointIP, listenPort)) if err != nil { - logger.Log(1, "failed to resolve udp addr for node: ", peer.ID, peer.Endpoint, err.Error()) + logger.Log(1, "failed to resolve udp addr for node: ", peer.ID.String(), peer.EndpointIP.String(), err.Error()) continue } allowedips := GetAllowedIPs(node, &peer, nil, false) @@ -107,34 +124,36 @@ func GetPeersForProxy(node *models.LegacyNode, onlyPeers bool) (manager.ProxyMan // set_keepalive keepalive, _ = time.ParseDuration(strconv.FormatInt(int64(node.PersistentKeepalive), 10) + "s") } - if peer.IsServer == "yes" { - proxyStatus = servercfg.IsProxyEnabled() - } peers = append(peers, wgtypes.PeerConfig{ - PublicKey: pubkey, + PublicKey: host.PublicKey, Endpoint: endpoint, AllowedIPs: allowedips, PersistentKeepaliveInterval: &keepalive, ReplaceAllowedIPs: true, }) - peerConfMap[peer.PublicKey] = proxy_models.PeerConf{ + peerConfMap[host.PublicKey.String()] = proxy_models.PeerConf{ Address: net.ParseIP(peer.PrimaryAddress()), Proxy: proxyStatus, - PublicListenPort: listenPort, + PublicListenPort: int32(listenPort), } - if !onlyPeers && peer.IsRelayed == "yes" { + if !onlyPeers && peer.IsRelayed { relayNode := FindRelay(&peer) if relayNode != nil { - relayTo, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayNode.Endpoint, relayNode.LocalListenPort)) + relayHost, err := GetHost(relayNode.HostID.String()) + if err != nil { + logger.Log(0, "error retrieving host for relayNode", relayNode.ID.String(), err.Error()) + continue + } + relayTo, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayNode.EndpointIP, relayHost.LocalListenPort)) if err == nil { - peerConfMap[peer.PublicKey] = proxy_models.PeerConf{ + peerConfMap[host.PublicKey.String()] = proxy_models.PeerConf{ IsRelayed: true, RelayedTo: relayTo, Address: net.ParseIP(peer.PrimaryAddress()), Proxy: proxyStatus, - PublicListenPort: listenPort, + PublicListenPort: int32(listenPort), } } @@ -142,7 +161,7 @@ func GetPeersForProxy(node *models.LegacyNode, onlyPeers bool) (manager.ProxyMan } } - if node.IsIngressGateway == "yes" { + if node.IsIngressGateway { var extPeers []wgtypes.PeerConfig extPeers, peerConfMap, err = getExtPeersForProxy(node, peerConfMap) if err == nil { @@ -153,36 +172,31 @@ func GetPeersForProxy(node *models.LegacyNode, onlyPeers bool) (manager.ProxyMan } } - proxyPayload.IsIngress = node.IsIngressGateway == "yes" + proxyPayload.IsIngress = node.IsIngressGateway addr := node.Address - if addr == "" { + if addr.String() == "" { addr = node.Address6 } - proxyPayload.WgAddr = addr + proxyPayload.WgAddr = addr.String() proxyPayload.Peers = peers proxyPayload.PeerMap = peerConfMap proxyPayload.Network = node.Network - proxyPayload.InterfaceName = node.Interface + //proxyPayload.InterfaceName = node.Interface + //hardcode or read from host ?? + proxyPayload.InterfaceName = "netmaker" + return proxyPayload, nil } // GetPeerUpdate - gets a wireguard peer config for each peer of a node -func GetPeerUpdate(node *models.LegacyNode) (models.PeerUpdate, error) { +func GetPeerUpdate(node *models.Node) (models.PeerUpdate, error) { var peerUpdate models.PeerUpdate var peers []wgtypes.PeerConfig var serverNodeAddresses = []models.ServerAddr{} - var isP2S bool - network, err := GetNetwork(node.Network) - if err != nil { - return peerUpdate, err - } else if network.IsPointToSite == "yes" && node.IsHub != "yes" { - isP2S = true - } var peerMap = make(models.PeerMap) - var metrics *models.Metrics if servercfg.Is_EE { - metrics, _ = GetMetrics(node.ID) + metrics, _ = GetMetrics(node.ID.String()) } if metrics == nil { metrics = &models.Metrics{} @@ -202,7 +216,7 @@ func GetPeerUpdate(node *models.LegacyNode) (models.PeerUpdate, error) { return models.PeerUpdate{}, err } - if node.IsRelayed == "yes" && !node.Proxy { + if node.IsRelayed && !node.Proxy { return GetPeerUpdateForRelayedNode(node, udppeers) } @@ -214,49 +228,51 @@ func GetPeerUpdate(node *models.LegacyNode) (models.PeerUpdate, error) { //skip yourself continue } - // on point to site networks -- get peers regularily if you are the hub --- otherwise the only peer is the hub - if node.NetworkSettings.IsPointToSite == "yes" && node.IsHub == "no" && peer.IsHub == "no" { - continue - } - if node.Connected != "yes" { + if node.Connected { //skip unconnected nodes continue } // if the node is not a server, set the endpoint - var setEndpoint = !(node.IsServer == "yes") + var setEndpoint = true - if peer.IsRelayed == "yes" { - if !peer.Proxy && !(node.IsRelay == "yes" && ncutils.StringSliceContains(node.RelayAddrs, peer.PrimaryAddress())) { + if peer.IsRelayed { + if !peer.Proxy && !(node.IsRelay && ncutils.StringSliceContains(node.RelayAddrs, peer.PrimaryAddress())) { //skip -- will be added to relay continue - } else if node.IsRelay == "yes" && ncutils.StringSliceContains(node.RelayAddrs, peer.PrimaryAddress()) { + } else if node.IsRelay && ncutils.StringSliceContains(node.RelayAddrs, peer.PrimaryAddress()) { // dont set peer endpoint if it's relayed by node setEndpoint = false } } - if !nodeacls.AreNodesAllowed(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID), nodeacls.NodeID(peer.ID)) { + if !nodeacls.AreNodesAllowed(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), nodeacls.NodeID(peer.ID.String())) { //skip if not permitted by acl continue } - if isP2S && peer.IsHub != "yes" { + if len(metrics.FailoverPeers[peer.ID.String()]) > 0 && IsFailoverPresent(node.Network) { + logger.Log(2, "peer", peer.ID.String(), peer.PrimaryAddress(), "was found to be in failover peers list for node", node.ID.String(), node.PrimaryAddress()) continue } - if len(metrics.FailoverPeers[peer.ID]) > 0 && IsFailoverPresent(node.Network) { - logger.Log(2, "peer", peer.Name, peer.PrimaryAddress(), "was found to be in failover peers list for node", node.Name, node.PrimaryAddress()) - continue - } - pubkey, err := wgtypes.ParseKey(peer.PublicKey) if err != nil { return models.PeerUpdate{}, err } - if node.Endpoint == peer.Endpoint { + host, err := GetHost(node.HostID.String()) + if err != nil { + logger.Log(0, "error retrieving host for node", node.ID.String(), err.Error()) + return models.PeerUpdate{}, err + } + peerHost, err := GetHost(peer.HostID.String()) + if err != nil { + logger.Log(0, "error retrieving host for peer", node.ID.String(), err.Error()) + return models.PeerUpdate{}, err + } + if node.EndpointIP.String() == peer.EndpointIP.String() { //peer is on same network // set_local - if node.LocalAddress != peer.LocalAddress && peer.LocalAddress != "" { - peer.Endpoint = peer.LocalAddress - if peer.LocalListenPort != 0 { - peer.ListenPort = peer.LocalListenPort + if host.LocalAddress.String() != peerHost.LocalAddress.String() && peerHost.LocalAddress.IP != nil { + peer.EndpointIP = peerHost.LocalAddress.IP + if peerHost.LocalListenPort != 0 { + peerHost.ListenPort = peerHost.LocalListenPort } } else { continue @@ -274,25 +290,25 @@ func GetPeerUpdate(node *models.LegacyNode) (models.PeerUpdate, error) { if setEndpoint { var setUDPPort = false - if peer.UDPHolePunch == "yes" && errN == nil && CheckEndpoint(udppeers[peer.PublicKey]) { - endpointstring := udppeers[peer.PublicKey] + if CheckEndpoint(udppeers[peerHost.PublicKey.String()]) { + endpointstring := udppeers[peerHost.PublicKey.String()] endpointarr := strings.Split(endpointstring, ":") if len(endpointarr) == 2 { port, err := strconv.Atoi(endpointarr[1]) if err == nil { setUDPPort = true - peer.ListenPort = int32(port) + peerHost.ListenPort = port } } } // if udp hole punching is on, but udp hole punching did not set it, use the LocalListenPort instead // or, if port is for some reason zero use the LocalListenPort // but only do this if LocalListenPort is not zero - if ((peer.UDPHolePunch == "yes" && !setUDPPort) || peer.ListenPort == 0) && peer.LocalListenPort != 0 { - peer.ListenPort = peer.LocalListenPort + if ((!setUDPPort) || peerHost.ListenPort == 0) && peerHost.LocalListenPort != 0 { + peerHost.ListenPort = peerHost.LocalListenPort } - endpoint := peer.Endpoint + ":" + strconv.FormatInt(int64(peer.ListenPort), 10) + endpoint := peer.EndpointIP.String() + ":" + strconv.FormatInt(int64(peerHost.ListenPort), 10) address, err = net.ResolveUDPAddr("udp", endpoint) if err != nil { return models.PeerUpdate{}, err @@ -309,7 +325,7 @@ func GetPeerUpdate(node *models.LegacyNode) (models.PeerUpdate, error) { keepalive, _ = time.ParseDuration(strconv.FormatInt(int64(node.PersistentKeepalive), 10) + "s") } var peerData = wgtypes.PeerConfig{ - PublicKey: pubkey, + PublicKey: peerHost.PublicKey, Endpoint: address, ReplaceAllowedIPs: true, AllowedIPs: allowedips, @@ -317,18 +333,15 @@ func GetPeerUpdate(node *models.LegacyNode) (models.PeerUpdate, error) { } peers = append(peers, peerData) - peerMap[peer.PublicKey] = models.IDandAddr{ - Name: peer.Name, - ID: peer.ID, + peerMap[peerHost.PublicKey.String()] = models.IDandAddr{ + Name: peerHost.Name, + ID: peer.ID.String(), Address: peer.PrimaryAddress(), - IsServer: peer.IsServer, + IsServer: "no", } - if peer.IsServer == "yes" { - serverNodeAddresses = append(serverNodeAddresses, models.ServerAddr{IsLeader: IsLeader(&peer), Address: peer.Address}) - } } - if node.IsIngressGateway == "yes" { + if node.IsIngressGateway { extPeers, idsAndAddr, err := getExtPeers(node, true) if err == nil { peers = append(peers, extPeers...) @@ -349,13 +362,17 @@ func GetPeerUpdate(node *models.LegacyNode) (models.PeerUpdate, error) { return peerUpdate, nil } -func getExtPeers(node *models.LegacyNode, forIngressNode bool) ([]wgtypes.PeerConfig, []models.IDandAddr, error) { +func getExtPeers(node *models.Node, forIngressNode bool) ([]wgtypes.PeerConfig, []models.IDandAddr, error) { var peers []wgtypes.PeerConfig var idsAndAddr []models.IDandAddr extPeers, err := GetNetworkExtClients(node.Network) if err != nil { return peers, idsAndAddr, err } + host, err := GetHost(node.HostID.String()) + if err != nil { + return peers, idsAndAddr, err + } for _, extPeer := range extPeers { pubkey, err := wgtypes.ParseKey(extPeer.PublicKey) if err != nil { @@ -363,7 +380,7 @@ func getExtPeers(node *models.LegacyNode, forIngressNode bool) ([]wgtypes.PeerCo continue } - if node.PublicKey == extPeer.PublicKey { + if host.PublicKey.String() == extPeer.PublicKey { continue } @@ -428,8 +445,12 @@ func getExtPeers(node *models.LegacyNode, forIngressNode bool) ([]wgtypes.PeerCo } -func getExtPeersForProxy(node *models.LegacyNode, proxyPeerConf map[string]proxy_models.PeerConf) ([]wgtypes.PeerConfig, map[string]proxy_models.PeerConf, error) { +func getExtPeersForProxy(node *models.Node, proxyPeerConf map[string]proxy_models.PeerConf) ([]wgtypes.PeerConfig, map[string]proxy_models.PeerConf, error) { var peers []wgtypes.PeerConfig + host, err := GetHost(node.HostID.String()) + if err != nil { + logger.Log(0, "error retrieving host for node", node.ID.String(), err.Error()) + } extPeers, err := GetNetworkExtClients(node.Network) if err != nil { @@ -442,7 +463,7 @@ func getExtPeersForProxy(node *models.LegacyNode, proxyPeerConf map[string]proxy continue } - if node.PublicKey == extPeer.PublicKey { + if host.PublicKey.String() == extPeer.PublicKey { continue } @@ -482,7 +503,7 @@ func getExtPeersForProxy(node *models.LegacyNode, proxyPeerConf map[string]proxy Address: net.ParseIP(extPeer.Address), ExtInternalIp: net.ParseIP(extInternalPrimaryAddr), } - if extPeer.IngressGatewayID == node.ID { + if extPeer.IngressGatewayID == node.ID.String() { extConf.IsAttachedExtClient = true } ingGatewayUdpAddr, err := net.ResolveUDPAddr("udp", extPeer.IngressGatewayEndpoint) @@ -499,34 +520,34 @@ func getExtPeersForProxy(node *models.LegacyNode, proxyPeerConf map[string]proxy } // GetAllowedIPs - calculates the wireguard allowedip field for a peer of a node based on the peer and node settings -func GetAllowedIPs(node, peer *models.LegacyNode, metrics *models.Metrics, fetchRelayedIps bool) []net.IPNet { +func GetAllowedIPs(node, peer *models.Node, metrics *models.Metrics, fetchRelayedIps bool) []net.IPNet { var allowedips []net.IPNet allowedips = getNodeAllowedIPs(peer, node) // handle ingress gateway peers - if peer.IsIngressGateway == "yes" { + if peer.IsIngressGateway { extPeers, _, err := getExtPeers(peer, false) if err != nil { - logger.Log(2, "could not retrieve ext peers for ", peer.Name, err.Error()) + logger.Log(2, "could not retrieve ext peers for ", peer.ID.String(), err.Error()) } for _, extPeer := range extPeers { allowedips = append(allowedips, extPeer.AllowedIPs...) } // if node is a failover node, add allowed ips from nodes it is handling - if metrics != nil && peer.Failover == "yes" && metrics.FailoverPeers != nil { + if metrics != nil && peer.Failover && metrics.FailoverPeers != nil { // traverse through nodes that need handling - logger.Log(3, "peer", peer.Name, "was found to be failover for", node.Name, "checking failover peers...") + logger.Log(3, "peer", peer.ID.String(), "was found to be failover for", node.ID.String(), "checking failover peers...") for k := range metrics.FailoverPeers { // if FailoverNode is me for this node, add allowedips - if metrics.FailoverPeers[k] == peer.ID { + if metrics.FailoverPeers[k] == peer.ID.String() { // get original node so we can traverse the allowed ips nodeToFailover, err := GetNodeByID(k) if err == nil { - failoverNodeMetrics, err := GetMetrics(nodeToFailover.ID) + failoverNodeMetrics, err := GetMetrics(nodeToFailover.ID.String()) if err == nil && failoverNodeMetrics != nil { if len(failoverNodeMetrics.NodeName) > 0 { allowedips = append(allowedips, getNodeAllowedIPs(&nodeToFailover, peer)...) - logger.Log(0, "failing over node", nodeToFailover.Name, nodeToFailover.PrimaryAddress(), "to failover node", peer.Name) + logger.Log(0, "failing over node", nodeToFailover.ID.String(), nodeToFailover.PrimaryAddress(), "to failover node", peer.ID.String()) } } } @@ -535,7 +556,7 @@ func GetAllowedIPs(node, peer *models.LegacyNode, metrics *models.Metrics, fetch } } // handle relay gateway peers - if fetchRelayedIps && peer.IsRelay == "yes" { + if fetchRelayedIps && peer.IsRelay { for _, ip := range peer.RelayAddrs { //find node ID of relayed peer relayedPeer, err := findNode(ip) @@ -551,7 +572,7 @@ func GetAllowedIPs(node, peer *models.LegacyNode, metrics *models.Metrics, fetch continue } //check if acl permits comms - if !nodeacls.AreNodesAllowed(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID), nodeacls.NodeID(relayedPeer.ID)) { + if !nodeacls.AreNodesAllowed(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), nodeacls.NodeID(relayedPeer.ID.String())) { continue } if iplib.Version(net.ParseIP(ip)) == 4 { @@ -573,11 +594,11 @@ func GetAllowedIPs(node, peer *models.LegacyNode, metrics *models.Metrics, fetch logger.Log(1, "unable to find node for relayed address", ip, err.Error()) continue } - if relayedNode.IsEgressGateway == "yes" { + if relayedNode.IsEgressGateway { extAllowedIPs := getEgressIPs(node, relayedNode) allowedips = append(allowedips, extAllowedIPs...) } - if relayedNode.IsIngressGateway == "yes" { + if relayedNode.IsIngressGateway { extPeers, _, err := getExtPeers(relayedNode, false) if err == nil { for _, extPeer := range extPeers { @@ -595,8 +616,12 @@ func GetAllowedIPs(node, peer *models.LegacyNode, metrics *models.Metrics, fetch func getPeerDNS(network string) string { var dns string if nodes, err := GetNetworkNodes(network); err == nil { - for i := range nodes { - dns = dns + fmt.Sprintf("%s %s.%s\n", nodes[i].Address, nodes[i].Name, nodes[i].Network) + for i, node := range nodes { + host, err := GetHost(node.HostID.String()) + if err != nil { + logger.Log(0, "error retrieving host for node", node.ID.String(), err.Error()) + } + dns = dns + fmt.Sprintf("%s %s.%s\n", nodes[i].Address, host.Name, nodes[i].Network) } } @@ -611,7 +636,7 @@ func getPeerDNS(network string) string { // GetPeerUpdateForRelayedNode - calculates peer update for a relayed node by getting the relay // copying the relay node's allowed ips and making appropriate substitutions -func GetPeerUpdateForRelayedNode(node *models.LegacyNode, udppeers map[string]string) (models.PeerUpdate, error) { +func GetPeerUpdateForRelayedNode(node *models.Node, udppeers map[string]string) (models.PeerUpdate, error) { var peerUpdate models.PeerUpdate var peers []wgtypes.PeerConfig var serverNodeAddresses = []models.ServerAddr{} @@ -623,18 +648,12 @@ func GetPeerUpdateForRelayedNode(node *models.LegacyNode, udppeers map[string]st } //add relay to lists of allowed ip - if relay.Address != "" { - relayIP := net.IPNet{ - IP: net.ParseIP(relay.Address), - Mask: net.CIDRMask(32, 32), - } + if relay.Address.IP != nil { + relayIP := relay.Address allowedips = append(allowedips, relayIP) } - if relay.Address6 != "" { - relayIP6 := net.IPNet{ - IP: net.ParseIP(relay.Address6), - Mask: net.CIDRMask(128, 128), - } + if relay.Address6.IP != nil { + relayIP6 := relay.Address6 allowedips = append(allowedips, relayIP6) } //get PeerUpdate for relayed node @@ -657,19 +676,19 @@ func GetPeerUpdateForRelayedNode(node *models.LegacyNode, udppeers map[string]st logger.Log(0, "failed to find node for ip", allowedips[i].IP.String()) continue } - if !nodeacls.AreNodesAllowed(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID), nodeacls.NodeID(target.ID)) { - logger.Log(0, "deleting node from relayednode per acl", node.Name, target.Name) + if !nodeacls.AreNodesAllowed(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), nodeacls.NodeID(target.ID.String())) { + logger.Log(0, "deleting node from relayednode per acl", node.ID.String(), target.ID.String()) allowedips = append(allowedips[:i], allowedips[i+1:]...) } } //delete self from allowed ips for i := len(allowedips) - 1; i >= 0; i-- { - if allowedips[i].IP.String() == node.Address || allowedips[i].IP.String() == node.Address6 { + if allowedips[i].IP.String() == node.Address.IP.String() || allowedips[i].IP.String() == node.Address6.IP.String() { allowedips = append(allowedips[:i], allowedips[i+1:]...) } } //delete egressrange from allowedip if we are egress gateway - if node.IsEgressGateway == "yes" { + if node.IsEgressGateway { for i := len(allowedips) - 1; i >= 0; i-- { if StringSliceContains(node.EgressGatewayRanges, allowedips[i].String()) { allowedips = append(allowedips[:i], allowedips[i+1:]...) @@ -677,7 +696,7 @@ func GetPeerUpdateForRelayedNode(node *models.LegacyNode, udppeers map[string]st } } //delete extclients from allowedip if we are ingress gateway - if node.IsIngressGateway == "yes" { + if node.IsIngressGateway { for i := len(allowedips) - 1; i >= 0; i-- { if strings.Contains(node.IngressGatewayRange, allowedips[i].IP.String()) { allowedips = append(allowedips[:i], allowedips[i+1:]...) @@ -685,7 +704,7 @@ func GetPeerUpdateForRelayedNode(node *models.LegacyNode, udppeers map[string]st } } //add egress range if relay is egress - if relay.IsEgressGateway == "yes" { + if relay.IsEgressGateway { var ip *net.IPNet for _, cidr := range relay.EgressGatewayRanges { _, ip, err = net.ParseCIDR(cidr) @@ -695,31 +714,34 @@ func GetPeerUpdateForRelayedNode(node *models.LegacyNode, udppeers map[string]st } allowedips = append(allowedips, *ip) } - - pubkey, err := wgtypes.ParseKey(relay.PublicKey) + relayHost, err := GetHost(relay.HostID.String()) + if err != nil { + logger.Log(0, "error retrieving host for relay node", node.ID.String(), err.Error()) + } if err != nil { return models.PeerUpdate{}, err } var setUDPPort = false - if relay.UDPHolePunch == "yes" && CheckEndpoint(udppeers[relay.PublicKey]) { - endpointstring := udppeers[relay.PublicKey] + var listenPort int + if CheckEndpoint(udppeers[relayHost.PublicKey.String()]) { + endpointstring := udppeers[relayHost.PublicKey.String()] endpointarr := strings.Split(endpointstring, ":") if len(endpointarr) == 2 { port, err := strconv.Atoi(endpointarr[1]) if err == nil { setUDPPort = true - relay.ListenPort = int32(port) + listenPort = port } } } // if udp hole punching is on, but udp hole punching did not set it, use the LocalListenPort instead // or, if port is for some reason zero use the LocalListenPort // but only do this if LocalListenPort is not zero - if ((relay.UDPHolePunch == "yes" && !setUDPPort) || relay.ListenPort == 0) && relay.LocalListenPort != 0 { - relay.ListenPort = relay.LocalListenPort + if ((!setUDPPort) || relayHost.ListenPort == 0) && relayHost.LocalListenPort != 0 { + listenPort = relayHost.LocalListenPort } - endpoint := relay.Endpoint + ":" + strconv.FormatInt(int64(relay.ListenPort), 10) + endpoint := relay.EndpointIP.String() + ":" + strconv.FormatInt(int64(listenPort), 10) address, err := net.ResolveUDPAddr("udp", endpoint) if err != nil { return models.PeerUpdate{}, err @@ -730,23 +752,20 @@ func GetPeerUpdateForRelayedNode(node *models.LegacyNode, udppeers map[string]st keepalive, _ = time.ParseDuration(strconv.FormatInt(int64(node.PersistentKeepalive), 10) + "s") } var peerData = wgtypes.PeerConfig{ - PublicKey: pubkey, + PublicKey: relayHost.PublicKey, Endpoint: address, ReplaceAllowedIPs: true, AllowedIPs: allowedips, PersistentKeepaliveInterval: &keepalive, } peers = append(peers, peerData) - if relay.IsServer == "yes" { - serverNodeAddresses = append(serverNodeAddresses, models.ServerAddr{IsLeader: IsLeader(relay), Address: relay.Address}) - } //if ingress add extclients - if node.IsIngressGateway == "yes" { + if node.IsIngressGateway { extPeers, _, err := getExtPeers(node, true) if err == nil { peers = append(peers, extPeers...) } else { - logger.Log(2, "could not retrieve ext peers for ", node.Name, err.Error()) + logger.Log(2, "could not retrieve ext peers for ", node.ID.String(), err.Error()) } } peerUpdate.Network = node.Network @@ -757,7 +776,11 @@ func GetPeerUpdateForRelayedNode(node *models.LegacyNode, udppeers map[string]st return peerUpdate, nil } -func getEgressIPs(node, peer *models.LegacyNode) []net.IPNet { +func getEgressIPs(node, peer *models.Node) []net.IPNet { + host, err := GetHost(node.HostID.String()) + if err != nil { + logger.Log(0, "error retrieving host for node", node.ID.String(), err.Error()) + } //check for internet gateway internetGateway := false if slices.Contains(peer.EgressGatewayRanges, "0.0.0.0/0") || slices.Contains(peer.EgressGatewayRanges, "::/0") { @@ -770,14 +793,14 @@ func getEgressIPs(node, peer *models.LegacyNode) []net.IPNet { logger.Log(1, "could not parse gateway IP range. Not adding ", iprange) continue // if can't parse CIDR } - nodeEndpointArr := strings.Split(peer.Endpoint, ":") // getting the public ip of node + nodeEndpointArr := strings.Split(peer.EndpointIP.String(), ":") // getting the public ip of node if ipnet.Contains(net.ParseIP(nodeEndpointArr[0])) && !internetGateway { // ensuring egress gateway range does not contain endpoint of node - logger.Log(2, "egress IP range of ", iprange, " overlaps with ", node.Endpoint, ", omitting") + logger.Log(2, "egress IP range of ", iprange, " overlaps with ", node.EndpointIP.String(), ", omitting") continue // skip adding egress range if overlaps with node's ip } // TODO: Could put in a lot of great logic to avoid conflicts / bad routes - if ipnet.Contains(net.ParseIP(node.LocalAddress)) && !internetGateway { // ensuring egress gateway range does not contain public ip of node - logger.Log(2, "egress IP range of ", iprange, " overlaps with ", node.LocalAddress, ", omitting") + if ipnet.Contains(net.ParseIP(host.LocalAddress.String())) && !internetGateway { // ensuring egress gateway range does not contain public ip of node + logger.Log(2, "egress IP range of ", iprange, " overlaps with ", host.LocalAddress.String(), ", omitting") continue // skip adding egress range if overlaps with node's local ip } if err != nil { @@ -789,42 +812,34 @@ func getEgressIPs(node, peer *models.LegacyNode) []net.IPNet { return allowedips } -func getNodeAllowedIPs(peer, node *models.LegacyNode) []net.IPNet { +func getNodeAllowedIPs(peer, node *models.Node) []net.IPNet { var allowedips = []net.IPNet{} - if peer.Address != "" { - var peeraddr = net.IPNet{ - IP: net.ParseIP(peer.Address), - Mask: net.CIDRMask(32, 32), - } - allowedips = append(allowedips, peeraddr) + if peer.Address.IP != nil { + allowedips = append(allowedips, peer.Address) } - if peer.Address6 != "" { - var addr6 = net.IPNet{ - IP: net.ParseIP(peer.Address6), - Mask: net.CIDRMask(128, 128), - } - allowedips = append(allowedips, addr6) + if peer.Address6.IP != nil { + allowedips = append(allowedips, peer.Address6) } // handle manually set peers for _, allowedIp := range peer.AllowedIPs { // parsing as a CIDR first. If valid CIDR, append if _, ipnet, err := net.ParseCIDR(allowedIp); err == nil { - nodeEndpointArr := strings.Split(node.Endpoint, ":") - if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != peer.Address { // don't need to add an allowed ip that already exists.. + nodeEndpointArr := strings.Split(node.EndpointIP.String(), ":") + if !ipnet.Contains(net.IP(nodeEndpointArr[0])) && ipnet.IP.String() != peer.Address.IP.String() { // don't need to add an allowed ip that already exists.. allowedips = append(allowedips, *ipnet) } } else { // parsing as an IP second. If valid IP, check if ipv4 or ipv6, then append - if iplib.Version(net.ParseIP(allowedIp)) == 4 && allowedIp != peer.Address { + if iplib.Version(net.ParseIP(allowedIp)) == 4 && allowedIp != peer.Address.IP.String() { ipnet := net.IPNet{ IP: net.ParseIP(allowedIp), Mask: net.CIDRMask(32, 32), } allowedips = append(allowedips, ipnet) - } else if iplib.Version(net.ParseIP(allowedIp)) == 6 && allowedIp != peer.Address6 { + } else if iplib.Version(net.ParseIP(allowedIp)) == 6 && allowedIp != peer.Address6.IP.String() { ipnet := net.IPNet{ IP: net.ParseIP(allowedIp), Mask: net.CIDRMask(128, 128), @@ -834,17 +849,9 @@ func getNodeAllowedIPs(peer, node *models.LegacyNode) []net.IPNet { } } // handle egress gateway peers - if peer.IsEgressGateway == "yes" { + if peer.IsEgressGateway { //hasGateway = true egressIPs := getEgressIPs(node, peer) - // remove internet gateway if server - if node.IsServer == "yes" { - for i := len(egressIPs) - 1; i >= 0; i-- { - if egressIPs[i].String() == "0.0.0.0/0" || egressIPs[i].String() == "::/0" { - egressIPs = append(egressIPs[:i], egressIPs[i+1:]...) - } - } - } allowedips = append(allowedips, egressIPs...) } return allowedips diff --git a/logic/pro/networkuser.go b/logic/pro/networkuser.go index 7ea794ff..14d918de 100644 --- a/logic/pro/networkuser.go +++ b/logic/pro/networkuser.go @@ -175,7 +175,7 @@ func RemoveAllNetworkUsers(network string) error { // IsUserNodeAllowed - given a list of nodes, determine if the user's node is allowed based on ID // Checks if node is in given nodes list as well as being in user's list -func IsUserNodeAllowed(nodes []models.LegacyNode, network, userID, nodeID string) bool { +func IsUserNodeAllowed(nodes []models.Node, network, userID, nodeID string) bool { netUser, err := GetNetworkUser(network, promodels.NetworkUserID(userID)) if err != nil { @@ -183,7 +183,7 @@ func IsUserNodeAllowed(nodes []models.LegacyNode, network, userID, nodeID string } for i := range nodes { - if nodes[i].ID == nodeID { + if nodes[i].ID.String() == nodeID { for j := range netUser.Nodes { if netUser.Nodes[j] == nodeID { return true diff --git a/logic/pro/proacls/nodes.go b/logic/pro/proacls/nodes.go index b7782b03..2d2d5ff6 100644 --- a/logic/pro/proacls/nodes.go +++ b/logic/pro/proacls/nodes.go @@ -7,16 +7,16 @@ import ( ) // AdjustNodeAcls - adjusts ACLs based on a node's default value -func AdjustNodeAcls(node *models.LegacyNode, networkNodes []models.LegacyNode) error { +func AdjustNodeAcls(node *models.Node, networkNodes []models.Node) error { networkID := nodeacls.NetworkID(node.Network) - nodeID := nodeacls.NodeID(node.ID) + nodeID := nodeacls.NodeID(node.ID.String()) currentACLs, err := nodeacls.FetchAllACLs(networkID) if err != nil { return err } for i := range networkNodes { - currentNodeID := nodeacls.NodeID(networkNodes[i].ID) + currentNodeID := nodeacls.NodeID(networkNodes[i].ID.String()) if currentNodeID == nodeID { continue } diff --git a/logic/relay.go b/logic/relay.go index d7ef416d..dd2b7c28 100644 --- a/logic/relay.go +++ b/logic/relay.go @@ -12,21 +12,25 @@ import ( ) // CreateRelay - creates a relay -func CreateRelay(relay models.RelayRequest) ([]models.LegacyNode, models.LegacyNode, error) { - var returnnodes []models.LegacyNode +func CreateRelay(relay models.RelayRequest) ([]models.Node, models.Node, error) { + var returnnodes []models.Node node, err := GetNodeByID(relay.NodeID) if err != nil { - return returnnodes, models.LegacyNode{}, err + return returnnodes, models.Node{}, err } - if node.OS != "linux" { - return returnnodes, models.LegacyNode{}, fmt.Errorf("only linux machines can be relay nodes") + host, err := GetHost(node.ID.String()) + if err != nil { + return returnnodes, models.Node{}, err + } + if host.OS != "linux" { + return returnnodes, models.Node{}, fmt.Errorf("only linux machines can be relay nodes") } err = ValidateRelay(relay) if err != nil { - return returnnodes, models.LegacyNode{}, err + return returnnodes, models.Node{}, err } - node.IsRelay = "yes" + node.IsRelay = true node.RelayAddrs = relay.RelayAddrs node.SetLastModified() @@ -34,8 +38,8 @@ func CreateRelay(relay models.RelayRequest) ([]models.LegacyNode, models.LegacyN if err != nil { return returnnodes, node, err } - if err = database.Insert(node.ID, string(nodeData), database.NODES_TABLE_NAME); err != nil { - return returnnodes, models.LegacyNode{}, err + if err = database.Insert(node.ID.String(), string(nodeData), database.NODES_TABLE_NAME); err != nil { + return returnnodes, models.Node{}, err } returnnodes, err = SetRelayedNodes(true, node.Network, node.RelayAddrs) if err != nil { @@ -45,45 +49,41 @@ func CreateRelay(relay models.RelayRequest) ([]models.LegacyNode, models.LegacyN } // SetRelayedNodes- set relayed nodes -func SetRelayedNodes(setRelayed bool, networkName string, addrs []string) ([]models.LegacyNode, error) { - var returnnodes []models.LegacyNode +func SetRelayedNodes(setRelayed bool, networkName string, addrs []string) ([]models.Node, error) { + var returnnodes []models.Node networkNodes, err := GetNetworkNodes(networkName) if err != nil { return returnnodes, err } for _, node := range networkNodes { - if node.IsServer != "yes" { - for _, addr := range addrs { - if addr == node.Address || addr == node.Address6 { - if setRelayed { - node.IsRelayed = "yes" - } else { - node.IsRelayed = "no" - } - data, err := json.Marshal(&node) - if err != nil { - return returnnodes, err - } - database.Insert(node.ID, string(data), database.NODES_TABLE_NAME) - returnnodes = append(returnnodes, node) + for _, addr := range addrs { + if addr == node.Address.IP.String() || addr == node.Address6.IP.String() { + if setRelayed { + node.IsRelayed = true + } else { + node.IsRelayed = false } + data, err := json.Marshal(&node) + if err != nil { + return returnnodes, err + } + database.Insert(node.ID.String(), string(data), database.NODES_TABLE_NAME) + returnnodes = append(returnnodes, node) } } } return returnnodes, nil } -func GetRelayedNodes(relayNode *models.LegacyNode) ([]models.LegacyNode, error) { - var returnnodes []models.LegacyNode +func GetRelayedNodes(relayNode *models.Node) ([]models.Node, error) { + var returnnodes []models.Node networkNodes, err := GetNetworkNodes(relayNode.Network) if err != nil { return returnnodes, err } for _, node := range networkNodes { - if node.IsServer != "yes" { - for _, addr := range relayNode.RelayAddrs { - if addr == node.Address || addr == node.Address6 { - returnnodes = append(returnnodes, node) - } + for _, addr := range relayNode.RelayAddrs { + if addr == node.Address.IP.String() || addr == node.Address6.IP.String() { + returnnodes = append(returnnodes, node) } } } @@ -102,8 +102,8 @@ func ValidateRelay(relay models.RelayRequest) error { } // UpdateRelay - updates a relay -func UpdateRelay(network string, oldAddrs []string, newAddrs []string) []models.LegacyNode { - var returnnodes []models.LegacyNode +func UpdateRelay(network string, oldAddrs []string, newAddrs []string) []models.Node { + var returnnodes []models.Node time.Sleep(time.Second / 4) _, err := SetRelayedNodes(false, network, oldAddrs) if err != nil { @@ -117,27 +117,27 @@ func UpdateRelay(network string, oldAddrs []string, newAddrs []string) []models. } // DeleteRelay - deletes a relay -func DeleteRelay(network, nodeid string) ([]models.LegacyNode, models.LegacyNode, error) { - var returnnodes []models.LegacyNode +func DeleteRelay(network, nodeid string) ([]models.Node, models.Node, error) { + var returnnodes []models.Node node, err := GetNodeByID(nodeid) if err != nil { - return returnnodes, models.LegacyNode{}, err + return returnnodes, models.Node{}, err } returnnodes, err = SetRelayedNodes(false, node.Network, node.RelayAddrs) if err != nil { return returnnodes, node, err } - node.IsRelay = "no" + node.IsRelay = false node.RelayAddrs = []string{} node.SetLastModified() data, err := json.Marshal(&node) if err != nil { - return returnnodes, models.LegacyNode{}, err + return returnnodes, models.Node{}, err } if err = database.Insert(nodeid, string(data), database.NODES_TABLE_NAME); err != nil { - return returnnodes, models.LegacyNode{}, err + return returnnodes, models.Node{}, err } return returnnodes, node, nil } diff --git a/logic/server.go b/logic/server.go index edd4f6f5..19ff4e46 100644 --- a/logic/server.go +++ b/logic/server.go @@ -1,22 +1,10 @@ package logic import ( - "encoding/json" - "errors" - "fmt" - "net" - "os" - "runtime" "strings" "github.com/gravitl/netclient/nmproxy/manager" - "github.com/gravitl/netmaker/database" - "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/netclient/wireguard" - "github.com/gravitl/netmaker/servercfg" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) var ProxyMgmChan = make(chan *manager.ProxyManagerPayload, 100) @@ -25,7 +13,7 @@ var ProxyMgmChan = make(chan *manager.ProxyManagerPayload, 100) var EnterpriseCheckFuncs []func() // EnterpriseFailoverFunc - interface to control failover funcs -var EnterpriseFailoverFunc func(node *models.LegacyNode) error +var EnterpriseFailoverFunc func(node *models.Node) error // EnterpriseResetFailoverFunc - interface to control reset failover funcs var EnterpriseResetFailoverFunc func(network string) error @@ -41,153 +29,6 @@ const KUBERNETES_LISTEN_PORT = 31821 // KUBERNETES_SERVER_MTU - ideal mtu for kubernetes deployments right now const KUBERNETES_SERVER_MTU = 1024 -// ServerJoin - responsible for joining a server to a network -func ServerJoin(networkSettings *models.Network) (models.LegacyNode, error) { - var returnNode models.LegacyNode - if networkSettings == nil || networkSettings.NetID == "" { - return returnNode, errors.New("no network provided") - } - - var err error - - var currentServers = GetServerNodes(networkSettings.NetID) - var serverCount = 1 - if currentServers != nil { - serverCount = len(currentServers) + 1 - } - var ishub = "no" - - if networkSettings.IsPointToSite == "yes" { - nodes, err := GetNetworkNodes(networkSettings.NetID) - if err != nil || nodes == nil { - ishub = "yes" - } else { - sethub := true - for i := range nodes { - if nodes[i].IsHub == "yes" { - sethub = false - } - } - if sethub { - ishub = "yes" - } - } - } - var node = &models.LegacyNode{ - IsServer: "yes", - DNSOn: "no", - IsStatic: "yes", - Name: fmt.Sprintf("%s-%d", models.NODE_SERVER_NAME, serverCount), - MacAddress: servercfg.GetNodeID(), - ID: "", // will be set to new uuid - UDPHolePunch: "no", - IsLocal: networkSettings.IsLocal, - LocalRange: networkSettings.LocalRange, - OS: runtime.GOOS, - Version: servercfg.Version, - IsHub: ishub, - NetworkSettings: *networkSettings, - } - - SetNodeDefaults(node) - - if servercfg.GetPlatform() == "Kubernetes" { - node.ListenPort = KUBERNETES_LISTEN_PORT - node.MTU = KUBERNETES_SERVER_MTU - } - - if node.LocalRange != "" && node.LocalAddress == "" { - logger.Log(1, "local vpn, getting local address from range:", networkSettings.LocalRange) - node.LocalAddress, err = getServerLocalIP(networkSettings) - if err != nil { - node.LocalAddress = "" - node.IsLocal = "no" - } - } - - if node.Endpoint == "" { - if node.IsLocal == "yes" && node.LocalAddress != "" { - node.Endpoint = node.LocalAddress - } else { - node.Endpoint, err = servercfg.GetPublicIP() - } - if err != nil || node.Endpoint == "" { - logger.Log(0, "Error setting server node Endpoint.") - return returnNode, err - } - } - - var privateKey = "" - - // Generate and set public/private WireGuard Keys - if privateKey == "" { - wgPrivatekey, err := wgtypes.GeneratePrivateKey() - if err != nil { - logger.Log(1, err.Error()) - return returnNode, err - } - privateKey = wgPrivatekey.String() - node.PublicKey = wgPrivatekey.PublicKey().String() - } - - node.Network = networkSettings.NetID - - logger.Log(2, "adding a server instance on network", node.Network) - if err != nil { - return returnNode, err - } - err = SetNetworkNodesLastModified(node.Network) - if err != nil { - return returnNode, err - } - - // get free port based on returned default listen port - node.ListenPort, err = ncutils.GetFreePort(node.ListenPort) - if err != nil { - logger.Log(2, "Error retrieving port:", err.Error()) - } else { - logger.Log(1, "Set client port to", fmt.Sprintf("%d", node.ListenPort), "for network", node.Network) - } - - // safety check. If returned node from server is local, but not currently configured as local, set to local addr - if node.IsLocal == "yes" && node.LocalRange != "" { - node.LocalAddress, err = ncutils.GetLocalIP(node.LocalRange) - if err != nil { - return returnNode, err - } - node.Endpoint = node.LocalAddress - } - - if err = CreateNode(node); err != nil { - return returnNode, err - } - if err = StorePrivKey(node.ID, privateKey); err != nil { - return returnNode, err - } - - peers, err := GetPeerUpdate(node) - if err != nil && !ncutils.IsEmptyRecord(err) { - logger.Log(1, "failed to retrieve peers") - return returnNode, err - } - - err = wireguard.InitWireguard(node, privateKey, peers.Peers) - if err != nil { - return returnNode, err - } - if servercfg.IsProxyEnabled() { - proxyPayload, err := GetPeersForProxy(node, false) - if err != nil && !ncutils.IsEmptyRecord(err) { - logger.Log(1, "failed to retrieve peers") - return returnNode, err - } - ProxyMgmChan <- &proxyPayload - - } - - return *node, nil -} - // EnterpriseCheck - Runs enterprise functions if presented func EnterpriseCheck() { for _, check := range EnterpriseCheckFuncs { @@ -195,163 +36,8 @@ func EnterpriseCheck() { } } -// ServerUpdate - updates the server -// replaces legacy Checkin code -func ServerUpdate(serverNode *models.LegacyNode, ifaceDelta bool) error { - if !IsLocalServer(serverNode) { - logger.Log(1, "skipping server update as not the leader") - return nil - } - - var err = ServerPull(serverNode, ifaceDelta) - if isDeleteError(err) { - return DeleteNode(serverNode, true) - } else if err != nil && !ifaceDelta { - err = ServerPull(serverNode, true) - if err != nil { - return err - } - } - - actionCompleted := checkNodeActions(serverNode) - if actionCompleted == models.NODE_DELETE { - return errors.New("node has been removed") - } - - return serverPush(serverNode) -} - // == Private == func isDeleteError(err error) bool { return err != nil && strings.Contains(err.Error(), models.NODE_DELETE) } - -func checkNodeActions(node *models.LegacyNode) string { - if node.Action == models.NODE_UPDATE_KEY { - err := setWGKeyConfig(node) - if err != nil { - logger.Log(1, "unable to process reset keys request:", err.Error()) - return "" - } - } - if node.Action == models.NODE_DELETE { - err := DeleteNode(node, true) - if err != nil { - logger.Log(1, "error deleting locally:", err.Error()) - } - return models.NODE_DELETE - } - return "" -} - -// == Private == - -// ServerPull - performs a server pull -func ServerPull(serverNode *models.LegacyNode, ifaceDelta bool) error { - if serverNode.IsServer != "yes" { - return fmt.Errorf("attempted pull from non-server node: %s - %s", serverNode.Name, serverNode.ID) - } - - var err error - if serverNode.IPForwarding == "yes" { - if err = setIPForwardingLinux(); err != nil { - return err - } - } - serverNode.OS = runtime.GOOS - - if ifaceDelta { - // check for interface change - // checks if address is in use by another interface - var oldIfaceName, isIfacePresent = isInterfacePresent(serverNode.Interface, serverNode.Address) - if !isIfacePresent { - if err = deleteInterface(oldIfaceName, serverNode.PostDown); err != nil { - logger.Log(1, "could not delete old interface", oldIfaceName) - } - logger.Log(1, "removed old interface", oldIfaceName) - } - if err = setWGConfig(serverNode, false); err != nil { - return err - } - // handle server side update - if err = UpdateNode(serverNode, serverNode); err != nil { - return err - } - } else { - if err = setWGConfig(serverNode, true); err != nil { - if errors.Is(err, os.ErrNotExist) { - return ServerPull(serverNode, true) - } else { - return err - } - } - } - - return nil -} - -func getServerLocalIP(networkSettings *models.Network) (string, error) { - - var networkCIDR = networkSettings.LocalRange - var currentAddresses, _ = net.InterfaceAddrs() - var _, currentCIDR, cidrErr = net.ParseCIDR(networkCIDR) - if cidrErr != nil { - logger.Log(1, "error on server local IP, invalid CIDR provided:", networkCIDR) - return "", cidrErr - } - for _, addr := range currentAddresses { - ip, _, err := net.ParseCIDR(addr.String()) - if err != nil { - continue - } - if currentCIDR.Contains(ip) { - logger.Log(1, "found local ip on network,", networkSettings.NetID, ", set to", ip.String()) - return ip.String(), nil - } - } - return "", errors.New("could not find a local ip for server") -} - -func serverPush(serverNode *models.LegacyNode) error { - serverNode.OS = runtime.GOOS - serverNode.SetLastCheckIn() - return UpdateNode(serverNode, serverNode) -} - -// AddServerIDIfNotPresent - add's current server ID to DB if not present -func AddServerIDIfNotPresent() error { - currentNodeID := servercfg.GetNodeID() - currentServerIDs := models.ServerIDs{} - - record, err := database.FetchRecord(database.SERVERCONF_TABLE_NAME, server_id_key) - if err != nil && !database.IsEmptyRecord(err) { - return err - } else if err == nil { - if err = json.Unmarshal([]byte(record), ¤tServerIDs); err != nil { - return err - } - } - - if !StringSliceContains(currentServerIDs.ServerIDs, currentNodeID) { - currentServerIDs.ServerIDs = append(currentServerIDs.ServerIDs, currentNodeID) - data, err := json.Marshal(¤tServerIDs) - if err != nil { - return err - } - return database.Insert(server_id_key, string(data), database.SERVERCONF_TABLE_NAME) - } - - return nil -} - -// GetServerCount - fetches server count from DB -func GetServerCount() int { - if record, err := database.FetchRecord(database.SERVERCONF_TABLE_NAME, server_id_key); err == nil { - currentServerIDs := models.ServerIDs{} - if err = json.Unmarshal([]byte(record), ¤tServerIDs); err == nil { - return len(currentServerIDs.ServerIDs) - } - } - return 1 -} diff --git a/logic/telemetry.go b/logic/telemetry.go index bbb8bf1c..5ecbe4cd 100644 --- a/logic/telemetry.go +++ b/logic/telemetry.go @@ -84,7 +84,7 @@ func fetchTelemetryData() (telemetryData, error) { data.Users = getDBLength(database.USERS_TABLE_NAME) data.Networks = getDBLength(database.NETWORKS_TABLE_NAME) data.Version = servercfg.GetVersion() - data.Servers = GetServerCount() + //data.Servers = GetServerCount() nodes, err := GetAllNodes() if err == nil { data.Nodes = len(nodes) @@ -111,10 +111,14 @@ func setTelemetryTimestamp(telRecord *models.Telemetry) error { } // getClientCount - returns counts of nodes with various OS types and conditions -func getClientCount(nodes []models.LegacyNode) clientCount { +func getClientCount(nodes []models.Node) clientCount { var count clientCount for _, node := range nodes { - switch node.OS { + host, err := GetHost(node.HostID.String()) + if err != nil { + continue + } + switch host.OS { case "darwin": count.MacOS += 1 case "windows": @@ -124,9 +128,6 @@ func getClientCount(nodes []models.LegacyNode) clientCount { case "freebsd": count.FreeBSD += 1 } - if !(node.IsServer == "yes") { - count.NonServer += 1 - } } return count } diff --git a/logic/util.go b/logic/util.go index 14b0e450..6315e41f 100644 --- a/logic/util.go +++ b/logic/util.go @@ -16,7 +16,6 @@ import ( "github.com/c-robinson/iplib" "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/netclient/ncutils" ) @@ -146,31 +145,6 @@ func StringSliceContains(slice []string, item string) bool { // == private == -// sets the network server peers of a given node -func setNetworkServerPeers(serverNode *models.LegacyNode) { - if currentPeersList, err := getSystemPeers(serverNode); err == nil { - if currentPeersList == nil { - currentPeersList = make(map[string]string) - } - if database.SetPeers(currentPeersList, serverNode.Network) { - logger.Log(1, "set new peers on network", serverNode.Network) - } - } else { - logger.Log(1, "could not set peers on network", serverNode.Network, ":", err.Error()) - } -} - -// ShouldPublishPeerPorts - Gets ports from iface, sets, and returns true if they are different -func ShouldPublishPeerPorts(serverNode *models.LegacyNode) bool { - if currentPeersList, err := getSystemPeers(serverNode); err == nil { - if database.SetPeers(currentPeersList, serverNode.Network) { - logger.Log(1, "set new peers on network", serverNode.Network) - return true - } - } - return false -} - // NormalCIDR - returns the first address of CIDR func NormalizeCIDR(address string) (string, error) { ip, IPNet, err := net.ParseCIDR(address) diff --git a/logic/wireguard.go b/logic/wireguard.go index e272ccf0..82cadffa 100644 --- a/logic/wireguard.go +++ b/logic/wireguard.go @@ -1,72 +1,25 @@ package logic import ( - "os" - "os/exec" - "strings" - - "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/netclient/wireguard" - "github.com/gravitl/netmaker/servercfg" - "golang.zx2c4.com/wireguard/wgctrl" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) -// RemoveConf - removes a configuration for a given WireGuard interface -func RemoveConf(iface string, printlog bool) error { - var err error - confPath := ncutils.GetNetclientPathSpecific() + iface + ".conf" - err = removeWGQuickConf(confPath, printlog) - return err -} - -// HasPeerConnected - checks if a client node has connected over WG -func HasPeerConnected(node *models.LegacyNode) bool { - client, err := wgctrl.New() - if err != nil { - return false - } - defer client.Close() - device, err := client.Device(node.Interface) - if err != nil { - return false - } - for _, peer := range device.Peers { - if peer.PublicKey.String() == node.PublicKey { - if peer.Endpoint != nil { - return true - } - } - } - return false -} - // IfaceDelta - checks if the new node causes an interface change -func IfaceDelta(currentNode *models.LegacyNode, newNode *models.LegacyNode) bool { +func IfaceDelta(currentNode *models.Node, newNode *models.Node) bool { // single comparison statements - if newNode.Endpoint != currentNode.Endpoint || - newNode.PublicKey != currentNode.PublicKey || - newNode.Address != currentNode.Address || - newNode.Address6 != currentNode.Address6 || + if newNode.Address.String() != currentNode.Address.String() || + newNode.Address6.String() != currentNode.Address6.String() || newNode.IsEgressGateway != currentNode.IsEgressGateway || newNode.IsIngressGateway != currentNode.IsIngressGateway || newNode.IsRelay != currentNode.IsRelay || - newNode.UDPHolePunch != currentNode.UDPHolePunch || - newNode.IsPending != currentNode.IsPending || - newNode.ListenPort != currentNode.ListenPort || - newNode.LocalListenPort != currentNode.LocalListenPort || - newNode.MTU != currentNode.MTU || newNode.PersistentKeepalive != currentNode.PersistentKeepalive || newNode.DNSOn != currentNode.DNSOn || newNode.Connected != currentNode.Connected || len(newNode.AllowedIPs) != len(currentNode.AllowedIPs) { return true } - // multi-comparison statements - if newNode.IsEgressGateway == "yes" { + if newNode.IsEgressGateway { if len(currentNode.EgressGatewayRanges) != len(newNode.EgressGatewayRanges) { return true } @@ -76,8 +29,7 @@ func IfaceDelta(currentNode *models.LegacyNode, newNode *models.LegacyNode) bool } } } - - if newNode.IsRelay == "yes" { + if newNode.IsRelay { if len(currentNode.RelayAddrs) != len(newNode.RelayAddrs) { return true } @@ -87,7 +39,6 @@ func IfaceDelta(currentNode *models.LegacyNode, newNode *models.LegacyNode) bool } } } - for _, address := range newNode.AllowedIPs { if !StringSliceContains(currentNode.AllowedIPs, address) { return true @@ -97,147 +48,3 @@ func IfaceDelta(currentNode *models.LegacyNode, newNode *models.LegacyNode) bool } // == Private Functions == - -// gets the server peers locally -func getSystemPeers(node *models.LegacyNode) (map[string]string, error) { - peers := make(map[string]string) - - client, err := wgctrl.New() - if err != nil { - return peers, err - } - defer client.Close() - device, err := client.Device(node.Interface) - if err != nil { - return nil, err - } - if device.Peers != nil && len(device.Peers) > 0 { - for _, peer := range device.Peers { - if IsBase64(peer.PublicKey.String()) && peer.Endpoint != nil && CheckEndpoint(peer.Endpoint.String()) { - peers[peer.PublicKey.String()] = peer.Endpoint.String() - } - } - } - return peers, nil -} -func removeWGQuickConf(confPath string, printlog bool) error { - if _, err := ncutils.RunCmd("wg-quick down "+confPath, printlog); err != nil { - return err - } - return nil -} - -func setWGConfig(node *models.LegacyNode, peerupdate bool) error { - peers, err := GetPeerUpdate(node) - if err != nil { - return err - } - privkey, err := FetchPrivKey(node.ID) - if err != nil { - return err - } - if peerupdate { - if err := wireguard.SetPeers(node.Interface, node, peers.Peers); err != nil { - logger.Log(0, "error updating peers", err.Error()) - return err - } - // logger.Log(0, "--------> UPDATE PEERS IN PROXY.....") - // ProxyMgmChan <- &manager.ManagerAction{ - // Action: manager.UpdatePeer, - // Payload: manager.ManagerPayload{ - // InterfaceName: node.Interface, - // Peers: peers.Peers, - // }, - // } - - logger.Log(2, "updated peers on server", node.Name) - } else { - err = wireguard.InitWireguard(node, privkey, peers.Peers) - if err != nil { - logger.Log(0, "failed to set wg config on server: ", node.Name, err.Error()) - return err - } - logger.Log(3, "finished setting wg config on server", node.Name) - - } - if servercfg.IsProxyEnabled() { - logger.Log(0, "--------> ADD/Update INTERFACE TO PROXY.....") - proxyPayload, err := GetPeersForProxy(node, false) - if err != nil { - logger.Log(0, "failed to get peers for proxy: ", err.Error()) - } else { - - ProxyMgmChan <- &proxyPayload - } - } - - return nil -} - -func setWGKeyConfig(node *models.LegacyNode) error { - - privatekey, err := wgtypes.GeneratePrivateKey() - if err != nil { - return err - } - privkeystring := privatekey.String() - publickey := privatekey.PublicKey() - node.PublicKey = publickey.String() - - err = StorePrivKey(node.ID, privkeystring) - if err != nil { - return err - } - if node.Action == models.NODE_UPDATE_KEY { - node.Action = models.NODE_NOOP - } - - return setWGConfig(node, false) -} - -func removeLocalServer(node *models.LegacyNode) error { - - var err error - var ifacename = node.Interface - if err = RemovePrivKey(node.ID); err != nil { - logger.Log(1, "failed to remove server conf from db", node.ID) - } - if ifacename != "" { - if !ncutils.IsKernel() { - if err = RemoveConf(ifacename, true); err == nil { - logger.Log(1, "removed WireGuard interface:", ifacename) - } - } else { - ipExec, err := exec.LookPath("ip") - if err != nil { - return err - } - out, err := ncutils.RunCmd(ipExec+" link del "+ifacename, false) - dontprint := strings.Contains(out, "does not exist") || strings.Contains(out, "Cannot find device") - if err != nil && !dontprint { - logger.Log(1, "error running command:", ipExec, "link del", ifacename) - logger.Log(1, out) - } - if node.PostDown != "" { - ncutils.RunCmd(node.PostDown, false) - } - } - } - home := ncutils.GetNetclientPathSpecific() - if ncutils.FileExists(home + "netconfig-" + node.Network) { - _ = os.Remove(home + "netconfig-" + node.Network) - } - if ncutils.FileExists(home + "nettoken-" + node.Network) { - _ = os.Remove(home + "nettoken-" + node.Network) - } - if ncutils.FileExists(home + "secret-" + node.Network) { - _ = os.Remove(home + "secret-" + node.Network) - } - if ncutils.FileExists(home + "wgkey-" + node.Network) { - _ = os.Remove(home + "wgkey-" + node.Network) - } - if ncutils.FileExists(home + "nm-" + node.Network + ".conf") { - _ = os.Remove(home + "nm-" + node.Network + ".conf") - } - return err -} diff --git a/logic/zombie.go b/logic/zombie.go index 4707e91b..e09e1116 100644 --- a/logic/zombie.go +++ b/logic/zombie.go @@ -2,8 +2,10 @@ package logic import ( "context" + "net" "time" + "github.com/google/uuid" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/models" ) @@ -16,22 +18,26 @@ const ( ) var ( - zombies []string - removeZombie chan string = make(chan (string), 10) - newZombie chan string = make(chan (string), 10) + zombies []uuid.UUID + removeZombie chan uuid.UUID = make(chan (uuid.UUID), 10) + newZombie chan uuid.UUID = make(chan (uuid.UUID), 10) ) // CheckZombies - checks if new node has same macaddress as existing node // if so, existing node is added to zombie node quarantine list -func CheckZombies(newnode *models.LegacyNode) { +func CheckZombies(newnode *models.Node, mac net.HardwareAddr) { nodes, err := GetNetworkNodes(newnode.Network) if err != nil { logger.Log(1, "Failed to retrieve network nodes", newnode.Network, err.Error()) return } for _, node := range nodes { - if node.MacAddress == newnode.MacAddress { - logger.Log(0, "adding ", node.ID, " to zombie list") + host, err := GetHost(node.HostID.String()) + if err != nil { + + } + if host.MacAddress.String() == mac.String() { + logger.Log(0, "adding ", node.ID.String(), " to zombie list") newZombie <- node.ID } } @@ -46,14 +52,14 @@ func ManageZombies(ctx context.Context) { case <-ctx.Done(): return case id := <-newZombie: - logger.Log(1, "adding", id, "to zombie quaratine list") + logger.Log(1, "adding", id.String(), "to zombie quaratine list") zombies = append(zombies, id) case id := <-removeZombie: found := false if len(zombies) > 0 { for i := len(zombies) - 1; i >= 0; i-- { if zombies[i] == id { - logger.Log(1, "removing zombie from quaratine list", zombies[i]) + logger.Log(1, "removing zombie from quaratine list", zombies[i].String()) zombies = append(zombies[:i], zombies[i+1:]...) found = true } @@ -66,19 +72,19 @@ func ManageZombies(ctx context.Context) { logger.Log(3, "checking for zombie nodes") if len(zombies) > 0 { for i := len(zombies) - 1; i >= 0; i-- { - node, err := GetNodeByID(zombies[i]) + node, err := GetNodeByID(zombies[i].String()) if err != nil { - logger.Log(1, "error retrieving zombie node", zombies[i], err.Error()) - logger.Log(1, "deleting ", node.Name, " from zombie list") + logger.Log(1, "error retrieving zombie node", zombies[i].String(), err.Error()) + logger.Log(1, "deleting ", node.ID.String(), " from zombie list") zombies = append(zombies[:i], zombies[i+1:]...) continue } - if time.Since(time.Unix(node.LastCheckIn, 0)) > time.Minute*ZOMBIE_DELETE_TIME { + if time.Since(node.LastCheckIn) > time.Minute*ZOMBIE_DELETE_TIME { if err := DeleteNode(&node, true); err != nil { - logger.Log(1, "error deleting zombie node", zombies[i], err.Error()) + logger.Log(1, "error deleting zombie node", zombies[i].String(), err.Error()) continue } - logger.Log(1, "deleting zombie node", node.Name) + logger.Log(1, "deleting zombie node", node.ID.String()) zombies = append(zombies[:i], zombies[i+1:]...) } } @@ -104,13 +110,13 @@ func InitializeZombies() { if node.ID == othernode.ID { continue } - if node.MacAddress == othernode.MacAddress { - if node.LastCheckIn > othernode.LastCheckIn { + if node.HostID == othernode.HostID { + if node.LastCheckIn.After(othernode.LastCheckIn) { zombies = append(zombies, othernode.ID) - logger.Log(1, "adding ", othernode.Name, " with ID ", othernode.ID, " to zombie list") + logger.Log(1, "adding", othernode.ID.String(), "to zombie list") } else { zombies = append(zombies, node.ID) - logger.Log(1, "adding ", node.Name, " with ID ", node.ID, " to zombie list") + logger.Log(1, "adding", node.ID.String(), "to zombie list") } } } diff --git a/main.go b/main.go index d89f9436..8d71333d 100644 --- a/main.go +++ b/main.go @@ -71,9 +71,6 @@ func initialize() { // Client Mode Prereq Check logger.FatalLog("Error connecting to database: ", err.Error()) } logger.Log(0, "database successfully connected") - if err = logic.AddServerIDIfNotPresent(); err != nil { - logger.Log(1, "failed to save server ID") - } logic.SetJWTSecret() @@ -112,9 +109,6 @@ func initialize() { // Client Mode Prereq Check if uid != 0 { logger.FatalLog("To run in client mode requires root privileges. Either disable client mode or run with sudo.") } - if err := serverctl.InitServerNetclient(); err != nil { - logger.FatalLog("Did not find netclient to use CLIENT_MODE") - } } // initialize iptables to ensure gateways work correctly and mq is forwarded if containerized if servercfg.ManageIPTables() != "off" { @@ -184,10 +178,6 @@ func startControllers() { waitnetwork.Add(1) //go nmproxy.Start(ctx, logic.ProxyMgmChan, servercfg.GetAPIHost()) - err := serverctl.SyncServerNetworkWithProxy() - if err != nil { - logger.Log(0, "failed to sync proxy with server interfaces: ", err.Error()) - } quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGTERM, os.Interrupt) <-quit diff --git a/models/host.go b/models/host.go index 2cc04a19..ecad264e 100644 --- a/models/host.go +++ b/models/host.go @@ -18,8 +18,8 @@ type Host struct { HostPass string `json:"hostpass" yaml:"hostpass"` Name string `json:"name" yaml:"name"` OS string `json:"os" yaml:"os"` + Interface string `json:"interface" yaml:"interface"` Debug bool `json:"debug" yaml:"debug"` - NodePassword string `json:"nodepassword" yaml:"nodepassword"` ListenPort int `json:"listenport" yaml:"listenport"` LocalAddress net.IPNet `json:"localaddress" yaml:"localaddress"` LocalRange net.IPNet `json:"localrange" yaml:"localrange"` diff --git a/models/node.go b/models/node.go index 3ccdedc1..c9fc9d78 100644 --- a/models/node.go +++ b/models/node.go @@ -8,7 +8,6 @@ import ( "time" "github.com/google/uuid" - "golang.org/x/crypto/bcrypt" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -44,7 +43,7 @@ var seededRand *rand.Rand = rand.New( // NodeCheckin - struct for node checkins with server type NodeCheckin struct { Version string - Connected string + Connected bool Ifaces []Iface } @@ -58,6 +57,7 @@ type Iface struct { // CommonNode - represents a commonn node data elements shared by netmaker and netclient type CommonNode struct { ID uuid.UUID `json:"id" yaml:"id"` + HostID uuid.UUID `json:"hostid" yaml:"hostid"` Network string `json:"network" yaml:"network"` NetworkRange net.IPNet `json:"networkrange" yaml:"networkrange"` NetworkRange6 net.IPNet `json:"networkrange6" yaml:"networkrange6"` @@ -71,14 +71,11 @@ type CommonNode struct { PostUp string `json:"postup" yaml:"postup"` PostDown string `json:"postdown" yaml:"postdown"` Action string `json:"action" yaml:"action"` - IsServer bool `json:"isserver" yaml:"isserver"` IsLocal bool `json:"islocal" yaml:"islocal"` IsEgressGateway bool `json:"isegressgateway" yaml:"isegressgateway"` IsIngressGateway bool `json:"isingressgateway" yaml:"isingressgateway"` IsStatic bool `json:"isstatic" yaml:"isstatic"` - IsPending bool `json:"ispending" yaml:"ispending"` DNSOn bool `json:"dnson" yaml:"dnson"` - IsHub bool `json:"ishub" yaml:"ishub"` PersistentKeepalive int `json:"persistentkeepalive" yaml:"persistentkeepalive"` Peers []wgtypes.PeerConfig `json:"peers" yaml:"peers"` Proxy bool `json:"proxy" bson:"proxy" yaml:"proxy"` @@ -87,10 +84,27 @@ type CommonNode struct { // Node - a model of a network node type Node struct { CommonNode - PendingDelete bool `json:"pendingdelete" bson:"pendingdelete" yaml:"pendingdelete"` + PendingDelete bool `json:"pendingdelete" bson:"pendingdelete" yaml:"pendingdelete"` + LastModified time.Time `json:"lastmodified" bson:"lastmodified" yaml:"lastmodified"` + LastCheckIn time.Time `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"` + LastPeerUpdate time.Time `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"` + ExpirationDateTime time.Time `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"` + AllowedIPs []string `json:"allowedips" bson:"allowedips" yaml:"allowedips"` + EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"` + EgressGatewayNatEnabled string `json:"egressgatewaynatenabled" bson:"egressgatewaynatenabled" yaml:"egressgatewaynatenabled"` + EgressGatewayRequest EgressGatewayRequest `json:"egressgatewayrequest" bson:"egressgatewayrequest" yaml:"egressgatewayrequest"` + IngressGatewayRange string `json:"ingressgatewayrange" bson:"ingressgatewayrange" yaml:"ingressgatewayrange"` + IngressGatewayRange6 string `json:"ingressgatewayrange6" bson:"ingressgatewayrange6" yaml:"ingressgatewayrange6"` + IsRelayed bool `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"` + IsRelay bool `json:"isrelay" bson:"isrelay" yaml:"isrelay" validate:"checkyesorno"` + RelayAddrs []string `json:"relayaddrs" bson:"relayaddrs" yaml:"relayaddrs"` + IsDocker string `json:"isdocker" bson:"isdocker" yaml:"isdocker" validate:"checkyesorno"` + IsK8S string `json:"isk8s" bson:"isk8s" yaml:"isk8s" validate:"checkyesorno"` // == PRO == - DefaultACL string `json:"defaultacl,omitempty" bson:"defaultacl,omitempty" yaml:"defaultacl,omitempty" validate:"checkyesornoorunset"` - OwnerID string `json:"ownerid,omitempty" bson:"ownerid,omitempty" yaml:"ownerid,omitempty"` + DefaultACL string `json:"defaultacl,omitempty" bson:"defaultacl,omitempty" yaml:"defaultacl,omitempty" validate:"checkyesornoorunset"` + OwnerID string `json:"ownerid,omitempty" bson:"ownerid,omitempty" yaml:"ownerid,omitempty"` + FailoverNode uuid.UUID `json:"failovernode" bson:"failovernode" yaml:"failovernode"` + Failover bool `json:"failover" bson:"failover" yaml:"failover"` } // LegacyNode - legacy struct for node model @@ -162,13 +176,15 @@ type LegacyNode struct { } // NodesArray - used for node sorting -type NodesArray []LegacyNode +type NodesArray []Node // NodesArray.Len - gets length of node array func (a NodesArray) Len() int { return len(a) } -// NodesArray.Less - gets returns lower rank of two node addresses -func (a NodesArray) Less(i, j int) bool { return isLess(a[i].Address, a[j].Address) } +// NodesArray.Less - gets returns lower rank of two node addressesFill +func (a NodesArray) Less(i, j int) bool { + return isLess(a[i].Address.IP.String(), a[j].Address.IP.String()) +} // NodesArray.Swap - swaps two nodes in array func (a NodesArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] } @@ -180,11 +196,11 @@ func isLess(ipA string, ipB string) bool { } // Node.PrimaryAddress - return ipv4 address if present, else return ipv6 -func (node *LegacyNode) PrimaryAddress() string { - if node.Address != "" { - return node.Address +func (node *Node) PrimaryAddress() string { + if node.Address.IP != nil { + return node.Address.IP.String() } - return node.Address6 + return node.Address6.IP.String() } // Node.SetDefaultConnected @@ -218,13 +234,6 @@ func (node *LegacyNode) SetDefaultNFTablesPresent() { } } -// Node.SetDefaulIsPending - sets ispending default -func (node *LegacyNode) SetDefaulIsPending() { - if node.IsPending == "" { - node.IsPending = "no" - } -} - // Node.SetDefaultIsRelayed - set default is relayed func (node *LegacyNode) SetDefaultIsRelayed() { if node.IsRelayed == "" { @@ -326,23 +335,23 @@ func (node *LegacyNode) SetIsStaticDefault() { } // Node.SetLastModified - set last modified initial time -func (node *LegacyNode) SetLastModified() { - node.LastModified = time.Now().Unix() +func (node *Node) SetLastModified() { + node.LastModified = time.Now() } -// Node.SetLastCheckIn - time.Now().Unix() -func (node *LegacyNode) SetLastCheckIn() { - node.LastCheckIn = time.Now().Unix() +// Node.SetLastCheckIn - set checkin time of node +func (node *Node) SetLastCheckIn() { + node.LastCheckIn = time.Now() } // Node.SetLastPeerUpdate - sets last peer update time -func (node *LegacyNode) SetLastPeerUpdate() { - node.LastPeerUpdate = time.Now().Unix() +func (node *Node) SetLastPeerUpdate() { + node.LastPeerUpdate = time.Now() } // Node.SetExpirationDateTime - sets node expiry time -func (node *LegacyNode) SetExpirationDateTime() { - node.ExpirationDateTime = time.Now().Unix() + TEN_YEARS_IN_SECONDS +func (node *Node) SetExpirationDateTime() { + node.ExpirationDateTime = time.Now().Add(TEN_YEARS_IN_SECONDS) } // Node.SetDefaultName - sets a random name to node @@ -360,33 +369,18 @@ func (node *LegacyNode) SetDefaultFailover() { } // Node.Fill - fills other node data into calling node data if not set on calling node -func (newNode *LegacyNode) Fill(currentNode *LegacyNode) { // TODO add new field for nftables present +func (newNode *Node) Fill(currentNode *Node) { // TODO add new field for nftables present newNode.ID = currentNode.ID - if newNode.Address == "" { + // Revisit the logic for boolean values + // TODO ---- !!!!!!!!!!!!!!!!!!!!!!!!!!!! + // TODO ---- !!!!!!!!!!!!!!!!!!!!!!!!!! + if newNode.Address.String() == "" { newNode.Address = currentNode.Address } - if newNode.Address6 == "" { + if newNode.Address6.String() == "" { newNode.Address6 = currentNode.Address6 } - if newNode.LocalAddress == "" { - newNode.LocalAddress = currentNode.LocalAddress - } - if newNode.Name == "" { - newNode.Name = currentNode.Name - } - if newNode.ListenPort == 0 { - newNode.ListenPort = currentNode.ListenPort - } - if newNode.LocalListenPort == 0 { - newNode.LocalListenPort = currentNode.LocalListenPort - } - if newNode.PublicKey == "" { - newNode.PublicKey = currentNode.PublicKey - } - if newNode.Endpoint == "" { - newNode.Endpoint = currentNode.Endpoint - } if newNode.PostUp == "" { newNode.PostUp = currentNode.PostUp } @@ -399,48 +393,25 @@ func (newNode *LegacyNode) Fill(currentNode *LegacyNode) { // TODO add new field if newNode.PersistentKeepalive < 0 { newNode.PersistentKeepalive = currentNode.PersistentKeepalive } - if newNode.AccessKey == "" { - newNode.AccessKey = currentNode.AccessKey - } - if newNode.Interface == "" { - newNode.Interface = currentNode.Interface - } - if newNode.LastModified == 0 { + if newNode.LastModified != currentNode.LastModified { newNode.LastModified = currentNode.LastModified } - if newNode.ExpirationDateTime == 0 { + if newNode.ExpirationDateTime.IsZero() { newNode.ExpirationDateTime = currentNode.ExpirationDateTime } - if newNode.LastPeerUpdate == 0 { + if newNode.LastPeerUpdate.IsZero() { newNode.LastPeerUpdate = currentNode.LastPeerUpdate } - if newNode.LastCheckIn == 0 { + if newNode.LastCheckIn.IsZero() { newNode.LastCheckIn = currentNode.LastCheckIn } - if newNode.MacAddress == "" { - newNode.MacAddress = currentNode.MacAddress - } - if newNode.Password != "" { - err := bcrypt.CompareHashAndPassword([]byte(newNode.Password), []byte(currentNode.Password)) - if err != nil && currentNode.Password != newNode.Password { - hash, err := bcrypt.GenerateFromPassword([]byte(newNode.Password), 5) - if err == nil { - newNode.Password = string(hash) - } - } - } else { - newNode.Password = currentNode.Password - } if newNode.Network == "" { newNode.Network = currentNode.Network } - if newNode.IsPending == "" { - newNode.IsPending = currentNode.IsPending - } - if newNode.IsEgressGateway == "" { + if newNode.IsEgressGateway != currentNode.IsEgressGateway { newNode.IsEgressGateway = currentNode.IsEgressGateway } - if newNode.IsIngressGateway == "" { + if newNode.IsIngressGateway != currentNode.IsIngressGateway { newNode.IsIngressGateway = currentNode.IsIngressGateway } if newNode.EgressGatewayRanges == nil { @@ -452,73 +423,46 @@ func (newNode *LegacyNode) Fill(currentNode *LegacyNode) { // TODO add new field if newNode.IngressGatewayRange6 == "" { newNode.IngressGatewayRange6 = currentNode.IngressGatewayRange6 } - if newNode.IsStatic == "" { + if newNode.IsStatic != currentNode.IsStatic { newNode.IsStatic = currentNode.IsStatic } - if newNode.UDPHolePunch == "" { - newNode.UDPHolePunch = currentNode.UDPHolePunch - } - if newNode.DNSOn == "" { + if newNode.DNSOn != currentNode.DNSOn { newNode.DNSOn = currentNode.DNSOn } - if newNode.IsLocal == "" { + if newNode.IsLocal != currentNode.IsLocal { newNode.IsLocal = currentNode.IsLocal } - if newNode.IPForwarding == "" { - newNode.IPForwarding = currentNode.IPForwarding - } if newNode.Action == "" { newNode.Action = currentNode.Action } - if newNode.IsServer == "" { - newNode.IsServer = currentNode.IsServer - } - if newNode.IsServer == "yes" { - newNode.IsStatic = "yes" - newNode.Connected = "yes" - } - if newNode.MTU == 0 { - newNode.MTU = currentNode.MTU - } - if newNode.OS == "" { - newNode.OS = currentNode.OS - } if newNode.RelayAddrs == nil { newNode.RelayAddrs = currentNode.RelayAddrs } - if newNode.IsRelay == "" { + if newNode.IsRelay != currentNode.IsRelay { newNode.IsRelay = currentNode.IsRelay } - if newNode.IsRelayed == "" { + if newNode.IsRelayed == currentNode.IsRelayed { newNode.IsRelayed = currentNode.IsRelayed } - if newNode.IsDocker == "" { + if newNode.IsDocker == currentNode.IsDocker { newNode.IsDocker = currentNode.IsDocker } - if newNode.IsK8S == "" { + if newNode.IsK8S != currentNode.IsK8S { newNode.IsK8S = currentNode.IsK8S } - if newNode.Version == "" { - newNode.Version = currentNode.Version - } - if newNode.IsHub == "" { - newNode.IsHub = currentNode.IsHub - } if newNode.Server == "" { newNode.Server = currentNode.Server } - if newNode.Connected == "" { + if newNode.Connected != currentNode.Connected { newNode.Connected = currentNode.Connected } if newNode.DefaultACL == "" { newNode.DefaultACL = currentNode.DefaultACL } - - if newNode.Failover == "" { + if newNode.Failover != currentNode.Failover { newNode.Failover = currentNode.Failover } newNode.Proxy = currentNode.Proxy - newNode.TrafficKeys = currentNode.TrafficKeys } // StringWithCharset - returns random string inside defined charset @@ -553,12 +497,12 @@ func (node *LegacyNode) NameInNodeCharSet() bool { // == PRO == // Node.DoesACLAllow - checks if default ACL on node is "yes" -func (node *LegacyNode) DoesACLAllow() bool { +func (node *Node) DoesACLAllow() bool { return node.DefaultACL == "yes" } // Node.DoesACLDeny - checks if default ACL on node is "no" -func (node *LegacyNode) DoesACLDeny() bool { +func (node *Node) DoesACLDeny() bool { return node.DefaultACL == "no" } @@ -587,7 +531,7 @@ func (ln *LegacyNode) ConvertToNewNode() (*Host, *Node) { gateway, _ := net.ResolveUDPAddr("udp", ln.InternetGateway) host.InternetGateway = *gateway id, _ := uuid.Parse(ln.ID) - host.Nodes = append(host.Nodes, id) + host.Nodes = append(host.Nodes, id.String()) } id, _ := uuid.Parse(ln.ID) node.ID = id @@ -607,7 +551,6 @@ func (ln *LegacyNode) ConvertToNewNode() (*Host, *Node) { node.PostUp = ln.PostUp node.PostDown = ln.PostDown node.Action = ln.Action - node.IsServer = parseBool(ln.IsServer) node.IsLocal = parseBool(ln.IsLocal) node.IsEgressGateway = parseBool(ln.IsEgressGateway) node.IsIngressGateway = parseBool(ln.IsIngressGateway) @@ -619,11 +562,77 @@ func (ln *LegacyNode) ConvertToNewNode() (*Host, *Node) { return &host, &node } +// Node.Legacy converts node to legacy format +func (n *Node) Legacy(h *Host, s *ServerConfig, net *Network) *LegacyNode { + l := LegacyNode{} + l.ID = n.ID.String() + l.HostID = h.ID.String() + l.Address = n.Address.String() + l.Address6 = n.Address6.String() + l.LocalAddress = h.LocalAddress.String() + l.Interfaces = n.Interfaces + l.Name = h.Name + l.NetworkSettings = *net + l.ListenPort = int32(h.ListenPort) + l.LocalListenPort = int32(h.LocalListenPort) + l.ProxyListenPort = int32(h.ProxyListenPort) + l.PublicKey = h.PublicKey.String() + l.Endpoint = n.EndpointIP.String() + l.PostUp = n.PostUp + l.PostDown = n.PostDown + //l.AllowedIPs = + l.PersistentKeepalive = int32(n.PersistentKeepalive) + l.AccessKey = "" + l.Interface = "netmaker" + //l.LastModified = + //l.ExpirationDateTime + //l.LastPeerUpdate + //l.LastCheckIn + l.MacAddress = h.MacAddress.String() + l.Password = h.HostPass + l.Network = n.Network + //l.IsRelayed = formatBool(n.Is) + //l.IsRelay = formatBool(n.IsRelay) + //l.IsDocker = formatBool(n.IsDocker) + //l.IsK8S = formatBool(n.IsK8S) + l.IsEgressGateway = formatBool(n.IsEgressGateway) + l.IsIngressGateway = formatBool(n.IsIngressGateway) + //l.EgressGatewayRanges = n.EgressGatewayRanges + //l.EgressGatewayNatEnabled = n.EgressGatewayNatEnabled + //l.RelayAddrs = n.RelayAddrs + //l.FailoverNode = n.FailoverNode + //l.IngressGatewayRange = n.IngressGatewayRange + //l.IngressGatewayRange6 = n.IngressGatewayRange6 + l.IsStatic = formatBool(n.IsStatic) + l.UDPHolePunch = formatBool(true) + l.DNSOn = formatBool(n.DNSOn) + l.Action = n.Action + l.IsLocal = formatBool(n.IsLocal) + l.LocalRange = h.LocalRange.String() + l.IPForwarding = formatBool(h.IPForwarding) + l.OS = h.OS + l.MTU = int32(h.MTU) + l.Version = h.Version + l.Server = n.Server + l.TrafficKeys.Mine = h.TrafficKeyPublic + l.TrafficKeys.Server = s.TrafficKey + l.FirewallInUse = h.FirewallInUse + l.InternetGateway = h.InternetGateway.String() + l.Connected = formatBool(n.Connected) + //l.PendingDelete = formatBool(n.PendingDelete) + l.Proxy = n.Proxy + l.DefaultACL = n.DefaultACL + l.OwnerID = n.OwnerID + //l.Failover = n.Failover + return &l +} + // Node.NetworkSettings updates a node with network settings func (node *Node) NetworkSettings(n Network) { _, cidr, _ := net.ParseCIDR(n.AddressRange) node.NetworkRange = *cidr - + _, cidr, _ = net.ParseCIDR(n.AddressRange6) + node.NetworkRange6 = *cidr } func parseBool(s string) bool { diff --git a/models/structs.go b/models/structs.go index 87d53a03..e1d7a9a6 100644 --- a/models/structs.go +++ b/models/structs.go @@ -6,6 +6,7 @@ import ( jwt "github.com/golang-jwt/jwt/v4" "github.com/gravitl/netclient/nmproxy/manager" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) const PLACEHOLDER_KEY_TEXT = "ACCESS_KEY" @@ -202,10 +203,18 @@ type TrafficKeys struct { // NodeGet - struct for a single node get response type NodeGet struct { - Node Node `json:"node" bson:"node" yaml:"node"` - Host Host `json:"host" yaml:"host"` - // Peers are included in Node - //Peers []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"` + Node LegacyNode `json:"node" bson:"node" yaml:"node"` + Host Host `json:"host" yaml:"host"` + Peers []wgtypes.PeerConfig `json:"peers" bson:"peers" yaml:"peers"` + ServerConfig ServerConfig `json:"serverconfig" bson:"serverconfig" yaml:"serverconfig"` + PeerIDs PeerMap `json:"peerids,omitempty" bson:"peerids,omitempty" yaml:"peerids,omitempty"` + ProxyUpdate manager.ProxyManagerPayload `json:"proxy_update,omitempty" bson:"proxy_update,omitempty" yaml:"proxy_update,omitempty"` +} + +// NodeJoinResponse data returned to node in response to join +type NodeJoinResponse struct { + Node Node `json:"node" bson:"node" yaml:"node"` + Host Host `json:"host" yaml:"host"` ServerConfig ServerConfig `json:"serverconfig" bson:"serverconfig" yaml:"serverconfig"` PeerIDs PeerMap `json:"peerids,omitempty" bson:"peerids,omitempty" yaml:"peerids,omitempty"` ProxyUpdate manager.ProxyManagerPayload `json:"proxy_update,omitempty" bson:"proxy_update,omitempty" yaml:"proxy_update,omitempty"` @@ -246,7 +255,7 @@ type ServerIDs struct { // JoinData - struct to hold data required for node to join a network on server type JoinData struct { - Host Host `json:"host yaml:"host"` + Host Host `json:"host" yaml:"host"` Node Node `json:"node" yaml:"node"` Key string `json:"key" yaml:"key"` } diff --git a/mq/handlers.go b/mq/handlers.go index 5c591ef5..365c8fd8 100644 --- a/mq/handlers.go +++ b/mq/handlers.go @@ -41,7 +41,7 @@ func Ping(client mqtt.Client, msg mqtt.Message) { } decrypted, decryptErr := decryptMsg(&node, msg.Payload()) if decryptErr != nil { - logger.Log(0, "error decrypting when updating node ", node.ID, decryptErr.Error()) + logger.Log(0, "error decrypting when updating node ", node.ID.String(), decryptErr.Error()) return } var checkin models.NodeCheckin @@ -49,19 +49,24 @@ func Ping(client mqtt.Client, msg mqtt.Message) { logger.Log(1, "error unmarshaling payload ", err.Error()) return } + host, err := logic.GetHost(node.HostID.String()) + if err != nil { + logger.Log(0, "error retrieving host for node ", node.ID.String(), err.Error()) + return + } node.SetLastCheckIn() - node.Version = checkin.Version + host.Version = checkin.Version node.Connected = checkin.Connected node.Interfaces = checkin.Ifaces for i := range node.Interfaces { node.Interfaces[i].AddressString = node.Interfaces[i].Address.String() } if err := logic.UpdateNode(&node, &node); err != nil { - logger.Log(0, "error updating node", node.Name, node.ID, " on checkin", err.Error()) + logger.Log(0, "error updating node", node.ID.String(), " on checkin", err.Error()) return } - logger.Log(3, "ping processed for node", node.Name, node.ID) + logger.Log(3, "ping processed for node", node.ID.String()) // --TODO --set client version once feature is implemented. //node.SetClientVersion(msg.Payload()) }() @@ -85,15 +90,15 @@ func UpdateNode(client mqtt.Client, msg mqtt.Message) { logger.Log(1, "failed to decrypt message for node ", id, decryptErr.Error()) return } - var newNode models.LegacyNode + var newNode models.Node if err := json.Unmarshal(decrypted, &newNode); err != nil { logger.Log(1, "error unmarshaling payload ", err.Error()) return } ifaceDelta := logic.IfaceDelta(¤tNode, &newNode) if servercfg.Is_EE && ifaceDelta { - if err = logic.EnterpriseResetAllPeersFailovers(currentNode.ID, currentNode.Network); err != nil { - logger.Log(1, "failed to reset failover list during node update", currentNode.Name, currentNode.Network) + if err = logic.EnterpriseResetAllPeersFailovers(currentNode.ID.String(), currentNode.Network); err != nil { + logger.Log(1, "failed to reset failover list during node update", currentNode.ID.String(), currentNode.Network) } } newNode.SetLastCheckIn() @@ -102,12 +107,13 @@ func UpdateNode(client mqtt.Client, msg mqtt.Message) { return } if ifaceDelta { // reduce number of unneeded updates, by only sending on iface changes - if err = PublishPeerUpdate(¤tNode, true); err != nil { - logger.Log(0, "error updating peers when node", currentNode.Name, currentNode.ID, "informed the server of an interface change", err.Error()) + if err = PublishPeerUpdate(currentNode.Network, true); err != nil { + logger.Log(0, "error updating peers when node", currentNode.ID.String(), "informed the server of an interface change", err.Error()) } } - logger.Log(1, "updated node", id, newNode.Name) + logger.Log(1, "updated node", id, newNode.ID.String()) + }() } @@ -140,31 +146,31 @@ func UpdateMetrics(client mqtt.Client, msg mqtt.Message) { shouldUpdate := updateNodeMetrics(¤tNode, &newMetrics) if err = logic.UpdateMetrics(id, &newMetrics); err != nil { - logger.Log(1, "faield to update node metrics", id, currentNode.Name, err.Error()) + logger.Log(1, "faield to update node metrics", id, err.Error()) return } if servercfg.IsMetricsExporter() { if err := pushMetricsToExporter(newMetrics); err != nil { logger.Log(2, fmt.Sprintf("failed to push node: [%s] metrics to exporter, err: %v", - currentNode.Name, err)) + currentNode.ID, err)) } } if newMetrics.Connectivity != nil { err := logic.EnterpriseFailoverFunc(¤tNode) if err != nil { - logger.Log(0, "failed to failover for node", currentNode.Name, "on network", currentNode.Network, "-", err.Error()) + logger.Log(0, "failed to failover for node", currentNode.ID.String(), "on network", currentNode.Network, "-", err.Error()) } } if shouldUpdate { - logger.Log(2, "updating peers after node", currentNode.Name, currentNode.Network, "detected connectivity issues") + logger.Log(2, "updating peers after node", currentNode.ID.String(), currentNode.Network, "detected connectivity issues") if err = PublishSinglePeerUpdate(¤tNode); err != nil { - logger.Log(0, "failed to publish update after failover peer change for node", currentNode.Name, currentNode.Network) + logger.Log(0, "failed to publish update after failover peer change for node", currentNode.ID.String(), currentNode.Network) } } - logger.Log(1, "updated node metrics", id, currentNode.Name) + logger.Log(1, "updated node metrics", id) }() } } @@ -189,47 +195,29 @@ func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) { } switch decrypted[0] { case ncutils.ACK: - currentServerNode, err := logic.GetNetworkServerLocal(currentNode.Network) - if err != nil { - return - } - if err := logic.ServerUpdate(¤tServerNode, false); err != nil { - logger.Log(1, "server node:", currentServerNode.ID, "failed update") - return - } + //do we still need this case ncutils.DONE: updateNodePeers(¤tNode) } - logger.Log(1, "sent peer updates after signal received from", id, currentNode.Name) + logger.Log(1, "sent peer updates after signal received from", id) }() } -func updateNodePeers(currentNode *models.LegacyNode) { - currentServerNode, err := logic.GetNetworkServerLocal(currentNode.Network) - if err != nil { - logger.Log(1, "failed to get server node failed update\n", err.Error()) +func updateNodePeers(currentNode *models.Node) { + if err := PublishPeerUpdate(currentNode.Network, false); err != nil { + logger.Log(1, "error publishing peer update ", err.Error()) return } - if err := logic.ServerUpdate(¤tServerNode, false); err != nil { - logger.Log(1, "server node:", currentServerNode.ID, "failed update") - return - } - if logic.IsLeader(¤tServerNode) { - if err := PublishPeerUpdate(currentNode, false); err != nil { - logger.Log(1, "error publishing peer update ", err.Error()) - return - } - } } -func updateNodeMetrics(currentNode *models.LegacyNode, newMetrics *models.Metrics) bool { +func updateNodeMetrics(currentNode *models.Node, newMetrics *models.Metrics) bool { if newMetrics.FailoverPeers == nil { newMetrics.FailoverPeers = make(map[string]string) } - oldMetrics, err := logic.GetMetrics(currentNode.ID) + oldMetrics, err := logic.GetMetrics(currentNode.ID.String()) if err != nil { - logger.Log(1, "error finding old metrics for node", currentNode.ID, currentNode.Name) + logger.Log(1, "error finding old metrics for node", currentNode.ID.String()) return false } if oldMetrics.FailoverPeers == nil { @@ -237,8 +225,8 @@ func updateNodeMetrics(currentNode *models.LegacyNode, newMetrics *models.Metric } var attachedClients []models.ExtClient - if currentNode.IsIngressGateway == "yes" { - clients, err := logic.GetExtClientsByID(currentNode.ID, currentNode.Network) + if currentNode.IsIngressGateway { + clients, err := logic.GetExtClientsByID(currentNode.ID.String(), currentNode.Network) if err == nil { attachedClients = clients } @@ -292,12 +280,12 @@ func updateNodeMetrics(currentNode *models.LegacyNode, newMetrics *models.Metric return false } for _, node := range nodes { - if !newMetrics.Connectivity[node.ID].Connected && - len(newMetrics.Connectivity[node.ID].NodeName) > 0 && - node.Connected == "yes" && + if !newMetrics.Connectivity[node.ID.String()].Connected && + len(newMetrics.Connectivity[node.ID.String()].NodeName) > 0 && + node.Connected == true && len(node.FailoverNode) > 0 && - node.Failover != "yes" { - newMetrics.FailoverPeers[node.ID] = node.FailoverNode + !node.Failover { + newMetrics.FailoverPeers[node.ID.String()] = node.FailoverNode.String() } } shouldUpdate := len(oldMetrics.FailoverPeers) == 0 && len(newMetrics.FailoverPeers) > 0 diff --git a/mq/publishers.go b/mq/publishers.go index dddfd8f2..f6e28ccc 100644 --- a/mq/publishers.go +++ b/mq/publishers.go @@ -9,48 +9,31 @@ import ( "github.com/gravitl/netclient/nmproxy/manager" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" - "github.com/gravitl/netmaker/logic/metrics" "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/serverctl" ) // PublishPeerUpdate --- deterines and publishes a peer update to all the peers of a node -func PublishPeerUpdate(newNode *models.LegacyNode, publishToSelf bool) error { +func PublishPeerUpdate(network string, publishToSelf bool) error { if !servercfg.IsMessageQueueBackend() { return nil } - networkNodes, err := logic.GetNetworkNodes(newNode.Network) + networkNodes, err := logic.GetNetworkNodes(network) if err != nil { logger.Log(1, "err getting Network Nodes", err.Error()) return err } for _, node := range networkNodes { - - if node.IsServer == "yes" { - if servercfg.IsProxyEnabled() { - err := PublishProxyPeerUpdate(&node) - if err != nil { - logger.Log(0, "failed to send proxy update for server: ", err.Error()) - } - } - - continue - } - if !publishToSelf && newNode.ID == node.ID { - //skip self - continue - } err = PublishSinglePeerUpdate(&node) if err != nil { - logger.Log(1, "failed to publish peer update to node", node.Name, "on network", node.Network, ":", err.Error()) + logger.Log(1, "failed to publish peer update to node", node.ID.String(), "on network", node.Network, ":", err.Error()) } - } return err } -func PublishProxyPeerUpdate(node *models.LegacyNode) error { +func PublishProxyPeerUpdate(node *models.Node) error { proxyUpdate, err := logic.GetPeersForProxy(node, false) if err != nil { return err @@ -65,7 +48,7 @@ func PublishProxyPeerUpdate(node *models.LegacyNode) error { } // PublishSinglePeerUpdate --- determines and publishes a peer update to one node -func PublishSinglePeerUpdate(node *models.LegacyNode) error { +func PublishSinglePeerUpdate(node *models.Node) error { peerUpdate, err := logic.GetPeerUpdate(node) if err != nil { @@ -89,16 +72,8 @@ func PublishSinglePeerUpdate(node *models.LegacyNode) error { } // PublishPeerUpdate --- publishes a peer update to all the peers of a node -func PublishExtPeerUpdate(node *models.LegacyNode) error { +func PublishExtPeerUpdate(node *models.Node) error { var err error - if logic.IsLocalServer(node) { - if err = logic.ServerUpdate(node, false); err != nil { - logger.Log(1, "server node:", node.ID, "failed to update peers with ext clients") - return err - } else { - return nil - } - } if !servercfg.IsMessageQueueBackend() { return nil } @@ -120,22 +95,21 @@ func PublishExtPeerUpdate(node *models.LegacyNode) error { if err = publish(node, fmt.Sprintf("peers/%s/%s", node.Network, node.ID), data); err != nil { return err } - go PublishPeerUpdate(node, false) + go PublishPeerUpdate(node.Network, false) return nil } // NodeUpdate -- publishes a node update -func NodeUpdate(node *models.LegacyNode) error { +func NodeUpdate(node *models.Node) error { var err error - if !servercfg.IsMessageQueueBackend() || node.IsServer == "yes" { - + if !servercfg.IsMessageQueueBackend() { return nil } - logger.Log(3, "publishing node update to "+node.Name) + logger.Log(3, "publishing node update to "+node.ID.String()) - if len(node.NetworkSettings.AccessKeys) > 0 { - node.NetworkSettings.AccessKeys = []models.AccessKey{} // not to be sent (don't need to spread access keys around the network; we need to know how to reach other nodes, not become them) - } + //if len(node.NetworkSettings.AccessKeys) > 0 { + //node.NetworkSettings.AccessKeys = []models.AccessKey{} // not to be sent (don't need to spread access keys around the network; we need to know how to reach other nodes, not become them) + //} data, err := json.Marshal(node) if err != nil { @@ -143,13 +117,13 @@ func NodeUpdate(node *models.LegacyNode) error { return err } if err = publish(node, fmt.Sprintf("update/%s/%s", node.Network, node.ID), data); err != nil { - logger.Log(2, "error publishing node update to peer ", node.ID, err.Error()) + logger.Log(2, "error publishing node update to peer ", node.ID.String(), err.Error()) return err } if node.Proxy { err = PublishProxyPeerUpdate(node) if err != nil { - logger.Log(1, "failed to publish proxy update to node", node.Name, "on network", node.Network, ":", err.Error()) + logger.Log(1, "failed to publish proxy update to node", node.ID.String(), "on network", node.Network, ":", err.Error()) } } @@ -157,15 +131,11 @@ func NodeUpdate(node *models.LegacyNode) error { } // ProxyUpdate -- publishes updates to peers related to proxy -func ProxyUpdate(proxyPayload *manager.ProxyManagerPayload, node *models.LegacyNode) error { +func ProxyUpdate(proxyPayload *manager.ProxyManagerPayload, node *models.Node) error { if !servercfg.IsMessageQueueBackend() || !node.Proxy { return nil } - if node.IsServer == "yes" { - logic.ProxyMgmChan <- proxyPayload - return nil - } - logger.Log(3, "publishing proxy update to "+node.Name) + logger.Log(3, "publishing proxy update to "+node.ID.String()) data, err := json.Marshal(proxyPayload) if err != nil { @@ -173,7 +143,7 @@ func ProxyUpdate(proxyPayload *manager.ProxyManagerPayload, node *models.LegacyN return err } if err = publish(node, fmt.Sprintf("proxy/%s/%s", node.Network, node.ID), data); err != nil { - logger.Log(2, "error publishing proxy update to peer ", node.ID, err.Error()) + logger.Log(2, "error publishing proxy update to peer ", node.ID.String(), err.Error()) return err } return nil @@ -204,45 +174,18 @@ func sendPeers() { logger.Log(3, "error occurred on timer,", err.Error()) } - collectServerMetrics(networks[:]) + //collectServerMetrics(networks[:]) } for _, network := range networks { - serverNode, errN := logic.GetNetworkServerLocal(network.NetID) - if errN == nil { - serverNode.SetLastCheckIn() - if err := logic.UpdateNode(&serverNode, &serverNode); err != nil { - logger.Log(0, "failed checkin for server node", serverNode.Name, "on network", network.NetID, err.Error()) + if force { + logger.Log(2, "sending scheduled peer update (5 min)") + err = PublishPeerUpdate(network.NetID, false) + if err != nil { + logger.Log(1, "error publishing udp port updates for network", network.NetID) + logger.Log(1, err.Error()) } } - isLeader := logic.IsLeader(&serverNode) - if errN == nil && isLeader { - if network.DefaultUDPHolePunch == "yes" { - if logic.ShouldPublishPeerPorts(&serverNode) || force { - if force { - logger.Log(2, "sending scheduled peer update (5 min)") - } - err = PublishPeerUpdate(&serverNode, false) - if err != nil { - logger.Log(1, "error publishing udp port updates for network", network.NetID) - logger.Log(1, errN.Error()) - } - } - } - } else { - if isLeader { - logger.Log(1, "unable to retrieve leader for network ", network.NetID) - } - logger.Log(2, "server checkin complete for server", serverNode.Name, "on network", network.NetID) - serverctl.SyncServerNetwork(network.NetID) - if errN != nil { - logger.Log(1, errN.Error()) - } - if servercfg.IsProxyEnabled() { - serverctl.SyncServerNetworkWithProxy() - } - - } } } @@ -255,54 +198,54 @@ func ServerStartNotify() error { for i := range nodes { nodes[i].Action = models.NODE_FORCE_UPDATE if err = NodeUpdate(&nodes[i]); err != nil { - logger.Log(1, "error when notifying node", nodes[i].Name, " - ", nodes[i].ID, "of a server startup") + logger.Log(1, "error when notifying node", nodes[i].ID.String(), "of a server startup") } } return nil } // function to collect and store metrics for server nodes -func collectServerMetrics(networks []models.Network) { - if !servercfg.Is_EE { - return - } - if len(networks) > 0 { - for i := range networks { - currentNetworkNodes, err := logic.GetNetworkNodes(networks[i].NetID) - if err != nil { - continue - } - currentServerNodes := logic.GetServerNodes(networks[i].NetID) - if len(currentServerNodes) > 0 { - for i := range currentServerNodes { - if logic.IsLocalServer(¤tServerNodes[i]) { - serverMetrics := logic.CollectServerMetrics(currentServerNodes[i].ID, currentNetworkNodes) - if serverMetrics != nil { - serverMetrics.NodeName = currentServerNodes[i].Name - serverMetrics.NodeID = currentServerNodes[i].ID - serverMetrics.IsServer = "yes" - serverMetrics.Network = currentServerNodes[i].Network - if err = metrics.GetExchangedBytesForNode(¤tServerNodes[i], serverMetrics); err != nil { - logger.Log(1, fmt.Sprintf("failed to update exchanged bytes info for server: %s, err: %v", - currentServerNodes[i].Name, err)) - } - updateNodeMetrics(¤tServerNodes[i], serverMetrics) - if err = logic.UpdateMetrics(currentServerNodes[i].ID, serverMetrics); err != nil { - logger.Log(1, "failed to update metrics for server node", currentServerNodes[i].ID) - } - if servercfg.IsMetricsExporter() { - logger.Log(2, "-------------> SERVER METRICS: ", fmt.Sprintf("%+v", serverMetrics)) - if err := pushMetricsToExporter(*serverMetrics); err != nil { - logger.Log(2, "failed to push server metrics to exporter: ", err.Error()) - } - } - } - } - } - } - } - } -} +//func collectServerMetrics(networks []models.Network) { +// if !servercfg.Is_EE { +// return +// } +// if len(networks) > 0 { +// for i := range networks { +// currentNetworkNodes, err := logic.GetNetworkNodes(networks[i].NetID) +// if err != nil { +// continue +// } +// currentServerNodes := logic.GetServerNodes(networks[i].NetID) +// if len(currentServerNodes) > 0 { +// for i := range currentServerNodes { +// if logic.IsLocalServer(¤tServerNodes[i]) { +// serverMetrics := logic.CollectServerMetrics(currentServerNodes[i].ID, currentNetworkNodes) +// if serverMetrics != nil { +// serverMetrics.NodeName = currentServerNodes[i].Name +// serverMetrics.NodeID = currentServerNodes[i].ID +// serverMetrics.IsServer = "yes" +// serverMetrics.Network = currentServerNodes[i].Network +// if err = metrics.GetExchangedBytesForNode(¤tServerNodes[i], serverMetrics); err != nil { +// logger.Log(1, fmt.Sprintf("failed to update exchanged bytes info for server: %s, err: %v", +// currentServerNodes[i].Name, err)) +// } +// updateNodeMetrics(¤tServerNodes[i], serverMetrics) +// if err = logic.UpdateMetrics(currentServerNodes[i].ID, serverMetrics); err != nil { +// logger.Log(1, "failed to update metrics for server node", currentServerNodes[i].ID) +// } +// if servercfg.IsMetricsExporter() { +// logger.Log(2, "-------------> SERVER METRICS: ", fmt.Sprintf("%+v", serverMetrics)) +// if err := pushMetricsToExporter(*serverMetrics); err != nil { +// logger.Log(2, "failed to push server metrics to exporter: ", err.Error()) +// } +// } +// } +// } +// } +// } +// } +// } +//} func pushMetricsToExporter(metrics models.Metrics) error { logger.Log(2, "----> Pushing metrics to exporter") diff --git a/mq/util.go b/mq/util.go index 1bfc3c66..eafa35db 100644 --- a/mq/util.go +++ b/mq/util.go @@ -11,10 +11,14 @@ import ( "github.com/gravitl/netmaker/netclient/ncutils" ) -func decryptMsg(node *models.LegacyNode, msg []byte) ([]byte, error) { +func decryptMsg(node *models.Node, msg []byte) ([]byte, error) { if len(msg) <= 24 { // make sure message is of appropriate length return nil, fmt.Errorf("recieved invalid message from broker %v", msg) } + host, err := logic.GetHost(node.HostID.String()) + if err != nil { + return nil, err + } trafficKey, trafficErr := logic.RetrievePrivateTrafficKey() // get server private key if trafficErr != nil { @@ -24,19 +28,19 @@ func decryptMsg(node *models.LegacyNode, msg []byte) ([]byte, error) { if err != nil { return nil, err } - nodePubTKey, err := ncutils.ConvertBytesToKey(node.TrafficKeys.Mine) + nodePubTKey, err := ncutils.ConvertBytesToKey(host.TrafficKeyPublic) if err != nil { return nil, err } - if strings.Contains(node.Version, "0.10.0") { + if strings.Contains(host.Version, "0.10.0") { return ncutils.BoxDecrypt(msg, nodePubTKey, serverPrivTKey) } return ncutils.DeChunk(msg, nodePubTKey, serverPrivTKey) } -func encryptMsg(node *models.LegacyNode, msg []byte) ([]byte, error) { +func encryptMsg(node *models.Node, msg []byte) ([]byte, error) { // fetch server public key to be certain hasn't changed in transit trafficKey, trafficErr := logic.RetrievePrivateTrafficKey() if trafficErr != nil { @@ -48,19 +52,23 @@ func encryptMsg(node *models.LegacyNode, msg []byte) ([]byte, error) { return nil, err } - nodePubKey, err := ncutils.ConvertBytesToKey(node.TrafficKeys.Mine) + host, err := logic.GetHost(node.HostID.String()) + if err != nil { + return nil, err + } + nodePubKey, err := ncutils.ConvertBytesToKey(host.TrafficKeyPublic) if err != nil { return nil, err } - if strings.Contains(node.Version, "0.10.0") { + if strings.Contains(host.Version, "0.10.0") { return ncutils.BoxEncrypt(msg, nodePubKey, serverPrivKey) } return ncutils.Chunk(msg, nodePubKey, serverPrivKey) } -func publish(node *models.LegacyNode, dest string, msg []byte) error { +func publish(node *models.Node, dest string, msg []byte) error { encrypted, encryptErr := encryptMsg(node, msg) if encryptErr != nil { return encryptErr diff --git a/netclient/Dockerfile b/netclient/Dockerfile deleted file mode 100644 index 7f970f48..00000000 --- a/netclient/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM debian:latest - -RUN apt-get update && apt-get -y install systemd procps - -WORKDIR /root/ - -COPY netclient . - -CMD ["./netclient checkin"] diff --git a/netclient/auth/auth.go b/netclient/auth/auth.go deleted file mode 100644 index 2f1423ae..00000000 --- a/netclient/auth/auth.go +++ /dev/null @@ -1,44 +0,0 @@ -package auth - -import ( - "os" - - "github.com/gravitl/netmaker/netclient/ncutils" - // "os" -) - -// StoreSecret - stores auth secret locally -func StoreSecret(key string, network string) error { - d1 := []byte(key) - return os.WriteFile(ncutils.GetNetclientPathSpecific()+"secret-"+network, d1, 0600) -} - -// RetrieveSecret - fetches secret locally -func RetrieveSecret(network string) (string, error) { - dat, err := ncutils.GetFileWithRetry(ncutils.GetNetclientPathSpecific()+"secret-"+network, 3) - return string(dat), err -} - -// StoreTrafficKey - stores traffic key -func StoreTrafficKey(key *[32]byte, network string) error { - var data, err = ncutils.ConvertKeyToBytes(key) - if err != nil { - return err - } - return os.WriteFile(ncutils.GetNetclientPathSpecific()+"traffic-"+network, data, 0600) -} - -// RetrieveTrafficKey - reads traffic file locally -func RetrieveTrafficKey(network string) (*[32]byte, error) { - data, err := ncutils.GetFileWithRetry(ncutils.GetNetclientPathSpecific()+"traffic-"+network, 2) - if err != nil { - return nil, err - } - return ncutils.ConvertBytesToKey(data) -} - -// Configuraion - struct for mac and pass -type Configuration struct { - MacAddress string - Password string -} diff --git a/netclient/bin-maker.sh b/netclient/bin-maker.sh deleted file mode 100755 index e686d7ba..00000000 --- a/netclient/bin-maker.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash -VERSION=${VERSION:-"develop"} -echo "build with version tag: $VERSION" -readonly __HOST_ARCH=${1:-"amd64"} # change this for your machine. -readonly __HOST_GOOSE=${2:-"linux"} # change this for your machine. -readonly __EXEC_DIR=$(dirname "$(realpath $0)") && cd $__EXEC_DIR - -__darwin=( arm64 amd64 ) -__linux=( amd64 arm arm64 mips mips64 mips64le mipsle ppc64 ppc64le riscv64 s390x 386 ) -__freebsd=( amd64 arm arm64 386 ) -__windows=( amd64 arm arm64 386 ) - -function build -{ - local _goarch=${1:-"None"} && if [[ $_goarch == "None" ]]; then exit 1; fi - local _goose="${2:-"None"}" && if [[ $_goose == "None" ]]; then exit 1; fi - local _goarm=${3:-""} - local _out=build/netclient-$_goose-$_goarch$_goarm && mkdir -p build - if [ "$_goarch" == "arm" ] && [ "$_goarm" == "" ]; then - build $_goarch $_goose 5 && build $_goarch $_goose 6 && build $_goarch $_goose 7 - else - - if [[ $_goarch == mips* ]]; then - #At present GOMIPS64 based binaries are not generated through this script, more details about GOMIPS environment variables in https://go.dev/doc/asm#mips . - echo $_out-softfloat - GOARM=$_goarm GOMIPS=softfloat GOARCH=$_goarch GOOS=$_goose GOHOSTARCH=$__HOST_ARCH CGO_ENABLED=0 go build -ldflags="-X 'main.version=$VERSION'" -o $_out-softfloat - echo $_out - GOARM=$_goarm GOARCH=$_goarch GOOS=$_goose GOHOSTARCH=$__HOST_ARCH CGO_ENABLED=0 go build -ldflags="-X 'main.version=$VERSION'" -o $_out - else - echo $_out - GOARM=$_goarm GOARCH=$_goarch GOOS=$_goose GOHOSTARCH=$__HOST_ARCH CGO_ENABLED=0 go build -ldflags="-X 'main.version=$VERSION'" -o $_out - fi - fi -} - -for arch in ${__linux[*]}; do build "$arch" "linux"; done - -for arch in ${__freebsd[*]}; do build "$arch" "freebsd"; done - -for arch in ${__darwin[*]}; do build "$arch" "darwin"; done - -for arch in ${__windows[*]}; do build "$arch" "windows"; done diff --git a/netclient/build/netclient.service b/netclient/build/netclient.service deleted file mode 100644 index e10f38e2..00000000 --- a/netclient/build/netclient.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=Netclient Daemon -Documentation=https://docs.netmaker.org https://k8s.netmaker.org -After=network-online.target -Wants=network-online.target - -[Service] -User=root -Type=simple -ExecStart=/sbin/netclient daemon -Restart=on-failure -RestartSec=15s - -[Install] -WantedBy=multi-user.target diff --git a/netclient/cli_options/cmds.go b/netclient/cli_options/cmds.go deleted file mode 100644 index f0e542a0..00000000 --- a/netclient/cli_options/cmds.go +++ /dev/null @@ -1,148 +0,0 @@ -package cli_options - -import ( - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/command" - "github.com/gravitl/netmaker/netclient/config" - "github.com/urfave/cli/v2" -) - -// GetCommands - return commands that CLI uses -func GetCommands(cliFlags []cli.Flag) []*cli.Command { - return []*cli.Command{ - { - Name: "join", - Usage: "Join a Netmaker network.", - Flags: cliFlags, - Action: func(c *cli.Context) error { - parseVerbosity(c) - cfg, pvtKey, err := config.GetCLIConfig(c) - if err != nil { - return err - } - err = command.Join(&cfg, pvtKey) - return err - }, - }, - { - Name: "leave", - Usage: "Leave a Netmaker network.", - Flags: cliFlags, - // the action, or code that will be executed when - // we execute our `ns` command - Action: func(c *cli.Context) error { - parseVerbosity(c) - cfg, _, err := config.GetCLIConfig(c) - if err != nil { - return err - } - err = command.Leave(&cfg) - return err - }, - }, - { - Name: "pull", - Usage: "Pull latest configuration and peers from server.", - Flags: cliFlags, - // the action, or code that will be executed when - // we execute our `ns` command - Action: func(c *cli.Context) error { - parseVerbosity(c) - cfg, _, err := config.GetCLIConfig(c) - if err != nil { - return err - } - err = command.Pull(&cfg) - return err - }, - }, - { - Name: "list", - Usage: "Get list of networks.", - Flags: cliFlags, - // the action, or code that will be executed when - // we execute our `ns` command - Action: func(c *cli.Context) error { - parseVerbosity(c) - cfg, _, err := config.GetCLIConfig(c) - if err != nil { - return err - } - err = command.List(cfg) - return err - }, - }, - { - Name: "uninstall", - Usage: "Uninstall the netclient system service.", - Flags: cliFlags, - // the action, or code that will be executed when - // we execute our `ns` command - Action: func(c *cli.Context) error { - parseVerbosity(c) - err := command.Uninstall() - return err - }, - }, - { - Name: "daemon", - Usage: "run netclient as daemon", - Flags: cliFlags, - Action: func(c *cli.Context) error { - // set max verbosity for daemon regardless - logger.Verbosity = 4 - err := command.Daemon() - return err - }, - }, - { - Name: "install", - Usage: "install binary and daemon", - Flags: cliFlags, - Action: func(c *cli.Context) error { - parseVerbosity(c) - return command.Install() - }, - }, - { - Name: "connect", - Usage: "connect netclient to a given network if disconnected", - Flags: cliFlags, - Action: func(c *cli.Context) error { - parseVerbosity(c) - cfg, _, err := config.GetCLIConfig(c) - if err != nil { - return err - } - return command.Connect(cfg) - }, - }, - { - Name: "disconnect", - Usage: "disconnect netclient from a given network if connected", - Flags: cliFlags, - Action: func(c *cli.Context) error { - parseVerbosity(c) - cfg, _, err := config.GetCLIConfig(c) - if err != nil { - return err - } - return command.Disconnect(cfg) - }, - }, - } -} - -// == Private funcs == - -func parseVerbosity(c *cli.Context) { - if c.Bool("v") { - logger.Verbosity = 1 - } else if c.Bool("vv") { - logger.Verbosity = 2 - } else if c.Bool("vvv") { - logger.Verbosity = 3 - } else if c.Bool("vvvv") { - logger.Verbosity = 4 - } -} diff --git a/netclient/cli_options/flags.go b/netclient/cli_options/flags.go deleted file mode 100644 index a0a1a8aa..00000000 --- a/netclient/cli_options/flags.go +++ /dev/null @@ -1,236 +0,0 @@ -package cli_options - -import "github.com/urfave/cli/v2" - -// GetFlags - Returns the flags used by cli -func GetFlags(hostname string) []cli.Flag { - return []cli.Flag{ - &cli.StringFlag{ - Name: "network", - Aliases: []string{"n"}, - EnvVars: []string{"NETCLIENT_NETWORK"}, - Value: "all", - Usage: "Network to perform specified action against.", - }, - &cli.StringFlag{ - Name: "proxy", - // Aliases: []string{"np"}, - EnvVars: []string{"NETMAKER_PROXY"}, - Value: "off", - Usage: "To enable/disable proxy.", - }, - &cli.StringFlag{ - Name: "password", - Aliases: []string{"p"}, - EnvVars: []string{"NETCLIENT_PASSWORD"}, - Value: "", - Usage: "Password for authenticating with netmaker.", - }, - &cli.StringFlag{ - Name: "endpoint", - Aliases: []string{"e"}, - EnvVars: []string{"NETCLIENT_ENDPOINT"}, - Value: "", - Usage: "Reachable (usually public) address for WireGuard (not the private WG address).", - }, - &cli.StringFlag{ - Name: "macaddress", - Aliases: []string{"m"}, - EnvVars: []string{"NETCLIENT_MACADDRESS"}, - Value: "", - Usage: "Mac Address for this machine. Used as a unique identifier within Netmaker network.", - }, - &cli.StringFlag{ - Name: "publickey", - Aliases: []string{"pubkey"}, - EnvVars: []string{"NETCLIENT_PUBLICKEY"}, - Value: "", - Usage: "Public Key for WireGuard Interface.", - }, - &cli.StringFlag{ - Name: "privatekey", - Aliases: []string{"privkey"}, - EnvVars: []string{"NETCLIENT_PRIVATEKEY"}, - Value: "", - Usage: "Private Key for WireGuard Interface.", - }, - &cli.StringFlag{ - Name: "port", - EnvVars: []string{"NETCLIENT_PORT"}, - Value: "", - Usage: "Port for WireGuard Interface.", - }, - &cli.IntFlag{ - Name: "keepalive", - EnvVars: []string{"NETCLIENT_KEEPALIVE"}, - Value: 0, - Usage: "Default PersistentKeepAlive for Peers in WireGuard Interface.", - }, - &cli.StringFlag{ - Name: "operatingsystem", - Aliases: []string{"os"}, - EnvVars: []string{"NETCLIENT_OS"}, - Value: "", - Usage: "Operating system of machine (linux, darwin, windows, freebsd).", - }, - &cli.StringFlag{ - Name: "publicipservice", - Aliases: []string{"ip-service"}, - EnvVars: []string{"NETCLIENT_IP_SERVICE"}, - Value: "", - Usage: "The service to call to obtain the public IP of the machine that is running netclient.", - }, - &cli.StringFlag{ - Name: "name", - EnvVars: []string{"NETCLIENT_NAME"}, - Value: hostname, - Usage: "Identifiable name for machine within Netmaker network.", - }, - &cli.StringFlag{ - Name: "localaddress", - EnvVars: []string{"NETCLIENT_LOCALADDRESS"}, - Value: "", - Usage: "Local address for machine. Can be used in place of Endpoint for machines on the same LAN.", - }, - &cli.StringFlag{ - Name: "isstatic", - Aliases: []string{"st"}, - EnvVars: []string{"NETCLIENT_IS_STATIC"}, - Value: "", - Usage: "Indicates if client is static by default (will not change addresses automatically).", - }, - &cli.StringFlag{ - Name: "address", - Aliases: []string{"a"}, - EnvVars: []string{"NETCLIENT_ADDRESS"}, - Value: "", - Usage: "WireGuard address for machine within Netmaker network.", - }, - &cli.StringFlag{ - Name: "addressIPv6", - Aliases: []string{"a6"}, - EnvVars: []string{"NETCLIENT_ADDRESSIPV6"}, - Value: "", - Usage: "WireGuard address for machine within Netmaker network.", - }, - &cli.StringFlag{ - Name: "interface", - Aliases: []string{"i"}, - EnvVars: []string{"NETCLIENT_INTERFACE"}, - Value: "", - Usage: "WireGuard local network interface name.", - }, - &cli.StringFlag{ - Name: "apiserver", - EnvVars: []string{"NETCLIENT_API_SERVER"}, - Value: "", - Usage: "Address + API Port (e.g. 1.2.3.4:8081) of Netmaker server.", - }, - &cli.StringFlag{ - Name: "key", - Aliases: []string{"k"}, - EnvVars: []string{"NETCLIENT_ACCESSKEY"}, - Value: "", - Usage: "Access Key for signing up machine with Netmaker server during initial 'add'.", - }, - &cli.StringFlag{ - Name: "token", - Aliases: []string{"t"}, - EnvVars: []string{"NETCLIENT_ACCESSTOKEN"}, - Value: "", - Usage: "Access Token for signing up machine with Netmaker server during initial 'add'.", - }, - &cli.StringFlag{ - Name: "server", - Aliases: []string{"s"}, - EnvVars: []string{"HOST_SERVER"}, - Value: "", - Usage: "Host server (domain of API) [Example: api.example.com]. Do not include \"http(s)://\" use it for the Single Sign-on along with the network parameter", - }, - &cli.StringFlag{ - Name: "user", - Aliases: []string{"u"}, - EnvVars: []string{"USER_NAME"}, - Value: "", - Usage: "User name provided upon joins if joining over basic auth is desired.", - }, - &cli.StringFlag{ - Name: "localrange", - EnvVars: []string{"NETCLIENT_LOCALRANGE"}, - Value: "", - Usage: "Local Range if network is local, for instance 192.168.1.0/24.", - }, - &cli.StringFlag{ - Name: "dnson", - EnvVars: []string{"NETCLIENT_DNS"}, - Value: "yes", - Usage: "Sets private dns if 'yes'. Ignores if 'no'. Will retrieve from network if unset.", - }, - &cli.StringFlag{ - Name: "islocal", - EnvVars: []string{"NETCLIENT_IS_LOCAL"}, - Value: "", - Usage: "Sets endpoint to local address if 'yes'. Ignores if 'no'. Will retrieve from network if unset.", - }, - &cli.StringFlag{ - Name: "udpholepunch", - EnvVars: []string{"NETCLIENT_UDP_HOLEPUNCH"}, - Value: "", - Usage: "Turns on udp holepunching if 'yes'. Ignores if 'no'. Will retrieve from network if unset.", - }, - &cli.StringFlag{ - Name: "ipforwarding", - EnvVars: []string{"NETCLIENT_IPFORWARDING"}, - Value: "on", - Usage: "Sets ip forwarding on if 'on'. Ignores if 'off'. On by default.", - }, - &cli.StringFlag{ - Name: "postup", - EnvVars: []string{"NETCLIENT_POSTUP"}, - Value: "", - Usage: "Sets PostUp command for WireGuard.", - }, - &cli.StringFlag{ - Name: "postdown", - EnvVars: []string{"NETCLIENT_POSTDOWN"}, - Value: "", - Usage: "Sets PostDown command for WireGuard.", - }, - &cli.StringFlag{ - Name: "daemon", - EnvVars: []string{"NETCLIENT_DAEMON"}, - Value: "on", - Usage: "Installs daemon if 'on'. Ignores if 'off'. On by default.", - }, - &cli.StringFlag{ - Name: "roaming", - EnvVars: []string{"NETCLIENT_ROAMING"}, - Value: "yes", - Usage: "Checks for IP changes if 'yes'. Ignores if 'no'. Yes by default.", - }, - &cli.BoolFlag{ - Name: "verbosity-level-1", - Aliases: []string{"v"}, - Value: false, - Usage: "Netclient Verbosity level 1.", - }, - &cli.BoolFlag{ - Name: "verbosity-level-2", - Aliases: []string{"vv"}, - Value: false, - Usage: "Netclient Verbosity level 2.", - }, - &cli.BoolFlag{ - Name: "verbosity-level-3", - Aliases: []string{"vvv"}, - Value: false, - Usage: "Netclient Verbosity level 3.", - }, - &cli.BoolFlag{ - Name: "verbosity-level-4", - Aliases: []string{"vvvv"}, - Value: false, - Usage: "Netclient Verbosity level 4.", - }, - } -} diff --git a/netclient/command/commands.go b/netclient/command/commands.go deleted file mode 100644 index 4dd4a8ed..00000000 --- a/netclient/command/commands.go +++ /dev/null @@ -1,167 +0,0 @@ -package command - -import ( - "errors" - "fmt" - "strings" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/daemon" - "github.com/gravitl/netmaker/netclient/functions" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// Join - join command to run from cli -func Join(cfg *config.ClientConfig, privateKey string) error { - var err error - //join network - if cfg.SsoServer != "" { - // User wants to get access key from the OIDC server - // Do that before the Joining Network flow by performing the end point auth flow - // if performed successfully an access key is obtained from the server and then we - // proceed with the usual flow 'pretending' that user is feeded us with an access token - if len(cfg.Network) == 0 || cfg.Network == "all" { - return fmt.Errorf("no network provided. Specify network with \"-n \"") - } - logger.Log(1, "Logging into %s via:", cfg.Network, cfg.SsoServer) - err = functions.JoinViaSSo(cfg, privateKey) - if err != nil { - logger.Log(0, "Join failed: ", err.Error()) - return err - } - - if cfg.AccessKey == "" { - return errors.New("login failed") - } - } - - logger.Log(1, "Joining network: ", cfg.Network) - err = functions.JoinNetwork(cfg, privateKey) - if err != nil { - if !strings.Contains(err.Error(), "ALREADY_INSTALLED") { - logger.Log(0, "error installing: ", err.Error()) - err = functions.WipeLocal(cfg) - if err != nil { - logger.Log(1, "error removing artifacts: ", err.Error()) - } - if cfg.Daemon != "off" { - if ncutils.IsLinux() { - err = daemon.RemoveSystemDServices() - } - if err != nil { - logger.Log(1, "error removing services: ", err.Error()) - } - if ncutils.IsFreeBSD() { - daemon.RemoveFreebsdDaemon() - } - } - } - if err != nil && strings.Contains(err.Error(), "ALREADY_INSTALLED") { - logger.Log(0, err.Error()) - err = nil - } - return err - } - logger.Log(1, "joined", cfg.Network) - - return err -} - -// Leave - runs the leave command from cli -func Leave(cfg *config.ClientConfig) error { - err := functions.LeaveNetwork(cfg.Network) - if err != nil { - logger.Log(1, "error attempting to leave network "+cfg.Network) - } else { - logger.Log(0, "success") - } - return err -} - -// Pull - runs pull command from cli -func Pull(cfg *config.ClientConfig) error { - var err error - var networks = []string{} - if cfg.Network == "all" { - logger.Log(0, "No network selected. Running Pull for all networks.") - networks, err = ncutils.GetSystemNetworks() - if err != nil { - logger.Log(1, "Error retrieving networks. Exiting.") - return err - } - } else { - networks = append(networks, cfg.Network) - } - - var currentServers = make(map[string]config.ClientConfig) - - for _, network := range networks { - currCfg, err := config.ReadConfig(network) - if err != nil { - logger.Log(1, "could not read config when pulling for network", network) - continue - } - - _, err = functions.Pull(network, true) - if err != nil { - logger.Log(1, "error pulling network config for network: ", network, "\n", err.Error()) - } else { - logger.Log(1, "pulled network config for "+network) - } - - currentServers[currCfg.Server.Server] = *currCfg - } - daemon.Restart() - logger.Log(1, "reset network", cfg.Network, "and peer configs") - return err -} - -// List - runs list command from cli -func List(cfg config.ClientConfig) error { - _, err := functions.List(cfg.Network) - return err -} - -// Uninstall - runs uninstall command from cli -func Uninstall() error { - logger.Log(0, "uninstalling netclient...") - err := functions.Uninstall() - logger.Log(0, "uninstalled netclient") - return err -} - -// Daemon - runs the daemon -func Daemon() error { - err := functions.Daemon() - return err -} - -// Install - installs binary and daemon -func Install() error { - return functions.Install() -} - -// Connect - re-instates a connection of a node -func Connect(cfg config.ClientConfig) error { - networkName := cfg.Network - if networkName == "" { - networkName = cfg.Node.Network - } - if networkName == "all" { - return fmt.Errorf("no network specified") - } - return functions.Connect(networkName) -} - -// Disconnect - disconnects a connection of a node -func Disconnect(cfg config.ClientConfig) error { - networkName := cfg.Network - if networkName == "" { - networkName = cfg.Node.Network - } - if networkName == "all" { - return fmt.Errorf("no network specified") - } - return functions.Disconnect(networkName) -} diff --git a/netclient/config/config.go b/netclient/config/config.go deleted file mode 100644 index 8ad354cf..00000000 --- a/netclient/config/config.go +++ /dev/null @@ -1,352 +0,0 @@ -package config - -import ( - "crypto/ed25519" - "crypto/x509" - "crypto/x509/pkix" - "errors" - "fmt" - "log" - "os" - "sync" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/global_settings" - "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/urfave/cli/v2" - "gopkg.in/yaml.v3" -) - -var ( - configLock sync.Mutex -) - -// ClientConfig - struct for dealing with client configuration -type ClientConfig struct { - Server models.ServerConfig `yaml:"server"` - Node models.LegacyNode `yaml:"node"` - NetworkSettings models.Network `yaml:"networksettings"` - Network string `yaml:"network"` - Daemon string `yaml:"daemon"` - OperatingSystem string `yaml:"operatingsystem"` - AccessKey string `yaml:"accesskey"` - PublicIPService string `yaml:"publicipservice"` - SsoServer string `yaml:"sso"` -} - -// RegisterRequest - struct for registation with netmaker server -type RegisterRequest struct { - Key ed25519.PrivateKey - CommonName pkix.Name -} - -// RegisterResponse - the response to register function -type RegisterResponse struct { - CA x509.Certificate - CAPubKey ed25519.PublicKey - Cert x509.Certificate - CertPubKey ed25519.PublicKey - Broker string - Port string -} - -// Write - writes the config of a client to disk -func Write(config *ClientConfig, network string) error { - configLock.Lock() - defer configLock.Unlock() - if network == "" { - err := errors.New("no network provided - exiting") - return err - } - _, err := os.Stat(ncutils.GetNetclientPath() + "/config") - if os.IsNotExist(err) { - os.MkdirAll(ncutils.GetNetclientPath()+"/config", 0700) - } else if err != nil { - return err - } - home := ncutils.GetNetclientPathSpecific() - - file := fmt.Sprintf(home + "netconfig-" + network) - f, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) - if err != nil { - return err - } - defer f.Close() - - err = yaml.NewEncoder(f).Encode(config) - if err != nil { - return err - } - return f.Sync() -} - -// ConfigFileExists - return true if config file exists -func (config *ClientConfig) ConfigFileExists() bool { - home := ncutils.GetNetclientPathSpecific() - - file := fmt.Sprintf(home + "netconfig-" + config.Network) - info, err := os.Stat(file) - if os.IsNotExist(err) { - return false - } - return !info.IsDir() -} - -// ClientConfig.ReadConfig - used to read config from client disk into memory -func (config *ClientConfig) ReadConfig() { - - network := config.Network - if network == "" { - return - } - - //home, err := homedir.Dir() - home := ncutils.GetNetclientPathSpecific() - - file := fmt.Sprintf(home + "netconfig-" + network) - //f, err := os.Open(file) - f, err := os.OpenFile(file, os.O_RDONLY, 0600) - if err != nil { - logger.Log(1, "trouble opening file: ", err.Error()) - if err = ReplaceWithBackup(network); err != nil { - log.Fatal(err) - } - f.Close() - f, err = os.Open(file) - if err != nil { - log.Fatal(err) - } - - } - defer f.Close() - if err := yaml.NewDecoder(f).Decode(&config); err != nil { - logger.Log(0, "no config or invalid, replacing with backup") - if err = ReplaceWithBackup(network); err != nil { - log.Fatal(err) - } - f.Close() - f, err = os.Open(file) - if err != nil { - log.Fatal(err) - } - defer f.Close() - if err := yaml.NewDecoder(f).Decode(&config); err != nil { - log.Fatal(err) - } - } -} - -// ModNodeConfig - overwrites the node inside client config on disk -func ModNodeConfig(node *models.LegacyNode) error { - network := node.Network - if network == "" { - return errors.New("no network provided") - } - var modconfig ClientConfig - if FileExists(ncutils.GetNetclientPathSpecific() + "netconfig-" + network) { - useconfig, err := ReadConfig(network) - if err != nil { - return err - } - modconfig = *useconfig - } - - modconfig.Node = (*node) - modconfig.NetworkSettings = node.NetworkSettings - return Write(&modconfig, network) -} - -// ModNodeConfig - overwrites the server settings inside client config on disk -func ModServerConfig(scfg *models.ServerConfig, network string) error { - var modconfig ClientConfig - if FileExists(ncutils.GetNetclientPathSpecific() + "netconfig-" + network) { - useconfig, err := ReadConfig(network) - if err != nil { - return err - } - modconfig = *useconfig - } - - modconfig.Server = (*scfg) - return Write(&modconfig, network) -} - -// SaveBackup - saves a backup file of a given network -func SaveBackup(network string) error { - - var configPath = ncutils.GetNetclientPathSpecific() + "netconfig-" + network - var backupPath = ncutils.GetNetclientPathSpecific() + "backup.netconfig-" + network - if FileExists(configPath) { - input, err := os.ReadFile(configPath) - if err != nil { - logger.Log(0, "failed to read ", configPath, " to make a backup") - return err - } - if err = os.WriteFile(backupPath, input, 0600); err != nil { - logger.Log(0, "failed to copy backup to ", backupPath) - return err - } - } - return nil -} - -// ReplaceWithBackup - replaces netconfig file with backup -func ReplaceWithBackup(network string) error { - var backupPath = ncutils.GetNetclientPathSpecific() + "backup.netconfig-" + network - var configPath = ncutils.GetNetclientPathSpecific() + "netconfig-" + network - if FileExists(backupPath) { - input, err := os.ReadFile(backupPath) - if err != nil { - logger.Log(0, "failed to read file ", backupPath, " to backup network: ", network) - return err - } - if err = os.WriteFile(configPath, input, 0600); err != nil { - logger.Log(0, "failed backup ", backupPath, " to ", configPath) - return err - } - } - logger.Log(0, "used backup file for network: ", network) - return nil -} - -// GetCLIConfig - gets the cli flags as a config -func GetCLIConfig(c *cli.Context) (ClientConfig, string, error) { - var cfg ClientConfig - if c.String("token") != "" { - accesstoken, err := ParseAccessToken(c.String("token")) - if err != nil { - return cfg, "", err - } - cfg.Network = accesstoken.ClientConfig.Network - cfg.Node.Network = accesstoken.ClientConfig.Network - cfg.AccessKey = accesstoken.ClientConfig.Key - cfg.Node.LocalRange = accesstoken.ClientConfig.LocalRange - //cfg.Server.Server = accesstoken.ServerConfig.Server - cfg.Server.API = accesstoken.APIConnString - if c.String("key") != "" { - cfg.AccessKey = c.String("key") - } - if c.String("proxy") != "" { - cfg.Node.Proxy = c.String("proxy") == "on" - } - log.Println("_______________> PROXY: ", cfg.Node.Proxy) - if c.String("network") != "all" { - cfg.Network = c.String("network") - cfg.Node.Network = c.String("network") - } - if c.String("localrange") != "" { - cfg.Node.LocalRange = c.String("localrange") - } - if c.String("corednsaddr") != "" { - cfg.Server.CoreDNSAddr = c.String("corednsaddr") - } - if c.String("apiserver") != "" { - cfg.Server.API = c.String("apiserver") - } - } else if c.String("server") != "" { - cfg.SsoServer = c.String("server") - cfg.Network = c.String("network") - cfg.Node.Network = c.String("network") - global_settings.User = c.String("user") - } else { - cfg.AccessKey = c.String("key") - cfg.Network = c.String("network") - cfg.Node.Network = c.String("network") - cfg.Node.LocalRange = c.String("localrange") - cfg.Server.CoreDNSAddr = c.String("corednsaddr") - cfg.Server.API = c.String("apiserver") - } - cfg.PublicIPService = c.String("publicipservice") - // populate the map as we're not running as a daemon so won't be building the map otherwise - // (and the map will be used by GetPublicIP()). - global_settings.PublicIPServices[cfg.Network] = cfg.PublicIPService - cfg.Node.Name = c.String("name") - cfg.Node.Interface = c.String("interface") - cfg.Node.Password = c.String("password") - cfg.Node.MacAddress = c.String("macaddress") - cfg.Node.LocalAddress = c.String("localaddress") - cfg.Node.Address = c.String("address") - cfg.Node.Address6 = c.String("address6") - //cfg.Node.Roaming = c.String("roaming") - cfg.Node.DNSOn = c.String("dnson") - cfg.Node.IsLocal = c.String("islocal") - cfg.Node.IsStatic = c.String("isstatic") - cfg.Node.PostUp = c.String("postup") - cfg.Node.PostDown = c.String("postdown") - cfg.Node.ListenPort = int32(c.Int("port")) - cfg.Node.PersistentKeepalive = int32(c.Int("keepalive")) - cfg.Node.PublicKey = c.String("publickey") - privateKey := c.String("privatekey") - cfg.Node.Endpoint = c.String("endpoint") - cfg.Node.IPForwarding = c.String("ipforwarding") - cfg.OperatingSystem = c.String("operatingsystem") - cfg.Daemon = c.String("daemon") - cfg.Node.UDPHolePunch = c.String("udpholepunch") - cfg.Node.MTU = int32(c.Int("mtu")) - - return cfg, privateKey, nil -} - -// ReadConfig - reads a config of a client from disk for specified network -func ReadConfig(network string) (*ClientConfig, error) { - if network == "" { - err := errors.New("no network provided - exiting") - return nil, err - } - home := ncutils.GetNetclientPathSpecific() - file := fmt.Sprintf(home + "netconfig-" + network) - f, err := os.Open(file) - if err != nil { - if err = ReplaceWithBackup(network); err != nil { - return nil, err - } - f, err = os.Open(file) - if err != nil { - return nil, err - } - } - defer f.Close() - - var cfg ClientConfig - decoder := yaml.NewDecoder(f) - err = decoder.Decode(&cfg) - if err != nil { - if err = ReplaceWithBackup(network); err != nil { - return nil, err - } - f.Close() - f, err = os.Open(file) - if err != nil { - return nil, err - } - defer f.Close() - if err := yaml.NewDecoder(f).Decode(&cfg); err != nil { - return nil, err - } - } - - return &cfg, err -} - -// FileExists - checks if a file exists on disk -func FileExists(f string) bool { - info, err := os.Stat(f) - if os.IsNotExist(err) { - return false - } - return !info.IsDir() -} - -// GetNode - parses a network specified client config for node data -func GetNode(network string) models.LegacyNode { - - modcfg, err := ReadConfig(network) - if err != nil { - log.Fatalf("Error: %v", err) - } - var node models.LegacyNode - node.Fill(&modcfg.Node) - - return node -} diff --git a/netclient/config/util.go b/netclient/config/util.go deleted file mode 100644 index fe6b2676..00000000 --- a/netclient/config/util.go +++ /dev/null @@ -1,31 +0,0 @@ -package config - -import ( - "encoding/base64" - "encoding/json" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/models" -) - -var ( - // GuiActive - indicates if gui is active or not - GuiActive = false - // GuiRun - holds function for main to call - GuiRun interface{} -) - -// ParseAccessToken - used to parse the base64 encoded access token -func ParseAccessToken(token string) (*models.AccessToken, error) { - tokenbytes, err := base64.StdEncoding.DecodeString(token) - if err != nil { - logger.Log(0, "error decoding token", err.Error()) - return nil, err - } - var accesstoken models.AccessToken - if err := json.Unmarshal(tokenbytes, &accesstoken); err != nil { - logger.Log(0, "error decoding token", err.Error()) - return nil, err - } - return &accesstoken, nil -} diff --git a/netclient/daemon/common.go b/netclient/daemon/common.go deleted file mode 100644 index 6035fbb0..00000000 --- a/netclient/daemon/common.go +++ /dev/null @@ -1,94 +0,0 @@ -package daemon - -import ( - "errors" - "fmt" - "os" - "runtime" - "syscall" - "time" - - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// InstallDaemon - Calls the correct function to install the netclient as a daemon service on the given operating system. -func InstallDaemon() error { - - os := runtime.GOOS - var err error - - switch os { - case "windows": - err = SetupWindowsDaemon() - case "darwin": - err = SetupMacDaemon() - case "linux": - err = SetupSystemDDaemon() - case "freebsd": - err = SetupFreebsdDaemon() - default: - err = errors.New("this os is not yet supported for daemon mode. Run join cmd with flag '--daemon off'") - } - return err -} - -// Restart - restarts a system daemon -func Restart() error { - if ncutils.IsWindows() { - RestartWindowsDaemon() - return nil - } - pid, err := ncutils.ReadPID() - if err != nil { - return fmt.Errorf("failed to find pid %w", err) - } - p, err := os.FindProcess(pid) - if err != nil { - return fmt.Errorf("failed to find running process for pid %d -- %w", pid, err) - } - if err := p.Signal(syscall.SIGHUP); err != nil { - return fmt.Errorf("SIGHUP failed -- %w", err) - } - return nil -} - -// Start - starts system daemon -func Start() error { - os := runtime.GOOS - var err error - switch os { - case "windows": - RestartWindowsDaemon() - case "darwin": - RestartLaunchD() - case "linux": - RestartSystemD() - case "freebsd": - FreebsdDaemon("restart") - default: - err = errors.New("this os is not yet supported for daemon mode. Run join cmd with flag '--daemon off'") - } - return err -} - -// Stop - stops a system daemon -func Stop() error { - os := runtime.GOOS - var err error - - time.Sleep(time.Second) - - switch os { - case "windows": - RunWinSWCMD("stop") - case "darwin": - StopLaunchD() - case "linux": - StopSystemD() - case "freebsd": - FreebsdDaemon("stop") - default: - err = errors.New("no OS daemon to stop") - } - return err -} diff --git a/netclient/daemon/freebsd.go b/netclient/daemon/freebsd.go deleted file mode 100644 index 27238412..00000000 --- a/netclient/daemon/freebsd.go +++ /dev/null @@ -1,135 +0,0 @@ -package daemon - -import ( - "log" - "os" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// SetupFreebsdDaemon -- sets up daemon for freebsd -func SetupFreebsdDaemon() error { - binarypath, err := os.Executable() - if err != nil { - return err - } - - _, err = os.Stat("/etc/netclient/config") - if os.IsNotExist(err) { - os.MkdirAll("/etc/netclient/config", 0744) - } else if err != nil { - log.Println("couldnt find or create /etc/netclient") - return err - } - //install binary - if ncutils.FileExists(EXEC_DIR + "netclient") { - logger.Log(0, "updating netclient binary in ", EXEC_DIR) - } - err = ncutils.Copy(binarypath, EXEC_DIR+"netclient") - if err != nil { - logger.Log(0, err.Error()) - return err - } - - rcFile := `#!/bin/sh -# -# PROVIDE: netclient -# REQUIRE: LOGIN -# KEYWORD: shutdown - -# Description: -# This script runs netclient as a service as root on boot - -# How to use: -# Place this file in /usr/local/etc/rc.d/ -# Add netclient="YES" to /etc/rc.config.d/netclient -# To pass args, add netclient_args="daemon" to /etc/rc.config.d/netclient - -# Freebsd rc library -. /etc/rc.subr - -# General Info -name="netclient" # Safe name of program -program_name="netclient" # Name of exec -title="netclient" # Title to display in top/htop - -# RC.config vars -load_rc_config $name # Loading rc config vars -: ${netclient_enable="YES"} # Default: enable netclient -: ${netclient_runAs="root"} # Default: Run Node-RED as root - -# Freebsd Setup -rcvar=netclient_enable # Enables the rc.conf YES/NO flag -pidfile="/var/run/${program_name}.pid" # File that allows the system to keep track of node-red status - -# Env Setup -#export HOME=$( getent passwd "$netclient_runAs" | cut -d: -f6 ) # Gets the home directory of the runAs user - -# Command Setup -exec_path="/sbin/${program_name}" # Path to the netclient exec -output_file="/var/log/${program_name}.log" # Path to netclient logs - -# Command -command="/usr/sbin/daemon" -command_args="-r -t ${title} -u ${netclient_runAs} -o ${output_file} -P ${pidfile} ${exec_path} ${netclient_args}" - -# Loading Config -load_rc_config ${name} -run_rc_command "$1" -` - - rcConfig := `netclient="YES" -netclient_args="daemon"` - - rcbytes := []byte(rcFile) - if !ncutils.FileExists("/etc/rc.d/netclient") { - err := os.WriteFile("/etc/rc.d/netclient", rcbytes, 0744) - if err != nil { - return err - } - rcConfigbytes := []byte(rcConfig) - if !ncutils.FileExists("/etc/rc.conf.d/netclient") { - err := os.WriteFile("/etc/rc.conf.d/netclient", rcConfigbytes, 0644) - if err != nil { - return err - } - FreebsdDaemon("start") - return nil - } - } - return nil -} - -// FreebsdDaemon - accepts args to service netclient and applies -func FreebsdDaemon(command string) { - _, _ = ncutils.RunCmdFormatted("service netclient "+command, true) -} - -// CleanupFreebsd - removes config files and netclient binary -func CleanupFreebsd() { - ncutils.RunCmd("service netclient stop", false) - RemoveFreebsdDaemon() - if err := os.RemoveAll(ncutils.GetNetclientPath()); err != nil { - logger.Log(1, "Removing netclient configs: ", err.Error()) - } - if err := os.Remove(EXEC_DIR + "netclient"); err != nil { - logger.Log(1, "Removing netclient binary: ", err.Error()) - } -} - -// RemoveFreebsdDaemon - remove freebsd daemon -func RemoveFreebsdDaemon() { - if ncutils.FileExists("/etc/rc.d/netclient") { - err := os.Remove("/etc/rc.d/netclient") - if err != nil { - logger.Log(0, "Error removing /etc/rc.d/netclient. Please investigate.") - } - } - if ncutils.FileExists("/etc/rc.conf.d/netclient") { - err := os.Remove("/etc/rc.conf.d/netclient") - if err != nil { - logger.Log(0, "Error removing /etc/rc.conf.d/netclient. Please investigate.") - } - } -} diff --git a/netclient/daemon/macos.go b/netclient/daemon/macos.go deleted file mode 100644 index d59ccf65..00000000 --- a/netclient/daemon/macos.go +++ /dev/null @@ -1,117 +0,0 @@ -package daemon - -import ( - "log" - "os" - "time" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -const MAC_SERVICE_NAME = "com.gravitl.netclient" -const MAC_EXEC_DIR = "/usr/local/bin/" - -// SetupMacDaemon - Creates a daemon service from the netclient under LaunchAgents for MacOS -func SetupMacDaemon() error { - - binarypath, err := os.Executable() - if err != nil { - return err - } - - if ncutils.FileExists(MAC_EXEC_DIR + "netclient") { - logger.Log(0, "updating netclient binary in", MAC_EXEC_DIR) - } - err = ncutils.Copy(binarypath, MAC_EXEC_DIR+"netclient") - if err != nil { - logger.Log(0, err.Error()) - return err - } - - err = CreateMacService(MAC_SERVICE_NAME) - if err != nil { - return err - } - _, err = ncutils.RunCmd("launchctl load /Library/LaunchDaemons/"+MAC_SERVICE_NAME+".plist", true) - return err -} - -// CleanupMac - Removes the netclient checkin daemon from LaunchDaemons -func CleanupMac() { - _, err := ncutils.RunCmd("launchctl unload /Library/LaunchDaemons/"+MAC_SERVICE_NAME+".plist", true) - if ncutils.FileExists("/Library/LaunchDaemons/" + MAC_SERVICE_NAME + ".plist") { - err = os.Remove("/Library/LaunchDaemons/" + MAC_SERVICE_NAME + ".plist") - } - if err != nil { - logger.Log(1, err.Error()) - } - - os.RemoveAll(ncutils.GetNetclientPath()) - os.Remove(MAC_EXEC_DIR + "netclient") -} - -// RestartLaunchD - restart launch daemon -func RestartLaunchD() { - ncutils.RunCmd("launchctl unload /Library/LaunchDaemons/"+MAC_SERVICE_NAME+".plist", true) - time.Sleep(time.Second >> 2) - ncutils.RunCmd("launchctl load /Library/LaunchDaemons/"+MAC_SERVICE_NAME+".plist", true) -} - -// StopLaunchD - stop launch daemon -func StopLaunchD() { - ncutils.RunCmd("launchctl unload /Library/LaunchDaemons/"+MAC_SERVICE_NAME+".plist", true) -} - -// CreateMacService - Creates the mac service file for LaunchDaemons -func CreateMacService(servicename string) error { - _, err := os.Stat("/Library/LaunchDaemons") - if os.IsNotExist(err) { - os.Mkdir("/Library/LaunchDaemons", 0755) - } else if err != nil { - log.Println("couldnt find or create /Library/LaunchDaemons") - return err - } - daemonstring := MacDaemonString() - daemonbytes := []byte(daemonstring) - - if !ncutils.FileExists("/Library/LaunchDaemons/com.gravitl.netclient.plist") { - err = os.WriteFile("/Library/LaunchDaemons/com.gravitl.netclient.plist", daemonbytes, 0644) - } - return err -} - -// MacDaemonString - the file contents for the mac netclient daemon service (launchdaemon) -func MacDaemonString() string { - return ` - - - - Labelcom.gravitl.netclient - ProgramArguments - - /usr/local/bin/netclient - daemon - - StandardOutPath/var/log/com.gravitl.netclient.log - StandardErrorPath/var/log/com.gravitl.netclient.log - RunAtLoad - - KeepAlive - - AbandonProcessGroup - EnvironmentVariables - - PATH - /usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin - - - -` -} - -// MacTemplateData - struct to represent the mac service -type MacTemplateData struct { - Label string - Interval string -} diff --git a/netclient/daemon/systemd.go b/netclient/daemon/systemd.go deleted file mode 100644 index 5916c6c0..00000000 --- a/netclient/daemon/systemd.go +++ /dev/null @@ -1,138 +0,0 @@ -package daemon - -import ( - //"github.com/davecgh/go-spew/spew" - - "log" - "os" - "path/filepath" - "time" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -const EXEC_DIR = "/sbin/" - -// SetupSystemDDaemon - sets system daemon for supported machines -func SetupSystemDDaemon() error { - - if ncutils.IsWindows() { - return nil - } - binarypath, err := os.Executable() - if err != nil { - return err - } - - _, err = os.Stat("/etc/netclient/config") - if os.IsNotExist(err) { - os.MkdirAll("/etc/netclient/config", 0744) - } else if err != nil { - log.Println("couldnt find or create /etc/netclient") - return err - } - //install binary - if ncutils.FileExists(EXEC_DIR + "netclient") { - logger.Log(0, "updating netclient binary in", EXEC_DIR) - } - err = ncutils.Copy(binarypath, EXEC_DIR+"netclient") - if err != nil { - logger.Log(0, err.Error()) - return err - } - - systemservice := `[Unit] -Description=Netclient Daemon -Documentation=https://docs.netmaker.org https://k8s.netmaker.org -After=network-online.target -Wants=network-online.target - -[Service] -User=root -Type=simple -ExecStart=/sbin/netclient daemon -Restart=on-failure -RestartSec=15s - -[Install] -WantedBy=multi-user.target -` - - servicebytes := []byte(systemservice) - - if !ncutils.FileExists("/etc/systemd/system/netclient.service") { - err = os.WriteFile("/etc/systemd/system/netclient.service", servicebytes, 0644) - if err != nil { - logger.Log(0, err.Error()) - return err - } - } - _, _ = ncutils.RunCmd("systemctl enable netclient.service", true) - _, _ = ncutils.RunCmd("systemctl daemon-reload", true) - _, _ = ncutils.RunCmd("systemctl start netclient.service", true) - return nil -} - -// RestartSystemD - restarts systemd service -func RestartSystemD() { - logger.Log(1, "restarting netclient.service") - time.Sleep(time.Second) - _, _ = ncutils.RunCmd("systemctl restart netclient.service", true) -} - -// CleanupLinux - cleans up neclient configs -func CleanupLinux() { - if _, err := ncutils.RunCmd("systemctl stop netclient", false); err != nil { - logger.Log(0, "failed to stop netclient service", err.Error()) - } - RemoveSystemDServices() - if err := os.RemoveAll(ncutils.GetNetclientPath()); err != nil { - logger.Log(1, "Removing netclient configs: ", err.Error()) - } - if err := os.Remove(EXEC_DIR + "netclient"); err != nil { - logger.Log(1, "Removing netclient binary: ", err.Error()) - } -} - -// StopSystemD - tells system to stop systemd -func StopSystemD() { - ncutils.RunCmd("systemctl stop netclient.service", false) -} - -// RemoveSystemDServices - removes the systemd services on a machine -func RemoveSystemDServices() error { - //sysExec, err := exec.LookPath("systemctl") - var err error - if !ncutils.IsWindows() && isOnlyService() { - if err != nil { - logger.Log(0, err.Error()) - } - ncutils.RunCmd("systemctl disable netclient.service", false) - ncutils.RunCmd("systemctl disable netclient.timer", false) - if ncutils.FileExists("/etc/systemd/system/netclient.service") { - err = os.Remove("/etc/systemd/system/netclient.service") - if err != nil { - logger.Log(0, "Error removing /etc/systemd/system/netclient.service. Please investigate.") - } - } - if ncutils.FileExists("/etc/systemd/system/netclient.timer") { - err = os.Remove("/etc/systemd/system/netclient.timer") - if err != nil { - logger.Log(0, "Error removing /etc/systemd/system/netclient.timer. Please investigate.") - } - } - ncutils.RunCmd("systemctl daemon-reload", false) - ncutils.RunCmd("systemctl reset-failed", false) - logger.Log(0, "removed systemd remnants if any existed") - } - return nil -} - -func isOnlyService() bool { - files, err := filepath.Glob("/etc/netclient/config/netconfig-*") - if err != nil { - return false - } - return len(files) == 0 -} diff --git a/netclient/daemon/windows.go b/netclient/daemon/windows.go deleted file mode 100644 index 97fba1ef..00000000 --- a/netclient/daemon/windows.go +++ /dev/null @@ -1,106 +0,0 @@ -package daemon - -import ( - "fmt" - "log" - "os" - "strings" - "time" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// SetupWindowsDaemon - sets up the Windows daemon service -func SetupWindowsDaemon() error { - - if ncutils.FileExists(ncutils.GetNetclientPathSpecific() + "winsw.xml") { - logger.Log(0, "updating netclient service") - } - if err := writeServiceConfig(); err != nil { - return err - } - - if ncutils.FileExists(ncutils.GetNetclientPathSpecific() + "winsw.exe") { - logger.Log(0, "updating netclient binary") - } - err := ncutils.GetEmbedded() - if err != nil { - return err - } - logger.Log(0, "finished daemon setup") - //get exact formatted commands - RunWinSWCMD("install") - time.Sleep(time.Millisecond) - RunWinSWCMD("start") - - return nil -} - -// RestartWindowsDaemon - restarts windows service -func RestartWindowsDaemon() { - RunWinSWCMD("stop") - time.Sleep(time.Millisecond) - RunWinSWCMD("start") -} - -// CleanupWindows - cleans up windows files -func CleanupWindows() { - if !ncutils.FileExists(ncutils.GetNetclientPathSpecific() + "winsw.xml") { - writeServiceConfig() - } - RunWinSWCMD("stop") - RunWinSWCMD("uninstall") - os.RemoveAll(ncutils.GetNetclientPath()) - log.Println("Netclient on Windows, uninstalled") -} - -func writeServiceConfig() error { - serviceConfigPath := ncutils.GetNetclientPathSpecific() + "winsw.xml" - scriptString := fmt.Sprintf(` -netclient -Netclient -Connects Windows nodes to one or more Netmaker networks. -%v -daemon - - -`, strings.Replace(ncutils.GetNetclientPathSpecific()+"netclient.exe", `\\`, `\`, -1)) - if !ncutils.FileExists(serviceConfigPath) { - err := os.WriteFile(serviceConfigPath, []byte(scriptString), 0600) - if err != nil { - return err - } - logger.Log(0, "wrote the daemon config file to the Netclient directory") - } - return nil -} - -// RunWinSWCMD - Run a command with the winsw.exe tool (start, stop, install, uninstall) -func RunWinSWCMD(command string) { - - // check if command allowed - allowedCommands := map[string]bool{ - "start": true, - "stop": true, - "install": true, - "uninstall": true, - } - if !allowedCommands[command] { - logger.Log(0, "command "+command+" unsupported by winsw") - return - } - - // format command - dirPath := strings.Replace(ncutils.GetNetclientPathSpecific(), `\\`, `\`, -1) - winCmd := fmt.Sprintf(`"%swinsw.exe" "%s"`, dirPath, command) - logger.Log(0, "running "+command+" of Windows Netclient daemon") - - // run command and log for success/failure - out, err := ncutils.RunCmdFormatted(winCmd, true) - if err != nil { - logger.Log(0, "error with "+command+" of Windows Netclient daemon: "+err.Error()+" : "+out) - } else { - logger.Log(0, "successfully ran "+command+" of Windows Netclient daemon") - } -} diff --git a/netclient/functions/clientconfig.go b/netclient/functions/clientconfig.go deleted file mode 100644 index 67793abd..00000000 --- a/netclient/functions/clientconfig.go +++ /dev/null @@ -1,78 +0,0 @@ -package functions - -import ( - "strconv" - "strings" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/functions/upgrades" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// UpdateClientConfig - function is called on daemon start to update clientConfig if required -// Usage : set update required to true and and update logic to function -func UpdateClientConfig() { - defer upgrades.ReleaseUpgrades() - upgrades.InitializeUpgrades() - - networks, _ := ncutils.GetSystemNetworks() - if len(networks) == 0 { - return - } - logger.Log(0, "checking for netclient updates...") - for _, network := range networks { - cfg := config.ClientConfig{} - cfg.Network = network - cfg.ReadConfig() - major, minor, _ := Version(cfg.Node.Version) - if major == 0 && minor < 14 { - logger.Log(0, "schema of network", cfg.Network, "is out of date and cannot be updated\n Correct behaviour of netclient cannot be guaranteed") - continue - } - configChanged := false - for _, u := range upgrades.Upgrades { - if ncutils.StringSliceContains(u.RequiredVersions, cfg.Node.Version) { - logger.Log(0, "upgrading node", cfg.Node.Name, "on network", cfg.Node.Network, "from", cfg.Node.Version, "to", u.NewVersion) - upgrades.UpgradeFunction(u.OP)(&cfg) - cfg.Node.Version = u.NewVersion - configChanged = true - } - } - if configChanged { - //save and publish - if err := PublishNodeUpdate(&cfg); err != nil { - logger.Log(0, "error publishing node update during schema change", err.Error()) - } - if err := config.ModNodeConfig(&cfg.Node); err != nil { - logger.Log(0, "error saving local config for node,", cfg.Node.Name, ", on network,", cfg.Node.Network) - } - } - } - logger.Log(0, "finished updates") -} - -// Version - parse version string into component parts -// version string must be semantic version of form 1.2.3 or v1.2.3 -// otherwise 0, 0, 0 will be returned. -func Version(version string) (int, int, int) { - var major, minor, patch int - var errMajor, errMinor, errPatch error - parts := strings.Split(version, ".") - //ensure semantic version - if len(parts) < 3 { - return major, minor, patch - } - if strings.Contains(parts[0], "v") { - majors := strings.Split(parts[0], "v") - major, errMajor = strconv.Atoi(majors[1]) - } else { - major, errMajor = strconv.Atoi(parts[0]) - } - minor, errMinor = strconv.Atoi(parts[1]) - patch, errPatch = strconv.Atoi(parts[2]) - if errMajor != nil || errMinor != nil || errPatch != nil { - return 0, 0, 0 - } - return major, minor, patch -} diff --git a/netclient/functions/common.go b/netclient/functions/common.go deleted file mode 100644 index 0a32a2cb..00000000 --- a/netclient/functions/common.go +++ /dev/null @@ -1,431 +0,0 @@ -package functions - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "io" - "log" - "net" - "net/http" - "os" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/daemon" - "github.com/gravitl/netmaker/netclient/local" - "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/netclient/wireguard" - "github.com/gravitl/netmaker/nm-proxy/manager" - "golang.zx2c4.com/wireguard/wgctrl" -) - -// LINUX_APP_DATA_PATH - linux path -const LINUX_APP_DATA_PATH = "/etc/netmaker" - -// HTTP_TIMEOUT - timeout in seconds for http requests -const HTTP_TIMEOUT = 30 - -// HTTPClient - http client to be reused by all -var HTTPClient http.Client - -// SetHTTPClient -sets http client with sane default -func SetHTTPClient() { - HTTPClient = http.Client{ - Timeout: HTTP_TIMEOUT * time.Second, - } -} - -// ListPorts - lists ports of WireGuard devices -func ListPorts() error { - wgclient, err := wgctrl.New() - if err != nil { - return err - } - defer wgclient.Close() - devices, err := wgclient.Devices() - if err != nil { - return err - } - fmt.Println("Here are your ports:") - for _, i := range devices { - fmt.Println(i.ListenPort) - } - return err -} - -func getPrivateAddr() (string, error) { - - var local string - conn, err := net.Dial("udp", "8.8.8.8:80") - if err == nil { - defer conn.Close() - - localAddr := conn.LocalAddr().(*net.UDPAddr) - localIP := localAddr.IP - local = localIP.String() - } - if local == "" { - local, err = getPrivateAddrBackup() - } - - if local == "" { - err = errors.New("could not find local ip") - } - if net.ParseIP(local).To16() != nil { - local = "[" + local + "]" - } - - return local, err -} - -func getPrivateAddrBackup() (string, error) { - ifaces, err := net.Interfaces() - if err != nil { - return "", err - } - var local string - found := false - for _, i := range ifaces { - if i.Flags&net.FlagUp == 0 { - continue // interface down - } - if i.Flags&net.FlagLoopback != 0 { - continue // loopback interface - } - addrs, err := i.Addrs() - if err != nil { - return "", err - } - for _, addr := range addrs { - var ip net.IP - switch v := addr.(type) { - case *net.IPNet: - if !found { - ip = v.IP - local = ip.String() - found = true - } - case *net.IPAddr: - if !found { - ip = v.IP - local = ip.String() - found = true - } - } - } - } - if !found { - err := errors.New("local ip address not found") - return "", err - } - return local, err -} - -func getInterfaces() (*[]models.Iface, error) { - ifaces, err := net.Interfaces() - if err != nil { - return nil, err - } - var data []models.Iface - var link models.Iface - for _, iface := range ifaces { - if iface.Flags&net.FlagUp == 0 { - continue // interface down - } - if iface.Flags&net.FlagLoopback != 0 { - continue // loopback interface - } - addrs, err := iface.Addrs() - if err != nil { - return nil, err - } - for _, addr := range addrs { - link.Name = iface.Name - _, cidr, err := net.ParseCIDR(addr.String()) - if err != nil { - continue - } - link.Address = *cidr - data = append(data, link) - } - } - return &data, nil -} - -// GetNode - gets node locally -func GetNode(network string) models.LegacyNode { - - modcfg, err := config.ReadConfig(network) - if err != nil { - log.Fatalf("Error: %v", err) - } - - return modcfg.Node -} - -// Uninstall - uninstalls networks from client -func Uninstall() error { - networks, err := ncutils.GetSystemNetworks() - if err != nil { - logger.Log(1, "unable to retrieve networks: ", err.Error()) - logger.Log(1, "continuing uninstall without leaving networks") - } else { - for _, network := range networks { - err = LeaveNetwork(network) - if err != nil { - logger.Log(1, "encounter issue leaving network", network, ":", err.Error()) - } - } - } - err = nil - - // clean up OS specific stuff - if ncutils.IsWindows() { - daemon.CleanupWindows() - } else if ncutils.IsMac() { - daemon.CleanupMac() - } else if ncutils.IsLinux() { - daemon.CleanupLinux() - } else if ncutils.IsFreeBSD() { - daemon.CleanupFreebsd() - } else if !ncutils.IsKernel() { - logger.Log(1, "manual cleanup required") - } - - return err -} - -// LeaveNetwork - client exits a network -func LeaveNetwork(network string) error { - cfg, err := config.ReadConfig(network) - if err != nil { - return err - } - logger.Log(2, "deleting node from server") - if err := deleteNodeFromServer(cfg); err != nil { - logger.Log(0, "error deleting node from server", err.Error()) - } - logger.Log(2, "deleting wireguard interface") - if err := deleteLocalNetwork(cfg); err != nil { - logger.Log(0, "error deleting wireguard interface", err.Error()) - } - logger.Log(2, "deleting configuration files") - if err := WipeLocal(cfg); err != nil { - logger.Log(0, "error deleting local network files", err.Error()) - } - logger.Log(2, "removing dns entries") - if err := removeHostDNS(cfg.Node.Interface, ncutils.IsWindows()); err != nil { - logger.Log(0, "failed to delete dns entries for", cfg.Node.Interface, err.Error()) - } - ProxyMgmChan <- &manager.ManagerAction{ - Action: manager.DeleteInterface, - Payload: manager.ManagerPayload{ - InterfaceName: cfg.Node.Interface, - }, - } - logger.Log(2, "restarting daemon") - return daemon.Restart() -} - -func deleteNodeFromServer(cfg *config.ClientConfig) error { - node := cfg.Node - if node.IsServer == "yes" { - return errors.New("attempt to delete server node ... not permitted") - } - token, err := Authenticate(cfg) - if err != nil { - return fmt.Errorf("unable to authenticate %w", err) - } - url := "https://" + cfg.Server.API + "/api/nodes/" + cfg.Network + "/" + cfg.Node.ID - response, err := API("", http.MethodDelete, url, token) - if err != nil { - return fmt.Errorf("error deleting node on server: %w", err) - } - if response.StatusCode != http.StatusOK { - bodybytes, _ := io.ReadAll(response.Body) - defer response.Body.Close() - return fmt.Errorf("error deleting node from network %s on server %s %s", cfg.Network, response.Status, string(bodybytes)) - } - return nil -} - -func deleteLocalNetwork(cfg *config.ClientConfig) error { - wgClient, wgErr := wgctrl.New() - if wgErr != nil { - return wgErr - } - removeIface := cfg.Node.Interface - queryAddr := cfg.Node.PrimaryAddress() - if ncutils.IsMac() { - var macIface string - macIface, wgErr = local.GetMacIface(queryAddr) - if wgErr == nil && removeIface != "" { - removeIface = macIface - } - } - dev, devErr := wgClient.Device(removeIface) - if devErr != nil { - return fmt.Errorf("error flushing routes %w", devErr) - } - local.FlushPeerRoutes(removeIface, queryAddr, dev.Peers[:]) - _, cidr, cidrErr := net.ParseCIDR(cfg.NetworkSettings.AddressRange) - if cidrErr != nil { - return fmt.Errorf("error flushing routes %w", cidrErr) - } - local.RemoveCIDRRoute(removeIface, queryAddr, cidr) - return nil -} - -// DeleteInterface - delete an interface of a network -func DeleteInterface(ifacename string, postdown string) error { - return wireguard.RemoveConf(ifacename, true) -} - -// WipeLocal - wipes local instance -func WipeLocal(cfg *config.ClientConfig) error { - if err := wireguard.RemoveConf(cfg.Node.Interface, true); err == nil { - logger.Log(1, "network:", cfg.Node.Network, "removed WireGuard interface: ", cfg.Node.Interface) - } else if strings.Contains(err.Error(), "does not exist") { - err = nil - } - dir := ncutils.GetNetclientPathSpecific() - fail := false - files, err := filepath.Glob(dir + "*" + cfg.Node.Network) - if err != nil { - logger.Log(0, "no matching files", err.Error()) - fail = true - } - for _, file := range files { - if err := os.Remove(file); err != nil { - logger.Log(0, "failed to delete file", file, err.Error()) - fail = true - } - } - - if cfg.Node.Interface != "" { - if ncutils.FileExists(dir + cfg.Node.Interface + ".conf") { - if err := os.Remove(dir + cfg.Node.Interface + ".conf"); err != nil { - logger.Log(0, err.Error()) - fail = true - } - } - } - if fail { - return errors.New("not all files were deleted") - } - return nil -} - -// GetNetmakerPath - gets netmaker path locally -func GetNetmakerPath() string { - return LINUX_APP_DATA_PATH -} - -// API function to interact with netmaker api endpoints. response from endpoint is returned -func API(data any, method, url, authorization string) (*http.Response, error) { - var request *http.Request - var err error - if data != "" { - payload, err := json.Marshal(data) - if err != nil { - return nil, fmt.Errorf("error encoding data %w", err) - } - request, err = http.NewRequest(method, url, bytes.NewBuffer(payload)) - if err != nil { - return nil, fmt.Errorf("error creating http request %w", err) - } - request.Header.Set("Content-Type", "application/json") - } else { - request, err = http.NewRequest(method, url, nil) - if err != nil { - return nil, fmt.Errorf("error creating http request %w", err) - } - } - if authorization != "" { - request.Header.Set("authorization", "Bearer "+authorization) - } - request.Header.Set("requestfrom", "node") - return HTTPClient.Do(request) -} - -// Authenticate authenticates with api to permit subsequent interactions with the api -func Authenticate(cfg *config.ClientConfig) (string, error) { - - pass, err := os.ReadFile(ncutils.GetNetclientPathSpecific() + "secret-" + cfg.Network) - if err != nil { - return "", fmt.Errorf("could not read secrets file %w", err) - } - data := models.AuthParams{ - MacAddress: cfg.Node.MacAddress, - ID: cfg.Node.ID, - Password: string(pass), - } - url := "https://" + cfg.Server.API + "/api/nodes/adm/" + cfg.Network + "/authenticate" - response, err := API(data, http.MethodPost, url, "") - if err != nil { - return "", err - } - defer response.Body.Close() - if response.StatusCode != http.StatusOK { - bodybytes, _ := io.ReadAll(response.Body) - return "", fmt.Errorf("failed to authenticate %s %s", response.Status, string(bodybytes)) - } - resp := models.SuccessResponse{} - if err := json.NewDecoder(response.Body).Decode(&resp); err != nil { - return "", fmt.Errorf("error decoding respone %w", err) - } - tokenData := resp.Response.(map[string]interface{}) - token := tokenData["AuthToken"] - return token.(string), nil -} - -// RegisterWithServer calls the register endpoint with privatekey and commonname - api returns ca and client certificate -func SetServerInfo(cfg *config.ClientConfig) error { - cfg, err := config.ReadConfig(cfg.Network) - if err != nil { - return err - } - url := "https://" + cfg.Server.API + "/api/server/getserverinfo" - logger.Log(1, "server at "+url) - - token, err := Authenticate(cfg) - if err != nil { - return err - } - response, err := API("", http.MethodGet, url, token) - if err != nil { - return err - } - if response.StatusCode != http.StatusOK { - return errors.New(response.Status) - } - var resp models.ServerConfig - if err := json.NewDecoder(response.Body).Decode(&resp); err != nil { - return errors.New("unmarshal cert error " + err.Error()) - } - - // set broker information on register - cfg.Server.Server = resp.Server - cfg.Server.MQPort = resp.MQPort - - if err = config.ModServerConfig(&cfg.Server, cfg.Node.Network); err != nil { - logger.Log(0, "error overwriting config with broker information: "+err.Error()) - } - - return nil -} - -func informPortChange(node *models.LegacyNode) { - if node.ListenPort == 0 { - logger.Log(0, "network:", node.Network, "UDP hole punching enabled for node", node.Name) - } else { - logger.Log(0, "network:", node.Network, "node", node.Name, "is using port", strconv.Itoa(int(node.ListenPort))) - } -} diff --git a/netclient/functions/connection.go b/netclient/functions/connection.go deleted file mode 100644 index f151a923..00000000 --- a/netclient/functions/connection.go +++ /dev/null @@ -1,60 +0,0 @@ -package functions - -import ( - "fmt" - - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/daemon" - "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/netclient/wireguard" -) - -// Connect - will attempt to connect a node on given network -func Connect(network string) error { - cfg, err := config.ReadConfig(network) - if err != nil { - return err - } - if cfg.Node.Connected == "yes" { - return fmt.Errorf("node already connected") - } - cfg.Node.Connected = "yes" - filePath := ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf" - - if err = wireguard.ApplyConf(&cfg.Node, cfg.Node.Interface, filePath); err != nil { - return err - } - if err := setupMQTTSingleton(cfg); err != nil { - return err - } - if err := PublishNodeUpdate(cfg); err != nil { - return err - } - daemon.Restart() - return nil -} - -// Disconnect - attempts to disconnect a node on given network -func Disconnect(network string) error { - cfg, err := config.ReadConfig(network) - if err != nil { - return err - } - if cfg.Node.Connected == "no" { - return fmt.Errorf("node already disconnected") - } - cfg.Node.Connected = "no" - filePath := ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf" - - if err = wireguard.ApplyConf(&cfg.Node, cfg.Node.Interface, filePath); err != nil { - return err - } - if err := setupMQTTSingleton(cfg); err != nil { - return err - } - if err := PublishNodeUpdate(cfg); err != nil { - return err - } - daemon.Restart() - return nil -} diff --git a/netclient/functions/daemon.go b/netclient/functions/daemon.go deleted file mode 100644 index 4e30fef5..00000000 --- a/netclient/functions/daemon.go +++ /dev/null @@ -1,428 +0,0 @@ -package functions - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net" - "net/http" - "os" - "os/signal" - "strings" - "sync" - "syscall" - "time" - - mqtt "github.com/eclipse/paho.mqtt.golang" - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/mq" - "github.com/gravitl/netmaker/netclient/auth" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/global_settings" - "github.com/gravitl/netmaker/netclient/local" - "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/netclient/wireguard" - - nmproxy "github.com/gravitl/netmaker/nm-proxy" - "github.com/gravitl/netmaker/nm-proxy/manager" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" -) - -var ProxyMgmChan = make(chan *manager.ManagerAction, 100) -var messageCache = new(sync.Map) -var serverSet map[string]bool - -var mqclient mqtt.Client - -const lastNodeUpdate = "lnu" -const lastPeerUpdate = "lpu" - -type cachedMessage struct { - Message string - LastSeen time.Time -} - -// Daemon runs netclient daemon from command line -func Daemon() error { - logger.Log(0, "netclient daemon started -- version:", ncutils.Version) - UpdateClientConfig() - if err := ncutils.SavePID(); err != nil { - return err - } - // reference required to eliminate unused statticcheck - serverSet = make(map[string]bool) - serverSet["dummy"] = false - // set ipforwarding on startup - err := local.SetIPForwarding() - if err != nil { - logger.Log(0, err.Error()) - } - - // == add waitgroup and cancel for checkin routine == - wg := sync.WaitGroup{} - quit := make(chan os.Signal, 1) - reset := make(chan os.Signal, 1) - signal.Notify(quit, syscall.SIGTERM, os.Interrupt) - signal.Notify(reset, syscall.SIGHUP) - cancel := startGoRoutines(&wg) - for { - select { - case <-quit: - cancel() - logger.Log(0, "shutting down netclient daemon") - wg.Wait() - if mqclient != nil { - mqclient.Disconnect(250) - } - logger.Log(0, "shutdown complete") - return nil - case <-reset: - logger.Log(0, "received reset") - cancel() - wg.Wait() - if mqclient != nil { - mqclient.Disconnect(250) - } - logger.Log(0, "restarting daemon") - cancel = startGoRoutines(&wg) - } - } -} - -func startGoRoutines(wg *sync.WaitGroup) context.CancelFunc { - ctx, cancel := context.WithCancel(context.Background()) - serverSet := make(map[string]bool) - networks, _ := ncutils.GetSystemNetworks() - for _, network := range networks { - logger.Log(3, "initializing network", network) - cfg := config.ClientConfig{} - cfg.Network = network - cfg.ReadConfig() - if cfg.Node.Connected == "yes" { - if err := wireguard.ApplyConf(&cfg.Node, cfg.Node.Interface, ncutils.GetNetclientPathSpecific()+cfg.Node.Interface+".conf"); err != nil { - logger.Log(0, "failed to start ", cfg.Node.Interface, "wg interface", err.Error()) - } - if cfg.PublicIPService != "" { - global_settings.PublicIPServices[network] = cfg.PublicIPService - } - } - - server := cfg.Server.Server - if !serverSet[server] { - // == subscribe to all nodes for each on machine == - serverSet[server] = true - logger.Log(1, "started daemon for server ", server) - local.SetNetmakerDomainRoute(cfg.Server.API) - wg.Add(1) - go messageQueue(ctx, wg, &cfg) - } - } - wg.Add(1) - go Checkin(ctx, wg) - - if len(networks) != 0 { - cfg := config.ClientConfig{} - cfg.Network = networks[0] - cfg.ReadConfig() - apiHost, _, err := net.SplitHostPort(cfg.Server.API) - if err == nil { - wg.Add(1) - go nmproxy.Start(ctx, ProxyMgmChan, apiHost) - logger.Log(0, "Proxy Shutting down....") - - } - - } - - go func(networks []string) { - - // for _, network := range networks { - // logger.Log(0, "Collecting interface and peers info to configure proxy...") - // cfg := config.ClientConfig{} - // cfg.Network = network - // cfg.ReadConfig() - // node, err := GetNodeInfo(&cfg) - // if err != nil { - // log.Println("Failed to get node info: ", err) - // continue - // } - // ProxyMgmChan <- &manager.ManagerAction{ - // Action: manager.AddInterface, - // Payload: manager.ManagerPayload{ - // InterfaceName: node.Node.Interface, - // Peers: node.Peers, - // }, - // } - - // } - - }(networks) - return cancel -} -func GetNodeInfo(cfg *config.ClientConfig) (models.NodeGet, error) { - var nodeGET models.NodeGet - token, err := Authenticate(cfg) - if err != nil { - return nodeGET, err - } - url := fmt.Sprintf("https://%s/api/nodes/%s/%s", cfg.Server.API, cfg.Network, cfg.Node.ID) - response, err := API("", http.MethodGet, url, token) - if err != nil { - return nodeGET, err - } - if response.StatusCode != http.StatusOK { - bytes, err := io.ReadAll(response.Body) - if err != nil { - fmt.Println(err) - } - return nodeGET, (fmt.Errorf("%s %w", string(bytes), err)) - } - defer response.Body.Close() - if err := json.NewDecoder(response.Body).Decode(&nodeGET); err != nil { - return nodeGET, fmt.Errorf("error decoding node %w", err) - } - return nodeGET, nil -} - -// UpdateKeys -- updates private key and returns new publickey -func UpdateKeys(nodeCfg *config.ClientConfig, client mqtt.Client) error { - logger.Log(0, "interface:", nodeCfg.Node.Interface, "received message to update wireguard keys for network ", nodeCfg.Network) - key, err := wgtypes.GeneratePrivateKey() - if err != nil { - logger.Log(0, "network:", nodeCfg.Node.Network, "error generating privatekey ", err.Error()) - return err - } - file := ncutils.GetNetclientPathSpecific() + nodeCfg.Node.Interface + ".conf" - if err := wireguard.UpdatePrivateKey(file, key.String()); err != nil { - logger.Log(0, "network:", nodeCfg.Node.Network, "error updating wireguard key ", err.Error()) - return err - } - if storeErr := wireguard.StorePrivKey(key.String(), nodeCfg.Network); storeErr != nil { - logger.Log(0, "network:", nodeCfg.Network, "failed to save private key", storeErr.Error()) - return storeErr - } - - nodeCfg.Node.PublicKey = key.PublicKey().String() - PublishNodeUpdate(nodeCfg) - return nil -} - -// == Private == - -// sets MQ client subscriptions for a specific node config -// should be called for each node belonging to a given server -func setSubscriptions(client mqtt.Client, nodeCfg *config.ClientConfig) { - if token := client.Subscribe(fmt.Sprintf("update/%s/%s", nodeCfg.Node.Network, nodeCfg.Node.ID), 0, mqtt.MessageHandler(NodeUpdate)); token.WaitTimeout(mq.MQ_TIMEOUT*time.Second) && token.Error() != nil { - if token.Error() == nil { - logger.Log(0, "network:", nodeCfg.Node.Network, "connection timeout") - } else { - logger.Log(0, "network:", nodeCfg.Node.Network, token.Error().Error()) - } - return - } - if token := client.Subscribe(fmt.Sprintf("proxy/%s/%s", nodeCfg.Node.Network, nodeCfg.Node.ID), 0, mqtt.MessageHandler(ProxyUpdate)); token.WaitTimeout(mq.MQ_TIMEOUT*time.Second) && token.Error() != nil { - if token.Error() == nil { - logger.Log(0, "###### network:", nodeCfg.Node.Network, "connection timeout") - } else { - logger.Log(0, "###### network:", nodeCfg.Node.Network, token.Error().Error()) - } - return - } - logger.Log(3, fmt.Sprintf("subscribed to node updates for node %s update/%s/%s", nodeCfg.Node.Name, nodeCfg.Node.Network, nodeCfg.Node.ID)) - if token := client.Subscribe(fmt.Sprintf("peers/%s/%s", nodeCfg.Node.Network, nodeCfg.Node.ID), 0, mqtt.MessageHandler(UpdatePeers)); token.Wait() && token.Error() != nil { - logger.Log(0, "network", nodeCfg.Node.Network, token.Error().Error()) - return - } - logger.Log(3, fmt.Sprintf("subscribed to peer updates for node %s peers/%s/%s", nodeCfg.Node.Name, nodeCfg.Node.Network, nodeCfg.Node.ID)) -} - -// on a delete usually, pass in the nodecfg to unsubscribe client broker communications -// for the node in nodeCfg -func unsubscribeNode(client mqtt.Client, nodeCfg *config.ClientConfig) { - client.Unsubscribe(fmt.Sprintf("update/%s/%s", nodeCfg.Node.Network, nodeCfg.Node.ID)) - var ok = true - if token := client.Unsubscribe(fmt.Sprintf("update/%s/%s", nodeCfg.Node.Network, nodeCfg.Node.ID)); token.WaitTimeout(mq.MQ_TIMEOUT*time.Second) && token.Error() != nil { - if token.Error() == nil { - logger.Log(1, "network:", nodeCfg.Node.Network, "unable to unsubscribe from updates for node ", nodeCfg.Node.Name, "\n", "connection timeout") - } else { - logger.Log(1, "network:", nodeCfg.Node.Network, "unable to unsubscribe from updates for node ", nodeCfg.Node.Name, "\n", token.Error().Error()) - } - ok = false - } - if token := client.Unsubscribe(fmt.Sprintf("peers/%s/%s", nodeCfg.Node.Network, nodeCfg.Node.ID)); token.WaitTimeout(mq.MQ_TIMEOUT*time.Second) && token.Error() != nil { - if token.Error() == nil { - logger.Log(1, "network:", nodeCfg.Node.Network, "unable to unsubscribe from peer updates for node", nodeCfg.Node.Name, "\n", "connection timeout") - } else { - logger.Log(1, "network:", nodeCfg.Node.Network, "unable to unsubscribe from peer updates for node", nodeCfg.Node.Name, "\n", token.Error().Error()) - } - ok = false - } - if ok { - logger.Log(1, "network:", nodeCfg.Node.Network, "successfully unsubscribed node ", nodeCfg.Node.ID, " : ", nodeCfg.Node.Name) - } -} - -// sets up Message Queue and subsribes/publishes updates to/from server -// the client should subscribe to ALL nodes that exist on server locally -func messageQueue(ctx context.Context, wg *sync.WaitGroup, cfg *config.ClientConfig) { - defer wg.Done() - logger.Log(0, "network:", cfg.Node.Network, "netclient message queue started for server:", cfg.Server.Server) - err := setupMQTT(cfg) - if err != nil { - logger.Log(0, "unable to connect to broker", cfg.Server.Server, err.Error()) - return - } - //defer mqclient.Disconnect(250) - <-ctx.Done() - logger.Log(0, "shutting down message queue for server", cfg.Server.Server) -} - -// func setMQTTSingenton creates a connection to broker for single use (ie to publish a message) -// only to be called from cli (eg. connect/disconnect, join, leave) and not from daemon --- -func setupMQTTSingleton(cfg *config.ClientConfig) error { - opts := mqtt.NewClientOptions() - server := cfg.Server.Server - port := cfg.Server.MQPort - pass, err := os.ReadFile(ncutils.GetNetclientPathSpecific() + "secret-" + cfg.Network) - if err != nil { - return fmt.Errorf("could not read secrets file %w", err) - } - opts.AddBroker("wss://" + server + ":" + port) - opts.SetUsername(cfg.Node.ID) - opts.SetPassword(string(pass)) - mqclient = mqtt.NewClient(opts) - var connecterr error - opts.SetClientID(ncutils.MakeRandomString(23)) - if token := mqclient.Connect(); !token.WaitTimeout(30*time.Second) || token.Error() != nil { - logger.Log(0, "unable to connect to broker, retrying ...") - if token.Error() == nil { - connecterr = errors.New("connect timeout") - } else { - connecterr = token.Error() - } - } - return connecterr -} - -// setupMQTT creates a connection to broker and returns client -// this function is primarily used to create a connection to publish to the broker -func setupMQTT(cfg *config.ClientConfig) error { - opts := mqtt.NewClientOptions() - server := cfg.Server.Server - port := cfg.Server.MQPort - pass, err := os.ReadFile(ncutils.GetNetclientPathSpecific() + "secret-" + cfg.Network) - if err != nil { - return fmt.Errorf("could not read secrets file %w", err) - } - opts.AddBroker(fmt.Sprintf("wss://%s:%s", server, port)) - opts.SetUsername(cfg.Node.ID) - opts.SetPassword(string(pass)) - opts.SetClientID(ncutils.MakeRandomString(23)) - opts.SetDefaultPublishHandler(All) - opts.SetAutoReconnect(true) - opts.SetConnectRetry(true) - opts.SetConnectRetryInterval(time.Second << 2) - opts.SetKeepAlive(time.Minute >> 1) - opts.SetWriteTimeout(time.Minute) - - opts.SetOnConnectHandler(func(client mqtt.Client) { - networks, err := ncutils.GetSystemNetworks() - if err != nil { - logger.Log(0, "error retriving networks", err.Error()) - } - for _, network := range networks { - var currNodeCfg config.ClientConfig - currNodeCfg.Network = network - currNodeCfg.ReadConfig() - setSubscriptions(client, &currNodeCfg) - } - }) - opts.SetOrderMatters(true) - opts.SetResumeSubs(true) - opts.SetConnectionLostHandler(func(c mqtt.Client, e error) { - logger.Log(0, "network:", cfg.Node.Network, "detected broker connection lost for", cfg.Server.Server) - }) - mqclient = mqtt.NewClient(opts) - var connecterr error - for count := 0; count < 3; count++ { - connecterr = nil - if token := mqclient.Connect(); !token.WaitTimeout(30*time.Second) || token.Error() != nil { - logger.Log(0, "unable to connect to broker, retrying ...") - if token.Error() == nil { - connecterr = errors.New("connect timeout") - } else { - connecterr = token.Error() - } - if err := checkBroker(cfg.Server.Server, cfg.Server.MQPort); err != nil { - logger.Log(0, "could not connect to broker", cfg.Server.Server, err.Error()) - } - } - } - if connecterr != nil { - logger.Log(0, "failed to establish connection to broker: ", connecterr.Error()) - return connecterr - } - - return nil -} - -// publishes a message to server to update peers on this peer's behalf -func publishSignal(nodeCfg *config.ClientConfig, signal byte) error { - if err := publish(nodeCfg, fmt.Sprintf("signal/%s", nodeCfg.Node.ID), []byte{signal}, 1); err != nil { - return err - } - return nil -} - -func parseNetworkFromTopic(topic string) string { - return strings.Split(topic, "/")[1] -} - -// should only ever use node client configs -func decryptMsg(nodeCfg *config.ClientConfig, msg []byte) ([]byte, error) { - if len(msg) <= 24 { // make sure message is of appropriate length - return nil, fmt.Errorf("recieved invalid message from broker %v", msg) - } - - // setup the keys - diskKey, keyErr := auth.RetrieveTrafficKey(nodeCfg.Node.Network) - if keyErr != nil { - return nil, keyErr - } - - serverPubKey, err := ncutils.ConvertBytesToKey(nodeCfg.Node.TrafficKeys.Server) - if err != nil { - return nil, err - } - - return ncutils.DeChunk(msg, serverPubKey, diskKey) -} - -// == Message Caches == - -func insert(network, which, cache string) { - var newMessage = cachedMessage{ - Message: cache, - LastSeen: time.Now(), - } - messageCache.Store(fmt.Sprintf("%s%s", network, which), newMessage) -} - -func read(network, which string) string { - val, isok := messageCache.Load(fmt.Sprintf("%s%s", network, which)) - if isok { - var readMessage = val.(cachedMessage) // fetch current cached message - if readMessage.LastSeen.IsZero() { - return "" - } - if time.Now().After(readMessage.LastSeen.Add(time.Hour * 24)) { // check if message has been there over a minute - messageCache.Delete(fmt.Sprintf("%s%s", network, which)) // remove old message if expired - return "" - } - return readMessage.Message // return current message if not expired - } - return "" -} diff --git a/netclient/functions/install.go b/netclient/functions/install.go deleted file mode 100644 index 1564d450..00000000 --- a/netclient/functions/install.go +++ /dev/null @@ -1,19 +0,0 @@ -package functions - -import ( - "time" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/daemon" -) - -//Install - installs binary/daemon -func Install() error { - daemon.Stop() - if err := daemon.InstallDaemon(); err != nil { - logger.Log(0, "error installing daemon", err.Error()) - return err - } - time.Sleep(time.Second * 5) - return daemon.Restart() -} diff --git a/netclient/functions/join.go b/netclient/functions/join.go deleted file mode 100644 index 8215e255..00000000 --- a/netclient/functions/join.go +++ /dev/null @@ -1,412 +0,0 @@ -package functions - -import ( - "crypto/rand" - "encoding/json" - "errors" - "fmt" - "io" - "log" - "net/http" - "os" - "os/signal" - "runtime" - "strings" - "syscall" - - "github.com/gorilla/websocket" - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/logic" - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/models/promodels" - "github.com/gravitl/netmaker/netclient/auth" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/daemon" - "github.com/gravitl/netmaker/netclient/global_settings" - "github.com/gravitl/netmaker/netclient/local" - "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/netclient/wireguard" - "golang.org/x/crypto/nacl/box" - "golang.org/x/term" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" -) - -// JoinViaSso - Handles the Single Sign-On flow on the end point VPN client side -// Contacts the server provided by the user (and thus specified in cfg.SsoServer) -// get the URL to authenticate with a provider and shows the user the URL. -// Then waits for user to authenticate with the URL. -// Upon user successful auth flow finished - server should return access token to the requested network -// Otherwise the error message is sent which can be displayed to the user -func JoinViaSSo(cfg *config.ClientConfig, privateKey string) error { - - // User must tell us which network he is joining - if cfg.Node.Network == "" { - return errors.New("no network provided") - } - - // Prepare a channel for interrupt - // Channel to listen for interrupt signal to terminate gracefully - interrupt := make(chan os.Signal, 1) - // Notify the interrupt channel for SIGINT - signal.Notify(interrupt, os.Interrupt) - - // Web Socket is used, construct the URL accordingly ... - socketUrl := fmt.Sprintf("wss://%s/api/oauth/node-handler", cfg.SsoServer) - // Dial the netmaker server controller - conn, _, err := websocket.DefaultDialer.Dial(socketUrl, nil) - if err != nil { - logger.Log(0, fmt.Sprintf("error connecting to %s : %s", cfg.Server.API, err.Error())) - return err - } - // Don't forget to close when finished - defer conn.Close() - // Find and set node MacAddress - if cfg.Node.MacAddress == "" { - macs, err := ncutils.GetMacAddr() - if err != nil { - //if macaddress can't be found set to random string - cfg.Node.MacAddress = ncutils.MakeRandomString(18) - } else { - cfg.Node.MacAddress = macs[0] - } - } - - var loginMsg promodels.LoginMsg - loginMsg.Mac = cfg.Node.MacAddress - loginMsg.Network = cfg.Node.Network - if global_settings.User != "" { - fmt.Printf("Continuing with user, %s.\nPlease input password:\n", global_settings.User) - pass, err := term.ReadPassword(int(syscall.Stdin)) - if err != nil || string(pass) == "" { - logger.FatalLog("no password provided, exiting") - } - loginMsg.User = global_settings.User - loginMsg.Password = string(pass) - fmt.Println("attempting login...") - } - - msgTx, err := json.Marshal(loginMsg) - if err != nil { - logger.Log(0, fmt.Sprintf("failed to marshal message %+v", loginMsg)) - return err - } - err = conn.WriteMessage(websocket.TextMessage, []byte(msgTx)) - if err != nil { - logger.FatalLog("Error during writing to websocket:", err.Error()) - return err - } - - // if user provided, server will handle authentication - if loginMsg.User == "" { - // We are going to get instructions on how to authenticate - // Wait to receive something from server - _, msg, err := conn.ReadMessage() - if err != nil { - return err - } - // Print message from the netmaker controller to the user - fmt.Printf("Please visit:\n %s \n to authenticate", string(msg)) - } - - // Now the user is authenticating and we need to block until received - // An answer from the server. - // Server waits ~5 min - If takes too long timeout will be triggered by the server - done := make(chan struct{}) - defer close(done) - // Following code will run in a separate go routine - // it reads a message from the server which either contains 'AccessToken:' string or not - // if not - then it contains an Error to display. - // if yes - then AccessToken is to be used to proceed joining the network - go func() { - for { - msgType, msg, err := conn.ReadMessage() - if err != nil { - if msgType < 0 { - logger.Log(1, "received close message from server") - done <- struct{}{} - return - } - // Error reading a message from the server - if !strings.Contains(err.Error(), "normal") { - logger.Log(0, "read:", err.Error()) - } - return - } - - if msgType == websocket.CloseMessage { - logger.Log(1, "received close message from server") - done <- struct{}{} - return - } - // Get the access token from the response - if strings.Contains(string(msg), "AccessToken: ") { - // Access was granted - rxToken := strings.TrimPrefix(string(msg), "AccessToken: ") - accesstoken, err := config.ParseAccessToken(rxToken) - if err != nil { - logger.Log(0, fmt.Sprintf("failed to parse received access token %s,err=%s\n", accesstoken, err.Error())) - return - } - - cfg.Network = accesstoken.ClientConfig.Network - cfg.Node.Network = accesstoken.ClientConfig.Network - cfg.AccessKey = accesstoken.ClientConfig.Key - cfg.Node.LocalRange = accesstoken.ClientConfig.LocalRange - //cfg.Server.Server = accesstoken.ServerConfig.Server - cfg.Server.API = accesstoken.APIConnString - } else { - // Access was not granted. Display a message from the server - logger.Log(0, "Message from server:", string(msg)) - cfg.AccessKey = "" - return - } - } - }() - - for { - select { - case <-done: - logger.Log(1, "finished") - return nil - case <-interrupt: - logger.Log(0, "interrupt received, closing connection") - // Cleanly close the connection by sending a close message and then - // waiting (with timeout) for the server to close the connection. - err := conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) - if err != nil { - logger.Log(0, "write close:", err.Error()) - return err - } - return nil - } - } -} - -// JoinNetwork - helps a client join a network -func JoinNetwork(cfg *config.ClientConfig, privateKey string) error { - if cfg.Node.Network == "" { - return errors.New("no network provided") - } - - var err error - if local.HasNetwork(cfg.Network) { - err := errors.New("ALREADY_INSTALLED. Netclient appears to already be installed for " + cfg.Network + ". To re-install, please remove by executing 'sudo netclient leave -n " + cfg.Network + "'. Then re-run the install command.") - return err - } - - err = config.Write(cfg, cfg.Network) - if err != nil { - return err - } - if cfg.Node.Password == "" { - cfg.Node.Password = logic.GenPassWord() - } - //check if ListenPort was set on command line - if cfg.Node.ListenPort != 0 { - cfg.Node.UDPHolePunch = "no" - } - var trafficPubKey, trafficPrivKey, errT = box.GenerateKey(rand.Reader) // generate traffic keys - if errT != nil { - return errT - } - - // == handle keys == - if err = auth.StoreSecret(cfg.Node.Password, cfg.Node.Network); err != nil { - return err - } - - if err = auth.StoreTrafficKey(trafficPrivKey, cfg.Node.Network); err != nil { - return err - } - - trafficPubKeyBytes, err := ncutils.ConvertKeyToBytes(trafficPubKey) - if err != nil { - return err - } else if trafficPubKeyBytes == nil { - return fmt.Errorf("traffic key is nil") - } - - cfg.Node.TrafficKeys.Mine = trafficPubKeyBytes - cfg.Node.TrafficKeys.Server = nil - // == end handle keys == - - if cfg.Node.LocalAddress == "" { - intIP, err := getPrivateAddr() - if err == nil { - cfg.Node.LocalAddress = intIP - } else { - logger.Log(1, "network:", cfg.Network, "error retrieving private address: ", err.Error()) - } - } - if len(cfg.Node.Interfaces) == 0 { - ip, err := getInterfaces() - if err != nil { - logger.Log(0, "failed to retrive local interfaces", err.Error()) - } else { - cfg.Node.Interfaces = *ip - } - } - - // set endpoint if blank. set to local if local net, retrieve from function if not - if cfg.Node.Endpoint == "" { - if cfg.Node.IsLocal == "yes" && cfg.Node.LocalAddress != "" { - cfg.Node.Endpoint = cfg.Node.LocalAddress - } else { - cfg.Node.Endpoint, err = ncutils.GetPublicIP(cfg.Server.API) - } - if err != nil || cfg.Node.Endpoint == "" { - logger.Log(0, "network:", cfg.Network, "error setting cfg.Node.Endpoint.") - return err - } - } - // Generate and set public/private WireGuard Keys - if privateKey == "" { - wgPrivatekey, err := wgtypes.GeneratePrivateKey() - if err != nil { - log.Fatal(err) - } - privateKey = wgPrivatekey.String() - cfg.Node.PublicKey = wgPrivatekey.PublicKey().String() - } - // Find and set node MacAddress - if cfg.Node.MacAddress == "" { - macs, err := ncutils.GetMacAddr() - if err != nil || len(macs) == 0 { - //if macaddress can't be found set to random string - cfg.Node.MacAddress = ncutils.MakeRandomString(18) - } else { - cfg.Node.MacAddress = macs[0] - } - } - - if ncutils.IsFreeBSD() { - cfg.Node.UDPHolePunch = "no" - cfg.Node.FirewallInUse = models.FIREWALL_IPTABLES // nftables not supported by FreeBSD - } - - if cfg.Node.FirewallInUse == "" { - if ncutils.IsNFTablesPresent() { - cfg.Node.FirewallInUse = models.FIREWALL_NFTABLES - } else if ncutils.IsIPTablesPresent() { - cfg.Node.FirewallInUse = models.FIREWALL_IPTABLES - } else { - cfg.Node.FirewallInUse = models.FIREWALL_NONE - } - } - - // make sure name is appropriate, if not, give blank name - cfg.Node.Name = formatName(cfg.Node) - cfg.Node.OS = runtime.GOOS - cfg.Node.Version = ncutils.Version - cfg.Node.AccessKey = cfg.AccessKey - //not sure why this is needed ... setnode defaults should take care of this on server - cfg.Node.IPForwarding = "yes" - logger.Log(0, "joining "+cfg.Network+" at "+cfg.Server.API) - url := "https://" + cfg.Server.API + "/api/nodes/" + cfg.Network - response, err := API(cfg.Node, http.MethodPost, url, cfg.AccessKey) - if err != nil { - return fmt.Errorf("error creating node %w", err) - } - defer response.Body.Close() - if response.StatusCode != http.StatusOK { - bodybytes, _ := io.ReadAll(response.Body) - return fmt.Errorf("error creating node %s %s", response.Status, string(bodybytes)) - } - var nodeGET models.NodeGet - if err := json.NewDecoder(response.Body).Decode(&nodeGET); err != nil { - //not sure the next line will work as response.Body probably needs to be reset before it can be read again - bodybytes, _ := io.ReadAll(response.Body) - return fmt.Errorf("error decoding node from server %w %s", err, string(bodybytes)) - } - node := nodeGET.Node - if nodeGET.Peers == nil { - nodeGET.Peers = []wgtypes.PeerConfig{} - } - - // safety check. If returned node from server is local, but not currently configured as local, set to local addr - if cfg.Node.IsLocal != "yes" && node.IsLocal == "yes" && node.LocalRange != "" { - node.LocalAddress, err = ncutils.GetLocalIP(node.LocalRange) - if err != nil { - return err - } - node.Endpoint = node.LocalAddress - } - if ncutils.IsFreeBSD() { - node.UDPHolePunch = "no" - cfg.Node.IsStatic = "yes" - } - cfg.Server = nodeGET.ServerConfig - - err = wireguard.StorePrivKey(privateKey, cfg.Network) - if err != nil { - return err - } - if node.IsPending == "yes" { - logger.Log(0, "network:", cfg.Network, "node is marked as PENDING.") - logger.Log(0, "network:", cfg.Network, "awaiting approval from Admin before configuring WireGuard.") - if cfg.Daemon != "off" { - return daemon.InstallDaemon() - } - } - logger.Log(1, "network:", cfg.Node.Network, "node created on remote server...updating configs") - err = ncutils.ModPort(&node) - if err != nil { - return err - } - informPortChange(&node) - - err = config.ModNodeConfig(&node) - if err != nil { - return err - } - err = config.ModServerConfig(&cfg.Server, node.Network) - if err != nil { - return err - } - // attempt to make backup - if err = config.SaveBackup(node.Network); err != nil { - logger.Log(0, "network:", node.Network, "failed to make backup, node will not auto restore if config is corrupted") - } - - local.SetNetmakerDomainRoute(cfg.Server.API) - cfg.Node = node - logger.Log(0, "starting wireguard") - err = wireguard.InitWireguard(&node, privateKey, nodeGET.Peers[:]) - if err != nil { - return err - } - if cfg.Server.Server == "" { - return errors.New("did not receive broker address from registration") - } - if cfg.Daemon == "install" || ncutils.IsFreeBSD() { - err = daemon.InstallDaemon() - if err != nil { - return err - } - } - - if err := daemon.Restart(); err != nil { - logger.Log(3, "daemon restart failed:", err.Error()) - if err := daemon.Start(); err != nil { - return err - } - } - return nil -} - -// format name appropriately. Set to blank on failure -func formatName(node models.LegacyNode) string { - // Logic to properly format name - if !node.NameInNodeCharSet() { - node.Name = ncutils.DNSFormatString(node.Name) - } - if len(node.Name) > models.MAX_NAME_LENGTH { - node.Name = ncutils.ShortenString(node.Name, models.MAX_NAME_LENGTH) - } - if !node.NameInNodeCharSet() || len(node.Name) > models.MAX_NAME_LENGTH { - logger.Log(1, "network:", node.Network, "could not properly format name: "+node.Name) - logger.Log(1, "network:", node.Network, "setting name to blank") - node.Name = "" - } - return node.Name -} diff --git a/netclient/functions/list.go b/netclient/functions/list.go deleted file mode 100644 index ee493b7f..00000000 --- a/netclient/functions/list.go +++ /dev/null @@ -1,147 +0,0 @@ -package functions - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/ncutils" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" -) - -// Peer - the peer struct for list -type Peer struct { - Name string `json:"name,omitempty"` - Interface string `json:"interface,omitempty"` - PrivateIPv4 string `json:"private_ipv4,omitempty"` - PrivateIPv6 string `json:"private_ipv6,omitempty"` - PublicKey string `json:"public_key,omitempty"` - PublicEndpoint string `json:"public_endpoint,omitempty"` - Addresses []address `json:"addresses,omitempty"` -} - -// Network - the local node network representation for list command -type Network struct { - Name string `json:"name"` - ID string `json:"node_id"` - CurrentNode Peer `json:"current_node"` - Peers []Peer `json:"peers"` -} - -type address struct { - CIDR string `json:"cidr,omitempty"` - IP string `json:"ip,omitempty"` -} - -// List - lists the current peers for the local node with name and node ID -func List(network string) ([]Network, error) { - nets := []Network{} - var err error - var networks []string - if network == "all" { - networks, err = ncutils.GetSystemNetworks() - if err != nil { - return nil, err - } - } else { - networks = append(networks, network) - } - - for _, network := range networks { - net, err := getNetwork(network) - if err != nil { - logger.Log(1, network+": Could not retrieve network configuration.") - return nil, err - } - peers, err := getPeers(network) - if err == nil && len(peers) > 0 { - net.Peers = peers - } - nets = append(nets, net) - } - - jsoncfg, _ := json.Marshal(struct { - Networks []Network `json:"networks"` - }{nets}) - fmt.Println(string(jsoncfg)) - - return nets, nil -} - -func getNetwork(network string) (Network, error) { - cfg, err := config.ReadConfig(network) - if err != nil { - return Network{}, fmt.Errorf("reading configuration for network %v: %w", network, err) - } - //peers, err := getPeers(network) - peers := []Peer{} - if err != nil { - return Network{}, fmt.Errorf("listing peers for network %v: %w", network, err) - } - return Network{ - Name: network, - ID: cfg.Node.ID, - Peers: peers, - CurrentNode: Peer{ - Name: cfg.Node.Name, - Interface: cfg.Node.Interface, - PrivateIPv4: cfg.Node.Address, - PrivateIPv6: cfg.Node.Address6, - PublicEndpoint: cfg.Node.Endpoint, - }, - }, nil -} - -func getPeers(network string) ([]Peer, error) { - cfg, err := config.ReadConfig(network) - if err != nil { - return []Peer{}, err - } - token, err := Authenticate(cfg) - if err != nil { - return nil, err - } - url := "https://" + cfg.Server.API + "/api/nodes/" + cfg.Network + "/" + cfg.Node.ID - response, err := API("", http.MethodGet, url, token) - if err != nil { - return nil, err - } - if response.StatusCode != http.StatusOK { - bytes, err := io.ReadAll(response.Body) - if err != nil { - fmt.Println(err) - } - return nil, (fmt.Errorf("%s %w", string(bytes), err)) - } - defer response.Body.Close() - var nodeGET models.NodeGet - if err := json.NewDecoder(response.Body).Decode(&nodeGET); err != nil { - return nil, fmt.Errorf("error decoding node %w", err) - } - if nodeGET.Peers == nil { - nodeGET.Peers = []wgtypes.PeerConfig{} - } - - peers := []Peer{} - for _, peer := range nodeGET.Peers { - var addresses = []address{} - for j := range peer.AllowedIPs { - newAddress := address{ - CIDR: peer.AllowedIPs[j].String(), - IP: peer.AllowedIPs[j].IP.String(), - } - addresses = append(addresses, newAddress) - } - peers = append(peers, Peer{ - PublicKey: peer.PublicKey.String(), - PublicEndpoint: peer.Endpoint.String(), - Addresses: addresses, - }) - } - - return peers, nil -} diff --git a/netclient/functions/localport.go b/netclient/functions/localport.go deleted file mode 100644 index a628d380..00000000 --- a/netclient/functions/localport.go +++ /dev/null @@ -1,63 +0,0 @@ -//go:build !freebsd -// +build !freebsd - -package functions - -import ( - "strconv" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/local" - "github.com/gravitl/netmaker/netclient/ncutils" - "golang.zx2c4.com/wireguard/wgctrl" -) - -// GetLocalListenPort - Gets the port running on the local interface -func GetLocalListenPort(ifacename string) (int32, error) { - client, err := wgctrl.New() - if err != nil { - logger.Log(0, "failed to start wgctrl") - return 0, err - } - defer client.Close() - device, err := client.Device(ifacename) - if err != nil { - logger.Log(0, "failed to parse interface", ifacename) - return 0, err - } - return int32(device.ListenPort), nil -} - -// UpdateLocalListenPort - check local port, if different, mod config and publish -func UpdateLocalListenPort(nodeCfg *config.ClientConfig) error { - var err error - ifacename := getRealIface(nodeCfg.Node.Interface, nodeCfg.Node.Address) - localPort, err := GetLocalListenPort(ifacename) - if err != nil { - logger.Log(1, "network:", nodeCfg.Node.Network, "error encountered checking local listen port: ", ifacename, err.Error()) - } else if nodeCfg.Node.LocalListenPort != localPort && localPort != 0 { - logger.Log(1, "network:", nodeCfg.Node.Network, "local port has changed from ", strconv.Itoa(int(nodeCfg.Node.LocalListenPort)), " to ", strconv.Itoa(int(localPort))) - nodeCfg.Node.LocalListenPort = localPort - err = config.ModNodeConfig(&nodeCfg.Node) - if err != nil { - return err - } - if err := PublishNodeUpdate(nodeCfg); err != nil { - logger.Log(0, "could not publish local port change", err.Error()) - } - } - return err -} - -func getRealIface(ifacename string, address string) string { - var deviceiface = ifacename - var err error - if ncutils.IsMac() { // if node is Mac (Darwin) get the tunnel name first - deviceiface, err = local.GetMacIface(address) - if err != nil || deviceiface == "" { - deviceiface = ifacename - } - } - return deviceiface -} diff --git a/netclient/functions/localport_freebsd.go b/netclient/functions/localport_freebsd.go deleted file mode 100644 index c69149fc..00000000 --- a/netclient/functions/localport_freebsd.go +++ /dev/null @@ -1,50 +0,0 @@ -//go:build freebsd -// +build freebsd - -package functions - -import ( - "errors" - "strconv" - "strings" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// GetLocalListenPort - Gets the port running on the local interface -func GetLocalListenPort(ifacename string) (int32, error) { - portstring, err := ncutils.RunCmd("wg show "+ifacename+" listen-port", false) - if err != nil { - return 0, err - } - portstring = strings.TrimSuffix(portstring, "\n") - i, err := strconv.ParseInt(portstring, 10, 32) - if err != nil { - return 0, err - } else if i == 0 { - return 0, errors.New("parsed port is unset or invalid") - } - return int32(i), nil -} - -// UpdateLocalListenPort - check local port, if different, mod config and publish -func UpdateLocalListenPort(nodeCfg *config.ClientConfig) error { - var err error - localPort, err := GetLocalListenPort(nodeCfg.Node.Interface) - if err != nil { - logger.Log(1, "network:", nodeCfg.Node.Network, "error encountered checking local listen port for interface : ", nodeCfg.Node.Interface, err.Error()) - } else if nodeCfg.Node.LocalListenPort != localPort && localPort != 0 { - logger.Log(1, "network:", nodeCfg.Node.Network, "local port has changed from ", strconv.Itoa(int(nodeCfg.Node.LocalListenPort)), " to ", strconv.Itoa(int(localPort))) - nodeCfg.Node.LocalListenPort = localPort - err = config.ModNodeConfig(&nodeCfg.Node) - if err != nil { - return err - } - if err := PublishNodeUpdate(nodeCfg); err != nil { - logger.Log(0, "network:", nodeCfg.Node.Network, "could not publish local port change") - } - } - return err -} diff --git a/netclient/functions/mqhandlers.go b/netclient/functions/mqhandlers.go deleted file mode 100644 index d18e7582..00000000 --- a/netclient/functions/mqhandlers.go +++ /dev/null @@ -1,369 +0,0 @@ -package functions - -import ( - "encoding/json" - "errors" - "fmt" - "net" - "os" - "runtime" - "strings" - "time" - - mqtt "github.com/eclipse/paho.mqtt.golang" - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/netclient/wireguard" - "github.com/gravitl/netmaker/nm-proxy/manager" - "github.com/guumaster/hostctl/pkg/file" - "github.com/guumaster/hostctl/pkg/parser" - "github.com/guumaster/hostctl/pkg/types" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" -) - -// All -- mqtt message hander for all ('#') topics -var All mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { - logger.Log(0, "default message handler -- received message but not handling") - logger.Log(0, "topic: "+string(msg.Topic())) - //logger.Log(0, "Message: " + string(msg.Payload())) -} - -func ProxyUpdate(client mqtt.Client, msg mqtt.Message) { - var nodeCfg config.ClientConfig - var proxyUpdate manager.ManagerAction - var network = parseNetworkFromTopic(msg.Topic()) - nodeCfg.Network = network - nodeCfg.ReadConfig() - logger.Log(0, "---------> Recieved a proxy update") - data, dataErr := decryptMsg(&nodeCfg, msg.Payload()) - if dataErr != nil { - return - } - err := json.Unmarshal([]byte(data), &proxyUpdate) - if err != nil { - logger.Log(0, "error unmarshalling proxy update data"+err.Error()) - return - } - - ProxyMgmChan <- &proxyUpdate -} - -// NodeUpdate -- mqtt message handler for /update/ topic -func NodeUpdate(client mqtt.Client, msg mqtt.Message) { - var newNode models.LegacyNode - var nodeCfg config.ClientConfig - var network = parseNetworkFromTopic(msg.Topic()) - nodeCfg.Network = network - nodeCfg.ReadConfig() - - data, dataErr := decryptMsg(&nodeCfg, msg.Payload()) - if dataErr != nil { - return - } - err := json.Unmarshal([]byte(data), &newNode) - if err != nil { - logger.Log(0, "error unmarshalling node update data"+err.Error()) - return - } - if newNode.Proxy { - if newNode.Proxy != nodeCfg.Node.Proxy { - if err := config.Write(&nodeCfg, nodeCfg.Network); err != nil { - logger.Log(0, nodeCfg.Node.Network, "error updating node configuration: ", err.Error()) - } - } - logger.Log(0, "Node is attached with proxy,ignore this node update...") - return - } - - // see if cache hit, if so skip - var currentMessage = read(newNode.Network, lastNodeUpdate) - if currentMessage == string(data) { - return - } - insert(newNode.Network, lastNodeUpdate, string(data)) // store new message in cache - logger.Log(0, "network:", newNode.Network, "received message to update node "+newNode.Name) - - // ensure that OS never changes - newNode.OS = runtime.GOOS - // check if interface needs to delta - ifaceDelta := ncutils.IfaceDelta(&nodeCfg.Node, &newNode) - shouldDNSChange := nodeCfg.Node.DNSOn != newNode.DNSOn - hubChange := nodeCfg.Node.IsHub != newNode.IsHub - keepaliveChange := nodeCfg.Node.PersistentKeepalive != newNode.PersistentKeepalive - - nodeCfg.Node = newNode - switch newNode.Action { - case models.NODE_DELETE: - logger.Log(0, "network:", nodeCfg.Node.Network, " received delete request for %s", nodeCfg.Node.Name) - unsubscribeNode(client, &nodeCfg) - if err = LeaveNetwork(nodeCfg.Node.Network); err != nil { - if !strings.Contains("rpc error", err.Error()) { - logger.Log(0, "failed to leave, please check that local files for network", nodeCfg.Node.Network, "were removed") - return - } - } - logger.Log(0, nodeCfg.Node.Name, "was removed from network", nodeCfg.Node.Network) - return - case models.NODE_UPDATE_KEY: - // == get the current key for node == - oldPrivateKey, retErr := wireguard.RetrievePrivKey(nodeCfg.Network) - if retErr != nil { - break - } - if err := UpdateKeys(&nodeCfg, client); err != nil { - logger.Log(0, "err updating wireguard keys, reusing last key\n", err.Error()) - if key, parseErr := wgtypes.ParseKey(oldPrivateKey); parseErr == nil { - wireguard.StorePrivKey(key.String(), nodeCfg.Network) - nodeCfg.Node.PublicKey = key.PublicKey().String() - } - } - ifaceDelta = true - case models.NODE_FORCE_UPDATE: - ifaceDelta = true - case models.NODE_NOOP: - default: - } - // Save new config - nodeCfg.Node.Action = models.NODE_NOOP - if err := config.Write(&nodeCfg, nodeCfg.Network); err != nil { - logger.Log(0, nodeCfg.Node.Network, "error updating node configuration: ", err.Error()) - } - nameserver := nodeCfg.Server.CoreDNSAddr - privateKey, err := wireguard.RetrievePrivKey(newNode.Network) - if err != nil { - logger.Log(0, "error reading PrivateKey "+err.Error()) - return - } - file := ncutils.GetNetclientPathSpecific() + nodeCfg.Node.Interface + ".conf" - - if newNode.ListenPort != nodeCfg.Node.LocalListenPort { - if err := wireguard.RemoveConf(newNode.Interface, false); err != nil { - logger.Log(0, "error remove interface", newNode.Interface, err.Error()) - } - err = ncutils.ModPort(&newNode) - if err != nil { - logger.Log(0, "network:", nodeCfg.Node.Network, "error modifying node port on", newNode.Name, "-", err.Error()) - return - } - ifaceDelta = true - informPortChange(&newNode) - } - if err := wireguard.UpdateWgInterface(file, privateKey, nameserver, newNode); err != nil { - logger.Log(0, "error updating wireguard config "+err.Error()) - return - } - if keepaliveChange { - wireguard.UpdateKeepAlive(file, newNode.PersistentKeepalive) - } - logger.Log(0, "applying WG conf to "+file) - err = wireguard.ApplyConf(&nodeCfg.Node, nodeCfg.Node.Interface, file) - if err != nil { - logger.Log(0, "error restarting wg after node update -", err.Error()) - return - } - - time.Sleep(time.Second) - // if newNode.DNSOn == "yes" { - // for _, server := range newNode.NetworkSettings.DefaultServerAddrs { - // if server.IsLeader { - // go local.SetDNSWithRetry(newNode, server.Address) - // break - // } - // } - // } - - if ifaceDelta { // if a change caused an ifacedelta we need to notify the server to update the peers - doneErr := publishSignal(&nodeCfg, ncutils.DONE) - if doneErr != nil { - logger.Log(0, "network:", nodeCfg.Node.Network, "could not notify server to update peers after interface change") - } else { - logger.Log(0, "network:", nodeCfg.Node.Network, "signalled finished interface update to server") - } - } else if hubChange { - doneErr := publishSignal(&nodeCfg, ncutils.DONE) - if doneErr != nil { - logger.Log(0, "network:", nodeCfg.Node.Network, "could not notify server to update peers after hub change") - } else { - logger.Log(0, "network:", nodeCfg.Node.Network, "signalled finished hub update to server") - } - } - //deal with DNS - if newNode.DNSOn != "yes" && shouldDNSChange && nodeCfg.Node.Interface != "" { - logger.Log(0, "network:", nodeCfg.Node.Network, "settng DNS off") - if err := removeHostDNS(nodeCfg.Node.Interface, ncutils.IsWindows()); err != nil { - logger.Log(0, "network:", nodeCfg.Node.Network, "error removing netmaker profile from /etc/hosts "+err.Error()) - } - // _, err := ncutils.RunCmd("/usr/bin/resolvectl revert "+nodeCfg.Node.Interface, true) - // if err != nil { - // logger.Log(0, "error applying dns" + err.Error()) - // } - } - _ = UpdateLocalListenPort(&nodeCfg) -} - -// UpdatePeers -- mqtt message handler for peers// topic -func UpdatePeers(client mqtt.Client, msg mqtt.Message) { - var peerUpdate models.PeerUpdate - var network = parseNetworkFromTopic(msg.Topic()) - var cfg = config.ClientConfig{} - cfg.Network = network - cfg.ReadConfig() - - data, dataErr := decryptMsg(&cfg, msg.Payload()) - if dataErr != nil { - return - } - err := json.Unmarshal([]byte(data), &peerUpdate) - if err != nil { - logger.Log(0, "error unmarshalling peer data") - return - } - // see if cached hit, if so skip - var currentMessage = read(peerUpdate.Network, lastPeerUpdate) - if currentMessage == string(data) { - return - } - insert(peerUpdate.Network, lastPeerUpdate, string(data)) - // check version - if peerUpdate.ServerVersion != ncutils.Version { - logger.Log(0, "server/client version mismatch server: ", peerUpdate.ServerVersion, " client: ", ncutils.Version) - } - if peerUpdate.ServerVersion != cfg.Server.Version { - logger.Log(1, "updating server version") - cfg.Server.Version = peerUpdate.ServerVersion - config.Write(&cfg, cfg.Network) - } - - // if cfg.Node.Proxy { - // ProxyMgmChan <- &peerUpdate.ProxyUpdate - // return - // } - file := ncutils.GetNetclientPathSpecific() + cfg.Node.Interface + ".conf" - internetGateway, err := wireguard.UpdateWgPeers(file, peerUpdate.Peers) - if err != nil { - logger.Log(0, "error updating wireguard peers"+err.Error()) - return - } - //check if internet gateway has changed - oldGateway, err := net.ResolveUDPAddr("udp", cfg.Node.InternetGateway) - - // note: may want to remove second part (oldGateway == &net.UDPAddr{}) - // since it's a pointer, will never be true - if err != nil || (oldGateway == &net.UDPAddr{}) { - oldGateway = nil - } - if (internetGateway == nil && oldGateway != nil) || (internetGateway != nil && internetGateway.String() != oldGateway.String()) { - cfg.Node.InternetGateway = internetGateway.String() - if err := config.ModNodeConfig(&cfg.Node); err != nil { - logger.Log(0, "failed to save internet gateway", err.Error()) - } - if err := wireguard.ApplyConf(&cfg.Node, cfg.Node.Interface, file); err != nil { - logger.Log(0, "error applying internet gateway", err.Error()) - } - UpdateLocalListenPort(&cfg) - return - } - // queryAddr := cfg.Node.PrimaryAddress() - - //err = wireguard.SyncWGQuickConf(cfg.Node.Interface, file) - // var iface = cfg.Node.Interface - // if ncutils.IsMac() { - // iface, err = local.GetMacIface(queryAddr) - // if err != nil { - // logger.Log(0, "error retrieving mac iface: "+err.Error()) - // return - // } - // } - // err = wireguard.SetPeers(iface, &cfg.Node, peerUpdate.Peers) - // if err != nil { - // logger.Log(0, "error syncing wg after peer update: "+err.Error()) - // return - // } - - logger.Log(0, "network:", cfg.Node.Network, "received peer update for node "+cfg.Node.Name+" "+cfg.Node.Network) - if cfg.Node.DNSOn == "yes" { - if err := setHostDNS(peerUpdate.DNS, cfg.Node.Interface, ncutils.IsWindows()); err != nil { - logger.Log(0, "network:", cfg.Node.Network, "error updating /etc/hosts "+err.Error()) - return - } - } else { - if err := removeHostDNS(cfg.Node.Interface, ncutils.IsWindows()); err != nil { - logger.Log(0, "network:", cfg.Node.Network, "error removing profile from /etc/hosts "+err.Error()) - return - } - } - - _ = UpdateLocalListenPort(&cfg) -} - -func setHostDNS(dns, iface string, windows bool) error { - etchosts := "/etc/hosts" - temp := os.TempDir() - lockfile := temp + "/netclient-lock" - if windows { - etchosts = "c:\\windows\\system32\\drivers\\etc\\hosts" - lockfile = temp + "\\netclient-lock" - } - if _, err := os.Stat(lockfile); !errors.Is(err, os.ErrNotExist) { - return errors.New("/etc/hosts file is locked .... aborting") - } - lock, err := os.Create(lockfile) - if err != nil { - return fmt.Errorf("could not create lock file %w", err) - } - lock.Close() - defer os.Remove(lockfile) - dnsdata := strings.NewReader(dns) - profile, err := parser.ParseProfile(dnsdata) - if err != nil { - return err - } - hosts, err := file.NewFile(etchosts) - if err != nil { - return err - } - profile.Name = strings.ToLower(iface) - profile.Status = types.Enabled - if err := hosts.ReplaceProfile(profile); err != nil { - return err - } - if err := hosts.Flush(); err != nil { - return err - } - return nil -} - -func removeHostDNS(iface string, windows bool) error { - etchosts := "/etc/hosts" - temp := os.TempDir() - lockfile := temp + "/netclient-lock" - if windows { - etchosts = "c:\\windows\\system32\\drivers\\etc\\hosts" - lockfile = temp + "\\netclient-lock" - } - if _, err := os.Stat(lockfile); !errors.Is(err, os.ErrNotExist) { - return errors.New("/etc/hosts file is locked .... aborting") - } - lock, err := os.Create(lockfile) - if err != nil { - return fmt.Errorf("could not create lock file %w", err) - } - lock.Close() - defer os.Remove(lockfile) - hosts, err := file.NewFile(etchosts) - if err != nil { - return err - } - if err := hosts.RemoveProfile(strings.ToLower(iface)); err != nil { - if err == types.ErrUnknownProfile { - return nil - } - return err - } - if err := hosts.Flush(); err != nil { - return err - } - return nil -} diff --git a/netclient/functions/mqpublish.go b/netclient/functions/mqpublish.go deleted file mode 100644 index fa7a574b..00000000 --- a/netclient/functions/mqpublish.go +++ /dev/null @@ -1,304 +0,0 @@ -package functions - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net" - "net/http" - "strconv" - "sync" - "time" - - "github.com/cloverstd/tcping/ping" - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/logic/metrics" - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/auth" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -var metricsCache = new(sync.Map) - -// Checkin -- go routine that checks for public or local ip changes, publishes changes -// -// if there are no updates, simply "pings" the server as a checkin -func Checkin(ctx context.Context, wg *sync.WaitGroup) { - logger.Log(2, "starting checkin goroutine") - defer wg.Done() - ticker := time.NewTicker(time.Minute * ncutils.CheckInInterval) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - logger.Log(0, "checkin routine closed") - return - case <-ticker.C: - if mqclient != nil && mqclient.IsConnected() { - checkin() - } else { - logger.Log(0, "MQ client is not connected, skipping checkin...") - } - - } - } -} - -func checkin() { - networks, _ := ncutils.GetSystemNetworks() - logger.Log(3, "checkin with server(s) for all networks") - for _, network := range networks { - var nodeCfg config.ClientConfig - nodeCfg.Network = network - nodeCfg.ReadConfig() - // check for nftables present if on Linux - if ncutils.IsLinux() { - if ncutils.IsNFTablesPresent() { - nodeCfg.Node.FirewallInUse = models.FIREWALL_NFTABLES - } else { - nodeCfg.Node.FirewallInUse = models.FIREWALL_IPTABLES - } - } else { - // defaults to iptables for now, may need another default for non-Linux OSes - nodeCfg.Node.FirewallInUse = models.FIREWALL_IPTABLES - } - if nodeCfg.Node.Connected == "yes" { - if nodeCfg.Node.IsStatic != "yes" { - extIP, err := ncutils.GetPublicIP(nodeCfg.Server.API) - if err != nil { - logger.Log(1, "error encountered checking public ip addresses: ", err.Error()) - } - if nodeCfg.Node.Endpoint != extIP && extIP != "" { - logger.Log(1, "network:", nodeCfg.Node.Network, "endpoint has changed from ", nodeCfg.Node.Endpoint, " to ", extIP) - nodeCfg.Node.Endpoint = extIP - if err := PublishNodeUpdate(&nodeCfg); err != nil { - logger.Log(0, "network:", nodeCfg.Node.Network, "could not publish endpoint change") - } - } - intIP, err := getPrivateAddr() - if err != nil { - logger.Log(1, "network:", nodeCfg.Node.Network, "error encountered checking private ip addresses: ", err.Error()) - } - if nodeCfg.Node.LocalAddress != intIP && intIP != "" { - logger.Log(1, "network:", nodeCfg.Node.Network, "local Address has changed from ", nodeCfg.Node.LocalAddress, " to ", intIP) - nodeCfg.Node.LocalAddress = intIP - if err := PublishNodeUpdate(&nodeCfg); err != nil { - logger.Log(0, "Network: ", nodeCfg.Node.Network, " could not publish local address change") - } - } - _ = UpdateLocalListenPort(&nodeCfg) - - } else if nodeCfg.Node.IsLocal == "yes" && nodeCfg.Node.LocalRange != "" { - localIP, err := ncutils.GetLocalIP(nodeCfg.Node.LocalRange) - if err != nil { - logger.Log(1, "network:", nodeCfg.Node.Network, "error encountered checking local ip addresses: ", err.Error()) - } - if nodeCfg.Node.Endpoint != localIP && localIP != "" { - logger.Log(1, "network:", nodeCfg.Node.Network, "endpoint has changed from "+nodeCfg.Node.Endpoint+" to ", localIP) - nodeCfg.Node.Endpoint = localIP - if err := PublishNodeUpdate(&nodeCfg); err != nil { - logger.Log(0, "network:", nodeCfg.Node.Network, "could not publish localip change") - } - } - } - } - //check version - if nodeCfg.Node.Version != ncutils.Version { - nodeCfg.Node.Version = ncutils.Version - config.Write(&nodeCfg, nodeCfg.Network) - } - Hello(&nodeCfg) - if nodeCfg.Server.Is_EE && nodeCfg.Node.Connected == "yes" { - logger.Log(0, "collecting metrics for node", nodeCfg.Node.Name) - publishMetrics(&nodeCfg) - } - } -} - -// PublishNodeUpdates -- saves node and pushes changes to broker -func PublishNodeUpdate(nodeCfg *config.ClientConfig) error { - if err := config.Write(nodeCfg, nodeCfg.Network); err != nil { - return err - } - data, err := json.Marshal(nodeCfg.Node) - if err != nil { - return err - } - if err = publish(nodeCfg, fmt.Sprintf("update/%s", nodeCfg.Node.ID), data, 1); err != nil { - return err - } - - logger.Log(0, "network:", nodeCfg.Node.Network, "sent a node update to server for node", nodeCfg.Node.Name, ", ", nodeCfg.Node.ID) - return nil -} - -// Hello -- ping the broker to let server know node it's alive and well -func Hello(nodeCfg *config.ClientConfig) { - var checkin models.NodeCheckin - checkin.Version = ncutils.Version - checkin.Connected = nodeCfg.Node.Connected - ip, err := getInterfaces() - if err != nil { - logger.Log(0, "failed to retrieve local interfaces", err.Error()) - } else { - nodeCfg.Node.Interfaces = *ip - config.Write(nodeCfg, nodeCfg.Network) - } - checkin.Ifaces = nodeCfg.Node.Interfaces - data, err := json.Marshal(checkin) - if err != nil { - logger.Log(0, "unable to marshal checkin data", err.Error()) - return - } - if err := publish(nodeCfg, fmt.Sprintf("ping/%s", nodeCfg.Node.ID), data, 0); err != nil { - logger.Log(0, fmt.Sprintf("Network: %s error publishing ping, %v", nodeCfg.Node.Network, err)) - logger.Log(0, "running pull on "+nodeCfg.Node.Network+" to reconnect") - _, err := Pull(nodeCfg.Node.Network, true) - if err != nil { - logger.Log(0, "could not run pull on "+nodeCfg.Node.Network+", error: "+err.Error()) - } - } else { - logger.Log(3, "checkin for", nodeCfg.Network, "complete") - } -} - -// publishMetrics - publishes the metrics of a given nodecfg -func publishMetrics(nodeCfg *config.ClientConfig) { - token, err := Authenticate(nodeCfg) - if err != nil { - logger.Log(1, "failed to authenticate when publishing metrics", err.Error()) - return - } - url := fmt.Sprintf("https://%s/api/nodes/%s/%s", nodeCfg.Server.API, nodeCfg.Network, nodeCfg.Node.ID) - response, err := API("", http.MethodGet, url, token) - if err != nil { - logger.Log(1, "failed to read from server during metrics publish", err.Error()) - return - } - if response.StatusCode != http.StatusOK { - bytes, err := io.ReadAll(response.Body) - if err != nil { - fmt.Println(err) - } - logger.Log(0, fmt.Sprintf("%s %s", string(bytes), err.Error())) - return - } - defer response.Body.Close() - var nodeGET models.NodeGet - if err := json.NewDecoder(response.Body).Decode(&nodeGET); err != nil { - logger.Log(0, "failed to decode node when running metrics update", err.Error()) - return - } - - metrics, err := metrics.Collect(nodeCfg.Node.Interface, nodeGET.Node.Network, nodeGET.Node.Proxy, nodeGET.PeerIDs) - if err != nil { - logger.Log(0, "failed metric collection for node", nodeCfg.Node.Name, err.Error()) - } - metrics.Network = nodeCfg.Node.Network - metrics.NodeName = nodeCfg.Node.Name - metrics.NodeID = nodeCfg.Node.ID - metrics.IsServer = "no" - data, err := json.Marshal(metrics) - if err != nil { - logger.Log(0, "something went wrong when marshalling metrics data for node", nodeCfg.Node.Name, err.Error()) - } - - if err = publish(nodeCfg, fmt.Sprintf("metrics/%s", nodeCfg.Node.ID), data, 1); err != nil { - logger.Log(0, "error occurred during publishing of metrics on node", nodeCfg.Node.Name, err.Error()) - logger.Log(0, "aggregating metrics locally until broker connection re-established") - val, ok := metricsCache.Load(nodeCfg.Node.ID) - if !ok { - metricsCache.Store(nodeCfg.Node.ID, data) - } else { - var oldMetrics models.Metrics - err = json.Unmarshal(val.([]byte), &oldMetrics) - if err == nil { - for k := range oldMetrics.Connectivity { - currentMetric := metrics.Connectivity[k] - if currentMetric.Latency == 0 { - currentMetric.Latency = oldMetrics.Connectivity[k].Latency - } - currentMetric.Uptime += oldMetrics.Connectivity[k].Uptime - currentMetric.TotalTime += oldMetrics.Connectivity[k].TotalTime - metrics.Connectivity[k] = currentMetric - } - newData, err := json.Marshal(metrics) - if err == nil { - metricsCache.Store(nodeCfg.Node.ID, newData) - } - } - } - } else { - metricsCache.Delete(nodeCfg.Node.ID) - logger.Log(0, "published metrics for node", nodeCfg.Node.Name) - } -} - -// node cfg is required in order to fetch the traffic keys of that node for encryption -func publish(nodeCfg *config.ClientConfig, dest string, msg []byte, qos byte) error { - // setup the keys - trafficPrivKey, err := auth.RetrieveTrafficKey(nodeCfg.Node.Network) - if err != nil { - return err - } - serverPubKey, err := ncutils.ConvertBytesToKey(nodeCfg.Node.TrafficKeys.Server) - if err != nil { - return err - } - - encrypted, err := ncutils.Chunk(msg, serverPubKey, trafficPrivKey) - if err != nil { - return err - } - if mqclient == nil { - return errors.New("unable to publish ... no mqclient") - } - if token := mqclient.Publish(dest, qos, false, encrypted); !token.WaitTimeout(30*time.Second) || token.Error() != nil { - logger.Log(0, "could not connect to broker at "+nodeCfg.Server.Server+":"+nodeCfg.Server.MQPort) - var err error - if token.Error() == nil { - err = errors.New("connection timeout") - } else { - err = token.Error() - } - if err != nil { - return err - } - } - return nil -} - -func checkBroker(broker string, port string) error { - if broker == "" { - return errors.New("error: broker address is blank") - } - if port == "" { - return errors.New("error: broker port is blank") - } - _, err := net.LookupIP(broker) - if err != nil { - return errors.New("nslookup failed for broker ... check dns records") - } - pinger := ping.NewTCPing() - intPort, err := strconv.Atoi(port) - if err != nil { - logger.Log(1, "error converting port to int: "+err.Error()) - } - pinger.SetTarget(&ping.Target{ - Protocol: ping.TCP, - Host: broker, - Port: intPort, - Counter: 3, - Interval: 1 * time.Second, - Timeout: 2 * time.Second, - }) - pingerDone := pinger.Start() - <-pingerDone - if pinger.Result().SuccessCounter == 0 { - return errors.New("unable to connect to broker port ... check netmaker server and firewalls") - } - return nil -} diff --git a/netclient/functions/pull.go b/netclient/functions/pull.go deleted file mode 100644 index 8a344f8a..00000000 --- a/netclient/functions/pull.go +++ /dev/null @@ -1,109 +0,0 @@ -package functions - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "os" - "runtime" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/local" - "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/netclient/wireguard" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" - //homedir "github.com/mitchellh/go-homedir" -) - -// Pull - pulls the latest config from the server, if manual it will overwrite -func Pull(network string, iface bool) (*models.LegacyNode, error) { - cfg, err := config.ReadConfig(network) - if err != nil { - return nil, err - } - if cfg.Node.IPForwarding == "yes" && !ncutils.IsWindows() { - if err = local.SetIPForwarding(); err != nil { - return nil, err - } - } - token, err := Authenticate(cfg) - if err != nil { - return nil, err - } - url := "https://" + cfg.Server.API + "/api/nodes/" + cfg.Network + "/" + cfg.Node.ID - response, err := API("", http.MethodGet, url, token) - if err != nil { - return nil, err - } - if response.StatusCode != http.StatusOK { - bytes, err := io.ReadAll(response.Body) - if err != nil { - fmt.Println(err) - } - return nil, (fmt.Errorf("%s %w", string(bytes), err)) - } - defer response.Body.Close() - var nodeGET models.NodeGet - if err := json.NewDecoder(response.Body).Decode(&nodeGET); err != nil { - return nil, fmt.Errorf("error decoding node %w", err) - } - resNode := nodeGET.Node - // ensure that the OS never changes - resNode.OS = runtime.GOOS - if nodeGET.Peers == nil { - nodeGET.Peers = []wgtypes.PeerConfig{} - } - if nodeGET.ServerConfig.API != "" && nodeGET.ServerConfig.MQPort != "" { - if err = config.ModServerConfig(&nodeGET.ServerConfig, resNode.Network); err != nil { - logger.Log(0, "unable to update server config: "+err.Error()) - } - } - // if nodeGET.Node.Proxy { - // ProxyMgmChan <- &manager.ManagerAction{ - // Action: manager.AddInterface, - // Payload: nodeGET.ProxyUpdate, - // } - // } - if !nodeGET.Node.Proxy { - if nodeGET.Node.ListenPort != cfg.Node.LocalListenPort { - if err := wireguard.RemoveConf(resNode.Interface, false); err != nil { - logger.Log(0, "error remove interface", resNode.Interface, err.Error()) - } - err = ncutils.ModPort(&resNode) - if err != nil { - return nil, err - } - informPortChange(&resNode) - } - } - - if err = config.ModNodeConfig(&resNode); err != nil { - return nil, err - } - if !nodeGET.Node.Proxy { - if iface { - if err = wireguard.SetWGConfig(network, false, nodeGET.Peers[:]); err != nil { - return nil, err - } - } else { - if err = wireguard.SetWGConfig(network, true, nodeGET.Peers[:]); err != nil { - if errors.Is(err, os.ErrNotExist) && !ncutils.IsFreeBSD() { - return Pull(network, true) - } else { - return nil, err - } - } - } - } - - var bkupErr = config.SaveBackup(network) - if bkupErr != nil { - logger.Log(0, "unable to update backup file for", network) - } - - return &resNode, err -} diff --git a/netclient/functions/upgrades/types.go b/netclient/functions/upgrades/types.go deleted file mode 100644 index 58607d9b..00000000 --- a/netclient/functions/upgrades/types.go +++ /dev/null @@ -1,13 +0,0 @@ -package upgrades - -import "github.com/gravitl/netmaker/netclient/config" - -// UpgradeFunction - logic for upgrade -type UpgradeFunction func(*config.ClientConfig) - -// UpgradeInfo - struct for holding upgrade info -type UpgradeInfo struct { - RequiredVersions []string - NewVersion string - OP UpgradeFunction -} diff --git a/netclient/functions/upgrades/upgrades.go b/netclient/functions/upgrades/upgrades.go deleted file mode 100644 index e21e88b2..00000000 --- a/netclient/functions/upgrades/upgrades.go +++ /dev/null @@ -1,25 +0,0 @@ -package upgrades - -// InitializeUpgrades - initializes written upgrades -func InitializeUpgrades() { - addUpgrades([]UpgradeInfo{ - upgrade0145, - upgrade0146, - upgrade0160, - upgrade0161, - upgrade0162, - }) -} - -// Upgrades - holds all upgrade funcs -var Upgrades = []UpgradeInfo{} - -// addUpgrades - Adds upgrades to make to client -func addUpgrades(upgrades []UpgradeInfo) { - Upgrades = append(Upgrades, upgrades...) -} - -// ReleaseUpgrades - releases upgrade funcs from memory -func ReleaseUpgrades() { - Upgrades = nil -} diff --git a/netclient/functions/upgrades/v0-14-5.go b/netclient/functions/upgrades/v0-14-5.go deleted file mode 100644 index 1d41638d..00000000 --- a/netclient/functions/upgrades/v0-14-5.go +++ /dev/null @@ -1,24 +0,0 @@ -package upgrades - -import ( - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/config" -) - -var upgrade0145 = UpgradeInfo{ - RequiredVersions: []string{ - "v0.14.0", - "v0.14.1", - "v0.14.2", - "v0.14.3", - "v0.14.4", - }, - NewVersion: "v0.14.5", - OP: update0145, -} - -func update0145(cfg *config.ClientConfig) { - // do stuff for 14.X -> 14.5 - // No-op - logger.Log(0, "updating schema for 0.14.5") -} diff --git a/netclient/functions/upgrades/v0-14-6.go b/netclient/functions/upgrades/v0-14-6.go deleted file mode 100644 index 2458726c..00000000 --- a/netclient/functions/upgrades/v0-14-6.go +++ /dev/null @@ -1,25 +0,0 @@ -package upgrades - -import ( - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/config" -) - -var upgrade0146 = UpgradeInfo{ - RequiredVersions: []string{ - "v0.14.0", - "v0.14.1", - "v0.14.2", - "v0.14.3", - "v0.14.4", - "v0.14.5", - }, - NewVersion: "v0.14.6", - OP: update0146, -} - -func update0146(cfg *config.ClientConfig) { - // do stuff for 14.X -> 14.5 - // No-op - logger.Log(0, "updating schema for 0.14.6") -} diff --git a/netclient/functions/upgrades/v0-16-0.go b/netclient/functions/upgrades/v0-16-0.go deleted file mode 100644 index e8c7eb45..00000000 --- a/netclient/functions/upgrades/v0-16-0.go +++ /dev/null @@ -1,23 +0,0 @@ -package upgrades - -import ( - "github.com/gravitl/netmaker/netclient/config" -) - -var upgrade0160 = UpgradeInfo{ - RequiredVersions: []string{ - "v0.14.6", - "v0.15.0", - "v0.15.1", - "v0.15.2", - }, - NewVersion: "v0.16.0", - OP: update0160, -} - -func update0160(cfg *config.ClientConfig) { - // set connect default if not present 15.X -> 16.0 - if cfg.Node.Connected == "" { - cfg.Node.SetDefaultConnected() - } -} diff --git a/netclient/functions/upgrades/v0-16-1.go b/netclient/functions/upgrades/v0-16-1.go deleted file mode 100644 index 78652670..00000000 --- a/netclient/functions/upgrades/v0-16-1.go +++ /dev/null @@ -1,24 +0,0 @@ -package upgrades - -import ( - "github.com/gravitl/netmaker/netclient/config" -) - -var upgrade0161 = UpgradeInfo{ - RequiredVersions: []string{ - "v0.14.6", - "v0.15.0", - "v0.15.1", - "v0.15.2", - "v0.16.1", - }, - NewVersion: "v0.16.1", - OP: update0161, -} - -func update0161(cfg *config.ClientConfig) { - // set connect default if not present 15.X -> 16.0 - if cfg.Node.Connected == "" { - cfg.Node.SetDefaultConnected() - } -} diff --git a/netclient/functions/upgrades/v0-16-2.go b/netclient/functions/upgrades/v0-16-2.go deleted file mode 100644 index 4b021c80..00000000 --- a/netclient/functions/upgrades/v0-16-2.go +++ /dev/null @@ -1,22 +0,0 @@ -package upgrades - -import ( - "github.com/gravitl/netmaker/netclient/config" -) - -var upgrade0162 = UpgradeInfo{ - RequiredVersions: []string{ - "v0.14.6", - "v0.15.0", - "v0.15.1", - "v0.15.2", - "v0.16.1", - }, - NewVersion: "v0.16.2", - OP: update0162, -} - -func update0162(cfg *config.ClientConfig) { - // set connect default if not present 15.X -> 16.0 - update0161(cfg) -} diff --git a/netclient/gui/components/buttons.go b/netclient/gui/components/buttons.go deleted file mode 100644 index 8ed31b9e..00000000 --- a/netclient/gui/components/buttons.go +++ /dev/null @@ -1,33 +0,0 @@ -package components - -import ( - "image/color" - - "fyne.io/fyne/v2" - "fyne.io/fyne/v2/canvas" - "fyne.io/fyne/v2/container" - "fyne.io/fyne/v2/layout" - "fyne.io/fyne/v2/widget" -) - -// ColoredButton - renders a colored button with text -func ColoredButton(text string, tapped func(), color color.Color) *fyne.Container { - btn := widget.NewButton(text, tapped) - bgColor := canvas.NewRectangle(color) - return container.New( - layout.NewMaxLayout(), - bgColor, - btn, - ) -} - -// ColoredIconButton - renders a colored button with an icon -func ColoredIconButton(text string, icon fyne.Resource, tapped func(), color color.Color) *fyne.Container { - btn := widget.NewButtonWithIcon(text, icon, tapped) - bgColor := canvas.NewRectangle(color) - return container.New( - layout.NewMaxLayout(), - btn, - bgColor, - ) -} diff --git a/netclient/gui/components/colors.go b/netclient/gui/components/colors.go deleted file mode 100644 index f1af46bc..00000000 --- a/netclient/gui/components/colors.go +++ /dev/null @@ -1,22 +0,0 @@ -package components - -import "image/color" - -var ( - // Red_color - preferred red color - Red_color = color.NRGBA{R: 233, G: 10, B: 17, A: 155} - // Gravitl_color - gravitl primary sea green color - Gravitl_color = color.NRGBA{R: 14, G: 173, B: 105, A: 155} - // Blue_color - preferred blue color - Blue_color = color.NRGBA{R: 17, G: 157, B: 164, A: 155} - // Danger_color - preferred danger color - Danger_color = color.NRGBA{R: 223, G: 71, B: 89, A: 155} - // Purple_color - preferred purple color - Purple_color = color.NRGBA{R: 115, G: 80, B: 159, A: 155} - // Orange_color - preferred orange color - Orange_color = color.NRGBA{R: 253, G: 76, B: 65, A: 155} - // Grey_color - preferred grey color - Grey_color = color.NRGBA{R: 27, G: 27, B: 27, A: 155} - // Gold_color - preferred gold color - Gold_color = color.NRGBA{R: 218, G: 165, B: 32, A: 155} -) diff --git a/netclient/gui/components/text.go b/netclient/gui/components/text.go deleted file mode 100644 index 55a2f097..00000000 --- a/netclient/gui/components/text.go +++ /dev/null @@ -1,23 +0,0 @@ -package components - -import ( - "image/color" - - "fyne.io/fyne/v2" - "fyne.io/fyne/v2/canvas" - "fyne.io/fyne/v2/container" - "fyne.io/fyne/v2/layout" - "fyne.io/fyne/v2/widget" -) - -// ColoredText - renders a colored label -func ColoredText(text string, color color.Color) *fyne.Container { - btn := widget.NewLabel(text) - btn.Wrapping = fyne.TextWrapWord - bgColor := canvas.NewRectangle(color) - return container.New( - layout.NewMaxLayout(), - bgColor, - btn, - ) -} diff --git a/netclient/gui/components/toolbar.go b/netclient/gui/components/toolbar.go deleted file mode 100644 index 2fe81239..00000000 --- a/netclient/gui/components/toolbar.go +++ /dev/null @@ -1,39 +0,0 @@ -package components - -import ( - "image/color" - - "fyne.io/fyne/v2" - "fyne.io/fyne/v2/container" - "fyne.io/fyne/v2/widget" -) - -// NewToolbarLabelButton - makes a toolbar button cell with label -func NewToolbarLabelButton(label string, icon fyne.Resource, onclick func(), colour color.Color) widget.ToolbarItem { - l := ColoredIconButton(label, icon, onclick, colour) - l.MinSize() - return &toolbarLabelButton{l} -} - -// NewToolbarLabel - makes a toolbar text cell -func NewToolbarLabel(label string) widget.ToolbarItem { - l := widget.NewLabel(label) - l.MinSize() - return &toolbarLabel{l} -} - -type toolbarLabelButton struct { - *fyne.Container -} - -type toolbarLabel struct { - *widget.Label -} - -func (t *toolbarLabelButton) ToolbarObject() fyne.CanvasObject { - return container.NewCenter(t.Container) -} - -func (t *toolbarLabel) ToolbarObject() fyne.CanvasObject { - return container.NewCenter(t.Label) -} diff --git a/netclient/gui/components/views/confirm.go b/netclient/gui/components/views/confirm.go deleted file mode 100644 index 5e69f1b3..00000000 --- a/netclient/gui/components/views/confirm.go +++ /dev/null @@ -1,21 +0,0 @@ -package views - -import ( - "fyne.io/fyne/v2" - "fyne.io/fyne/v2/container" - "fyne.io/fyne/v2/theme" - "fyne.io/fyne/v2/widget" - "github.com/gravitl/netmaker/netclient/gui/components" -) - -// GetConfirmation - displays a confirmation message -func GetConfirmation(msg string, onCancel, onConfirm func()) fyne.CanvasObject { - return container.NewGridWithColumns(1, - container.NewCenter(widget.NewLabel(msg)), - container.NewCenter( - container.NewHBox( - components.ColoredIconButton("Confirm", theme.ConfirmIcon(), onConfirm, components.Gravitl_color), - components.ColoredIconButton("Cancel", theme.CancelIcon(), onCancel, components.Danger_color), - )), - ) -} diff --git a/netclient/gui/components/views/content.go b/netclient/gui/components/views/content.go deleted file mode 100644 index 1e1328ce..00000000 --- a/netclient/gui/components/views/content.go +++ /dev/null @@ -1,25 +0,0 @@ -package views - -import ( - "fyne.io/fyne/v2" -) - -// CurrentContent - the content currently being displayed -var CurrentContent *fyne.Container - -// RemoveContent - removes a rendered content -func RemoveContent(name string) { - CurrentContent.Remove(GetView(name)) -} - -// AddContent - adds content to be rendered -func AddContent(name string) { - CurrentContent.Add(GetView(name)) -} - -// RefreshComponent - refreshes the component to re-render -func RefreshComponent(name string, c fyne.CanvasObject) { - RemoveContent(name) - SetView(name, c) - AddContent(name) -} diff --git a/netclient/gui/components/views/join.go b/netclient/gui/components/views/join.go deleted file mode 100644 index f34c1270..00000000 --- a/netclient/gui/components/views/join.go +++ /dev/null @@ -1,61 +0,0 @@ -package views - -import ( - "fyne.io/fyne/v2" - "fyne.io/fyne/v2/container" - "fyne.io/fyne/v2/theme" - "fyne.io/fyne/v2/widget" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/functions" - "github.com/gravitl/netmaker/netclient/gui/components" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// GetJoinView - get's the join screen where a user inputs an access token -func GetJoinView() fyne.CanvasObject { - - input := widget.NewMultiLineEntry() - input.SetPlaceHolder("access token here...") - - submitBtn := components.ColoredIconButton("Submit", theme.UploadIcon(), func() { - // ErrorNotify("Could not process token") - LoadingNotify() - var cfg config.ClientConfig - accesstoken, err := config.ParseAccessToken(input.Text) - if err != nil { - ErrorNotify("Failed to parse access token!") - return - } - cfg.Network = accesstoken.ClientConfig.Network - cfg.Node.Network = accesstoken.ClientConfig.Network - cfg.Node.Name = ncutils.GetHostname() - cfg.AccessKey = accesstoken.ClientConfig.Key - cfg.Node.LocalRange = accesstoken.ClientConfig.LocalRange - cfg.Server.API = accesstoken.APIConnString - err = functions.JoinNetwork(&cfg, "") - if err != nil { - ErrorNotify("Failed to join " + cfg.Network + "!") - return - } - networks, err := ncutils.GetSystemNetworks() - if err != nil { - ErrorNotify("Failed to read local networks!") - return - } - SuccessNotify("Joined " + cfg.Network + "!") - input.Text = "" - RefreshComponent(Networks, GetNetworksView(networks)) - ShowView(Networks) - // TODO - // - call join - // - display loading - // - on error display error notification - // - on success notify success, refresh networks & networks view, display networks view - }, components.Blue_color) - - return container.NewGridWithColumns(1, - container.NewCenter(widget.NewLabel("Join new network with Access Token")), - input, - container.NewCenter(submitBtn), - ) -} diff --git a/netclient/gui/components/views/networks.go b/netclient/gui/components/views/networks.go deleted file mode 100644 index ae74eb28..00000000 --- a/netclient/gui/components/views/networks.go +++ /dev/null @@ -1,236 +0,0 @@ -package views - -import ( - "fmt" - "time" - - "fyne.io/fyne/v2" - "fyne.io/fyne/v2/container" - "fyne.io/fyne/v2/layout" - "fyne.io/fyne/v2/theme" - "fyne.io/fyne/v2/widget" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/functions" - "github.com/gravitl/netmaker/netclient/gui/components" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// GetNetworksView - displays the view of all networks -func GetNetworksView(networks []string) fyne.CanvasObject { - // renders := []fyne.CanvasObject{} - if len(networks) == 0 { - return container.NewCenter(widget.NewLabel("No networks present")) - } - grid := container.New(layout.NewGridLayout(5), - container.NewCenter(widget.NewLabel("Network Name")), - container.NewCenter(widget.NewLabel("Node Info")), - container.NewCenter(widget.NewLabel("Pull Latest")), - container.NewCenter(widget.NewLabel("Leave network")), - container.NewCenter(widget.NewLabel("Connection status")), - ) - for i := range networks { - network := &networks[i] - grid.Add( - container.NewCenter(widget.NewLabel(*network)), - ) - grid.Add( - components.ColoredIconButton("info", theme.InfoIcon(), func() { - RefreshComponent(NetDetails, GetSingleNetworkView(*network)) - ShowView(NetDetails) - }, components.Gold_color), - ) - grid.Add( - components.ColoredIconButton("pull", theme.DownloadIcon(), func() { - // TODO call pull with network name - pull(*network) - }, components.Blue_color), - ) - grid.Add( - components.ColoredIconButton("leave", theme.DeleteIcon(), func() { - leave(*network) - }, components.Danger_color), - ) - cfg, err := config.ReadConfig(*network) - if err != nil { - fmt.Println(err) - } - if cfg.Node.Connected == "yes" { - grid.Add( - components.ColoredIconButton("disconnect", theme.CheckButtonCheckedIcon(), func() { - disconnect(*network) - }, components.Gravitl_color), - ) - } else { - grid.Add( - components.ColoredIconButton("connect", theme.CheckButtonIcon(), func() { - connect(*network) - }, components.Danger_color), - ) - } - - // renders = append(renders, container.NewCenter(netToolbar)) - } - - return container.NewCenter(grid) -} - -// GetSingleNetworkView - returns details and option to pull a network -func GetSingleNetworkView(network string) fyne.CanvasObject { - if len(network) == 0 { - return container.NewCenter(widget.NewLabel("No valid network selected")) - } - - // == read node values == - LoadingNotify() - nets, err := functions.List(network) - if err != nil || len(nets) < 1 { - ClearNotification() - return container.NewCenter(widget.NewLabel("No data retrieved.")) - } - var nodecfg config.ClientConfig - nodecfg.Network = network - nodecfg.ReadConfig() - nodeID := nodecfg.Node.ID - lastCheckInTime := time.Unix(nodecfg.Node.LastCheckIn, 0) - lastCheckIn := lastCheckInTime.Format("2006-01-02 15:04:05") - privateAddr := nodecfg.Node.Address - privateAddr6 := nodecfg.Node.Address6 - endpoint := nodecfg.Node.Endpoint - health := " (HEALTHY)" - if time.Now().After(lastCheckInTime.Add(time.Minute * 30)) { - health = " (ERROR)" - } else if time.Now().After(lastCheckInTime.Add(time.Minute * 5)) { - health = " (WARNING)" - } - lastCheckIn += health - version := nodecfg.Node.Version - - pullBtn := components.ColoredButton("pull "+network, func() { pull(network) }, components.Blue_color) - pullBtn.Resize(fyne.NewSize(pullBtn.Size().Width, 50)) - - view := container.NewGridWithColumns(1, widget.NewRichTextFromMarkdown(fmt.Sprintf(`### %s -- ID: %s -- Last Check In: %s -- Endpoint: %s -- Address (IPv4): %s -- Address6 (IPv6): %s -- Version: %s -### Peers - `, network, nodeID, lastCheckIn, endpoint, privateAddr, privateAddr6, version)), - ) - netDetailsView := container.NewCenter( - view, - ) - - peerView := container.NewVBox() - - for _, p := range nets[0].Peers { - peerString := "" - endpointEntry := widget.NewEntry() - endpointEntry.Text = fmt.Sprintf("Endpoint: %s", p.PublicEndpoint) - endpointEntry.Disable() - newEntry := widget.NewEntry() - for i, addr := range p.Addresses { - if i > 0 && i < len(p.Addresses) { - peerString += ", " - } - peerString += addr.IP - } - newEntry.Text = peerString - newEntry.Disable() - peerView.Add(widget.NewLabel(fmt.Sprintf("Peer: %s", p.PublicKey))) - peerView.Add(container.NewVBox(container.NewVBox(endpointEntry), container.NewVBox(newEntry))) - } - peerScroller := container.NewVScroll(peerView) - view.Add(peerScroller) - view.Add(container.NewVBox(pullBtn)) - netDetailsView.Refresh() - ClearNotification() - return netDetailsView -} - -// == private == -func pull(network string) { - LoadingNotify() - _, err := functions.Pull(network, true) - if err != nil { - ErrorNotify("Failed to pull " + network + " : " + err.Error()) - } else { - SuccessNotify("Pulled " + network + "!") - } -} - -func leave(network string) { - - confirmView := GetConfirmation("Confirm leaving "+network+"?", func() { - ShowView(Networks) - }, func() { - LoadingNotify() - err := functions.LeaveNetwork(network) - if err != nil { - ErrorNotify("Failed to leave " + network + " : " + err.Error()) - } else { - SuccessNotify("Left " + network) - } - networks, err := ncutils.GetSystemNetworks() - if err != nil { - networks = []string{} - ErrorNotify("Failed to read local networks!") - } - RefreshComponent(Networks, GetNetworksView(networks)) - ShowView(Networks) - }) - RefreshComponent(Confirm, confirmView) - ShowView(Confirm) -} -func connect(network string) { - - confirmView := GetConfirmation("Confirm connecting "+network+"?", func() { - ShowView(Networks) - }, func() { - LoadingNotify() - err := functions.Connect(network) - if err != nil { - - ErrorNotify("Failed to connect " + network + " : " + err.Error()) - - } else { - SuccessNotify("connected to " + network) - } - networks, err := ncutils.GetSystemNetworks() - if err != nil { - networks = []string{} - ErrorNotify("Failed to read local networks!") - } - RefreshComponent(Networks, GetNetworksView(networks)) - ShowView(Networks) - }) - RefreshComponent(Confirm, confirmView) - ShowView(Confirm) -} -func disconnect(network string) { - - confirmView := GetConfirmation("Confirm disconnecting "+network+"?", func() { - ShowView(Networks) - }, func() { - LoadingNotify() - fmt.Println(network) - err := functions.Disconnect(network) - if err != nil { - - ErrorNotify("Failed to disconnect " + network + " : " + err.Error()) - - } else { - SuccessNotify("disconnected from " + network) - } - networks, err := ncutils.GetSystemNetworks() - if err != nil { - networks = []string{} - ErrorNotify("Failed to read local networks!") - } - RefreshComponent(Networks, GetNetworksView(networks)) - ShowView(Networks) - }) - RefreshComponent(Confirm, confirmView) - ShowView(Confirm) -} diff --git a/netclient/gui/components/views/notification.go b/netclient/gui/components/views/notification.go deleted file mode 100644 index cba41cb6..00000000 --- a/netclient/gui/components/views/notification.go +++ /dev/null @@ -1,38 +0,0 @@ -package views - -import ( - "image/color" - - "fyne.io/fyne/v2" - "github.com/gravitl/netmaker/netclient/gui/components" -) - -// GenerateNotification - generates a notification -func GenerateNotification(text string, c color.Color) fyne.CanvasObject { - return components.ColoredText(text, c) -} - -// ChangeNotification - changes the current notification in the view -func ChangeNotification(text string, c color.Color) { - RefreshComponent(Notify, GenerateNotification(text, c)) -} - -// ClearNotification - hides the notifications -func ClearNotification() { - RefreshComponent(Notify, GenerateNotification("", color.Transparent)) -} - -// LoadingNotify - changes notification to loading... -func LoadingNotify() { - RefreshComponent(Notify, GenerateNotification("loading...", components.Blue_color)) -} - -// ErrorNotify - changes notification to a specified error -func ErrorNotify(msg string) { - RefreshComponent(Notify, GenerateNotification(msg, components.Danger_color)) -} - -// SuccessNotify - changes notification to a specified success message -func SuccessNotify(msg string) { - RefreshComponent(Notify, GenerateNotification(msg, components.Gravitl_color)) -} diff --git a/netclient/gui/components/views/state.go b/netclient/gui/components/views/state.go deleted file mode 100644 index cab8433c..00000000 --- a/netclient/gui/components/views/state.go +++ /dev/null @@ -1,44 +0,0 @@ -package views - -import ( - "fyne.io/fyne/v2" -) - -var ( - // Views - the map of all the view components - views = make(map[string]fyne.CanvasObject) -) - -const ( - Networks = "networks" - NetDetails = "netdetails" - Notify = "notification" - Join = "join" - Confirm = "confirm" -) - -// GetView - returns the requested view and sets the CurrentView state -func GetView(viewName string) fyne.CanvasObject { - return views[viewName] -} - -// SetView - sets a view in the views map -func SetView(viewName string, component fyne.CanvasObject) { - views[viewName] = component -} - -// HideView - hides a specific view -func HideView(viewName string) { - views[viewName].Hide() -} - -// ShowView - show's a specific view -func ShowView(viewName string) { - for k := range views { - if k == Notify { - continue - } - HideView(k) - } - views[viewName].Show() -} diff --git a/netclient/gui/gui.go b/netclient/gui/gui.go deleted file mode 100644 index 4db728bc..00000000 --- a/netclient/gui/gui.go +++ /dev/null @@ -1,147 +0,0 @@ -package gui - -import ( - "embed" - "image/color" - "os" - - "fyne.io/fyne/v2" - "fyne.io/fyne/v2/app" - "fyne.io/fyne/v2/container" - "fyne.io/fyne/v2/theme" - "fyne.io/fyne/v2/widget" - "github.com/agnivade/levenshtein" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/functions" - "github.com/gravitl/netmaker/netclient/gui/components" - "github.com/gravitl/netmaker/netclient/gui/components/views" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -//go:embed nm-logo-sm.png -var logoContent embed.FS - -// Run - run's the netclient GUI -func Run(networks []string) error { - defer func() { - if r := recover(); r != nil { - logger.Log(0, "No monitor detected, please use CLI commands; use -help for more info.") - } - }() - a := app.New() - window := a.NewWindow("Netclient - " + ncutils.Version) - - img, err := logoContent.ReadFile("nm-logo-sm.png") - if err != nil { - logger.Log(0, "failed to read logo", err.Error()) - return err - } - - window.SetIcon(&fyne.StaticResource{StaticName: "Netmaker logo", StaticContent: img}) - window.Resize(fyne.NewSize(600, 450)) - - networkView := container.NewVScroll(views.GetNetworksView(networks)) - networkView.SetMinSize(fyne.NewSize(400, 300)) - views.SetView(views.Networks, networkView) - - netDetailsViews := container.NewVScroll(views.GetSingleNetworkView("")) - netDetailsViews.SetMinSize(fyne.NewSize(400, 300)) - views.SetView(views.NetDetails, netDetailsViews) - window.SetFixedSize(false) - - searchBar := widget.NewEntry() - searchBar.PlaceHolder = "Search a Network ..." - searchBar.TextStyle = fyne.TextStyle{ - Italic: true, - } - searchBar.OnChanged = func(text string) { - if text == "" { - networkView = container.NewVScroll(views.GetNetworksView(networks)) - networkView.SetMinSize(fyne.NewSize(400, 300)) - views.RefreshComponent(views.Networks, networkView) - views.ShowView(views.Networks) - return - } - - opts := []string{} - for _, n := range networks { - r := levenshtein.ComputeDistance(text, n) - if r <= 2 { - opts = append(opts, n) - } - } - - // fmt.Println(opts) - networkView = container.NewVScroll(views.GetNetworksView(opts)) - networkView.SetMinSize(fyne.NewSize(400, 300)) - views.RefreshComponent(views.Networks, networkView) - views.ShowView(views.Networks) - opts = nil - } - - toolbar := container.NewCenter(widget.NewToolbar( - components.NewToolbarLabelButton("Networks", theme.HomeIcon(), func() { - searchBar.Show() - views.ShowView(views.Networks) - views.ClearNotification() - }, components.Blue_color), - components.NewToolbarLabelButton("Join new", theme.ContentAddIcon(), func() { - searchBar.Hide() - views.ShowView(views.Join) - }, components.Gravitl_color), - components.NewToolbarLabelButton("Uninstall", theme.ErrorIcon(), func() { - searchBar.Hide() - confirmView := views.GetConfirmation("Confirm Netclient uninstall?", func() { - views.ShowView(views.Networks) - }, func() { - views.LoadingNotify() - err := functions.Uninstall() - if err != nil { - views.ErrorNotify("Failed to uninstall: \n" + err.Error()) - } else { - views.SuccessNotify("Uninstalled Netclient!") - } - networks, err := ncutils.GetSystemNetworks() - if err != nil { - networks = []string{} - } - views.RefreshComponent(views.Networks, views.GetNetworksView(networks)) - views.ShowView(views.Networks) - }) - views.RefreshComponent(views.Confirm, confirmView) - views.ShowView(views.Confirm) - }, components.Red_color), - components.NewToolbarLabelButton("Close", theme.ContentClearIcon(), func() { - os.Exit(0) - }, components.Purple_color), - )) - - joinView := views.GetJoinView() - views.SetView(views.Join, joinView) - - confirmView := views.GetConfirmation("", func() {}, func() {}) - views.SetView(views.Confirm, confirmView) - - views.ShowView(views.Networks) - - initialNotification := views.GenerateNotification("", color.Transparent) - views.SetView(views.Notify, initialNotification) - - views.CurrentContent = container.NewVBox() - - views.CurrentContent.Add(container.NewGridWithRows( - 2, - toolbar, - searchBar, - )) - views.CurrentContent.Add(views.GetView(views.Networks)) - views.CurrentContent.Add(views.GetView(views.NetDetails)) - views.CurrentContent.Add(views.GetView(views.Notify)) - views.CurrentContent.Add(views.GetView(views.Join)) - - window.SetContent(views.CurrentContent) - window.ShowAndRun() - - return nil -} diff --git a/netclient/gui/nm-logo-sm.png b/netclient/gui/nm-logo-sm.png deleted file mode 100644 index 256ea96b..00000000 Binary files a/netclient/gui/nm-logo-sm.png and /dev/null differ diff --git a/netclient/local/local.go b/netclient/local/local.go deleted file mode 100644 index dcbeaa08..00000000 --- a/netclient/local/local.go +++ /dev/null @@ -1,142 +0,0 @@ -package local - -import ( - //"github.com/davecgh/go-spew/spew" - "errors" - "log" - "net" - "os" - "os/exec" - "runtime" - "strings" - - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// SetIPForwarding - Sets IP forwarding if it's mac or linux -func SetIPForwarding() error { - os := runtime.GOOS - var err error - switch os { - case "linux": - err = SetIPForwardingUnix() - case "freebsd": - err = SetIPForwardingFreeBSD() - case "darwin": - err = SetIPForwardingMac() - default: - err = errors.New("this OS is not currently supported") - } - return err -} - -// SetIPForwardingLinux - sets the ipforwarding for linux -func SetIPForwardingUnix() error { - - // ipv4 - out, err := ncutils.RunCmd("sysctl net.ipv4.ip_forward", true) - if err != nil { - log.Println("WARNING: Error encountered setting ip forwarding. This can break functionality.") - return err - } else { - s := strings.Fields(string(out)) - if s[2] != "1" { - _, err = ncutils.RunCmd("sysctl -w net.ipv4.ip_forward=1", true) - if err != nil { - log.Println("WARNING: Error encountered setting ip forwarding. You may want to investigate this.") - return err - } - } - } - - // ipv6 - out, err = ncutils.RunCmd("sysctl net.ipv6.conf.all.forwarding", true) - if err != nil { - log.Println("WARNING: Error encountered setting ipv6 forwarding. This can break functionality.") - return err - } else { - s := strings.Fields(string(out)) - if s[2] != "1" { - _, err = ncutils.RunCmd("sysctl -w net.ipv6.conf.all.forwarding=1", true) - if err != nil { - log.Println("WARNING: Error encountered setting ipv6 forwarding. You may want to investigate this.") - return err - } - } - } - - return nil -} - -// SetIPForwardingLinux - sets the ipforwarding for linux -func SetIPForwardingFreeBSD() error { - out, err := ncutils.RunCmd("sysctl net.inet.ip.forwarding", true) - if err != nil { - log.Println("WARNING: Error encountered setting ip forwarding. This can break functionality.") - return err - } else { - s := strings.Fields(string(out)) - if s[1] != "1" { - _, err = ncutils.RunCmd("sysctl -w net.inet.ip.forwarding=1", true) - if err != nil { - log.Println("WARNING: Error encountered setting ip forwarding. You may want to investigate this.") - return err - } - } - } - return nil -} - -// SetIPForwardingMac - sets ip forwarding for mac -func SetIPForwardingMac() error { - _, err := ncutils.RunCmd("sysctl -w net.inet.ip.forwarding=1", true) - if err != nil { - log.Println("WARNING: Error encountered setting ip forwarding. This can break functionality.") - } - return err -} - -// IsWGInstalled - checks if WireGuard is installed -func IsWGInstalled() bool { - out, err := ncutils.RunCmd("wg help", true) - if err != nil { - _, err = exec.LookPath(os.Getenv("WG_QUICK_USERSPACE_IMPLEMENTATION")) - return err == nil - } - return strings.Contains(out, "Available subcommand") -} - -// GetMacIface - gets mac interface -func GetMacIface(ipstring string) (string, error) { - var wgiface string - _, checknet, err := net.ParseCIDR(ipstring + "/24") - if err != nil { - return wgiface, errors.New("could not parse ip " + ipstring) - } - ifaces, err := net.Interfaces() - if err != nil { - return wgiface, err - } - for _, iface := range ifaces { - addrs, err := iface.Addrs() - if err != nil { - continue - } - for _, addr := range addrs { - ip := addr.(*net.IPNet).IP - if checknet.Contains(ip) { - wgiface = iface.Name - break - } - } - } - if wgiface == "" { - err = errors.New("could not find iface for address " + ipstring) - } - return wgiface, err -} - -// HasNetwork - checks if a network exists locally -func HasNetwork(network string) bool { - return ncutils.FileExists(ncutils.GetNetclientPathSpecific() + "netconfig-" + network) -} diff --git a/netclient/local/routes.go b/netclient/local/routes.go deleted file mode 100644 index 2aaa0c38..00000000 --- a/netclient/local/routes.go +++ /dev/null @@ -1,159 +0,0 @@ -package local - -import ( - "fmt" - "net" - "strings" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/ncutils" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" -) - -// TODO handle ipv6 in future - -// SetPeerRoutes - sets/removes ip routes for each peer on a network -func SetPeerRoutes(iface string, oldPeers map[string]bool, newPeers []wgtypes.PeerConfig) { - - // get the default route - var hasRoute bool - gwIP, gwIface, err := GetDefaultRoute() - if err != nil { - logger.Log(0, "error getting default route:", err.Error()) - } - if gwIP != "" && gwIface != "" && err == nil { - hasRoute = true - } - - // traverse through all recieved peers - for _, peer := range newPeers { - for _, allowedIP := range peer.AllowedIPs { - if !oldPeers[allowedIP.String()] { - if err := setRoute(iface, &allowedIP, allowedIP.IP.String()); err != nil { - logger.Log(1, err.Error()) - } - } else { - delete(oldPeers, allowedIP.String()) - } - } - if peer.Endpoint == nil { - continue - } - if hasRoute && !ncutils.IpIsPrivate(peer.Endpoint.IP) { - ipNet, err := ncutils.GetIPNetFromString(peer.Endpoint.IP.String()) - if err != nil { - logger.Log(0, "error parsing ip:", err.Error()) - } - SetExplicitRoute(gwIface, &ipNet, gwIP) - } - } - // traverse through all remaining existing peers - for i := range oldPeers { - ip, err := ncutils.GetIPNetFromString(i) - if err != nil { - logger.Log(1, err.Error()) - } else { - deleteRoute(iface, &ip, ip.IP.String()) - } - } -} - -// SetCurrentPeerRoutes - sets all the current peers -func SetCurrentPeerRoutes(iface, currentAddr string, peers []wgtypes.PeerConfig) { - - // get the default route - var hasRoute bool - gwIP, gwIface, err := GetDefaultRoute() - if err != nil { - logger.Log(0, "error getting default route:", err.Error()) - } - if gwIP != "" && gwIface != "" && err == nil { - hasRoute = true - } - - // traverse through all recieved peers - for _, peer := range peers { - for _, allowedIP := range peer.AllowedIPs { - setRoute(iface, &allowedIP, currentAddr) - } - if peer.Endpoint == nil { - continue - } - if hasRoute && !ncutils.IpIsPrivate(peer.Endpoint.IP) { - ipNet, err := ncutils.GetIPNetFromString(peer.Endpoint.IP.String()) - if err != nil { - logger.Log(0, "error parsing ip:", err.Error()) - } - SetExplicitRoute(gwIface, &ipNet, gwIP) - } - } - -} - -// FlushPeerRoutes - removes all current peer routes -func FlushPeerRoutes(iface, currentAddr string, peers []wgtypes.Peer) { - // get the default route - var hasRoute bool - gwIP, gwIface, err := GetDefaultRoute() - if err != nil { - logger.Log(0, "error getting default route:", err.Error()) - } - if gwIP != "" && gwIface != "" && err == nil { - hasRoute = true - } - - for _, peer := range peers { - for _, allowedIP := range peer.AllowedIPs { - deleteRoute(iface, &allowedIP, currentAddr) - } - if peer.Endpoint == nil { - continue - } - if hasRoute && !ncutils.IpIsPrivate(peer.Endpoint.IP) { - ipNet, err := ncutils.GetIPNetFromString(peer.Endpoint.IP.String()) - if err != nil { - logger.Log(0, "error parsing ip:", err.Error()) - } - deleteRoute(gwIface, &ipNet, gwIP) - } - } -} - -// SetCIDRRoute - sets the CIDR route, used on join and restarts -func SetCIDRRoute(iface, currentAddr string, cidr *net.IPNet) { - setCidr(iface, currentAddr, cidr) -} - -// RemoveCIDRRoute - removes a static cidr route -func RemoveCIDRRoute(iface, currentAddr string, cidr *net.IPNet) { - removeCidr(iface, cidr, currentAddr) -} - -// SetNetmakerDomainRoute - sets explicit route over Gateway for a given DNS name -func SetNetmakerDomainRoute(domainRaw string) error { - parts := strings.Split(domainRaw, ":") - hostname := parts[0] - var address net.IPNet - - gwIP, gwIface, err := GetDefaultRoute() - if err != nil { - return fmt.Errorf("error getting default route: %w", err) - } - - ips, err := net.LookupIP(hostname) - if err != nil { - return err - } - for _, ip := range ips { - if ipv4 := ip.To4(); ipv4 != nil { - address, err = ncutils.GetIPNetFromString(ipv4.String()) - if err == nil { - break - } - } - } - if err != nil || address.IP == nil { - return fmt.Errorf("address not found") - } - return SetExplicitRoute(gwIface, &address, gwIP) -} diff --git a/netclient/local/routes_darwin.go b/netclient/local/routes_darwin.go deleted file mode 100644 index 0b2d63dd..00000000 --- a/netclient/local/routes_darwin.go +++ /dev/null @@ -1,86 +0,0 @@ -package local - -import ( - "fmt" - "github.com/c-robinson/iplib" - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/ncutils" - "net" - "regexp" - "strings" -) - -// GetDefaultRoute - Gets the default route (ip and interface) on a mac machine -func GetDefaultRoute() (string, string, error) { - var ipaddr string - var iface string - var err error - var outLine string - output, err := ncutils.RunCmd("netstat -nr", false) - for _, line := range strings.Split(strings.TrimSuffix(output, "\n"), "\n") { - if strings.Contains(line, "default") { - outLine = line - break - } - } - space := regexp.MustCompile(`\s+`) - outFormatted := space.ReplaceAllString(outLine, " ") - if err != nil { - return ipaddr, iface, err - } - outputSlice := strings.Split(string(outFormatted), " ") - if !strings.Contains(outputSlice[0], "default") { - return ipaddr, iface, fmt.Errorf("could not find default gateway") - } - ipaddr = outputSlice[1] - if err = ncutils.CheckIPAddress(ipaddr); err != nil { - return ipaddr, iface, err - } - iface = outputSlice[3] - - return ipaddr, iface, err -} - -// route -n add -net 10.0.0.0/8 192.168.0.254 -// networksetup -setadditionalroutes Ethernet 192.168.1.0 255.255.255.0 10.0.0.2 persistent -func setRoute(iface string, addr *net.IPNet, address string) error { - var err error - var out string - var inetx = "inet" - if strings.Contains(addr.IP.String(), ":") { - inetx = "inet6" - } - out, err = ncutils.RunCmd("route -n get -"+inetx+" "+addr.IP.String(), false) - if err != nil { - return err - } - if !(strings.Contains(out, iface)) { - _, err = ncutils.RunCmd("route -q -n add -"+inetx+" "+addr.String()+" -interface "+iface, false) - } - return err -} - -// SetExplicitRoute - sets route via explicit ip address -func SetExplicitRoute(iface string, destination *net.IPNet, gateway string) error { - return setRoute(iface, destination, gateway) -} - -func deleteRoute(iface string, addr *net.IPNet, address string) error { - var err error - _, err = ncutils.RunCmd("route -q -n delete "+addr.String(), false) - return err -} - -func setCidr(iface, address string, addr *net.IPNet) { - if iplib.Version(addr.IP) == 4 { - ncutils.RunCmd("route -q -n add -net "+addr.String()+" "+address, false) - } else if iplib.Version(addr.IP) == 6 { - ncutils.RunCmd("route -A inet6 -q -n add -net "+addr.String()+" "+address, false) - } else { - logger.Log(1, "could not parse address: "+addr.String()) - } -} - -func removeCidr(iface string, addr *net.IPNet, address string) { - ncutils.RunCmd("route -q -n delete "+addr.String()+" -interface "+iface, false) -} diff --git a/netclient/local/routes_freebsd.go b/netclient/local/routes_freebsd.go deleted file mode 100644 index 7e8d796f..00000000 --- a/netclient/local/routes_freebsd.go +++ /dev/null @@ -1,69 +0,0 @@ -package local - -import ( - "fmt" - "net" - "strings" - - "github.com/c-robinson/iplib" - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// GetDefaultRoute - Gets the default route (ip and interface) on a freebsd machine -func GetDefaultRoute() (string, string, error) { - var ipaddr string - var iface string - var err error - - output, err := ncutils.RunCmd("route show default", true) - if err != nil { - return ipaddr, iface, err - } - outFormatted := strings.ReplaceAll(output, "\n", "") - if !strings.Contains(outFormatted, "default") && !strings.Contains(outFormatted, "interface:") { - return ipaddr, iface, fmt.Errorf("could not find default gateway") - } - outputSlice := strings.Split(string(outFormatted), " ") - for i, outString := range outputSlice { - if outString == "gateway:" { - ipaddr = outputSlice[i+1] - } - if outString == "interface:" { - iface = outputSlice[i+1] - } - } - return ipaddr, iface, err -} - -func setRoute(iface string, addr *net.IPNet, address string) error { - _, err := ncutils.RunCmd("route add -net "+addr.String()+" -interface "+iface, false) - return err -} - -// SetExplicitRoute - sets route via explicit ip address -func SetExplicitRoute(iface string, destination *net.IPNet, gateway string) error { - _, err := ncutils.RunCmd("route add "+destination.String()+" "+gateway, false) - return err -} - -func deleteRoute(iface string, addr *net.IPNet, address string) error { - var err error - _, _ = ncutils.RunCmd("route delete -net "+addr.String()+" -interface "+iface, false) - return err -} - -func setCidr(iface, address string, addr *net.IPNet) { - if iplib.Version(addr.IP) == 4 { - ncutils.RunCmd("route add -net "+addr.String()+" -interface "+iface, false) - } else if iplib.Version(addr.IP) == 6 { - ncutils.RunCmd("route add -net -inet6 "+addr.String()+" -interface "+iface, false) - } else { - logger.Log(1, "could not parse address: "+addr.String()) - } - ncutils.RunCmd("route add -net "+addr.String()+" -interface "+iface, false) -} - -func removeCidr(iface string, addr *net.IPNet, address string) { - ncutils.RunCmd("route delete -net "+addr.String()+" -interface "+iface, false) -} diff --git a/netclient/local/routes_linux.go b/netclient/local/routes_linux.go deleted file mode 100644 index 1fc25123..00000000 --- a/netclient/local/routes_linux.go +++ /dev/null @@ -1,74 +0,0 @@ -package local - -import ( - //"github.com/davecgh/go-spew/spew" - - "fmt" - "net" - "strings" - - "github.com/c-robinson/iplib" - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// GetDefaultRoute - Gets the default route (ip and interface) on a linux machine -func GetDefaultRoute() (string, string, error) { - var ipaddr string - var iface string - var err error - output, err := ncutils.RunCmd("ip route show default", false) - if err != nil { - return ipaddr, iface, err - } - outputSlice := strings.Split(output, " ") - if !strings.Contains(outputSlice[0], "default") { - return ipaddr, iface, fmt.Errorf("could not find default gateway") - } - for i, outString := range outputSlice { - if outString == "via" { - ipaddr = outputSlice[i+1] - } - if outString == "dev" { - iface = outputSlice[i+1] - } - } - return ipaddr, iface, err -} - -func setRoute(iface string, addr *net.IPNet, address string) error { - out, err := ncutils.RunCmd(fmt.Sprintf("ip route get %s", addr.IP.String()), false) - if err != nil || !strings.Contains(out, iface) { - _, err = ncutils.RunCmd(fmt.Sprintf("ip route add %s dev %s", addr.String(), iface), false) - } - return err -} - -// SetExplicitRoute - sets route via explicit ip address -func SetExplicitRoute(iface string, destination *net.IPNet, gateway string) error { - _, err := ncutils.RunCmd(fmt.Sprintf("ip route add %s via %s dev %s", destination.String(), gateway, iface), false) - return err -} - -func deleteRoute(iface string, addr *net.IPNet, address string) error { - var err error - out, _ := ncutils.RunCmd(fmt.Sprintf("ip route get %s", addr.IP.String()), false) - if strings.Contains(out, iface) { - _, err = ncutils.RunCmd(fmt.Sprintf("ip route del %s dev %s", addr.String(), iface), false) - } - return err -} - -func setCidr(iface, address string, addr *net.IPNet) { - if iplib.Version(addr.IP) == 4 { - ncutils.RunCmd("ip -4 route add "+addr.String()+" dev "+iface, false) - } else if iplib.Version(addr.IP) == 6 { - ncutils.RunCmd("ip -6 route add "+addr.String()+" dev "+iface, false) - } else { - logger.Log(1, "could not parse address: "+addr.String()) - } -} - -func removeCidr(iface string, addr *net.IPNet, address string) { - ncutils.RunCmd("ip route delete "+addr.String()+" dev "+iface, false) -} diff --git a/netclient/local/routes_windows.go b/netclient/local/routes_windows.go deleted file mode 100644 index 47b3746d..00000000 --- a/netclient/local/routes_windows.go +++ /dev/null @@ -1,77 +0,0 @@ -package local - -import ( - "fmt" - "net" - "regexp" - "strings" - "time" - - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// GetDefaultRoute - Gets the default route (ip and interface) on a windows machine -func GetDefaultRoute() (string, string, error) { - var ipaddr string - var iface string - var err error - var outLine string - output, err := ncutils.RunCmd("netstat -rn", false) - if err != nil { - return ipaddr, iface, err - } - var startLook bool - for _, line := range strings.Split(strings.TrimSuffix(output, "\n"), "\n") { - if strings.Contains(line, "Active Routes:") { - startLook = true - } - if startLook && strings.Contains(line, "0.0.0.0") { - outLine = line - break - } - } - if outLine == "" { - return ipaddr, iface, fmt.Errorf("could not find default gateway") - } - space := regexp.MustCompile(`\s+`) - outputSlice := strings.Split(strings.TrimSpace(space.ReplaceAllString(outLine, " ")), " ") - ipaddr = outputSlice[len(outputSlice)-3] - if err = ncutils.CheckIPAddress(ipaddr); err != nil { - return ipaddr, iface, fmt.Errorf("invalid output for ip address check: " + err.Error()) - } - iface = "irrelevant" - return ipaddr, iface, err -} - -func setRoute(iface string, addr *net.IPNet, address string) error { - var err error - _, err = ncutils.RunCmd("route ADD "+addr.String()+" "+address, false) - time.Sleep(time.Second >> 2) - ncutils.RunCmd("route CHANGE "+addr.IP.String()+" MASK "+addr.Mask.String()+" "+address, false) - return err -} - -// SetExplicitRoute - sets route via explicit ip address -func SetExplicitRoute(iface string, destination *net.IPNet, gateway string) error { - var err error - _, err = ncutils.RunCmd("route ADD "+destination.String()+" "+gateway, false) - time.Sleep(time.Second >> 2) - ncutils.RunCmd("route CHANGE "+destination.IP.String()+" MASK "+destination.Mask.String()+" "+gateway, false) - return err -} - -func deleteRoute(iface string, addr *net.IPNet, address string) error { - var err error - _, err = ncutils.RunCmd("route DELETE "+addr.IP.String()+" MASK "+addr.Mask.String()+" "+address, false) - return err -} - -func setCidr(iface, address string, addr *net.IPNet) { - ncutils.RunCmd("route ADD "+addr.String()+" "+address, false) - time.Sleep(time.Second >> 2) - ncutils.RunCmd("route CHANGE "+addr.IP.String()+" MASK "+addr.Mask.String()+" "+address, false) -} - -func removeCidr(iface string, addr *net.IPNet, address string) { - ncutils.RunCmd("route DELETE "+addr.String(), false) -} diff --git a/netclient/main.exe b/netclient/main.exe deleted file mode 100755 index 2d9353ec..00000000 Binary files a/netclient/main.exe and /dev/null differ diff --git a/netclient/main.go b/netclient/main.go deleted file mode 100644 index 8987e3b8..00000000 --- a/netclient/main.go +++ /dev/null @@ -1,60 +0,0 @@ -//go:generate goversioninfo -icon=windowsdata/resource/netclient.ico -manifest=netclient.exe.manifest.xml -64=true -o=netclient.syso -// -build gui - -package main - -import ( - "os" - "runtime/debug" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/cli_options" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/functions" - "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/netclient/ncwindows" - "github.com/urfave/cli/v2" -) - -var version = "dev" - -func main() { - app := cli.NewApp() - app.Name = "Netclient" - app.Version = version - ncutils.SetVersion(version) - cliFlags := cli_options.GetFlags(ncutils.GetHostname()) - app.Commands = cli_options.GetCommands(cliFlags[:]) - app.Description = "Used to perform interactions with Netmaker server and set local WireGuard config." - app.Usage = "Netmaker's netclient agent and CLI." - app.UsageText = "netclient [global options] command [command options] [arguments...]. Adjust verbosity of given command with -v, -vv or -vvv (max)." - - setGarbageCollection() - functions.SetHTTPClient() - - if ncutils.IsWindows() { - ncwindows.InitWindows() - } else { - ncutils.CheckUID() - ncutils.CheckWG() - if ncutils.IsLinux() { - ncutils.CheckFirewall() - } - } - - if len(os.Args) <= 1 && config.GuiActive { - config.GuiRun.(func())() - } else { - err := app.Run(os.Args) - if err != nil { - logger.FatalLog(err.Error()) - } - } -} - -func setGarbageCollection() { - _, gcset := os.LookupEnv("GOGC") - if !gcset { - debug.SetGCPercent(ncutils.DEFAULT_GC_PERCENT) - } -} diff --git a/netclient/main_gui.go b/netclient/main_gui.go deleted file mode 100644 index a5db7868..00000000 --- a/netclient/main_gui.go +++ /dev/null @@ -1,22 +0,0 @@ -//go:build gui -// +build gui - -package main - -import ( - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/gui" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -func init() { - config.GuiActive = true - - config.GuiRun = func() { - networks, err := ncutils.GetSystemNetworks() - if err != nil { - networks = []string{} - } - gui.Run(networks) - } -} diff --git a/netclient/ncwindows/windows.go b/netclient/ncwindows/windows.go deleted file mode 100644 index e1601778..00000000 --- a/netclient/ncwindows/windows.go +++ /dev/null @@ -1,46 +0,0 @@ -package ncwindows - -import ( - "log" - "os" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// InitWindows - Initialize windows directory & files and such -func InitWindows() { - - _, directoryErr := os.Stat(ncutils.GetNetclientPath()) // Check if data directory exists or not - if os.IsNotExist(directoryErr) { // create a data directory - os.Mkdir(ncutils.GetNetclientPath(), 0755) - } - wdPath, wdErr := os.Getwd() // get the current working directory - if wdErr != nil { - log.Fatal("failed to get current directory..") - } - - dataPath := ncutils.GetNetclientPathSpecific() + "netclient.exe" - currentPath := wdPath + "\\netclient.exe" - _, dataNetclientErr := os.Stat(dataPath) - _, currentNetclientErr := os.Stat(currentPath) - - if currentPath == dataPath && currentNetclientErr == nil { - logger.Log(0, "netclient.exe is in proper location, "+currentPath) - } else if os.IsNotExist(dataNetclientErr) { // check and see if netclient.exe is in appdata - if currentNetclientErr == nil { // copy it if it exists locally - input, err := os.ReadFile(currentPath) - if err != nil { - log.Println("failed to find netclient.exe") - return - } - if err = os.WriteFile(dataPath, input, 0700); err != nil { - log.Println("failed to copy netclient.exe to", ncutils.GetNetclientPath()) - return - } - } else { - log.Fatalf("[netclient] netclient.exe not found in current working directory: %s \nexiting.", wdPath) - } - } - log.Println("Gravitl Netclient on Windows started") -} diff --git a/netclient/netclient.exe.manifest.xml b/netclient/netclient.exe.manifest.xml deleted file mode 100644 index 0db144e5..00000000 --- a/netclient/netclient.exe.manifest.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - Windows Netclient - - - - - - - - diff --git a/netclient/resources.rc b/netclient/resources.rc deleted file mode 100644 index e8f33856..00000000 --- a/netclient/resources.rc +++ /dev/null @@ -1,8 +0,0 @@ -#include - -#pragma code_page(65001) - -#define STRINGIZE(x) #x -#define EXPAND(x) STRINGIZE(x) -CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST netclient.exe.manifest.xml -wintun.dll RCDATA wintun.dll diff --git a/netclient/versioninfo.json b/netclient/versioninfo.json deleted file mode 100644 index 691669cb..00000000 --- a/netclient/versioninfo.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "FixedFileInfo": { - "FileVersion": { - "Major": 0, - "Minor": 17, - "Patch": 0, - "Build": 0 - }, - "ProductVersion": { - "Major": 0, - "Minor": 17, - "Patch": 0, - "Build": 0 - }, - "FileFlagsMask": "3f", - "FileFlags ": "00", - "FileOS": "040004", - "FileType": "01", - "FileSubType": "00" - }, - "StringFileInfo": { - "Comments": "", - "CompanyName": "Gravitl", - "FileDescription": "", - "FileVersion": "", - "InternalName": "", - "LegalCopyright": "", - "LegalTrademarks": "", - "OriginalFilename": "", - "PrivateBuild": "", - "ProductName": "Netclient", - "ProductVersion": "v0.17.0.0", - "SpecialBuild": "" - }, - "VarFileInfo": { - "Translation": { - "LangID": "0409", - "CharsetID": "04B0" - } - }, - "IconPath": "windowsdata/resource/netclient.ico", - "ManifestPath": "netclient.exe.manifest.xml" -} diff --git a/netclient/windowsdata/resource/netclient.ico b/netclient/windowsdata/resource/netclient.ico deleted file mode 100644 index 1a736e4c..00000000 Binary files a/netclient/windowsdata/resource/netclient.ico and /dev/null differ diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go deleted file mode 100644 index c3d5c361..00000000 --- a/netclient/wireguard/common.go +++ /dev/null @@ -1,589 +0,0 @@ -package wireguard - -import ( - "fmt" - "net" - "runtime" - "strconv" - "strings" - "time" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/local" - "github.com/gravitl/netmaker/netclient/ncutils" - "golang.zx2c4.com/wireguard/wgctrl" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" - "gopkg.in/ini.v1" -) - -const ( - section_interface = "Interface" - section_peers = "Peer" -) - -// SetPeers - sets peers on a given WireGuard interface -func SetPeers(iface string, node *models.LegacyNode, peers []wgtypes.PeerConfig) error { - var devicePeers []wgtypes.Peer - var keepalive = node.PersistentKeepalive - var oldPeerAllowedIps = make(map[string]bool, len(peers)) - var err error - devicePeers, err = GetDevicePeers(iface) - if err != nil { - return err - } - - if len(devicePeers) > 1 && len(peers) == 0 { - logger.Log(1, "no peers pulled") - return err - } - for _, peer := range peers { - // make sure peer has AllowedIP's before comparison - hasPeerIP := len(peer.AllowedIPs) > 0 - for _, currentPeer := range devicePeers { - // make sure currenPeer has AllowedIP's before comparison - hascurrentPeerIP := len(currentPeer.AllowedIPs) > 0 - - if hasPeerIP && hascurrentPeerIP && - currentPeer.AllowedIPs[0].String() == peer.AllowedIPs[0].String() && - currentPeer.PublicKey.String() != peer.PublicKey.String() { - _, err := ncutils.RunCmd("wg set "+iface+" peer "+currentPeer.PublicKey.String()+" remove", true) - if err != nil { - logger.Log(0, "error removing peer", peer.Endpoint.String()) - } - } - } - udpendpoint := peer.Endpoint.String() - var allowedips string - var iparr []string - for _, ipaddr := range peer.AllowedIPs { - if hasPeerIP { - iparr = append(iparr, ipaddr.String()) - } - } - if len(iparr) > 0 { - allowedips = strings.Join(iparr, ",") - } - keepAliveString := strconv.Itoa(int(keepalive)) - if keepAliveString == "0" { - keepAliveString = "15" - } - if node.IsServer == "yes" || peer.Endpoint == nil { - _, err = ncutils.RunCmd("wg set "+iface+" peer "+peer.PublicKey.String()+ - " persistent-keepalive "+keepAliveString+ - " allowed-ips "+allowedips, true) - } else { - _, err = ncutils.RunCmd("wg set "+iface+" peer "+peer.PublicKey.String()+ - " endpoint "+udpendpoint+ - " persistent-keepalive "+keepAliveString+ - " allowed-ips "+allowedips, true) - } - if err != nil { - logger.Log(0, "error setting peer", peer.PublicKey.String()) - } - } - if len(devicePeers) > 0 { - for _, currentPeer := range devicePeers { - shouldDelete := true - if len(peers) > 0 { - for _, peer := range peers { - - if len(peer.AllowedIPs) > 0 && len(currentPeer.AllowedIPs) > 0 && - peer.AllowedIPs[0].String() == currentPeer.AllowedIPs[0].String() { - shouldDelete = false - } - // re-check this if logic is not working, added in case of allowedips not working - if peer.PublicKey.String() == currentPeer.PublicKey.String() { - shouldDelete = false - } - } - if shouldDelete { - output, err := ncutils.RunCmd("wg set "+iface+" peer "+currentPeer.PublicKey.String()+" remove", true) - if err != nil { - logger.Log(0, output, "error removing peer", currentPeer.PublicKey.String()) - } - } - for _, ip := range currentPeer.AllowedIPs { - oldPeerAllowedIps[ip.String()] = true - } - } - } - } - - // if routes are wrong, come back to this, but should work...I would think. Or we should get it working. - if len(peers) > 0 { - local.SetPeerRoutes(iface, oldPeerAllowedIps, peers) - } - - return nil -} - -// Initializes a WireGuard interface -func InitWireguard(node *models.LegacyNode, privkey string, peers []wgtypes.PeerConfig) error { - - key, err := wgtypes.ParseKey(privkey) - if err != nil { - return err - } - - wgclient, err := wgctrl.New() - if err != nil { - return err - } - defer wgclient.Close() - //nodecfg := modcfg.Node - var ifacename string - if node.Interface != "" { - ifacename = node.Interface - } else { - return fmt.Errorf("no interface to configure") - } - if node.PrimaryAddress() == "" { - return fmt.Errorf("no address to configure") - } - if err := WriteWgConfig(node, key.String(), peers); err != nil { - logger.Log(1, "error writing wg conf file: ", err.Error()) - return err - } - // spin up userspace / windows interface + apply the conf file - confPath := ncutils.GetNetclientPathSpecific() + ifacename + ".conf" - var deviceiface = ifacename - var mErr error - if ncutils.IsMac() { // if node is Mac (Darwin) get the tunnel name first - deviceiface, mErr = local.GetMacIface(node.PrimaryAddress()) - if mErr != nil || deviceiface == "" { - deviceiface = ifacename - } - } - // ensure you clear any existing interface first - RemoveConfGraceful(deviceiface) - ApplyConf(node, ifacename, confPath) // Apply initially - logger.Log(1, "waiting for interface...") // ensure interface is created - output, _ := ncutils.RunCmd("wg", false) - starttime := time.Now() - ifaceReady := strings.Contains(output, deviceiface) - for !ifaceReady && !(time.Now().After(starttime.Add(time.Second << 4))) { - if ncutils.IsMac() { // if node is Mac (Darwin) get the tunnel name first - deviceiface, mErr = local.GetMacIface(node.PrimaryAddress()) - if mErr != nil || deviceiface == "" { - deviceiface = ifacename - } - } - output, _ = ncutils.RunCmd("wg", false) - err = ApplyConf(node, node.Interface, confPath) - time.Sleep(time.Second) - ifaceReady = strings.Contains(output, deviceiface) - } - //wgclient does not work well on freebsd - if node.OS == "freebsd" { - if !ifaceReady { - return fmt.Errorf("could not reliably create interface, please check wg installation and retry") - } - } else { - _, devErr := wgclient.Device(deviceiface) - if !ifaceReady || devErr != nil { - fmt.Printf("%v\n", devErr) - return fmt.Errorf("could not reliably create interface, please check wg installation and retry") - } - } - logger.Log(1, "interface ready - netclient.. ENGAGE") - - if !ncutils.HasWgQuick() && ncutils.IsLinux() { - err = SetPeers(ifacename, node, peers) - if err != nil { - logger.Log(1, "error setting peers: ", err.Error()) - } - - time.Sleep(time.Second) - } - - //ipv4 - if node.Address != "" { - _, cidr, cidrErr := net.ParseCIDR(node.NetworkSettings.AddressRange) - if cidrErr == nil { - local.SetCIDRRoute(ifacename, node.Address, cidr) - } else { - logger.Log(1, "could not set cidr route properly: ", cidrErr.Error()) - } - local.SetCurrentPeerRoutes(ifacename, node.Address, peers) - } - if node.Address6 != "" { - //ipv6 - _, cidr, cidrErr := net.ParseCIDR(node.NetworkSettings.AddressRange6) - if cidrErr == nil { - local.SetCIDRRoute(ifacename, node.Address6, cidr) - } else { - logger.Log(1, "could not set cidr route properly: ", cidrErr.Error()) - } - local.SetCurrentPeerRoutes(ifacename, node.Address6, peers) - } - return err -} - -// SetWGConfig - sets the WireGuard Config of a given network and checks if it needs a peer update -func SetWGConfig(network string, peerupdate bool, peers []wgtypes.PeerConfig) error { - - cfg, err := config.ReadConfig(network) - if err != nil { - return err - } - privkey, err := RetrievePrivKey(network) - if err != nil { - return err - } - if peerupdate && !ncutils.IsFreeBSD() && !(ncutils.IsLinux() && !ncutils.IsKernel()) { - var iface string - iface = cfg.Node.Interface - if ncutils.IsMac() { - iface, err = local.GetMacIface(cfg.Node.PrimaryAddress()) - if err != nil { - return err - } - } - err = SetPeers(iface, &cfg.Node, peers) - } else { - err = InitWireguard(&cfg.Node, privkey, peers) - } - return err -} - -// RemoveConf - removes a configuration for a given WireGuard interface -func RemoveConf(iface string, printlog bool) error { - os := runtime.GOOS - if ncutils.IsLinux() && !ncutils.HasWgQuick() { - os = "nowgquick" - } - var err error - switch os { - case "nowgquick": - err = RemoveWithoutWGQuick(iface) - case "windows": - err = RemoveWindowsConf(iface, printlog) - default: - confPath := ncutils.GetNetclientPathSpecific() + iface + ".conf" - err = RemoveWGQuickConf(confPath, printlog) - } - return err -} - -// ApplyConf - applys a conf on disk to WireGuard interface -func ApplyConf(node *models.LegacyNode, ifacename string, confPath string) error { - os := runtime.GOOS - if ncutils.IsLinux() && !ncutils.HasWgQuick() { - os = "nowgquick" - } - var isConnected = node.Connected != "no" - var err error - switch os { - case "windows": - ApplyWindowsConf(confPath, ifacename, isConnected) - case "nowgquick": - ApplyWithoutWGQuick(node, ifacename, confPath, isConnected) - default: - ApplyWGQuickConf(confPath, ifacename, isConnected) - } - - var nodeCfg config.ClientConfig - nodeCfg.Network = node.Network - if !(node.IsServer == "yes") { - nodeCfg.ReadConfig() - if nodeCfg.NetworkSettings.AddressRange != "" { - ip, cidr, err := net.ParseCIDR(nodeCfg.NetworkSettings.AddressRange) - if err == nil { - local.SetCIDRRoute(node.Interface, ip.String(), cidr) - } - } - if nodeCfg.NetworkSettings.AddressRange6 != "" { - ip, cidr, err := net.ParseCIDR(nodeCfg.NetworkSettings.AddressRange6) - if err == nil { - local.SetCIDRRoute(node.Interface, ip.String(), cidr) - } - } - } - return err -} - -// WriteWgConfig - creates a wireguard config file -func WriteWgConfig(node *models.LegacyNode, privateKey string, peers []wgtypes.PeerConfig) error { - options := ini.LoadOptions{ - AllowNonUniqueSections: true, - AllowShadows: true, - } - wireguard := ini.Empty(options) - wireguard.Section(section_interface).Key("PrivateKey").SetValue(privateKey) - if node.ListenPort > 0 && node.UDPHolePunch != "yes" { - wireguard.Section(section_interface).Key("ListenPort").SetValue(strconv.Itoa(int(node.ListenPort))) - } - addrString := node.Address - if node.Address6 != "" { - if addrString != "" { - addrString += "," - } - addrString += node.Address6 - } - wireguard.Section(section_interface).Key("Address").SetValue(addrString) - // need to figure out DNS - //if node.DNSOn == "yes" { - // wireguard.Section(section_interface).Key("DNS").SetValue(cfg.Server.CoreDNSAddr) - //} - //need to split postup/postdown because ini lib adds a ` and the ` breaks freebsd - //works fine on others - if node.PostUp != "" { - if node.OS == "freebsd" { - parts := strings.Split(node.PostUp, " ; ") - for i, part := range parts { - if i == 0 { - wireguard.Section(section_interface).Key("PostUp").SetValue(part) - } - wireguard.Section(section_interface).Key("PostUp").AddShadow(part) - } - } else { - wireguard.Section(section_interface).Key("PostUp").SetValue((node.PostUp)) - } - } - if node.PostDown != "" { - if node.OS == "freebsd" { - parts := strings.Split(node.PostDown, " ; ") - for i, part := range parts { - if i == 0 { - wireguard.Section(section_interface).Key("PostDown").SetValue(part) - } - wireguard.Section(section_interface).Key("PostDown").AddShadow(part) - } - } else { - wireguard.Section(section_interface).Key("PostDown").SetValue((node.PostDown)) - } - } - if node.MTU != 0 { - wireguard.Section(section_interface).Key("MTU").SetValue(strconv.FormatInt(int64(node.MTU), 10)) - } - for i, peer := range peers { - wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) - if peer.PresharedKey != nil { - wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) - } - if peer.AllowedIPs != nil { - var allowedIPs string - for i, ip := range peer.AllowedIPs { - if i == 0 { - allowedIPs = ip.String() - } else { - allowedIPs = allowedIPs + ", " + ip.String() - } - } - wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) - } - if peer.Endpoint != nil { - wireguard.SectionWithIndex(section_peers, i).Key("Endpoint").SetValue(peer.Endpoint.String()) - } - - if peer.PersistentKeepaliveInterval != nil && peer.PersistentKeepaliveInterval.Seconds() > 0 { - wireguard.SectionWithIndex(section_peers, i).Key("PersistentKeepalive").SetValue(strconv.FormatInt((int64)(peer.PersistentKeepaliveInterval.Seconds()), 10)) - } - } - if err := wireguard.SaveTo(ncutils.GetNetclientPathSpecific() + node.Interface + ".conf"); err != nil { - return err - } - return nil -} - -// UpdateWgPeers - updates the peers of a network -func UpdateWgPeers(file string, peers []wgtypes.PeerConfig) (*net.UDPAddr, error) { - var internetGateway *net.UDPAddr - options := ini.LoadOptions{ - AllowNonUniqueSections: true, - AllowShadows: true, - } - wireguard, err := ini.LoadSources(options, file) - if err != nil { - return internetGateway, err - } - //delete the peers sections as they are going to be replaced - wireguard.DeleteSection(section_peers) - for i, peer := range peers { - wireguard.SectionWithIndex(section_peers, i).Key("PublicKey").SetValue(peer.PublicKey.String()) - if peer.PresharedKey != nil { - wireguard.SectionWithIndex(section_peers, i).Key("PreSharedKey").SetValue(peer.PresharedKey.String()) - } - if peer.AllowedIPs != nil { - var allowedIPs string - for i, ip := range peer.AllowedIPs { - if i == 0 { - allowedIPs = ip.String() - } else { - allowedIPs = allowedIPs + ", " + ip.String() - } - } - wireguard.SectionWithIndex(section_peers, i).Key("AllowedIps").SetValue(allowedIPs) - if strings.Contains(allowedIPs, "0.0.0.0/0") || strings.Contains(allowedIPs, "::/0") { - internetGateway = peer.Endpoint - } - } - if peer.Endpoint != nil { - wireguard.SectionWithIndex(section_peers, i).Key("Endpoint").SetValue(peer.Endpoint.String()) - } - if peer.PersistentKeepaliveInterval != nil && peer.PersistentKeepaliveInterval.Seconds() > 0 { - wireguard.SectionWithIndex(section_peers, i).Key("PersistentKeepalive").SetValue(strconv.FormatInt((int64)(peer.PersistentKeepaliveInterval.Seconds()), 10)) - } - } - if err := wireguard.SaveTo(file); err != nil { - return internetGateway, err - } - return internetGateway, nil -} - -// UpdateWgInterface - updates the interface section of a wireguard config file -func UpdateWgInterface(file, privateKey, nameserver string, node models.LegacyNode) error { - options := ini.LoadOptions{ - AllowNonUniqueSections: true, - AllowShadows: true, - } - wireguard, err := ini.LoadSources(options, file) - if err != nil { - return err - } - if node.UDPHolePunch == "yes" { - node.ListenPort = 0 - } - wireguard.DeleteSection(section_interface) - wireguard.Section(section_interface).Key("PrivateKey").SetValue(privateKey) - wireguard.Section(section_interface).Key("ListenPort").SetValue(strconv.Itoa(int(node.ListenPort))) - addrString := node.Address - if node.Address6 != "" { - if addrString != "" { - addrString += "," - } - addrString += node.Address6 - } - wireguard.Section(section_interface).Key("Address").SetValue(addrString) - //if node.DNSOn == "yes" { - // wireguard.Section(section_interface).Key("DNS").SetValue(nameserver) - //} - //need to split postup/postdown because ini lib adds a quotes which breaks freebsd - if node.PostUp != "" { - if node.OS == "freebsd" { - parts := strings.Split(node.PostUp, " ; ") - for i, part := range parts { - if i == 0 { - wireguard.Section(section_interface).Key("PostUp").SetValue(part) - } - wireguard.Section(section_interface).Key("PostUp").AddShadow(part) - } - } else { - wireguard.Section(section_interface).Key("PostUp").SetValue(node.PostUp) - } - } - if node.PostDown != "" { - if node.OS == "freebsd" { - parts := strings.Split(node.PostDown, " ; ") - for i, part := range parts { - if i == 0 { - wireguard.Section(section_interface).Key("PostDown").SetValue(part) - } - wireguard.Section(section_interface).Key("PostDown").AddShadow(part) - } - } else { - wireguard.Section(section_interface).Key("PostDown").SetValue(node.PostDown) - } - } - if node.MTU != 0 { - wireguard.Section(section_interface).Key("MTU").SetValue(strconv.FormatInt(int64(node.MTU), 10)) - } - if err := wireguard.SaveTo(file); err != nil { - return err - } - return nil -} - -// UpdatePrivateKey - updates the private key of a wireguard config file -func UpdatePrivateKey(file, privateKey string) error { - options := ini.LoadOptions{ - AllowNonUniqueSections: true, - AllowShadows: true, - } - wireguard, err := ini.LoadSources(options, file) - if err != nil { - return err - } - wireguard.Section(section_interface).Key("PrivateKey").SetValue(privateKey) - if err := wireguard.SaveTo(file); err != nil { - return err - } - return nil -} - -// UpdateKeepAlive - updates the persistentkeepalive of all peers -func UpdateKeepAlive(file string, keepalive int32) error { - options := ini.LoadOptions{ - AllowNonUniqueSections: true, - AllowShadows: true, - } - wireguard, err := ini.LoadSources(options, file) - if err != nil { - return err - } - peers, err := wireguard.SectionsByName(section_peers) - if err != nil { - return err - } - newvalue := strconv.Itoa(int(keepalive)) - for i := range peers { - wireguard.SectionWithIndex(section_peers, i).Key("PersistentKeepALive").SetValue(newvalue) - } - if err := wireguard.SaveTo(file); err != nil { - return err - } - return nil -} - -// RemoveConfGraceful - Run remove conf and wait for it to actually be gone before proceeding -func RemoveConfGraceful(ifacename string) { - // ensure you clear any existing interface first - wgclient, err := wgctrl.New() - if err != nil { - logger.Log(0, "could not create wgclient") - return - } - defer wgclient.Close() - d, _ := wgclient.Device(ifacename) - startTime := time.Now() - for d != nil && d.Name == ifacename { - if err = RemoveConf(ifacename, false); err != nil { // remove interface first - if strings.Contains(err.Error(), "does not exist") { - err = nil - break - } - } - time.Sleep(time.Second >> 2) - d, _ = wgclient.Device(ifacename) - if time.Now().After(startTime.Add(time.Second << 4)) { - break - } - } - time.Sleep(time.Second << 1) -} - -// GetDevicePeers - gets the current device's peers -func GetDevicePeers(iface string) ([]wgtypes.Peer, error) { - if ncutils.IsFreeBSD() { - if devicePeers, err := ncutils.GetPeers(iface); err != nil { - return nil, err - } else { - return devicePeers, nil - } - } else { - client, err := wgctrl.New() - if err != nil { - logger.Log(0, "failed to start wgctrl") - return nil, err - } - defer client.Close() - device, err := client.Device(iface) - if err != nil { - logger.Log(0, "failed to parse interface", iface) - return nil, err - } - return device.Peers, nil - } -} diff --git a/netclient/wireguard/mac.go b/netclient/wireguard/mac.go deleted file mode 100644 index a44f62ee..00000000 --- a/netclient/wireguard/mac.go +++ /dev/null @@ -1,27 +0,0 @@ -package wireguard - -import ( - "errors" - "fmt" - "strings" - - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// GetRealIface - retrieves tun iface based on reference iface name from config file -func GetRealIface(iface string) (string, error) { - ncutils.RunCmd("wg show interfaces", false) - ifacePath := "/var/run/wireguard/" + iface + ".name" - if !(ncutils.FileExists(ifacePath)) { - return "", errors.New(ifacePath + " does not exist") - } - realIfaceName, err := ncutils.GetFileAsString(ifacePath) - if err != nil { - return "", err - } - realIfaceName = strings.TrimSpace(realIfaceName) - if !(ncutils.FileExists(fmt.Sprintf("/var/run/wireguard/%s.sock", realIfaceName))) { - return "", errors.New("interface file does not exist") - } - return realIfaceName, nil -} diff --git a/netclient/wireguard/noquick.go b/netclient/wireguard/noquick.go deleted file mode 100644 index 8df9e4f9..00000000 --- a/netclient/wireguard/noquick.go +++ /dev/null @@ -1,168 +0,0 @@ -package wireguard - -import ( - "errors" - "fmt" - "os" - "os/exec" - "strconv" - "strings" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/config" - "github.com/gravitl/netmaker/netclient/ncutils" - "golang.zx2c4.com/wireguard/wgctrl" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" -) - -const disconnect_error = "node disconnected" - -// ApplyWithoutWGQuick - Function for running the equivalent of "wg-quick up" for linux if wg-quick is missing -func ApplyWithoutWGQuick(node *models.LegacyNode, ifacename, confPath string, isConnected bool) error { - - ipExec, err := exec.LookPath("ip") - if err != nil { - return err - } - wgclient, err := wgctrl.New() - if err != nil { - return err - } - defer wgclient.Close() - - privkey, err := RetrievePrivKey(node.Network) - if err != nil { - return err - } - key, err := wgtypes.ParseKey(privkey) - if err != nil { - return err - } - conf := wgtypes.Config{} - nodeport := int(node.ListenPort) - if node.UDPHolePunch == "yes" && - node.IsServer == "no" && - node.IsIngressGateway != "yes" { - conf = wgtypes.Config{ - PrivateKey: &key, - } - } else { - conf = wgtypes.Config{ - PrivateKey: &key, - ListenPort: &nodeport, - } - } - var address4 string - var address6 string - var mask4 string - var mask6 string - if node.Address != "" { - netmaskArr := strings.Split(node.NetworkSettings.AddressRange, "/") - var netmask = "32" - if len(netmaskArr) == 2 { - netmask = netmaskArr[1] - } - mask4 = netmask - address4 = node.Address - } - if node.Address6 != "" { - netmaskArr := strings.Split(node.NetworkSettings.AddressRange6, "/") - var netmask = "128" - if len(netmaskArr) == 2 { - netmask = netmaskArr[1] - } - mask6 = netmask - address6 = node.Address6 - } - err = setKernelDevice(ifacename, address4, mask4, address6, mask6, isConnected) - if err != nil { - if err.Error() == disconnect_error { - return nil - } - } - - _, err = wgclient.Device(ifacename) - if err != nil { - if !os.IsNotExist(err) { - return errors.New("Unknown config error: " + err.Error()) - } - } - err = wgclient.ConfigureDevice(ifacename, conf) - if err != nil { - if os.IsNotExist(err) { - logger.Log(0, "Could not configure device: ", err.Error()) - } - } - if _, err := ncutils.RunCmd(ipExec+" link set down dev "+ifacename, false); err != nil { - logger.Log(1, "attempted to remove interface before editing") - return err - } - if node.PostDown != "" { - ncutils.RunCmd(node.PostDown, false) - } - // set MTU of node interface - if _, err := ncutils.RunCmd(ipExec+" link set mtu "+strconv.Itoa(int(node.MTU))+" up dev "+ifacename, true); err != nil { - logger.Log(1, "failed to create interface with mtu ", strconv.Itoa(int(node.MTU)), "-", ifacename) - return err - } - if node.PostUp != "" { - ncutils.RunCmd(node.PostUp, false) - } - if node.Address6 != "" { - logger.Log(1, "adding address: ", node.Address6) - netmaskArr := strings.Split(node.NetworkSettings.AddressRange6, "/") - var netmask = "64" - if len(netmaskArr) == 2 { - netmask = netmaskArr[1] - } - ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+node.Address6+"/"+netmask, true) - } - return nil -} - -// RemoveWithoutWGQuick - Function for running the equivalent of "wg-quick down" for linux if wg-quick is missing -func RemoveWithoutWGQuick(ifacename string) error { - ipExec, err := exec.LookPath("ip") - if err != nil { - return err - } - out, err := ncutils.RunCmd(ipExec+" link del "+ifacename, false) - dontprint := strings.Contains(out, "does not exist") || strings.Contains(out, "Cannot find device") - if err != nil && !dontprint { - logger.Log(1, "error running command: ", ipExec, " link del ", ifacename) - logger.Log(1, out) - } - network := strings.ReplaceAll(ifacename, "nm-", "") - nodeconf, err := config.ReadConfig(network) - if nodeconf != nil && err == nil { - if nodeconf.Node.PostDown != "" { - ncutils.RunCmd(nodeconf.Node.PostDown, false) - } - } else if err != nil { - logger.Log(1, "error retrieving config: ", err.Error()) - } - return err -} - -func setKernelDevice(ifacename, address4, mask4, address6, mask6 string, isConnected bool) error { - ipExec, err := exec.LookPath("ip") - if err != nil { - return err - } - - // == best effort == - ncutils.RunCmd("ip link delete dev "+ifacename, false) - if !isConnected { - return fmt.Errorf(disconnect_error) - } - - ncutils.RunCmd(ipExec+" link add dev "+ifacename+" type wireguard", true) - if address4 != "" { - ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+address4+"/"+mask4, true) - } - if address6 != "" { - ncutils.RunCmd(ipExec+" address add dev "+ifacename+" "+address6+"/"+mask6, true) - } - return nil -} diff --git a/netclient/wireguard/unix.go b/netclient/wireguard/unix.go deleted file mode 100644 index 1847b717..00000000 --- a/netclient/wireguard/unix.go +++ /dev/null @@ -1,51 +0,0 @@ -package wireguard - -import ( - "fmt" - "os" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// ApplyWGQuickConf - applies wg-quick commands if os supports -func ApplyWGQuickConf(confPath, ifacename string, isConnected bool) error { - if ncutils.IsWindows() { - return ApplyWindowsConf(confPath, ifacename, isConnected) - } else { - _, err := os.Stat(confPath) - if err != nil { - logger.Log(0, confPath+" does not exist "+err.Error()) - return err - } - if ncutils.IfaceExists(ifacename) { - ncutils.RunCmd("wg-quick down "+confPath, true) - } - if !isConnected { - return nil - } - _, err = ncutils.RunCmd("wg-quick up "+confPath, true) - - return err - } -} - -// RemoveWGQuickConf - calls wg-quick down -func RemoveWGQuickConf(confPath string, printlog bool) error { - _, err := ncutils.RunCmd(fmt.Sprintf("wg-quick down %s", confPath), printlog) - return err -} - -// StorePrivKey - stores wg priv key on disk locally -func StorePrivKey(key string, network string) error { - var err error - d1 := []byte(key) - err = os.WriteFile(ncutils.GetNetclientPathSpecific()+"wgkey-"+network, d1, 0600) - return err -} - -// RetrievePrivKey - reads wg priv key from local disk -func RetrievePrivKey(network string) (string, error) { - dat, err := ncutils.GetFileWithRetry(ncutils.GetNetclientPathSpecific()+"wgkey-"+network, 2) - return string(dat), err -} diff --git a/netclient/wireguard/windows.go b/netclient/wireguard/windows.go deleted file mode 100644 index cafac90d..00000000 --- a/netclient/wireguard/windows.go +++ /dev/null @@ -1,30 +0,0 @@ -package wireguard - -import ( - "fmt" - - "github.com/gravitl/netmaker/logger" - "github.com/gravitl/netmaker/netclient/ncutils" -) - -// ApplyWindowsConf - applies the WireGuard configuration file on Windows -func ApplyWindowsConf(confPath, iface string, isConnected bool) error { - RemoveConfGraceful(iface) // have to remove gracefully before applying windows conf - - if !isConnected { - return nil - } - var commandLine = fmt.Sprintf(`wireguard.exe /installtunnelservice "%s"`, confPath) - if _, err := ncutils.RunCmdFormatted(commandLine, false); err != nil { - return err - } - return nil -} - -// RemoveWindowsConf - removes the WireGuard configuration file on Windows and dpapi file -func RemoveWindowsConf(ifacename string, printlog bool) error { - if _, err := ncutils.RunCmd("wireguard.exe /uninstalltunnelservice "+ifacename, printlog); err != nil { - logger.Log(1, err.Error()) - } - return nil -} diff --git a/serverctl/serverctl.go b/serverctl/serverctl.go index 3833ac5f..ef450599 100644 --- a/serverctl/serverctl.go +++ b/serverctl/serverctl.go @@ -1,8 +1,6 @@ package serverctl import ( - "net" - "os" "strings" "github.com/gravitl/netmaker/database" @@ -11,8 +9,6 @@ import ( "github.com/gravitl/netmaker/logic/acls" "github.com/gravitl/netmaker/logic/acls/nodeacls" "github.com/gravitl/netmaker/logic/pro" - "github.com/gravitl/netmaker/netclient/ncutils" - "github.com/gravitl/netmaker/servercfg" ) const ( @@ -20,110 +16,6 @@ const ( NETMAKER_BINARY_NAME = "netmaker" ) -// InitServerNetclient - intializes the server netclient -// 1. Check if config directory exists, if not attempt to make -// 2. Check current networks and run pull to get interface up to date in case of restart -func InitServerNetclient() error { - netclientDir := ncutils.GetNetclientPath() - _, err := os.Stat(netclientDir + "/config") - if os.IsNotExist(err) { - os.MkdirAll(netclientDir+"/config", 0700) - } else if err != nil { - logger.Log(1, "could not find or create", netclientDir) - return err - } - - var networks, netsErr = logic.GetNetworks() - if netsErr == nil || database.IsEmptyRecord(netsErr) { - for _, network := range networks { - var currentServerNode, nodeErr = logic.GetNetworkServerLocal(network.NetID) - if nodeErr == nil { - if currentServerNode.Version != servercfg.Version { - currentServerNode.Version = servercfg.Version - logic.UpdateNode(¤tServerNode, ¤tServerNode) - } - if err = logic.ServerPull(¤tServerNode, true); err != nil { - logger.Log(1, "failed pull for network", network.NetID, ", on server node", currentServerNode.ID) - } - } - if err = logic.InitializeNetUsers(&network); err != nil { - logger.Log(0, "something went wrong syncing usrs on network", network.NetID, "-", err.Error()) - } - } - } - - return nil -} - -func SyncServerNetworkWithProxy() error { - networks, err := logic.GetNetworks() - if err != nil { - logger.Log(1, "error retrieving networks for keepalive", err.Error()) - } - for _, network := range networks { - serverNetworkSettings, err := logic.GetNetwork(network.NetID) - if err != nil { - continue - } - localnets, err := net.Interfaces() - if err != nil { - return err - } - ifaceExists := false - for _, localnet := range localnets { - if serverNetworkSettings.DefaultInterface == localnet.Name { - ifaceExists = true - } - } - if ifaceExists { - serverNode, err := logic.GetNetworkServerLocal(network.NetID) - if err != nil { - logger.Log(1, "failed to retrieve local server node: ", serverNode.ID) - continue - } - proxyPayload, err := logic.GetPeersForProxy(&serverNode, false) - if err != nil && !ncutils.IsEmptyRecord(err) { - logger.Log(1, "failed to retrieve peers for server node: ", serverNode.ID) - continue - } - logic.ProxyMgmChan <- &proxyPayload - - } - - } - return nil -} - -// SyncServerNetwork - ensures a wg interface and node exists for server -func SyncServerNetwork(network string) error { - serverNetworkSettings, err := logic.GetNetwork(network) - if err != nil { - return err - } - localnets, err := net.Interfaces() - if err != nil { - return err - } - - ifaceExists := false - for _, localnet := range localnets { - if serverNetworkSettings.DefaultInterface == localnet.Name { - ifaceExists = true - } - } - - serverNode, err := logic.GetNetworkServerLocal(network) - if !ifaceExists && (err == nil && serverNode.ID != "") { - return logic.ServerUpdate(&serverNode, true) - } else if !ifaceExists { - _, err := logic.ServerJoin(&serverNetworkSettings) - if err != nil { - logger.Log(0, "network add failed for "+serverNetworkSettings.NetID) - } - } - return nil -} - func SetDefaults() error { if err := setNodeDefaults(); err != nil { return err @@ -150,10 +42,10 @@ func setNodeDefaults() error { for i := range nodes { logic.SetNodeDefaults(&nodes[i]) logic.UpdateNode(&nodes[i], &nodes[i]) - currentNodeACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(nodes[i].Network), nodeacls.NodeID(nodes[i].ID)) + currentNodeACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(nodes[i].Network), nodeacls.NodeID(nodes[i].ID.String())) if (err != nil && (database.IsEmptyRecord(err) || strings.Contains(err.Error(), "no node ACL present"))) || currentNodeACL == nil { - if _, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(nodes[i].Network), nodeacls.NodeID(nodes[i].ID), acls.Allowed); err != nil { - logger.Log(1, "could not create a default ACL for node", nodes[i].ID) + if _, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(nodes[i].Network), nodeacls.NodeID(nodes[i].ID.String()), acls.Allowed); err != nil { + logger.Log(1, "could not create a default ACL for node", nodes[i].ID.String()) } } }