From 1a1ba1ccf4d7aed68cd0c1ce35f06e950ef91dcb Mon Sep 17 00:00:00 2001 From: Gabriel de Souza Seibel Date: Thu, 31 Aug 2023 23:12:05 -0300 Subject: [PATCH] [NET-546] Move ee code to ee package, unify ee status and terminology (#2538) * Move ee code to ee package and unify ee status to IsPro * Consolidate naming for paid/professional/enterprise version as "pro". Notes: - Changes image tags - Changes build tags - Changes package names - Doesn't change links to docs that mention "ee" - Doesn't change parameters sent to PostHog that mention "ee" * Revert docker image tag being -pro, back to -ee * Revert go build tag being pro, back to ee * Add build tags for some ee content * [2] Revert go build tag being pro, back to ee * Fix test workflow * Add a json tag to be backwards compatible with frontend "IsEE" check * Add a json tag for the serverconfig struct for IsEE * Ammend json tag to Is_EE * fix ee tags --------- Co-authored-by: Abhishek Kondur --- .github/workflows/publish-docker.yml | 2 +- .github/workflows/test.yml | 2 +- cli/functions/network_user.go | 6 +- ...-compose.ee.yml => docker-compose.pro.yml} | 0 config/config.go | 2 +- controllers/hosts.go | 2 +- controllers/migrate.go | 2 +- controllers/node.go | 53 ++--- controllers/server.go | 7 +- docker/{Caddyfile-EE => Caddyfile-pro} | 0 ee/logic/ext_acls.go | 41 ---- logic/auth.go | 2 +- logic/clients.go | 43 +--- logic/gateway.go | 2 +- logic/hosts.go | 2 +- logic/metrics.go | 39 +--- logic/nodes.go | 40 +--- logic/peers.go | 65 +----- logic/pro/proacls/nodes.go | 35 --- logic/relay.go | 144 +----------- logic/security.go | 2 +- logic/telemetry.go | 14 +- main.go | 2 +- main_ee.go | 6 +- models/node.go | 6 +- models/structs.go | 2 +- mq/handlers.go | 194 ++-------------- mq/publishers.go | 2 +- mq/util.go | 4 +- {ee => pro}/LICENSE | 0 .../controllers}/metrics.go | 13 +- .../controllers}/middleware.go | 2 +- .../controllers}/networkusers.go | 2 +- .../controllers}/relay.go | 9 +- .../controllers}/usergroups.go | 2 +- {ee => pro}/initialize.go | 54 +++-- {ee => pro}/license.go | 2 +- {ee => pro}/license_test.go | 2 +- pro/logic/ext_acls.go | 114 +++++++++ {ee => pro}/logic/failover.go | 6 +- pro/logic/metrics.go | 203 ++++++++++++++++ pro/logic/nodes.go | 21 ++ pro/logic/relays.go | 218 ++++++++++++++++++ {ee => pro}/types.go | 5 +- {ee => pro}/util.go | 13 +- release.md | 2 +- scripts/nm-certs.sh | 2 +- scripts/nm-quick.sh | 40 ++-- scripts/nm-upgrade.sh | 28 +-- servercfg/serverconf.go | 10 +- 50 files changed, 753 insertions(+), 716 deletions(-) rename compose/{docker-compose.ee.yml => docker-compose.pro.yml} (100%) rename docker/{Caddyfile-EE => Caddyfile-pro} (100%) delete mode 100644 ee/logic/ext_acls.go delete mode 100644 logic/pro/proacls/nodes.go rename {ee => pro}/LICENSE (100%) rename {ee/ee_controllers => pro/controllers}/metrics.go (93%) rename {ee/ee_controllers => pro/controllers}/middleware.go (95%) rename {ee/ee_controllers => pro/controllers}/networkusers.go (99%) rename {ee/ee_controllers => pro/controllers}/relay.go (93%) rename {ee/ee_controllers => pro/controllers}/usergroups.go (98%) rename {ee => pro}/initialize.go (56%) rename {ee => pro}/license.go (99%) rename {ee => pro}/license_test.go (99%) create mode 100644 pro/logic/ext_acls.go rename {ee => pro}/logic/failover.go (94%) create mode 100644 pro/logic/metrics.go create mode 100644 pro/logic/nodes.go create mode 100644 pro/logic/relays.go rename {ee => pro}/types.go (98%) rename {ee => pro}/util.go (85%) diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml index 19bd4998..fcf709ff 100644 --- a/.github/workflows/publish-docker.yml +++ b/.github/workflows/publish-docker.yml @@ -53,7 +53,7 @@ jobs: build-args: | tags=ce - docker-ee: + docker-pro: runs-on: ubuntu-latest steps: - diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 649a6313..072f07b2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -51,7 +51,7 @@ jobs: run: | go vet ./... go test -p 1 ./... -v - go test -p 1 ./ee -v --tags ee + go test -p 1 ./pro -v --tags ee env: DATABASE: sqlite CLIENT_MODE: "off" diff --git a/cli/functions/network_user.go b/cli/functions/network_user.go index f412fdee..b7563728 100644 --- a/cli/functions/network_user.go +++ b/cli/functions/network_user.go @@ -4,8 +4,8 @@ import ( "fmt" "net/http" - "github.com/gravitl/netmaker/ee/ee_controllers" "github.com/gravitl/netmaker/models/promodels" + proControllers "github.com/gravitl/netmaker/pro/controllers" ) // GetAllNetworkUsers - fetch all network users @@ -34,8 +34,8 @@ func UpdateNetworkUser(networkName string, payload *promodels.NetworkUser) { } // GetNetworkUserData - fetch a network user's complete data -func GetNetworkUserData(networkUserName string) *ee_controllers.NetworkUserDataMap { - return request[ee_controllers.NetworkUserDataMap](http.MethodGet, fmt.Sprintf("/api/networkusers/data/%s/me", networkUserName), nil) +func GetNetworkUserData(networkUserName string) *proControllers.NetworkUserDataMap { + return request[proControllers.NetworkUserDataMap](http.MethodGet, fmt.Sprintf("/api/networkusers/data/%s/me", networkUserName), nil) } // DeleteNetworkUser - delete a network user diff --git a/compose/docker-compose.ee.yml b/compose/docker-compose.pro.yml similarity index 100% rename from compose/docker-compose.ee.yml rename to compose/docker-compose.pro.yml diff --git a/config/config.go b/config/config.go index 569d430a..20a55b25 100644 --- a/config/config.go +++ b/config/config.go @@ -72,7 +72,7 @@ type ServerConfig struct { BasicAuth string `yaml:"basic_auth"` LicenseValue string `yaml:"license_value"` NetmakerTenantID string `yaml:"netmaker_tenant_id"` - IsEE string `yaml:"is_ee"` + IsPro string `yaml:"is_ee" json:"IsEE"` StunPort int `yaml:"stun_port"` StunList string `yaml:"stun_list"` TurnServer string `yaml:"turn_server"` diff --git a/controllers/hosts.go b/controllers/hosts.go index fee27871..17c13b07 100644 --- a/controllers/hosts.go +++ b/controllers/hosts.go @@ -336,7 +336,7 @@ func deleteHostFromNetwork(w http.ResponseWriter, r *http.Request) { node.Action = models.NODE_DELETE node.PendingDelete = true // notify node change - runUpdates(node, false) + mq.RunUpdates(node, false) go func() { // notify of peer change err = mq.PublishDeletedNodePeerUpdate(node) if err != nil { diff --git a/controllers/migrate.go b/controllers/migrate.go index 0d365664..cf808906 100644 --- a/controllers/migrate.go +++ b/controllers/migrate.go @@ -123,7 +123,7 @@ func migrate(w http.ResponseWriter, r *http.Request) { if err != nil { logger.Log(0, "error creating ingress gateway for node", node.ID, err.Error()) } - runUpdates(&ingressNode, true) + mq.RunUpdates(&ingressNode, true) } } } diff --git a/controllers/node.go b/controllers/node.go index 28de485d..dd3c39f2 100644 --- a/controllers/node.go +++ b/controllers/node.go @@ -415,7 +415,7 @@ func getNode(w http.ResponseWriter, r *http.Request) { PeerIDs: hostPeerUpdate.PeerIDs, } - if servercfg.Is_EE && nodeRequest { + if servercfg.IsPro && nodeRequest { if err = logic.EnterpriseResetAllPeersFailovers(node.ID, node.Network); err != nil { logger.Log(1, "failed to reset failover list during node config pull", node.ID.String(), node.Network) } @@ -471,7 +471,7 @@ func createEgressGateway(w http.ResponseWriter, r *http.Request) { go func() { mq.PublishPeerUpdate() }() - runUpdates(&node, true) + mq.RunUpdates(&node, true) } // swagger:route DELETE /api/nodes/{network}/{nodeid}/deletegateway nodes deleteEgressGateway @@ -512,7 +512,7 @@ func deleteEgressGateway(w http.ResponseWriter, r *http.Request) { go func() { mq.PublishPeerUpdate() }() - runUpdates(&node, true) + mq.RunUpdates(&node, true) } // == INGRESS == @@ -549,7 +549,7 @@ func createIngressGateway(w http.ResponseWriter, r *http.Request) { return } - if servercfg.Is_EE && request.Failover { + if servercfg.IsPro && request.Failover { if err = logic.EnterpriseResetFailoverFunc(node.Network); err != nil { logger.Log(1, "failed to reset failover list during failover create", node.ID.String(), node.Network) } @@ -560,7 +560,7 @@ func createIngressGateway(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(apiNode) - runUpdates(&node, true) + mq.RunUpdates(&node, true) } // swagger:route DELETE /api/nodes/{network}/{nodeid}/deleteingress nodes deleteIngressGateway @@ -593,7 +593,7 @@ func deleteIngressGateway(w http.ResponseWriter, r *http.Request) { return } - if servercfg.Is_EE && wasFailover { + if servercfg.IsPro && wasFailover { if err = logic.EnterpriseResetFailoverFunc(node.Network); err != nil { logger.Log(1, "failed to reset failover list during failover create", node.ID.String(), node.Network) } @@ -620,7 +620,7 @@ func deleteIngressGateway(w http.ResponseWriter, r *http.Request) { } } - runUpdates(&node, true) + mq.RunUpdates(&node, true) } // swagger:route PUT /api/nodes/{network}/{nodeid} nodes updateNode @@ -655,18 +655,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) { return } newNode := newData.ConvertToServerNode(¤tNode) - relayupdate := false - if servercfg.Is_EE && newNode.IsRelay && len(newNode.RelayedNodes) > 0 { - if len(newNode.RelayedNodes) != len(currentNode.RelayedNodes) { - relayupdate = true - } else { - for i, node := range newNode.RelayedNodes { - if node != currentNode.RelayedNodes[i] { - relayupdate = true - } - } - } - } + relayUpdate := logic.RelayUpdates(¤tNode, newNode) host, err := logic.GetHost(newNode.HostID.String()) if err != nil { logger.Log(0, r.Header.Get("user"), @@ -676,7 +665,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) { } ifaceDelta := logic.IfaceDelta(¤tNode, newNode) aclUpdate := currentNode.DefaultACL != newNode.DefaultACL - if ifaceDelta && servercfg.Is_EE { + if ifaceDelta && servercfg.IsPro { if err = logic.EnterpriseResetAllPeersFailovers(currentNode.ID, currentNode.Network); err != nil { logger.Log(0, "failed to reset failover lists during node update for node", currentNode.ID.String(), currentNode.Network) } @@ -689,13 +678,8 @@ func updateNode(w http.ResponseWriter, r *http.Request) { logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) return } - if relayupdate { - updatenodes := logic.UpdateRelayed(currentNode.ID.String(), currentNode.RelayedNodes, newNode.RelayedNodes) - if len(updatenodes) > 0 { - for _, relayedNode := range updatenodes { - runUpdates(&relayedNode, false) - } - } + if relayUpdate { + logic.UpdateRelayed(¤tNode, newNode) } if servercfg.IsDNSMode() { logic.SetDNS() @@ -705,7 +689,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) { logger.Log(1, r.Header.Get("user"), "updated node", currentNode.ID.String(), "on network", currentNode.Network) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(apiNode) - runUpdates(newNode, ifaceDelta) + mq.RunUpdates(newNode, ifaceDelta) go func(aclUpdate, relayupdate bool, newNode *models.Node) { if aclUpdate || relayupdate { if err := mq.PublishPeerUpdate(); err != nil { @@ -715,7 +699,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) { if err := mq.PublishReplaceDNS(¤tNode, newNode, host); err != nil { logger.Log(1, "failed to publish dns update", err.Error()) } - }(aclUpdate, relayupdate, newNode) + }(aclUpdate, relayUpdate, newNode) } // swagger:route DELETE /api/nodes/{network}/{nodeid} nodes deleteNode @@ -778,7 +762,7 @@ 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"]) if !fromNode { // notify node change - runUpdates(&node, false) + mq.RunUpdates(&node, false) } go func() { // notify of peer change var err error @@ -796,15 +780,6 @@ func deleteNode(w http.ResponseWriter, r *http.Request) { }() } -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.ID.String(), err.Error()) - } - }() -} - func doesUserOwnNode(username, network, nodeID string) bool { u, err := logic.GetUser(username) if err != nil { diff --git a/controllers/server.go b/controllers/server.go index df23f122..b4d4f696 100644 --- a/controllers/server.go +++ b/controllers/server.go @@ -25,7 +25,6 @@ func serverHandlers(r *mux.Router) { r.HandleFunc("/api/server/usage", Authorize(true, false, "user", http.HandlerFunc(getUsage))).Methods(http.MethodGet) } -// TODO move to EE package? there is a function and a type there for that already func getUsage(w http.ResponseWriter, r *http.Request) { type usage struct { Hosts int `json:"hosts"` @@ -164,9 +163,9 @@ func getConfig(w http.ResponseWriter, r *http.Request) { // get params scfg := servercfg.GetServerConfig() - scfg.IsEE = "no" - if servercfg.Is_EE { - scfg.IsEE = "yes" + scfg.IsPro = "no" + if servercfg.IsPro { + scfg.IsPro = "yes" } json.NewEncoder(w).Encode(scfg) //w.WriteHeader(http.StatusOK) diff --git a/docker/Caddyfile-EE b/docker/Caddyfile-pro similarity index 100% rename from docker/Caddyfile-EE rename to docker/Caddyfile-pro diff --git a/ee/logic/ext_acls.go b/ee/logic/ext_acls.go deleted file mode 100644 index 32138e25..00000000 --- a/ee/logic/ext_acls.go +++ /dev/null @@ -1,41 +0,0 @@ -package logic - -import "github.com/gravitl/netmaker/models" - -// DenyClientNode - add a denied node to an ext client's list -func DenyClientNode(ec *models.ExtClient, clientOrNodeID string) (ok bool) { - if ec == nil || len(clientOrNodeID) == 0 { - return - } - if ec.DeniedACLs == nil { - ec.DeniedACLs = map[string]struct{}{} - } - ok = true - ec.DeniedACLs[clientOrNodeID] = struct{}{} - return -} - -// IsClientNodeAllowed - checks if given ext client and node are allowed to communicate -func IsClientNodeAllowed(ec *models.ExtClient, clientOrNodeID string) bool { - if ec == nil || len(clientOrNodeID) == 0 { - return false - } - if ec.DeniedACLs == nil { - return true - } - _, ok := ec.DeniedACLs[clientOrNodeID] - return !ok -} - -// RemoveDeniedNodeFromClient - removes a node id from set of denied nodes -func RemoveDeniedNodeFromClient(ec *models.ExtClient, clientOrNodeID string) bool { - if ec.DeniedACLs == nil { - return true - } - _, ok := ec.DeniedACLs[clientOrNodeID] - if !ok { - return false - } - delete(ec.DeniedACLs, clientOrNodeID) - return true -} diff --git a/logic/auth.go b/logic/auth.go index 6c2b210b..66e1e02d 100644 --- a/logic/auth.go +++ b/logic/auth.go @@ -128,7 +128,7 @@ func CreateUser(user *models.User) error { // legacy if StringSliceContains(user.Networks, currentNets[i].NetID) { - if !servercfg.Is_EE { + if !servercfg.IsPro { newUser.AccessLevel = pro.NET_ADMIN } } diff --git a/logic/clients.go b/logic/clients.go index db6dbab6..c11fb0cc 100644 --- a/logic/clients.go +++ b/logic/clients.go @@ -22,48 +22,15 @@ var ( AllowClientNodeAccess = func(ec *models.ExtClient, clientOrNodeID string) bool { return true } -) - -// SetClientDefaultACLs - set's a client's default ACLs based on network and nodes in network -func SetClientDefaultACLs(ec *models.ExtClient) error { - if !isEE { + SetClientDefaultACLs = func(ec *models.ExtClient) error { return nil } - networkNodes, err := GetNetworkNodes(ec.Network) - if err != nil { - return err + SetClientACLs = func(ec *models.ExtClient, newACLs map[string]struct{}) { } - network, err := GetNetwork(ec.Network) - if err != nil { - return err + UpdateProNodeACLs = func(node *models.Node) error { + return nil } - for i := range networkNodes { - currNode := networkNodes[i] - if network.DefaultACL == "no" || currNode.DefaultACL == "no" { - DenyClientNodeAccess(ec, currNode.ID.String()) - } else { - AllowClientNodeAccess(ec, currNode.ID.String()) - } - } - return nil -} - -// SetClientACLs - overwrites an ext client's ACL -func SetClientACLs(ec *models.ExtClient, newACLs map[string]struct{}) { - if ec == nil || newACLs == nil || !isEE { - return - } - ec.DeniedACLs = newACLs -} - -// IsClientNodeAllowedByID - checks if a given ext client ID + nodeID are allowed -func IsClientNodeAllowedByID(clientID, networkName, clientOrNodeID string) bool { - client, err := GetExtClient(clientID, networkName) - if err != nil { - return false - } - return IsClientNodeAllowed(&client, clientOrNodeID) -} +) // SortExtClient - Sorts slice of ExtClients by their ClientID alphabetically with numbers first func SortExtClient(unsortedExtClient []models.ExtClient) { diff --git a/logic/gateway.go b/logic/gateway.go index 094ffa80..e25aaa91 100644 --- a/logic/gateway.go +++ b/logic/gateway.go @@ -148,7 +148,7 @@ func CreateIngressGateway(netid string, nodeid string, ingress models.IngressReq node.IngressGatewayRange6 = network.AddressRange6 node.IngressDNS = ingress.ExtclientDNS node.SetLastModified() - if ingress.Failover && servercfg.Is_EE { + if ingress.Failover && servercfg.IsPro { node.Failover = true } err = UpsertNode(&node) diff --git a/logic/hosts.go b/logic/hosts.go index 895f571e..90e5d588 100644 --- a/logic/hosts.go +++ b/logic/hosts.go @@ -382,7 +382,7 @@ func DissasociateNodeFromHost(n *models.Node, h *models.Host) error { h.Nodes = RemoveStringSlice(h.Nodes, index) } go func() { - if servercfg.Is_EE { + if servercfg.IsPro { if clients, err := GetNetworkExtClients(n.Network); err != nil { for i := range clients { AllowClientNodeAccess(&clients[i], n.ID.String()) diff --git a/logic/metrics.go b/logic/metrics.go index 9c9816a3..2ac11552 100644 --- a/logic/metrics.go +++ b/logic/metrics.go @@ -1,39 +1,18 @@ package logic import ( - "encoding/json" - - "github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/models" ) -// GetMetrics - gets the metrics -func GetMetrics(nodeid string) (*models.Metrics, error) { +var DeleteMetrics = func(string) error { + return nil +} + +var UpdateMetrics = func(string, *models.Metrics) error { + return nil +} + +var GetMetrics = func(string) (*models.Metrics, error) { var metrics models.Metrics - record, err := database.FetchRecord(database.METRICS_TABLE_NAME, nodeid) - if err != nil { - if database.IsEmptyRecord(err) { - return &metrics, nil - } - return &metrics, err - } - err = json.Unmarshal([]byte(record), &metrics) - if err != nil { - return &metrics, err - } return &metrics, nil } - -// UpdateMetrics - updates the metrics of a given client -func UpdateMetrics(nodeid string, metrics *models.Metrics) error { - data, err := json.Marshal(metrics) - if err != nil { - return err - } - return database.Insert(nodeid, string(data), database.METRICS_TABLE_NAME) -} - -// DeleteMetrics - deletes metrics of a given node -func DeleteMetrics(nodeid string) error { - return database.DeleteRecord(database.METRICS_TABLE_NAME, nodeid) -} diff --git a/logic/nodes.go b/logic/nodes.go index 7c85b998..a809bbec 100644 --- a/logic/nodes.go +++ b/logic/nodes.go @@ -17,7 +17,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/logic/pro/proacls" "github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/validation" @@ -150,7 +149,7 @@ func UpdateNode(currentNode *models.Node, newNode *models.Node) error { } } nodeACLDelta := currentNode.DefaultACL != newNode.DefaultACL - newNode.Fill(currentNode, servercfg.Is_EE) + newNode.Fill(currentNode, servercfg.IsPro) // check for un-settable server values if err := ValidateNode(newNode, true); err != nil { @@ -159,7 +158,7 @@ func UpdateNode(currentNode *models.Node, newNode *models.Node) error { if newNode.ID == currentNode.ID { if nodeACLDelta { - if err := updateProNodeACLS(newNode); err != nil { + if err := UpdateProNodeACLs(newNode); err != nil { logger.Log(1, "failed to apply node level ACLs during creation of node", newNode.ID.String(), "-", err.Error()) return err } @@ -208,7 +207,7 @@ func DeleteNode(node *models.Node, purge bool) error { if err := DissasociateNodeFromHost(node, host); err != nil { return err } - if servercfg.Is_EE { + if servercfg.IsPro { if err := EnterpriseResetAllPeersFailovers(node.ID, node.Network); err != nil { logger.Log(0, "failed to reset failover lists during node delete for node", host.Name, node.Network) } @@ -421,21 +420,6 @@ func FindRelay(node *models.Node) *models.Node { return &relay } -// GetNetworkIngresses - gets the gateways of a network -func GetNetworkIngresses(network string) ([]models.Node, error) { - var ingresses []models.Node - netNodes, err := GetNetworkNodes(network) - if err != nil { - return []models.Node{}, err - } - for i := range netNodes { - if netNodes[i].IsIngressGateway { - ingresses = append(ingresses, netNodes[i]) - } - } - return ingresses, nil -} - // GetAllNodesAPI - get all nodes for api usage func GetAllNodesAPI(nodes []models.Node) []models.ApiNode { apiNodes := []models.ApiNode{} @@ -475,20 +459,6 @@ func DeleteExpiredNodes(ctx context.Context, peerUpdate chan *models.Node) { } } -// == PRO == - -func updateProNodeACLS(node *models.Node) error { - // == PRO node ACLs == - networkNodes, err := GetNetworkNodes(node.Network) - if err != nil { - return err - } - if err = proacls.AdjustNodeAcls(node, networkNodes[:]); err != nil { - return err - } - return nil -} - // createNode - creates a node in database func createNode(node *models.Node) error { // lock because we need unique IPs and having it concurrent makes parallel calls result in same "unique" IPs @@ -578,7 +548,7 @@ func createNode(node *models.Node) error { return err } - if err = updateProNodeACLS(node); err != nil { + if err = UpdateProNodeACLs(node); err != nil { logger.Log(1, "failed to apply node level ACLs during creation of node", node.ID.String(), "-", err.Error()) return err } @@ -600,5 +570,3 @@ func SortApiNodes(unsortedNodes []models.ApiNode) { return unsortedNodes[i].ID < unsortedNodes[j].ID }) } - -// == END PRO == diff --git a/logic/peers.go b/logic/peers.go index 0fe33298..33a19c99 100644 --- a/logic/peers.go +++ b/logic/peers.go @@ -377,36 +377,14 @@ func GetAllowedIPs(node, peer *models.Node, metrics *models.Metrics) []net.IPNet 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 && metrics.FailoverPeers != nil { - // traverse through nodes that need handling - 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.String() { - // get original node so we can traverse the allowed ips - nodeToFailover, err := GetNodeByID(k) - if err == nil { - 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.ID.String(), nodeToFailover.PrimaryAddress(), "to failover node", peer.ID.String()) - } - } - } - } - } - } } if node.IsRelayed && node.RelayedBy == peer.ID.String() { - allowedips = append(allowedips, getAllowedIpsForRelayed(node, peer)...) - + allowedips = append(allowedips, GetAllowedIpsForRelayed(node, peer)...) } return allowedips } -func getEgressIPs(peer *models.Node) []net.IPNet { +func GetEgressIPs(peer *models.Node) []net.IPNet { peerHost, err := GetHost(peer.HostID.String()) if err != nil { @@ -463,50 +441,15 @@ func getNodeAllowedIPs(peer, node *models.Node) []net.IPNet { // handle egress gateway peers if peer.IsEgressGateway { //hasGateway = true - egressIPs := getEgressIPs(peer) + egressIPs := GetEgressIPs(peer) allowedips = append(allowedips, egressIPs...) } if peer.IsRelay { - for _, relayedNodeID := range peer.RelayedNodes { - if node.ID.String() == relayedNodeID { - continue - } - relayedNode, err := GetNodeByID(relayedNodeID) - if err != nil { - continue - } - allowed := getRelayedAddresses(relayedNodeID) - if relayedNode.IsEgressGateway { - allowed = append(allowed, getEgressIPs(&relayedNode)...) - } - allowedips = append(allowedips, allowed...) - } + allowedips = append(allowedips, RelayedAllowedIPs(peer, node)...) } return allowedips } -// getAllowedIpsForRelayed - returns the peerConfig for a node relayed by relay -func getAllowedIpsForRelayed(relayed, relay *models.Node) (allowedIPs []net.IPNet) { - if relayed.RelayedBy != relay.ID.String() { - logger.Log(0, "RelayedByRelay called with invalid parameters") - return - } - peers, err := GetNetworkNodes(relay.Network) - if err != nil { - logger.Log(0, "error getting network clients", err.Error()) - return - } - for _, peer := range peers { - if peer.ID == relayed.ID || peer.ID == relay.ID { - continue - } - if nodeacls.AreNodesAllowed(nodeacls.NetworkID(relayed.Network), nodeacls.NodeID(relayed.ID.String()), nodeacls.NodeID(peer.ID.String())) { - allowedIPs = append(allowedIPs, GetAllowedIPs(relayed, &peer, nil)...) - } - } - return -} - func getCIDRMaskFromAddr(addr string) net.IPMask { cidr := net.CIDRMask(32, 32) ipAddr, err := netip.ParseAddr(addr) diff --git a/logic/pro/proacls/nodes.go b/logic/pro/proacls/nodes.go deleted file mode 100644 index 2d2d5ff6..00000000 --- a/logic/pro/proacls/nodes.go +++ /dev/null @@ -1,35 +0,0 @@ -package proacls - -import ( - "github.com/gravitl/netmaker/logic/acls" - "github.com/gravitl/netmaker/logic/acls/nodeacls" - "github.com/gravitl/netmaker/models" -) - -// AdjustNodeAcls - adjusts ACLs based on a node's default value -func AdjustNodeAcls(node *models.Node, networkNodes []models.Node) error { - networkID := nodeacls.NetworkID(node.Network) - 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.String()) - if currentNodeID == nodeID { - continue - } - // 2 cases - // both allow - allow - // either 1 denies - deny - if node.DoesACLDeny() || networkNodes[i].DoesACLDeny() { - currentACLs.ChangeAccess(acls.AclID(nodeID), acls.AclID(currentNodeID), acls.NotAllowed) - } else if node.DoesACLAllow() || networkNodes[i].DoesACLAllow() { - currentACLs.ChangeAccess(acls.AclID(nodeID), acls.AclID(currentNodeID), acls.Allowed) - } - } - - _, err = currentACLs.Save(acls.ContainerID(node.Network)) - return err -} diff --git a/logic/relay.go b/logic/relay.go index 4782c156..394f3cf2 100644 --- a/logic/relay.go +++ b/logic/relay.go @@ -1,149 +1,25 @@ package logic import ( - "errors" - "fmt" - "net" - - "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/models" + "net" ) -// CreateRelay - creates a relay -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.Node{}, err - } - host, err := GetHost(node.HostID.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.Node{}, err - } - node.IsRelay = true - node.RelayedNodes = relay.RelayedNodes - node.SetLastModified() - err = UpsertNode(&node) - if err != nil { - return returnnodes, node, err - } - returnnodes = SetRelayedNodes(true, relay.NodeID, relay.RelayedNodes) - return returnnodes, node, nil +var RelayedAllowedIPs = func(peer, node *models.Node) []net.IPNet { + return []net.IPNet{} } -// SetRelayedNodes- sets and saves node as relayed -func SetRelayedNodes(setRelayed bool, relay string, relayed []string) []models.Node { - var returnnodes []models.Node - for _, id := range relayed { - node, err := GetNodeByID(id) - if err != nil { - logger.Log(0, "setRelayedNodes.GetNodebyID", err.Error()) - continue - } - node.IsRelayed = setRelayed - if node.IsRelayed { - node.RelayedBy = relay - } else { - node.RelayedBy = "" - } - node.SetLastModified() - if err := UpsertNode(&node); err != nil { - logger.Log(0, "setRelayedNodes.Insert", err.Error()) - continue - } - returnnodes = append(returnnodes, node) - } - return returnnodes +var GetAllowedIpsForRelayed = func(relayed, relay *models.Node) []net.IPNet { + return []net.IPNet{} } -//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 { -// for _, addr := range relayNode.RelayAddrs { -// if addr == node.Address.IP.String() || addr == node.Address6.IP.String() { -// returnnodes = append(returnnodes, node) -// } -// } -// } -// return returnnodes, nil -//} - -// ValidateRelay - checks if relay is valid -func ValidateRelay(relay models.RelayRequest) error { - var err error - //isIp := functions.IsIpCIDR(gateway.RangeString) - empty := len(relay.RelayedNodes) == 0 - if empty { - return errors.New("IP Ranges Cannot Be Empty") - } - node, err := GetNodeByID(relay.NodeID) - if err != nil { - return err - } - if node.IsRelay { - return errors.New("node is already acting as a relay") - } - for _, relayedNodeID := range relay.RelayedNodes { - relayedNode, err := GetNodeByID(relayedNodeID) - if err != nil { - return err - } - if relayedNode.IsIngressGateway { - return errors.New("cannot relay an ingress gateway (" + relayedNodeID + ")") - } - } - return err +var UpdateRelayed = func(currentNode, newNode *models.Node) { } -// UpdateRelayed - updates relay nodes -func UpdateRelayed(relay string, oldNodes []string, newNodes []string) []models.Node { - _ = SetRelayedNodes(false, relay, oldNodes) - return SetRelayedNodes(true, relay, newNodes) +var SetRelayedNodes = func(setRelayed bool, relay string, relayed []string) []models.Node { + return []models.Node{} } -// DeleteRelay - deletes a relay -func DeleteRelay(network, nodeid string) ([]models.Node, models.Node, error) { - var returnnodes []models.Node - node, err := GetNodeByID(nodeid) - if err != nil { - return returnnodes, models.Node{}, err - } - returnnodes = SetRelayedNodes(false, nodeid, node.RelayedNodes) - node.IsRelay = false - node.RelayedNodes = []string{} - node.SetLastModified() - if err = UpsertNode(&node); err != nil { - return returnnodes, models.Node{}, err - } - return returnnodes, node, nil -} - -func getRelayedAddresses(id string) []net.IPNet { - addrs := []net.IPNet{} - node, err := GetNodeByID(id) - if err != nil { - logger.Log(0, "getRelayedAddresses: "+err.Error()) - return addrs - } - if node.Address.IP != nil { - node.Address.Mask = net.CIDRMask(32, 32) - addrs = append(addrs, node.Address) - } - if node.Address6.IP != nil { - node.Address.Mask = net.CIDRMask(128, 128) - addrs = append(addrs, node.Address6) - } - return addrs +var RelayUpdates = func(currentNode, newNode *models.Node) bool { + return false } diff --git a/logic/security.go b/logic/security.go index f1374324..36dda5e3 100644 --- a/logic/security.go +++ b/logic/security.go @@ -170,7 +170,7 @@ func UserPermissions(reqAdmin bool, netname string, token string) ([]string, str if len(netname) > 0 && (len(userNetworks) == 0 || !authenticateNetworkUser(netname, userNetworks)) { return nil, username, Forbidden_Err } - if isEE && len(netname) > 0 && !pro.IsUserNetAdmin(netname, username) { + if servercfg.IsPro && len(netname) > 0 && !pro.IsUserNetAdmin(netname, username) { return nil, "", Forbidden_Err } return userNetworks, username, nil diff --git a/logic/telemetry.go b/logic/telemetry.go index e867cbc8..e4d48030 100644 --- a/logic/telemetry.go +++ b/logic/telemetry.go @@ -13,7 +13,6 @@ import ( // flags to keep for telemetry var isFreeTier bool -var isEE bool // posthog_pub_key - Key for sending data to PostHog const posthog_pub_key = "phc_1vEXhPOA1P7HP5jP2dVU9xDTUqXHAelmtravyZ1vvES" @@ -21,14 +20,8 @@ const posthog_pub_key = "phc_1vEXhPOA1P7HP5jP2dVU9xDTUqXHAelmtravyZ1vvES" // posthog_endpoint - Endpoint of PostHog server const posthog_endpoint = "https://app.posthog.com" -// setEEForTelemetry - store EE flag without having an import cycle when used for telemetry -// (as the ee package needs the logic package as currently written). -func SetEEForTelemetry(eeFlag bool) { - isEE = eeFlag -} - // setFreeTierForTelemetry - store free tier flag without having an import cycle when used for telemetry -// (as the ee package needs the logic package as currently written). +// (as the pro package needs the logic package as currently written). func SetFreeTierForTelemetry(freeTierFlag bool) { isFreeTier = freeTierFlag } @@ -73,7 +66,7 @@ func sendTelemetry() error { Set("docker", d.Count.Docker). Set("k8s", d.Count.K8S). Set("version", d.Version). - Set("is_ee", isEE). + Set("is_ee", d.IsPro). // TODO change is_ee to is_pro for consistency, but probably needs changes in posthog Set("is_free_tier", isFreeTier), }) } @@ -82,6 +75,7 @@ func sendTelemetry() error { func fetchTelemetryData() (telemetryData, error) { var data telemetryData + data.IsPro = servercfg.IsPro data.ExtClients = getDBLength(database.EXT_CLIENT_TABLE_NAME) data.Users = getDBLength(database.USERS_TABLE_NAME) data.Networks = getDBLength(database.NETWORKS_TABLE_NAME) @@ -176,7 +170,7 @@ type telemetryData struct { Networks int Servers int Version string - IsEE bool + IsPro bool IsFreeTier bool } diff --git a/main.go b/main.go index 4bf42487..bd3cfc71 100644 --- a/main.go +++ b/main.go @@ -41,7 +41,7 @@ func main() { initialize() // initial db and acls setGarbageCollection() setVerbosity() - if servercfg.DeployedByOperator() && !servercfg.Is_EE { + if servercfg.DeployedByOperator() && !servercfg.IsPro { logic.SetFreeTierLimits() } defer database.CloseDB() diff --git a/main_ee.go b/main_ee.go index dd4bb3a4..90001d87 100644 --- a/main_ee.go +++ b/main_ee.go @@ -3,10 +3,8 @@ package main -import ( - "github.com/gravitl/netmaker/ee" -) +import "github.com/gravitl/netmaker/pro" func init() { - ee.InitEE() + pro.InitPro() } diff --git a/models/node.go b/models/node.go index ed778d00..b011321e 100644 --- a/models/node.go +++ b/models/node.go @@ -357,7 +357,7 @@ func (node *LegacyNode) SetDefaultFailover() { } // Node.Fill - fills other node data into calling node data if not set on calling node (skips DNSOn) -func (newNode *Node) Fill(currentNode *Node, isEE bool) { // TODO add new field for nftables present +func (newNode *Node) Fill(currentNode *Node, isPro bool) { // TODO add new field for nftables present newNode.ID = currentNode.ID newNode.HostID = currentNode.HostID // Revisit the logic for boolean values @@ -408,10 +408,10 @@ func (newNode *Node) Fill(currentNode *Node, isEE bool) { // TODO add new field if newNode.RelayedNodes == nil { newNode.RelayedNodes = currentNode.RelayedNodes } - if newNode.IsRelay != currentNode.IsRelay && isEE { + if newNode.IsRelay != currentNode.IsRelay && isPro { newNode.IsRelay = currentNode.IsRelay } - if newNode.IsRelayed == currentNode.IsRelayed && isEE { + if newNode.IsRelayed == currentNode.IsRelayed && isPro { newNode.IsRelayed = currentNode.IsRelayed } if newNode.Server == "" { diff --git a/models/structs.go b/models/structs.go index bff547c3..d161e283 100644 --- a/models/structs.go +++ b/models/structs.go @@ -238,7 +238,7 @@ type ServerConfig struct { MQPassword string `yaml:"mq_password"` Server string `yaml:"server"` Broker string `yaml:"broker"` - Is_EE bool `yaml:"isee"` + IsPro bool `yaml:"isee" json:"Is_EE"` StunPort int `yaml:"stun_port"` StunList []StunServer `yaml:"stun_list"` TrafficKey []byte `yaml:"traffickey"` diff --git a/mq/handlers.go b/mq/handlers.go index 52e9664d..e2acc730 100644 --- a/mq/handlers.go +++ b/mq/handlers.go @@ -3,12 +3,10 @@ package mq import ( "encoding/json" "fmt" - "math" - "time" - mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/google/uuid" "github.com/gravitl/netmaker/database" + "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/logic/hostactions" "github.com/gravitl/netmaker/models" @@ -18,6 +16,19 @@ import ( "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) +// UpdateMetrics message Handler -- handles updates from client nodes for metrics +var UpdateMetrics = func(client mqtt.Client, msg mqtt.Message) { +} + +func RunUpdates(node *models.Node, ifaceDelta bool) { + go func() { // don't block http response + // publish node update if not server + if err := NodeUpdate(node); err != nil { + logger.Log(1, "error publishing node update to node", node.ID.String(), err.Error()) + } + }() +} + // DefaultHandler default message queue handler -- NOT USED func DefaultHandler(client mqtt.Client, msg mqtt.Message) { slog.Info("mqtt default handler", "topic", msg.Topic(), "message", msg.Payload()) @@ -25,7 +36,7 @@ func DefaultHandler(client mqtt.Client, msg mqtt.Message) { // UpdateNode message Handler -- handles updates from client nodes func UpdateNode(client mqtt.Client, msg mqtt.Message) { - id, err := getID(msg.Topic()) + id, err := GetID(msg.Topic()) if err != nil { slog.Error("error getting node.ID ", "topic", msg.Topic(), "error", err) return @@ -35,7 +46,7 @@ func UpdateNode(client mqtt.Client, msg mqtt.Message) { slog.Error("error getting node", "id", id, "error", err) return } - decrypted, decryptErr := decryptMsg(¤tNode, msg.Payload()) + decrypted, decryptErr := DecryptMsg(¤tNode, msg.Payload()) if decryptErr != nil { slog.Error("failed to decrypt message for node", "id", id, "error", decryptErr) return @@ -47,7 +58,7 @@ func UpdateNode(client mqtt.Client, msg mqtt.Message) { } ifaceDelta := logic.IfaceDelta(¤tNode, &newNode) - if servercfg.Is_EE && ifaceDelta { + if servercfg.IsPro && ifaceDelta { if err = logic.EnterpriseResetAllPeersFailovers(currentNode.ID, currentNode.Network); err != nil { slog.Warn("failed to reset failover list during node update", "nodeid", currentNode.ID, "network", currentNode.Network) } @@ -68,7 +79,7 @@ func UpdateNode(client mqtt.Client, msg mqtt.Message) { // UpdateHost message Handler -- handles host updates from clients func UpdateHost(client mqtt.Client, msg mqtt.Message) { - id, err := getID(msg.Topic()) + id, err := GetID(msg.Topic()) if err != nil { slog.Error("error getting host.ID sent on ", "topic", msg.Topic(), "error", err) return @@ -183,77 +194,11 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) { slog.Error("failed to publish peer update", "error", err) } } - // if servercfg.Is_EE && ifaceDelta { - // if err = logic.EnterpriseResetAllPeersFailovers(currentHost.ID.String(), currentHost.Network); err != nil { - // logger.Log(1, "failed to reset failover list during node update", currentHost.ID.String(), currentHost.Network) - // } - // } -} - -// UpdateMetrics message Handler -- handles updates from client nodes for metrics -func UpdateMetrics(client mqtt.Client, msg mqtt.Message) { - if servercfg.Is_EE { - id, err := getID(msg.Topic()) - if err != nil { - slog.Error("error getting ID sent on ", "topic", msg.Topic(), "error", err) - return - } - currentNode, err := logic.GetNodeByID(id) - if err != nil { - slog.Error("error getting node", "id", id, "error", err) - return - } - decrypted, decryptErr := decryptMsg(¤tNode, msg.Payload()) - if decryptErr != nil { - slog.Error("failed to decrypt message for node", "id", id, "error", decryptErr) - return - } - - var newMetrics models.Metrics - if err := json.Unmarshal(decrypted, &newMetrics); err != nil { - slog.Error("error unmarshaling payload", "error", err) - return - } - - shouldUpdate := updateNodeMetrics(¤tNode, &newMetrics) - - if err = logic.UpdateMetrics(id, &newMetrics); err != nil { - slog.Error("failed to update node metrics", "id", id, "error", err) - return - } - if servercfg.IsMetricsExporter() { - if err := pushMetricsToExporter(newMetrics); err != nil { - slog.Error("failed to push node metrics to exporter", "id", currentNode.ID, "error", err) - } - } - - if newMetrics.Connectivity != nil { - err := logic.EnterpriseFailoverFunc(¤tNode) - if err != nil { - slog.Error("failed to failover for node", "id", currentNode.ID, "network", currentNode.Network, "error", err) - } - } - - if shouldUpdate { - slog.Info("updating peers after node detected connectivity issues", "id", currentNode.ID, "network", currentNode.Network) - host, err := logic.GetHost(currentNode.HostID.String()) - if err == nil { - nodes, err := logic.GetAllNodes() - if err != nil { - return - } - if err = PublishSingleHostPeerUpdate(host, nodes, nil, nil); err != nil { - slog.Warn("failed to publish update after failover peer change for node", "id", currentNode.ID, "network", currentNode.Network, "error", err) - } - } - } - slog.Debug("updated node metrics", "id", id) - } } // ClientPeerUpdate message handler -- handles updating peers after signal from client nodes func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) { - id, err := getID(msg.Topic()) + id, err := GetID(msg.Topic()) if err != nil { slog.Error("error getting node.ID sent on ", "topic", msg.Topic(), "error", err) return @@ -263,7 +208,7 @@ func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) { slog.Error("error getting node", "id", id, "error", err) return } - decrypted, decryptErr := decryptMsg(¤tNode, msg.Payload()) + decrypted, decryptErr := DecryptMsg(¤tNode, msg.Payload()) if decryptErr != nil { slog.Error("failed to decrypt message for node", "id", id, "error", decryptErr) return @@ -281,105 +226,6 @@ func ClientPeerUpdate(client mqtt.Client, msg mqtt.Message) { slog.Info("sent peer updates after signal received from", "id", id) } -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.String()) - if err != nil { - slog.Error("error finding old metrics for node", "id", currentNode.ID, "error", err) - return false - } - if oldMetrics.FailoverPeers == nil { - oldMetrics.FailoverPeers = make(map[string]string) - } - - var attachedClients []models.ExtClient - if currentNode.IsIngressGateway { - clients, err := logic.GetExtClientsByID(currentNode.ID.String(), currentNode.Network) - if err == nil { - attachedClients = clients - } - } - if len(attachedClients) > 0 { - // associate ext clients with IDs - for i := range attachedClients { - extMetric := newMetrics.Connectivity[attachedClients[i].PublicKey] - if len(extMetric.NodeName) == 0 && - len(newMetrics.Connectivity[attachedClients[i].ClientID].NodeName) > 0 { // cover server clients - extMetric = newMetrics.Connectivity[attachedClients[i].ClientID] - if extMetric.TotalReceived > 0 && extMetric.TotalSent > 0 { - extMetric.Connected = true - } - } - extMetric.NodeName = attachedClients[i].ClientID - delete(newMetrics.Connectivity, attachedClients[i].PublicKey) - newMetrics.Connectivity[attachedClients[i].ClientID] = extMetric - } - } - - // run through metrics for each peer - for k := range newMetrics.Connectivity { - currMetric := newMetrics.Connectivity[k] - oldMetric := oldMetrics.Connectivity[k] - currMetric.TotalTime += oldMetric.TotalTime - currMetric.Uptime += oldMetric.Uptime // get the total uptime for this connection - - if currMetric.TotalReceived < oldMetric.TotalReceived { - currMetric.TotalReceived += oldMetric.TotalReceived - } else { - currMetric.TotalReceived += int64(math.Abs(float64(currMetric.TotalReceived) - float64(oldMetric.TotalReceived))) - } - if currMetric.TotalSent < oldMetric.TotalSent { - currMetric.TotalSent += oldMetric.TotalSent - } else { - currMetric.TotalSent += int64(math.Abs(float64(currMetric.TotalSent) - float64(oldMetric.TotalSent))) - } - - if currMetric.Uptime == 0 || currMetric.TotalTime == 0 { - currMetric.PercentUp = 0 - } else { - currMetric.PercentUp = 100.0 * (float64(currMetric.Uptime) / float64(currMetric.TotalTime)) - } - totalUpMinutes := currMetric.Uptime * ncutils.CheckInInterval - currMetric.ActualUptime = time.Duration(totalUpMinutes) * time.Minute - delete(oldMetrics.Connectivity, k) // remove from old data - newMetrics.Connectivity[k] = currMetric - - } - - // add nodes that need failover - nodes, err := logic.GetNetworkNodes(currentNode.Network) - if err != nil { - slog.Error("failed to retrieve nodes while updating metrics", "error", err) - return false - } - for _, node := range nodes { - if !newMetrics.Connectivity[node.ID.String()].Connected && - len(newMetrics.Connectivity[node.ID.String()].NodeName) > 0 && - node.Connected && - len(node.FailoverNode) > 0 && - !node.Failover { - newMetrics.FailoverPeers[node.ID.String()] = node.FailoverNode.String() - } - } - shouldUpdate := len(oldMetrics.FailoverPeers) == 0 && len(newMetrics.FailoverPeers) > 0 - for k, v := range oldMetrics.FailoverPeers { - if len(newMetrics.FailoverPeers[k]) > 0 && len(v) == 0 { - shouldUpdate = true - } - - if len(v) > 0 && len(newMetrics.FailoverPeers[k]) == 0 { - newMetrics.FailoverPeers[k] = v - } - } - - for k := range oldMetrics.Connectivity { // cleanup any left over data, self healing - delete(newMetrics.Connectivity, k) - } - return shouldUpdate -} - func handleNewNodeDNS(host *models.Host, node *models.Node) error { dns := models.DNSUpdate{ Action: models.DNSInsert, diff --git a/mq/publishers.go b/mq/publishers.go index a470b99e..50f1040f 100644 --- a/mq/publishers.go +++ b/mq/publishers.go @@ -344,7 +344,7 @@ func PublishHostDNSUpdate(old, new *models.Host, networks []string) error { return nil } -func pushMetricsToExporter(metrics models.Metrics) error { +func PushMetricsToExporter(metrics models.Metrics) error { logger.Log(2, "----> Pushing metrics to exporter") data, err := json.Marshal(metrics) if err != nil { diff --git a/mq/util.go b/mq/util.go index fb7688de..8d781993 100644 --- a/mq/util.go +++ b/mq/util.go @@ -32,7 +32,7 @@ func decryptMsgWithHost(host *models.Host, msg []byte) ([]byte, error) { return ncutils.DeChunk(msg, nodePubTKey, serverPrivTKey) } -func decryptMsg(node *models.Node, 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) } @@ -93,7 +93,7 @@ func publish(host *models.Host, dest string, msg []byte) error { } // decodes a message queue topic and returns the embedded node.ID -func getID(topic string) (string, error) { +func GetID(topic string) (string, error) { parts := strings.Split(topic, "/") count := len(parts) if count == 1 { diff --git a/ee/LICENSE b/pro/LICENSE similarity index 100% rename from ee/LICENSE rename to pro/LICENSE diff --git a/ee/ee_controllers/metrics.go b/pro/controllers/metrics.go similarity index 93% rename from ee/ee_controllers/metrics.go rename to pro/controllers/metrics.go index d2379d27..84328bf9 100644 --- a/ee/ee_controllers/metrics.go +++ b/pro/controllers/metrics.go @@ -1,7 +1,8 @@ -package ee_controllers +package controllers import ( "encoding/json" + proLogic "github.com/gravitl/netmaker/pro/logic" "net/http" "github.com/gorilla/mux" @@ -11,7 +12,7 @@ import ( "github.com/gravitl/netmaker/models" ) -// MetricHandlers - How we handle EE Metrics +// MetricHandlers - How we handle Pro Metrics func MetricHandlers(r *mux.Router) { r.HandleFunc("/api/metrics/{network}/{nodeid}", logic.SecurityCheck(true, http.HandlerFunc(getNodeMetrics))).Methods(http.MethodGet) r.HandleFunc("/api/metrics/{network}", logic.SecurityCheck(true, http.HandlerFunc(getNetworkNodesMetrics))).Methods(http.MethodGet) @@ -61,7 +62,7 @@ func getNetworkNodesMetrics(w http.ResponseWriter, r *http.Request) { for i := range networkNodes { id := networkNodes[i].ID - metrics, err := logic.GetMetrics(id.String()) + metrics, err := proLogic.GetMetrics(id.String()) if err != nil { logger.Log(1, r.Header.Get("user"), "failed to append metrics of node", id.String(), "during network metrics fetch", err.Error()) continue @@ -83,7 +84,7 @@ func getNetworkExtMetrics(w http.ResponseWriter, r *http.Request) { network := params["network"] logger.Log(1, r.Header.Get("user"), "requested fetching external client metrics on network", network) - ingresses, err := logic.GetNetworkIngresses(network) // grab all the ingress gateways + ingresses, err := proLogic.GetNetworkIngresses(network) // grab all the ingress gateways if err != nil { logger.Log(1, r.Header.Get("user"), "failed to fetch metrics of ext clients in network", network, err.Error()) logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) @@ -108,7 +109,7 @@ func getNetworkExtMetrics(w http.ResponseWriter, r *http.Request) { for i := range ingresses { id := ingresses[i].ID - ingressMetrics, err := logic.GetMetrics(id.String()) + ingressMetrics, err := proLogic.GetMetrics(id.String()) if err != nil { logger.Log(1, r.Header.Get("user"), "failed to append external client metrics from ingress node", id.String(), err.Error()) continue @@ -149,7 +150,7 @@ func getAllMetrics(w http.ResponseWriter, r *http.Request) { for i := range allNodes { id := allNodes[i].ID - metrics, err := logic.GetMetrics(id.String()) + metrics, err := proLogic.GetMetrics(id.String()) if err != nil { logger.Log(1, r.Header.Get("user"), "failed to append metrics of node", id.String(), "during all nodes metrics fetch", err.Error()) continue diff --git a/ee/ee_controllers/middleware.go b/pro/controllers/middleware.go similarity index 95% rename from ee/ee_controllers/middleware.go rename to pro/controllers/middleware.go index dc853524..3e939b57 100644 --- a/ee/ee_controllers/middleware.go +++ b/pro/controllers/middleware.go @@ -1,4 +1,4 @@ -package ee_controllers +package controllers import ( "github.com/gravitl/netmaker/logic" diff --git a/ee/ee_controllers/networkusers.go b/pro/controllers/networkusers.go similarity index 99% rename from ee/ee_controllers/networkusers.go rename to pro/controllers/networkusers.go index 8ae41b16..fe5a0fc5 100644 --- a/ee/ee_controllers/networkusers.go +++ b/pro/controllers/networkusers.go @@ -1,4 +1,4 @@ -package ee_controllers +package controllers import ( "encoding/json" diff --git a/ee/ee_controllers/relay.go b/pro/controllers/relay.go similarity index 93% rename from ee/ee_controllers/relay.go rename to pro/controllers/relay.go index 3963352f..65b81399 100644 --- a/ee/ee_controllers/relay.go +++ b/pro/controllers/relay.go @@ -1,8 +1,9 @@ -package ee_controllers +package controllers import ( "encoding/json" "fmt" + proLogic "github.com/gravitl/netmaker/pro/logic" "net/http" "github.com/gorilla/mux" @@ -13,7 +14,7 @@ import ( "github.com/gravitl/netmaker/mq" ) -// RelayHandlers - handle EE Relays +// RelayHandlers - handle Pro Relays func RelayHandlers(r *mux.Router) { r.HandleFunc("/api/nodes/{network}/{nodeid}/createrelay", controller.Authorize(false, true, "user", http.HandlerFunc(createRelay))).Methods(http.MethodPost) @@ -43,7 +44,7 @@ func createRelay(w http.ResponseWriter, r *http.Request) { } relayRequest.NetID = params["network"] relayRequest.NodeID = params["nodeid"] - _, relayNode, err := logic.CreateRelay(relayRequest) + _, relayNode, err := proLogic.CreateRelay(relayRequest) if err != nil { logger.Log(0, r.Header.Get("user"), fmt.Sprintf("failed to create relay on node [%s] on network [%s]: %v", relayRequest.NodeID, relayRequest.NetID, err)) @@ -73,7 +74,7 @@ func deleteRelay(w http.ResponseWriter, r *http.Request) { var params = mux.Vars(r) nodeid := params["nodeid"] netid := params["network"] - updateNodes, node, err := logic.DeleteRelay(netid, nodeid) + updateNodes, node, err := proLogic.DeleteRelay(netid, nodeid) if err != nil { logger.Log(0, r.Header.Get("user"), "error decoding request body: ", err.Error()) logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) diff --git a/ee/ee_controllers/usergroups.go b/pro/controllers/usergroups.go similarity index 98% rename from ee/ee_controllers/usergroups.go rename to pro/controllers/usergroups.go index 787d5268..2e64d276 100644 --- a/ee/ee_controllers/usergroups.go +++ b/pro/controllers/usergroups.go @@ -1,4 +1,4 @@ -package ee_controllers +package controllers import ( "encoding/json" diff --git a/ee/initialize.go b/pro/initialize.go similarity index 56% rename from ee/initialize.go rename to pro/initialize.go index e779147b..bcc42c48 100644 --- a/ee/initialize.go +++ b/pro/initialize.go @@ -1,33 +1,33 @@ //go:build ee // +build ee -package ee +package pro import ( controller "github.com/gravitl/netmaker/controllers" - "github.com/gravitl/netmaker/ee/ee_controllers" - eelogic "github.com/gravitl/netmaker/ee/logic" "github.com/gravitl/netmaker/logic" "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/mq" + proControllers "github.com/gravitl/netmaker/pro/controllers" + proLogic "github.com/gravitl/netmaker/pro/logic" "github.com/gravitl/netmaker/servercfg" "golang.org/x/exp/slog" ) -// InitEE - Initialize EE Logic -func InitEE() { - setIsEnterprise() - servercfg.Is_EE = true - models.SetLogo(retrieveEELogo()) +// InitPro - Initialize Pro Logic +func InitPro() { + servercfg.IsPro = true + models.SetLogo(retrieveProLogo()) controller.HttpMiddlewares = append( controller.HttpMiddlewares, - ee_controllers.OnlyServerAPIWhenUnlicensedMiddleware, + proControllers.OnlyServerAPIWhenUnlicensedMiddleware, ) controller.HttpHandlers = append( controller.HttpHandlers, - ee_controllers.MetricHandlers, - ee_controllers.NetworkUsersHandlers, - ee_controllers.UserGroupsHandlers, - ee_controllers.RelayHandlers, + proControllers.MetricHandlers, + proControllers.NetworkUsersHandlers, + proControllers.UserGroupsHandlers, + proControllers.RelayHandlers, ) logic.EnterpriseCheckFuncs = append(logic.EnterpriseCheckFuncs, func() { // == License Handling == @@ -41,19 +41,31 @@ func InitEE() { AddLicenseHooks() resetFailover() }) - logic.EnterpriseFailoverFunc = eelogic.SetFailover - logic.EnterpriseResetFailoverFunc = eelogic.ResetFailover - logic.EnterpriseResetAllPeersFailovers = eelogic.WipeAffectedFailoversOnly - logic.DenyClientNodeAccess = eelogic.DenyClientNode - logic.IsClientNodeAllowed = eelogic.IsClientNodeAllowed - logic.AllowClientNodeAccess = eelogic.RemoveDeniedNodeFromClient + logic.EnterpriseFailoverFunc = proLogic.SetFailover + logic.EnterpriseResetFailoverFunc = proLogic.ResetFailover + logic.EnterpriseResetAllPeersFailovers = proLogic.WipeAffectedFailoversOnly + logic.DenyClientNodeAccess = proLogic.DenyClientNode + logic.IsClientNodeAllowed = proLogic.IsClientNodeAllowed + logic.AllowClientNodeAccess = proLogic.RemoveDeniedNodeFromClient + logic.SetClientDefaultACLs = proLogic.SetClientDefaultACLs + logic.SetClientACLs = proLogic.SetClientACLs + logic.UpdateProNodeACLs = proLogic.UpdateProNodeACLs + logic.GetMetrics = proLogic.GetMetrics + logic.UpdateMetrics = proLogic.UpdateMetrics + logic.DeleteMetrics = proLogic.DeleteMetrics + logic.GetAllowedIpsForRelayed = proLogic.GetAllowedIpsForRelayed + logic.RelayedAllowedIPs = proLogic.RelayedAllowedIPs + logic.UpdateRelayed = proLogic.UpdateRelayed + logic.SetRelayedNodes = proLogic.SetRelayedNodes + logic.RelayUpdates = proLogic.RelayUpdates + mq.UpdateMetrics = proLogic.MQUpdateMetrics } func resetFailover() { nets, err := logic.GetNetworks() if err == nil { for _, net := range nets { - err = eelogic.ResetFailover(net.NetID) + err = proLogic.ResetFailover(net.NetID) if err != nil { slog.Error("failed to reset failover", "network", net.NetID, "error", err.Error()) } @@ -61,7 +73,7 @@ func resetFailover() { } } -func retrieveEELogo() string { +func retrieveProLogo() string { return ` __ __ ______ ______ __ __ ______ __ __ ______ ______ /\ "-.\ \ /\ ___\ /\__ _\ /\ "-./ \ /\ __ \ /\ \/ / /\ ___\ /\ == \ diff --git a/ee/license.go b/pro/license.go similarity index 99% rename from ee/license.go rename to pro/license.go index 8bf7345b..4e25026a 100644 --- a/ee/license.go +++ b/pro/license.go @@ -1,7 +1,7 @@ //go:build ee // +build ee -package ee +package pro import ( "bytes" diff --git a/ee/license_test.go b/pro/license_test.go similarity index 99% rename from ee/license_test.go rename to pro/license_test.go index 30984680..12d15d3f 100644 --- a/ee/license_test.go +++ b/pro/license_test.go @@ -1,7 +1,7 @@ //go:build ee // +build ee -package ee +package pro import ( "github.com/gravitl/netmaker/config" diff --git a/pro/logic/ext_acls.go b/pro/logic/ext_acls.go new file mode 100644 index 00000000..b96051ef --- /dev/null +++ b/pro/logic/ext_acls.go @@ -0,0 +1,114 @@ +package logic + +import ( + "github.com/gravitl/netmaker/logic" + "github.com/gravitl/netmaker/logic/acls" + "github.com/gravitl/netmaker/logic/acls/nodeacls" + "github.com/gravitl/netmaker/models" +) + +// DenyClientNode - add a denied node to an ext client's list +func DenyClientNode(ec *models.ExtClient, clientOrNodeID string) (ok bool) { + if ec == nil || len(clientOrNodeID) == 0 { + return + } + if ec.DeniedACLs == nil { + ec.DeniedACLs = map[string]struct{}{} + } + ok = true + ec.DeniedACLs[clientOrNodeID] = struct{}{} + return +} + +// IsClientNodeAllowed - checks if given ext client and node are allowed to communicate +func IsClientNodeAllowed(ec *models.ExtClient, clientOrNodeID string) bool { + if ec == nil || len(clientOrNodeID) == 0 { + return false + } + if ec.DeniedACLs == nil { + return true + } + _, ok := ec.DeniedACLs[clientOrNodeID] + return !ok +} + +// RemoveDeniedNodeFromClient - removes a node id from set of denied nodes +func RemoveDeniedNodeFromClient(ec *models.ExtClient, clientOrNodeID string) bool { + if ec.DeniedACLs == nil { + return true + } + _, ok := ec.DeniedACLs[clientOrNodeID] + if !ok { + return false + } + delete(ec.DeniedACLs, clientOrNodeID) + return true +} + +// SetClientDefaultACLs - set's a client's default ACLs based on network and nodes in network +func SetClientDefaultACLs(ec *models.ExtClient) error { + networkNodes, err := logic.GetNetworkNodes(ec.Network) + if err != nil { + return err + } + network, err := logic.GetNetwork(ec.Network) + if err != nil { + return err + } + for i := range networkNodes { + currNode := networkNodes[i] + if network.DefaultACL == "no" || currNode.DefaultACL == "no" { + DenyClientNode(ec, currNode.ID.String()) + } else { + RemoveDeniedNodeFromClient(ec, currNode.ID.String()) + } + } + return nil +} + +// SetClientACLs - overwrites an ext client's ACL +func SetClientACLs(ec *models.ExtClient, newACLs map[string]struct{}) { + if ec == nil || newACLs == nil { + return + } + ec.DeniedACLs = newACLs +} + +func UpdateProNodeACLs(node *models.Node) error { + networkNodes, err := logic.GetNetworkNodes(node.Network) + if err != nil { + return err + } + if err = adjustNodeAcls(node, networkNodes[:]); err != nil { + return err + } + return nil +} + +// adjustNodeAcls - adjusts ACLs based on a node's default value +func adjustNodeAcls(node *models.Node, networkNodes []models.Node) error { + networkID := nodeacls.NetworkID(node.Network) + 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.String()) + if currentNodeID == nodeID { + continue + } + // 2 cases + // both allow - allow + // either 1 denies - deny + if node.DoesACLDeny() || networkNodes[i].DoesACLDeny() { + currentACLs.ChangeAccess(acls.AclID(nodeID), acls.AclID(currentNodeID), acls.NotAllowed) + } else if node.DoesACLAllow() || networkNodes[i].DoesACLAllow() { + currentACLs.ChangeAccess(acls.AclID(nodeID), acls.AclID(currentNodeID), acls.Allowed) + } + } + + _, err = currentACLs.Save(acls.ContainerID(node.Network)) + return err +} diff --git a/ee/logic/failover.go b/pro/logic/failover.go similarity index 94% rename from ee/logic/failover.go rename to pro/logic/failover.go index 19900e43..71883c5c 100644 --- a/ee/logic/failover.go +++ b/pro/logic/failover.go @@ -45,7 +45,7 @@ func determineFailoverCandidate(nodeToBeRelayed *models.Node) *models.Node { return nil } - currentMetrics, err := logic.GetMetrics(nodeToBeRelayed.ID.String()) + currentMetrics, err := GetMetrics(nodeToBeRelayed.ID.String()) if err != nil || currentMetrics == nil || currentMetrics.Connectivity == nil { return nil } @@ -84,7 +84,7 @@ func setFailoverNode(failoverNode, node *models.Node) error { // WipeFailover - removes the failover peers of given node (ID) func WipeFailover(nodeid string) error { - metrics, err := logic.GetMetrics(nodeid) + metrics, err := GetMetrics(nodeid) if err != nil { return err } @@ -109,7 +109,7 @@ func WipeAffectedFailoversOnly(nodeid uuid.UUID, network string) error { if currNodeID == nodeid { continue } - currMetrics, err := logic.GetMetrics(currNodeID.String()) + currMetrics, err := GetMetrics(currNodeID.String()) if err != nil || currMetrics == nil { continue } diff --git a/pro/logic/metrics.go b/pro/logic/metrics.go new file mode 100644 index 00000000..78d20349 --- /dev/null +++ b/pro/logic/metrics.go @@ -0,0 +1,203 @@ +package logic + +import ( + "encoding/json" + mqtt "github.com/eclipse/paho.mqtt.golang" + "github.com/gravitl/netmaker/database" + "github.com/gravitl/netmaker/logic" + "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/mq" + "github.com/gravitl/netmaker/netclient/ncutils" + "github.com/gravitl/netmaker/servercfg" + "golang.org/x/exp/slog" + "math" + "time" +) + +// GetMetrics - gets the metrics +func GetMetrics(nodeid string) (*models.Metrics, error) { + var metrics models.Metrics + record, err := database.FetchRecord(database.METRICS_TABLE_NAME, nodeid) + if err != nil { + if database.IsEmptyRecord(err) { + return &metrics, nil + } + return &metrics, err + } + err = json.Unmarshal([]byte(record), &metrics) + if err != nil { + return &metrics, err + } + return &metrics, nil +} + +// UpdateMetrics - updates the metrics of a given client +func UpdateMetrics(nodeid string, metrics *models.Metrics) error { + data, err := json.Marshal(metrics) + if err != nil { + return err + } + return database.Insert(nodeid, string(data), database.METRICS_TABLE_NAME) +} + +// DeleteMetrics - deletes metrics of a given node +func DeleteMetrics(nodeid string) error { + return database.DeleteRecord(database.METRICS_TABLE_NAME, nodeid) +} + +func MQUpdateMetrics(client mqtt.Client, msg mqtt.Message) { + id, err := mq.GetID(msg.Topic()) + if err != nil { + slog.Error("error getting ID sent on ", "topic", msg.Topic(), "error", err) + return + } + currentNode, err := logic.GetNodeByID(id) + if err != nil { + slog.Error("error getting node", "id", id, "error", err) + return + } + decrypted, decryptErr := mq.DecryptMsg(¤tNode, msg.Payload()) + if decryptErr != nil { + slog.Error("failed to decrypt message for node", "id", id, "error", decryptErr) + return + } + + var newMetrics models.Metrics + if err := json.Unmarshal(decrypted, &newMetrics); err != nil { + slog.Error("error unmarshaling payload", "error", err) + return + } + + shouldUpdate := updateNodeMetrics(¤tNode, &newMetrics) + + if err = logic.UpdateMetrics(id, &newMetrics); err != nil { + slog.Error("failed to update node metrics", "id", id, "error", err) + return + } + if servercfg.IsMetricsExporter() { + if err := mq.PushMetricsToExporter(newMetrics); err != nil { + slog.Error("failed to push node metrics to exporter", "id", currentNode.ID, "error", err) + } + } + + if newMetrics.Connectivity != nil { + err := logic.EnterpriseFailoverFunc(¤tNode) + if err != nil { + slog.Error("failed to failover for node", "id", currentNode.ID, "network", currentNode.Network, "error", err) + } + } + + if shouldUpdate { + slog.Info("updating peers after node detected connectivity issues", "id", currentNode.ID, "network", currentNode.Network) + host, err := logic.GetHost(currentNode.HostID.String()) + if err == nil { + nodes, err := logic.GetAllNodes() + if err != nil { + return + } + if err = mq.PublishSingleHostPeerUpdate(host, nodes, nil, nil); err != nil { + slog.Warn("failed to publish update after failover peer change for node", "id", currentNode.ID, "network", currentNode.Network, "error", err) + } + } + } + slog.Debug("updated node metrics", "id", id) +} + +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.String()) + if err != nil { + slog.Error("error finding old metrics for node", "id", currentNode.ID, "error", err) + return false + } + if oldMetrics.FailoverPeers == nil { + oldMetrics.FailoverPeers = make(map[string]string) + } + + var attachedClients []models.ExtClient + if currentNode.IsIngressGateway { + clients, err := logic.GetExtClientsByID(currentNode.ID.String(), currentNode.Network) + if err == nil { + attachedClients = clients + } + } + if len(attachedClients) > 0 { + // associate ext clients with IDs + for i := range attachedClients { + extMetric := newMetrics.Connectivity[attachedClients[i].PublicKey] + if len(extMetric.NodeName) == 0 && + len(newMetrics.Connectivity[attachedClients[i].ClientID].NodeName) > 0 { // cover server clients + extMetric = newMetrics.Connectivity[attachedClients[i].ClientID] + if extMetric.TotalReceived > 0 && extMetric.TotalSent > 0 { + extMetric.Connected = true + } + } + extMetric.NodeName = attachedClients[i].ClientID + delete(newMetrics.Connectivity, attachedClients[i].PublicKey) + newMetrics.Connectivity[attachedClients[i].ClientID] = extMetric + } + } + + // run through metrics for each peer + for k := range newMetrics.Connectivity { + currMetric := newMetrics.Connectivity[k] + oldMetric := oldMetrics.Connectivity[k] + currMetric.TotalTime += oldMetric.TotalTime + currMetric.Uptime += oldMetric.Uptime // get the total uptime for this connection + + if currMetric.TotalReceived < oldMetric.TotalReceived { + currMetric.TotalReceived += oldMetric.TotalReceived + } else { + currMetric.TotalReceived += int64(math.Abs(float64(currMetric.TotalReceived) - float64(oldMetric.TotalReceived))) + } + if currMetric.TotalSent < oldMetric.TotalSent { + currMetric.TotalSent += oldMetric.TotalSent + } else { + currMetric.TotalSent += int64(math.Abs(float64(currMetric.TotalSent) - float64(oldMetric.TotalSent))) + } + + if currMetric.Uptime == 0 || currMetric.TotalTime == 0 { + currMetric.PercentUp = 0 + } else { + currMetric.PercentUp = 100.0 * (float64(currMetric.Uptime) / float64(currMetric.TotalTime)) + } + totalUpMinutes := currMetric.Uptime * ncutils.CheckInInterval + currMetric.ActualUptime = time.Duration(totalUpMinutes) * time.Minute + delete(oldMetrics.Connectivity, k) // remove from old data + newMetrics.Connectivity[k] = currMetric + + } + + // add nodes that need failover + nodes, err := logic.GetNetworkNodes(currentNode.Network) + if err != nil { + slog.Error("failed to retrieve nodes while updating metrics", "error", err) + return false + } + for _, node := range nodes { + if !newMetrics.Connectivity[node.ID.String()].Connected && + len(newMetrics.Connectivity[node.ID.String()].NodeName) > 0 && + node.Connected && + len(node.FailoverNode) > 0 && + !node.Failover { + newMetrics.FailoverPeers[node.ID.String()] = node.FailoverNode.String() + } + } + shouldUpdate := len(oldMetrics.FailoverPeers) == 0 && len(newMetrics.FailoverPeers) > 0 + for k, v := range oldMetrics.FailoverPeers { + if len(newMetrics.FailoverPeers[k]) > 0 && len(v) == 0 { + shouldUpdate = true + } + + if len(v) > 0 && len(newMetrics.FailoverPeers[k]) == 0 { + newMetrics.FailoverPeers[k] = v + } + } + + for k := range oldMetrics.Connectivity { // cleanup any left over data, self healing + delete(newMetrics.Connectivity, k) + } + return shouldUpdate +} diff --git a/pro/logic/nodes.go b/pro/logic/nodes.go new file mode 100644 index 00000000..153b710a --- /dev/null +++ b/pro/logic/nodes.go @@ -0,0 +1,21 @@ +package logic + +import ( + celogic "github.com/gravitl/netmaker/logic" + "github.com/gravitl/netmaker/models" +) + +// GetNetworkIngresses - gets the gateways of a network +func GetNetworkIngresses(network string) ([]models.Node, error) { + var ingresses []models.Node + netNodes, err := celogic.GetNetworkNodes(network) + if err != nil { + return []models.Node{}, err + } + for i := range netNodes { + if netNodes[i].IsIngressGateway { + ingresses = append(ingresses, netNodes[i]) + } + } + return ingresses, nil +} diff --git a/pro/logic/relays.go b/pro/logic/relays.go new file mode 100644 index 00000000..95614dd6 --- /dev/null +++ b/pro/logic/relays.go @@ -0,0 +1,218 @@ +package logic + +import ( + "errors" + "fmt" + "github.com/gravitl/netmaker/logger" + "github.com/gravitl/netmaker/logic" + "github.com/gravitl/netmaker/logic/acls/nodeacls" + "github.com/gravitl/netmaker/models" + "github.com/gravitl/netmaker/mq" + "github.com/gravitl/netmaker/servercfg" + "net" +) + +// CreateRelay - creates a relay +func CreateRelay(relay models.RelayRequest) ([]models.Node, models.Node, error) { + var returnnodes []models.Node + + node, err := logic.GetNodeByID(relay.NodeID) + if err != nil { + return returnnodes, models.Node{}, err + } + host, err := logic.GetHost(node.HostID.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.Node{}, err + } + node.IsRelay = true + node.RelayedNodes = relay.RelayedNodes + node.SetLastModified() + err = logic.UpsertNode(&node) + if err != nil { + return returnnodes, node, err + } + returnnodes = SetRelayedNodes(true, relay.NodeID, relay.RelayedNodes) + return returnnodes, node, nil +} + +// SetRelayedNodes- sets and saves node as relayed +func SetRelayedNodes(setRelayed bool, relay string, relayed []string) []models.Node { + var returnnodes []models.Node + for _, id := range relayed { + node, err := logic.GetNodeByID(id) + if err != nil { + logger.Log(0, "setRelayedNodes.GetNodebyID", err.Error()) + continue + } + node.IsRelayed = setRelayed + if node.IsRelayed { + node.RelayedBy = relay + } else { + node.RelayedBy = "" + } + node.SetLastModified() + if err := logic.UpsertNode(&node); err != nil { + logger.Log(0, "setRelayedNodes.Insert", err.Error()) + continue + } + returnnodes = append(returnnodes, node) + } + return returnnodes +} + +//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 { +// for _, addr := range relayNode.RelayAddrs { +// if addr == node.Address.IP.String() || addr == node.Address6.IP.String() { +// returnnodes = append(returnnodes, node) +// } +// } +// } +// return returnnodes, nil +//} + +// ValidateRelay - checks if relay is valid +func ValidateRelay(relay models.RelayRequest) error { + var err error + //isIp := functions.IsIpCIDR(gateway.RangeString) + empty := len(relay.RelayedNodes) == 0 + if empty { + return errors.New("IP Ranges Cannot Be Empty") + } + node, err := logic.GetNodeByID(relay.NodeID) + if err != nil { + return err + } + if node.IsRelay { + return errors.New("node is already acting as a relay") + } + for _, relayedNodeID := range relay.RelayedNodes { + relayedNode, err := logic.GetNodeByID(relayedNodeID) + if err != nil { + return err + } + if relayedNode.IsIngressGateway { + return errors.New("cannot relay an ingress gateway (" + relayedNodeID + ")") + } + } + return err +} + +// UpdateRelayNodes - updates relay nodes +func updateRelayNodes(relay string, oldNodes []string, newNodes []string) []models.Node { + _ = SetRelayedNodes(false, relay, oldNodes) + return SetRelayedNodes(true, relay, newNodes) +} + +func RelayUpdates(currentNode, newNode *models.Node) bool { + relayUpdates := false + if servercfg.IsPro && newNode.IsRelay && len(newNode.RelayedNodes) > 0 { + if len(newNode.RelayedNodes) != len(currentNode.RelayedNodes) { + relayUpdates = true + } else { + for i, node := range newNode.RelayedNodes { + if node != currentNode.RelayedNodes[i] { + relayUpdates = true + } + } + } + } + return relayUpdates +} + +func UpdateRelayed(currentNode, newNode *models.Node) { + updatenodes := updateRelayNodes(currentNode.ID.String(), currentNode.RelayedNodes, newNode.RelayedNodes) + if len(updatenodes) > 0 { + for _, relayedNode := range updatenodes { + mq.RunUpdates(&relayedNode, false) + } + } +} + +// DeleteRelay - deletes a relay +func DeleteRelay(network, nodeid string) ([]models.Node, models.Node, error) { + var returnnodes []models.Node + node, err := logic.GetNodeByID(nodeid) + if err != nil { + return returnnodes, models.Node{}, err + } + returnnodes = SetRelayedNodes(false, nodeid, node.RelayedNodes) + node.IsRelay = false + node.RelayedNodes = []string{} + node.SetLastModified() + if err = logic.UpsertNode(&node); err != nil { + return returnnodes, models.Node{}, err + } + return returnnodes, node, nil +} + +func RelayedAllowedIPs(peer, node *models.Node) []net.IPNet { + var allowedIPs = []net.IPNet{} + for _, relayedNodeID := range peer.RelayedNodes { + if node.ID.String() == relayedNodeID { + continue + } + relayedNode, err := logic.GetNodeByID(relayedNodeID) + if err != nil { + continue + } + allowed := getRelayedAddresses(relayedNodeID) + if relayedNode.IsEgressGateway { + allowed = append(allowed, logic.GetEgressIPs(&relayedNode)...) + } + allowedIPs = append(allowedIPs, allowed...) + } + return allowedIPs +} + +// GetAllowedIpsForRelayed - returns the peerConfig for a node relayed by relay +func GetAllowedIpsForRelayed(relayed, relay *models.Node) (allowedIPs []net.IPNet) { + if relayed.RelayedBy != relay.ID.String() { + logger.Log(0, "RelayedByRelay called with invalid parameters") + return + } + peers, err := logic.GetNetworkNodes(relay.Network) + if err != nil { + logger.Log(0, "error getting network clients", err.Error()) + return + } + for _, peer := range peers { + if peer.ID == relayed.ID || peer.ID == relay.ID { + continue + } + if nodeacls.AreNodesAllowed(nodeacls.NetworkID(relayed.Network), nodeacls.NodeID(relayed.ID.String()), nodeacls.NodeID(peer.ID.String())) { + allowedIPs = append(allowedIPs, logic.GetAllowedIPs(relayed, &peer, nil)...) + } + } + return +} + +func getRelayedAddresses(id string) []net.IPNet { + addrs := []net.IPNet{} + node, err := logic.GetNodeByID(id) + if err != nil { + logger.Log(0, "getRelayedAddresses: "+err.Error()) + return addrs + } + if node.Address.IP != nil { + node.Address.Mask = net.CIDRMask(32, 32) + addrs = append(addrs, node.Address) + } + if node.Address6.IP != nil { + node.Address.Mask = net.CIDRMask(128, 128) + addrs = append(addrs, node.Address6) + } + return addrs +} diff --git a/ee/types.go b/pro/types.go similarity index 98% rename from ee/types.go rename to pro/types.go index 1bae0bb1..97be7194 100644 --- a/ee/types.go +++ b/pro/types.go @@ -1,4 +1,7 @@ -package ee +//go:build ee +// +build ee + +package pro import ( "fmt" diff --git a/ee/util.go b/pro/util.go similarity index 85% rename from ee/util.go rename to pro/util.go index 8712981f..f48418b1 100644 --- a/ee/util.go +++ b/pro/util.go @@ -1,4 +1,7 @@ -package ee +//go:build ee +// +build ee + +package pro import ( "encoding/base64" @@ -6,14 +9,6 @@ import ( "github.com/gravitl/netmaker/logic" ) -var isEnterprise bool - -// setIsEnterprise - sets server to use enterprise features -func setIsEnterprise() { - isEnterprise = true - logic.SetEEForTelemetry(isEnterprise) -} - // base64encode - base64 encode helper function func base64encode(input []byte) string { return base64.StdEncoding.EncodeToString(input) diff --git a/release.md b/release.md index 1c363132..29ca258f 100644 --- a/release.md +++ b/release.md @@ -8,7 +8,7 @@ - Upgrade Process from v0.17.1 to latest version can be now done seamlessly, please refer docs for more information - Expired nodes clean up is handled correctly now - Ext client config generation fixed for ipv6 endpoints -- installation process will only generate certs required for required Domains based on CE or EE +- installation process will only generate certs required for required Domains based on CE or Pro - support for ARM machines on install script ## known issues diff --git a/scripts/nm-certs.sh b/scripts/nm-certs.sh index 1d99710b..41122969 100755 --- a/scripts/nm-certs.sh +++ b/scripts/nm-certs.sh @@ -39,7 +39,7 @@ if [ "$INSTALL_TYPE" = "ce" ]; then -d turnapi.$NM_DOMAIN EOF ) -elif [ "$INSTALL_TYPE" = "ee" ]; then +elif [ "$INSTALL_TYPE" = "pro" ]; then CERTBOT_PARAMS=$(cat <