From 0ff216dabddea2a0f164e499ff13ab675eb532c3 Mon Sep 17 00:00:00 2001 From: Abhishek K Date: Thu, 5 Jun 2025 13:28:23 +0530 Subject: [PATCH] NET-1932: Fix static node comms on CE (#3481) * move relevant acl and tag code to CE and Pro pkgs * intialise pro acl funcs * list gateways by user access * check user gw access by policies * filter out user policies on CE * filter out tagged policies on CE * fix ce acl comms * allow gateways tag * allow gateway tag on CE, remove failover and gw check on acl policy * add gw rules func to pro * add inet gw support on CE * add egress acl API * add egress acl API * fix(go): set is_gw when converting api node to server node; * fix(go): set is_gw when converting api node to server node; * fix policy validity checker for inet gws * move dns option to host model * fix node removal from egress policy on delete * add migration logic for ManageDNS * fix dns json field * fix nil error on node tags * add egress info to relayed nodes * fix default network user policy * fix egress migration * fix egress migration * add failover inet gw check * optiomise egress calls * auto create gw on inet egress node * optimise egress calls * add global user role check * fix egress on inet gw * remove addtional checks on inet policy * add acl policy for static nodes on CE * remove chained inet gws * fix multi-inet issue --------- Co-authored-by: Vishal Dalwadi --- controllers/acls.go | 3 +- controllers/egress.go | 6 + controllers/ext_client.go | 5 +- logic/acls.go | 271 +++++++++++++++++++++++++++++++++++- logic/egress.go | 15 +- logic/extpeers.go | 3 +- logic/peers.go | 12 +- logic/relay.go | 12 +- pro/controllers/failover.go | 14 +- pro/initialize.go | 4 +- pro/logic/acls.go | 107 +------------- pro/logic/failover.go | 3 +- 12 files changed, 317 insertions(+), 138 deletions(-) diff --git a/controllers/acls.go b/controllers/acls.go index 16d65659..ef56b3a0 100644 --- a/controllers/acls.go +++ b/controllers/acls.go @@ -181,11 +181,12 @@ func aclDebug(w http.ResponseWriter, r *http.Request) { allowed, ps := logic.IsNodeAllowedToCommunicate(node, peer, true) isallowed := logic.IsPeerAllowed(node, peer, true) + acls, _ := logic.ListAclsByNetwork(models.NetworkID(node.Network)) re := resp{ IsNodeAllowed: allowed, IsPeerAllowed: isallowed, Policies: ps, - EgressNets: logic.GetNetworkEgressInfo(models.NetworkID(node.Network)), + EgressNets: logic.GetNetworkEgressInfo(models.NetworkID(node.Network), acls), } if peerIsStatic == "true" { ingress, err := logic.GetNodeByID(peer.StaticNode.IngressGatewayID) diff --git a/controllers/egress.go b/controllers/egress.go index 5af9e921..67809902 100644 --- a/controllers/egress.go +++ b/controllers/egress.go @@ -92,6 +92,12 @@ func createEgress(w http.ResponseWriter, r *http.Request) { node.IsGw = true node.IsIngressGateway = true node.IsRelay = true + if node.Address.IP != nil { + node.IngressDNS = node.Address.IP.String() + } else { + node.IngressDNS = node.Address6.IP.String() + } + logic.UpsertNode(&node) } } diff --git a/controllers/ext_client.go b/controllers/ext_client.go index 944c010f..2b640a19 100644 --- a/controllers/ext_client.go +++ b/controllers/ext_client.go @@ -178,7 +178,8 @@ func getExtClientConf(w http.ResponseWriter, r *http.Request) { return } eli, _ := (&schema.Egress{Network: gwnode.Network}).ListByNetwork(db.WithContext(context.TODO())) - logic.GetNodeEgressInfo(&gwnode, eli) + acls, _ := logic.ListAclsByNetwork(models.NetworkID(client.Network)) + logic.GetNodeEgressInfo(&gwnode, eli, acls) host, err := logic.GetHost(gwnode.HostID.String()) if err != nil { logger.Log( @@ -266,7 +267,7 @@ func getExtClientConf(w http.ResponseWriter, r *http.Request) { } var newAllowedIPs string - if logic.IsInternetGw(gwnode) || gwnode.EgressDetails.InternetGwID != "" { + if logic.IsInternetGw(gwnode) { egressrange := "0.0.0.0/0" if gwnode.Address6.IP != nil && client.Address6 != "" { egressrange += "," + "::/0" diff --git a/logic/acls.go b/logic/acls.go index 9349fd84..bdb6e417 100644 --- a/logic/acls.go +++ b/logic/acls.go @@ -21,8 +21,272 @@ import ( // TODO: Write Diff Funcs var IsNodeAllowedToCommunicate = isNodeAllowedToCommunicate -var GetStaticNodeIps = func(node models.Node) (ips []net.IP) { return } -var GetFwRulesOnIngressGateway = func(node models.Node) (rules []models.FwRule) { return } + +var GetFwRulesForNodeAndPeerOnGw = getFwRulesForNodeAndPeerOnGw + +var GetFwRulesForUserNodesOnGw = func(node models.Node, nodes []models.Node) (rules []models.FwRule) { return } + +func GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) { + // fetch user access to static clients via policies + defer func() { + sort.Slice(rules, func(i, j int) bool { + if !rules[i].SrcIP.IP.Equal(rules[j].SrcIP.IP) { + return string(rules[i].SrcIP.IP.To16()) < string(rules[j].SrcIP.IP.To16()) + } + return string(rules[i].DstIP.IP.To16()) < string(rules[j].DstIP.IP.To16()) + }) + }() + defaultDevicePolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy) + nodes, _ := GetNetworkNodes(node.Network) + nodes = append(nodes, GetStaticNodesByNetwork(models.NetworkID(node.Network), true)...) + rules = GetFwRulesForUserNodesOnGw(node, nodes) + if defaultDevicePolicy.Enabled { + return + } + for _, nodeI := range nodes { + if !nodeI.IsStatic || nodeI.IsUserNode { + continue + } + // if nodeI.StaticNode.IngressGatewayID != node.ID.String() { + // continue + // } + for _, peer := range nodes { + if peer.StaticNode.ClientID == nodeI.StaticNode.ClientID || peer.IsUserNode { + continue + } + if nodeI.StaticNode.IngressGatewayID != node.ID.String() && + ((!peer.IsStatic && peer.ID.String() != node.ID.String()) || + (peer.IsStatic && peer.StaticNode.IngressGatewayID != node.ID.String())) { + continue + } + if peer.IsStatic { + peer = peer.StaticNode.ConvertToStaticNode() + } + var allowedPolicies1 []models.Acl + var ok bool + if ok, allowedPolicies1 = IsNodeAllowedToCommunicate(nodeI.StaticNode.ConvertToStaticNode(), peer, true); ok { + rules = append(rules, GetFwRulesForNodeAndPeerOnGw(nodeI.StaticNode.ConvertToStaticNode(), peer, allowedPolicies1)...) + } + if ok, allowedPolicies2 := IsNodeAllowedToCommunicate(peer, nodeI.StaticNode.ConvertToStaticNode(), true); ok { + rules = append(rules, + GetFwRulesForNodeAndPeerOnGw(peer, nodeI.StaticNode.ConvertToStaticNode(), + getUniquePolicies(allowedPolicies1, allowedPolicies2))...) + } + } + } + return +} + +func getFwRulesForNodeAndPeerOnGw(node, peer models.Node, allowedPolicies []models.Acl) (rules []models.FwRule) { + + for _, policy := range allowedPolicies { + // if static peer dst rule not for ingress node -> skip + if node.Address.IP != nil { + rules = append(rules, models.FwRule{ + SrcIP: net.IPNet{ + IP: node.Address.IP, + Mask: net.CIDRMask(32, 32), + }, + DstIP: net.IPNet{ + IP: peer.Address.IP, + Mask: net.CIDRMask(32, 32), + }, + Allow: true, + }) + } + + if node.Address6.IP != nil { + rules = append(rules, models.FwRule{ + SrcIP: net.IPNet{ + IP: node.Address6.IP, + Mask: net.CIDRMask(128, 128), + }, + DstIP: net.IPNet{ + IP: peer.Address6.IP, + Mask: net.CIDRMask(128, 128), + }, + Allow: true, + }) + } + if policy.AllowedDirection == models.TrafficDirectionBi { + if node.Address.IP != nil { + rules = append(rules, models.FwRule{ + SrcIP: net.IPNet{ + IP: peer.Address.IP, + Mask: net.CIDRMask(32, 32), + }, + DstIP: net.IPNet{ + IP: node.Address.IP, + Mask: net.CIDRMask(32, 32), + }, + Allow: true, + }) + } + + if node.Address6.IP != nil { + rules = append(rules, models.FwRule{ + SrcIP: net.IPNet{ + IP: peer.Address6.IP, + Mask: net.CIDRMask(128, 128), + }, + DstIP: net.IPNet{ + IP: node.Address6.IP, + Mask: net.CIDRMask(128, 128), + }, + Allow: true, + }) + } + } + if len(node.StaticNode.ExtraAllowedIPs) > 0 { + for _, additionalAllowedIPNet := range node.StaticNode.ExtraAllowedIPs { + _, ipNet, err := net.ParseCIDR(additionalAllowedIPNet) + if err != nil { + continue + } + if ipNet.IP.To4() != nil && peer.Address.IP != nil { + rules = append(rules, models.FwRule{ + SrcIP: net.IPNet{ + IP: peer.Address.IP, + Mask: net.CIDRMask(32, 32), + }, + DstIP: *ipNet, + Allow: true, + }) + } else if peer.Address6.IP != nil { + rules = append(rules, models.FwRule{ + SrcIP: net.IPNet{ + IP: peer.Address6.IP, + Mask: net.CIDRMask(128, 128), + }, + DstIP: *ipNet, + Allow: true, + }) + } + + } + + } + if len(peer.StaticNode.ExtraAllowedIPs) > 0 { + for _, additionalAllowedIPNet := range peer.StaticNode.ExtraAllowedIPs { + _, ipNet, err := net.ParseCIDR(additionalAllowedIPNet) + if err != nil { + continue + } + if ipNet.IP.To4() != nil && node.Address.IP != nil { + rules = append(rules, models.FwRule{ + SrcIP: net.IPNet{ + IP: node.Address.IP, + Mask: net.CIDRMask(32, 32), + }, + DstIP: *ipNet, + Allow: true, + }) + } else if node.Address6.IP != nil { + rules = append(rules, models.FwRule{ + SrcIP: net.IPNet{ + IP: node.Address6.IP, + Mask: net.CIDRMask(128, 128), + }, + DstIP: *ipNet, + Allow: true, + }) + } + + } + + } + + // add egress range rules + for _, dstI := range policy.Dst { + if dstI.ID == models.EgressID { + + e := schema.Egress{ID: dstI.Value} + err := e.Get(db.WithContext(context.TODO())) + if err != nil { + continue + } + dstI.Value = e.Range + + ip, cidr, err := net.ParseCIDR(dstI.Value) + if err == nil { + if ip.To4() != nil { + if node.Address.IP != nil { + rules = append(rules, models.FwRule{ + SrcIP: net.IPNet{ + IP: node.Address.IP, + Mask: net.CIDRMask(32, 32), + }, + DstIP: *cidr, + Allow: true, + }) + } + } else { + if node.Address6.IP != nil { + rules = append(rules, models.FwRule{ + SrcIP: net.IPNet{ + IP: node.Address6.IP, + Mask: net.CIDRMask(128, 128), + }, + DstIP: *cidr, + Allow: true, + }) + } + } + + } + } + } + } + + return +} + +func getUniquePolicies(policies1, policies2 []models.Acl) []models.Acl { + policies1Map := make(map[string]struct{}) + for _, policy1I := range policies1 { + policies1Map[policy1I.ID] = struct{}{} + } + for i := len(policies2) - 1; i >= 0; i-- { + if _, ok := policies1Map[policies2[i].ID]; ok { + policies2 = append(policies2[:i], policies2[i+1:]...) + } + } + return policies2 +} + +// Sort a slice of net.IP addresses +func sortIPs(ips []net.IP) { + sort.Slice(ips, func(i, j int) bool { + ip1, ip2 := ips[i].To16(), ips[j].To16() + return string(ip1) < string(ip2) // Compare as byte slices + }) +} + +func GetStaticNodeIps(node models.Node) (ips []net.IP) { + defer func() { + sortIPs(ips) + }() + defaultUserPolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy) + defaultDevicePolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy) + + extclients := GetStaticNodesByNetwork(models.NetworkID(node.Network), false) + for _, extclient := range extclients { + if extclient.IsUserNode && defaultUserPolicy.Enabled { + continue + } + if !extclient.IsUserNode && defaultDevicePolicy.Enabled { + continue + } + if extclient.StaticNode.Address != "" { + ips = append(ips, extclient.StaticNode.AddressIPNet4().IP) + } + if extclient.StaticNode.Address6 != "" { + ips = append(ips, extclient.StaticNode.AddressIPNet6().IP) + } + } + return +} + var MigrateToGws = func() { nodes, err := GetAllNodes() @@ -582,7 +846,7 @@ var GetInetClientsFromAclPolicies = func(eID string) (inetClientIDs []string) { return } -var IsNodeUsingInternetGw = func(node *models.Node) { +var IsNodeUsingInternetGw = func(node *models.Node, acls []models.Acl) { host, err := GetHost(node.HostID.String()) if err != nil { return @@ -590,7 +854,6 @@ var IsNodeUsingInternetGw = func(node *models.Node) { if host.IsDefault || node.IsFailOver { return } - acls, _ := ListAclsByNetwork(models.NetworkID(node.Network)) var isUsing bool for _, acl := range acls { if !acl.Enabled { diff --git a/logic/egress.go b/logic/egress.go index 2ca0321f..949154a9 100644 --- a/logic/egress.go +++ b/logic/egress.go @@ -36,6 +36,7 @@ func ValidateEgressReq(e *schema.Egress) error { if len(e.Nodes) > 1 { return errors.New("can only set one internet routing node") } + acls, _ := ListAclsByNetwork(models.NetworkID(e.Network)) req := models.InetNodeReq{} eli, _ := (&schema.Egress{Network: e.Network}).ListByNetwork(db.WithContext(context.TODO())) for k := range e.Nodes { @@ -45,7 +46,7 @@ func ValidateEgressReq(e *schema.Egress) error { } // check if node is acting as egress gw already - GetNodeEgressInfo(&inetNode, eli) + GetNodeEgressInfo(&inetNode, eli, acls) if err := ValidateInetGwReq(inetNode, req, false); err != nil { return err } @@ -130,7 +131,7 @@ func AddEgressInfoToPeerByAccess(node, targetNode *models.Node, eli []schema.Egr if targetNode.Mutex != nil { targetNode.Mutex.Lock() } - IsNodeUsingInternetGw(targetNode) + IsNodeUsingInternetGw(targetNode, acls) if targetNode.Mutex != nil { targetNode.Mutex.Unlock() } @@ -140,7 +141,7 @@ func AddEgressInfoToPeerByAccess(node, targetNode *models.Node, eli []schema.Egr if !e.Status || e.Network != targetNode.Network { continue } - if !isDefaultPolicyActive && !e.IsInetGw { + if !isDefaultPolicyActive || e.IsInetGw { if !DoesNodeHaveAccessToEgress(node, &e, acls) { if node.IsRelayed && node.RelayedBy == targetNode.ID.String() { if !DoesNodeHaveAccessToEgress(targetNode, &e, acls) { @@ -205,7 +206,7 @@ func AddEgressInfoToPeerByAccess(node, targetNode *models.Node, eli []schema.Egr } // TODO -func GetNetworkEgressInfo(network models.NetworkID) (egressNodes map[string]models.Node) { +func GetNetworkEgressInfo(network models.NetworkID, acls []models.Acl) (egressNodes map[string]models.Node) { eli, _ := (&schema.Egress{Network: network.String()}).ListByNetwork(db.WithContext(context.TODO())) egressNodes = make(map[string]models.Node) var err error @@ -227,7 +228,7 @@ func GetNetworkEgressInfo(network models.NetworkID) (egressNodes map[string]mode NodeID: targetNode.ID.String(), NetID: targetNode.Network, } - IsNodeUsingInternetGw(&targetNode) + IsNodeUsingInternetGw(&targetNode, acls) if e.IsInetGw { targetNode.EgressDetails.IsInternetGateway = true targetNode.EgressDetails.InetNodeReq = models.InetNodeReq{ @@ -280,7 +281,7 @@ func GetNetworkEgressInfo(network models.NetworkID) (egressNodes map[string]mode return } -func GetNodeEgressInfo(targetNode *models.Node, eli []schema.Egress) { +func GetNodeEgressInfo(targetNode *models.Node, eli []schema.Egress, acls []models.Acl) { req := models.EgressGatewayRequest{ NodeID: targetNode.ID.String(), @@ -290,7 +291,7 @@ func GetNodeEgressInfo(targetNode *models.Node, eli []schema.Egress) { if targetNode.Mutex != nil { targetNode.Mutex.Lock() } - IsNodeUsingInternetGw(targetNode) + IsNodeUsingInternetGw(targetNode, acls) if targetNode.Mutex != nil { targetNode.Mutex.Unlock() } diff --git a/logic/extpeers.go b/logic/extpeers.go index ea571054..7a892c28 100644 --- a/logic/extpeers.go +++ b/logic/extpeers.go @@ -75,12 +75,13 @@ func GetEgressRangesOnNetwork(client *models.ExtClient) ([]string, error) { return []string{}, err } eli, _ := (&schema.Egress{Network: client.Network}).ListByNetwork(db.WithContext(context.TODO())) + acls, _ := ListAclsByNetwork(models.NetworkID(client.Network)) // clientNode := client.ConvertToStaticNode() for _, currentNode := range networkNodes { if currentNode.Network != client.Network { continue } - GetNodeEgressInfo(¤tNode, eli) + GetNodeEgressInfo(¤tNode, eli, acls) if currentNode.EgressDetails.IsEgressGateway { // add the egress gateway range(s) to the result if len(currentNode.EgressDetails.EgressGatewayRanges) > 0 { if currentNode.EgressDetails.IsInternetGateway && client.IngressGatewayID != currentNode.ID.String() { diff --git a/logic/peers.go b/logic/peers.go index b81ce71d..4b0419d2 100644 --- a/logic/peers.go +++ b/logic/peers.go @@ -178,15 +178,15 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N if !node.Connected || node.PendingDelete || node.Action == models.NODE_DELETE || time.Since(node.LastCheckIn) > time.Hour { continue } + acls, _ := ListAclsByNetwork(models.NetworkID(node.Network)) eli, _ := (&schema.Egress{Network: node.Network}).ListByNetwork(db.WithContext(context.TODO())) - GetNodeEgressInfo(&node, eli) + GetNodeEgressInfo(&node, eli, acls) hostPeerUpdate = SetDefaultGw(node, hostPeerUpdate) if !hostPeerUpdate.IsInternetGw { hostPeerUpdate.IsInternetGw = IsInternetGw(node) } defaultUserPolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy) defaultDevicePolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy) - acls, _ := ListAclsByNetwork(models.NetworkID(node.Network)) if (defaultDevicePolicy.Enabled && defaultUserPolicy.Enabled) || (!CheckIfAnyPolicyisUniDirectional(node, acls) && !CheckIfAnyActiveEgressPolicy(node, acls)) || CheckIfNodeHasAccessToAllResources(&node, acls) { @@ -239,7 +239,7 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N PersistentKeepaliveInterval: &peerHost.PersistentKeepalive, ReplaceAllowedIPs: true, } - GetNodeEgressInfo(&peer, eli) + GetNodeEgressInfo(&peer, eli, acls) if peer.EgressDetails.IsEgressGateway { AddEgressInfoToPeerByAccess(&node, &peer, eli, acls, defaultDevicePolicy.Enabled) } @@ -589,9 +589,9 @@ func GetAllowedIPs(node, peer *models.Node, metrics *models.Metrics) []net.IPNet } if node.IsRelayed && node.RelayedBy == peer.ID.String() { allowedips = append(allowedips, GetAllowedIpsForRelayed(node, peer)...) - if peer.EgressDetails.InternetGwID != "" { - return allowedips - } + // if peer.EgressDetails.InternetGwID != "" { + // return allowedips + // } } // handle ingress gateway peers diff --git a/logic/relay.go b/logic/relay.go index 41d799ae..f3be7b80 100644 --- a/logic/relay.go +++ b/logic/relay.go @@ -113,12 +113,13 @@ func ValidateRelay(relay models.RelayRequest, update bool) error { return errors.New("node is already acting as a relay") } eli, _ := (&schema.Egress{Network: node.Network}).ListByNetwork(db.WithContext(context.TODO())) + acls, _ := ListAclsByNetwork(models.NetworkID(node.Network)) for _, relayedNodeID := range relay.RelayedNodes { relayedNode, err := GetNodeByID(relayedNodeID) if err != nil { return err } - GetNodeEgressInfo(&relayedNode, eli) + GetNodeEgressInfo(&relayedNode, eli, acls) if relayedNode.IsIngressGateway { return errors.New("cannot relay an ingress gateway (" + relayedNodeID + ")") } @@ -191,6 +192,7 @@ func DeleteRelay(network, nodeid string) ([]models.Node, models.Node, error) { func RelayedAllowedIPs(peer, node *models.Node) []net.IPNet { var allowedIPs = []net.IPNet{} eli, _ := (&schema.Egress{Network: node.Network}).ListByNetwork(db.WithContext(context.TODO())) + acls, _ := ListAclsByNetwork(models.NetworkID(node.Network)) for _, relayedNodeID := range peer.RelayedNodes { if node.ID.String() == relayedNodeID { continue @@ -199,7 +201,7 @@ func RelayedAllowedIPs(peer, node *models.Node) []net.IPNet { if err != nil { continue } - GetNodeEgressInfo(&relayedNode, eli) + GetNodeEgressInfo(&relayedNode, eli, acls) allowed := getRelayedAddresses(relayedNodeID) if relayedNode.EgressDetails.IsEgressGateway { allowed = append(allowed, GetEgressIPs(&relayedNode)...) @@ -215,9 +217,9 @@ func GetAllowedIpsForRelayed(relayed, relay *models.Node) (allowedIPs []net.IPNe logger.Log(0, "RelayedByRelay called with invalid parameters") return } - if relay.EgressDetails.InternetGwID != "" { - return GetAllowedIpForInetNodeClient(relayed, relay) - } + // if relay.EgressDetails.InternetGwID != "" { + // return GetAllowedIpForInetNodeClient(relayed, relay) + // } peers, err := GetNetworkNodes(relay.Network) if err != nil { logger.Log(0, "error getting network clients", err.Error()) diff --git a/pro/controllers/failover.go b/pro/controllers/failover.go index 5437c55f..5957494c 100644 --- a/pro/controllers/failover.go +++ b/pro/controllers/failover.go @@ -209,9 +209,10 @@ func failOverME(w http.ResponseWriter, r *http.Request) { return } eli, _ := (&schema.Egress{Network: node.Network}).ListByNetwork(db.WithContext(context.TODO())) - logic.GetNodeEgressInfo(&node, eli) - logic.GetNodeEgressInfo(&peerNode, eli) - logic.GetNodeEgressInfo(&failOverNode, eli) + acls, _ := logic.ListAclsByNetwork(models.NetworkID(node.Network)) + logic.GetNodeEgressInfo(&node, eli, acls) + logic.GetNodeEgressInfo(&peerNode, eli, acls) + logic.GetNodeEgressInfo(&failOverNode, eli, acls) if peerNode.IsFailOver { logic.ReturnErrorResponse( w, @@ -369,9 +370,10 @@ func checkfailOverCtx(w http.ResponseWriter, r *http.Request) { return } eli, _ := (&schema.Egress{Network: node.Network}).ListByNetwork(db.WithContext(context.TODO())) - logic.GetNodeEgressInfo(&node, eli) - logic.GetNodeEgressInfo(&peerNode, eli) - logic.GetNodeEgressInfo(&failOverNode, eli) + acls, _ := logic.ListAclsByNetwork(models.NetworkID(node.Network)) + logic.GetNodeEgressInfo(&node, eli, acls) + logic.GetNodeEgressInfo(&peerNode, eli, acls) + logic.GetNodeEgressInfo(&failOverNode, eli, acls) if peerNode.IsFailOver { logic.ReturnErrorResponse( w, diff --git a/pro/initialize.go b/pro/initialize.go index 7e4ec672..91e29eda 100644 --- a/pro/initialize.go +++ b/pro/initialize.go @@ -155,8 +155,8 @@ func InitPro() { logic.CheckIfAnyPolicyisUniDirectional = proLogic.CheckIfAnyPolicyisUniDirectional logic.MigrateToGws = proLogic.MigrateToGws logic.IsNodeAllowedToCommunicate = proLogic.IsNodeAllowedToCommunicate - logic.GetStaticNodeIps = proLogic.GetStaticNodeIps - logic.GetFwRulesOnIngressGateway = proLogic.GetFwRulesOnIngressGateway + logic.GetFwRulesForNodeAndPeerOnGw = proLogic.GetFwRulesForNodeAndPeerOnGw + logic.GetFwRulesForUserNodesOnGw = proLogic.GetFwRulesForUserNodesOnGw } diff --git a/pro/logic/acls.go b/pro/logic/acls.go index 6fb45a53..621085bb 100644 --- a/pro/logic/acls.go +++ b/pro/logic/acls.go @@ -5,7 +5,6 @@ import ( "errors" "maps" "net" - "sort" "github.com/google/uuid" "github.com/gravitl/netmaker/db" @@ -25,7 +24,7 @@ ranges should be replaced by egress identifier */ -func getFwRulesForUserNodesOnGw(node models.Node, nodes []models.Node) (rules []models.FwRule) { +func GetFwRulesForUserNodesOnGw(node models.Node, nodes []models.Node) (rules []models.FwRule) { defaultUserPolicy, _ := logic.GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy) userNodes := logic.GetStaticUserNodesByNetwork(models.NetworkID(node.Network)) for _, userNodeI := range userNodes { @@ -108,58 +107,7 @@ func getFwRulesForUserNodesOnGw(node models.Node, nodes []models.Node) (rules [] return } -func GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) { - // fetch user access to static clients via policies - defer func() { - sort.Slice(rules, func(i, j int) bool { - if !rules[i].SrcIP.IP.Equal(rules[j].SrcIP.IP) { - return string(rules[i].SrcIP.IP.To16()) < string(rules[j].SrcIP.IP.To16()) - } - return string(rules[i].DstIP.IP.To16()) < string(rules[j].DstIP.IP.To16()) - }) - }() - defaultDevicePolicy, _ := logic.GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy) - nodes, _ := logic.GetNetworkNodes(node.Network) - nodes = append(nodes, logic.GetStaticNodesByNetwork(models.NetworkID(node.Network), true)...) - rules = getFwRulesForUserNodesOnGw(node, nodes) - if defaultDevicePolicy.Enabled { - return - } - for _, nodeI := range nodes { - if !nodeI.IsStatic || nodeI.IsUserNode { - continue - } - // if nodeI.StaticNode.IngressGatewayID != node.ID.String() { - // continue - // } - for _, peer := range nodes { - if peer.StaticNode.ClientID == nodeI.StaticNode.ClientID || peer.IsUserNode { - continue - } - if nodeI.StaticNode.IngressGatewayID != node.ID.String() && - ((!peer.IsStatic && peer.ID.String() != node.ID.String()) || - (peer.IsStatic && peer.StaticNode.IngressGatewayID != node.ID.String())) { - continue - } - if peer.IsStatic { - peer = peer.StaticNode.ConvertToStaticNode() - } - var allowedPolicies1 []models.Acl - var ok bool - if ok, allowedPolicies1 = IsNodeAllowedToCommunicate(nodeI.StaticNode.ConvertToStaticNode(), peer, true); ok { - rules = append(rules, getFwRulesForNodeAndPeerOnGw(nodeI.StaticNode.ConvertToStaticNode(), peer, allowedPolicies1)...) - } - if ok, allowedPolicies2 := IsNodeAllowedToCommunicate(peer, nodeI.StaticNode.ConvertToStaticNode(), true); ok { - rules = append(rules, - getFwRulesForNodeAndPeerOnGw(peer, nodeI.StaticNode.ConvertToStaticNode(), - getUniquePolicies(allowedPolicies1, allowedPolicies2))...) - } - } - } - return -} - -func getFwRulesForNodeAndPeerOnGw(node, peer models.Node, allowedPolicies []models.Acl) (rules []models.FwRule) { +func GetFwRulesForNodeAndPeerOnGw(node, peer models.Node, allowedPolicies []models.Acl) (rules []models.FwRule) { for _, policy := range allowedPolicies { // if static peer dst rule not for ingress node -> skip @@ -335,52 +283,6 @@ func getFwRulesForNodeAndPeerOnGw(node, peer models.Node, allowedPolicies []mode return } -func getUniquePolicies(policies1, policies2 []models.Acl) []models.Acl { - policies1Map := make(map[string]struct{}) - for _, policy1I := range policies1 { - policies1Map[policy1I.ID] = struct{}{} - } - for i := len(policies2) - 1; i >= 0; i-- { - if _, ok := policies1Map[policies2[i].ID]; ok { - policies2 = append(policies2[:i], policies2[i+1:]...) - } - } - return policies2 -} - -func GetStaticNodeIps(node models.Node) (ips []net.IP) { - defer func() { - sortIPs(ips) - }() - defaultUserPolicy, _ := logic.GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy) - defaultDevicePolicy, _ := logic.GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy) - - extclients := logic.GetStaticNodesByNetwork(models.NetworkID(node.Network), false) - for _, extclient := range extclients { - if extclient.IsUserNode && defaultUserPolicy.Enabled { - continue - } - if !extclient.IsUserNode && defaultDevicePolicy.Enabled { - continue - } - if extclient.StaticNode.Address != "" { - ips = append(ips, extclient.StaticNode.AddressIPNet4().IP) - } - if extclient.StaticNode.Address6 != "" { - ips = append(ips, extclient.StaticNode.AddressIPNet6().IP) - } - } - return -} - -// Sort a slice of net.IP addresses -func sortIPs(ips []net.IP) { - sort.Slice(ips, func(i, j int) bool { - ip1, ip2 := ips[i].To16(), ips[j].To16() - return string(ip1) < string(ip2) // Compare as byte slices - }) -} - func checkIfAclTagisValid(a models.Acl, t models.AclPolicyTag, isSrc bool) (err error) { switch t.ID { case models.NodeTagID: @@ -1628,7 +1530,7 @@ func GetEgressRulesForNode(targetnode models.Node) (rules map[string]models.AclR continue } if _, ok := egI.Nodes[targetnode.ID.String()]; ok { - if egI.Range == "*" { + if egI.IsInetGw { targetNodeTags[models.TagID("0.0.0.0/0")] = struct{}{} targetNodeTags[models.TagID("::/0")] = struct{}{} } else { @@ -1867,7 +1769,7 @@ func GetInetClientsFromAclPolicies(eID string) (inetClientIDs []string) { return } -func IsNodeUsingInternetGw(node *models.Node) { +func IsNodeUsingInternetGw(node *models.Node, acls []models.Acl) { host, err := logic.GetHost(node.HostID.String()) if err != nil { return @@ -1880,7 +1782,6 @@ func IsNodeUsingInternetGw(node *models.Node) { nodeTags = make(map[models.TagID]struct{}) } nodeTags[models.TagID(node.ID.String())] = struct{}{} - acls, _ := logic.ListAclsByNetwork(models.NetworkID(node.Network)) var isUsing bool for _, acl := range acls { if !acl.Enabled { diff --git a/pro/logic/failover.go b/pro/logic/failover.go index 7a42ef77..29f39cc2 100644 --- a/pro/logic/failover.go +++ b/pro/logic/failover.go @@ -166,10 +166,11 @@ func ResetFailOver(failOverNode *models.Node) error { func GetFailOverPeerIps(peer, node *models.Node) []net.IPNet { allowedips := []net.IPNet{} eli, _ := (&schema.Egress{Network: node.Network}).ListByNetwork(db.WithContext(context.TODO())) + acls, _ := logic.ListAclsByNetwork(models.NetworkID(node.Network)) for failOverpeerID := range node.FailOverPeers { failOverpeer, err := logic.GetNodeByID(failOverpeerID) if err == nil && failOverpeer.FailedOverBy == peer.ID { - logic.GetNodeEgressInfo(&failOverpeer, eli) + logic.GetNodeEgressInfo(&failOverpeer, eli, acls) if failOverpeer.Address.IP != nil { allowed := net.IPNet{ IP: failOverpeer.Address.IP,