NM-9: User All resources Policy and relayed node acl Fix (#3592)

* user policies fix

* fix user acl rules for all resources tag

* handle relayed comms via gateway with active acl policies

* fix static node comms to all resources
This commit is contained in:
Abhishek K 2025-08-11 14:32:26 +05:30 committed by GitHub
parent b972e7a969
commit 32657dde82
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 375 additions and 187 deletions

View file

@ -50,6 +50,27 @@ func GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) {
// if nodeI.StaticNode.IngressGatewayID != node.ID.String() {
// continue
// }
if IsNodeAllowedToCommunicateWithAllRsrcs(nodeI) {
if nodeI.Address.IP != nil {
rules = append(rules, models.FwRule{
SrcIP: net.IPNet{
IP: nodeI.Address.IP,
Mask: net.CIDRMask(32, 32),
},
Allow: true,
})
}
if nodeI.Address6.IP != nil {
rules = append(rules, models.FwRule{
SrcIP: net.IPNet{
IP: nodeI.Address6.IP,
Mask: net.CIDRMask(128, 128),
},
Allow: true,
})
}
continue
}
for _, peer := range nodes {
if peer.StaticNode.ClientID == nodeI.StaticNode.ClientID || peer.IsUserNode {
continue
@ -74,6 +95,37 @@ func GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) {
}
}
}
if len(node.RelayedNodes) > 0 {
for _, relayedNodeID := range node.RelayedNodes {
relayedNode, err := GetNodeByID(relayedNodeID)
if err != nil {
continue
}
if relayedNode.Address.IP != nil {
relayedFwRule := models.FwRule{
AllowedProtocol: models.ALL,
AllowedPorts: []string{},
Allow: true,
}
relayedFwRule.DstIP = relayedNode.AddressIPNet4()
relayedFwRule.SrcIP = node.NetworkRange
rules = append(rules, relayedFwRule)
}
if relayedNode.Address6.IP != nil {
relayedFwRule := models.FwRule{
AllowedProtocol: models.ALL,
AllowedPorts: []string{},
Allow: true,
}
relayedFwRule.DstIP = relayedNode.AddressIPNet6()
relayedFwRule.SrcIP = node.NetworkRange6
rules = append(rules, relayedFwRule)
}
}
}
return
}
@ -851,6 +903,60 @@ func MigrateAclPolicies() {
}
func IsNodeAllowedToCommunicateWithAllRsrcs(node models.Node) bool {
// check default policy if all allowed return true
defaultPolicy, err := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
if err == nil {
if defaultPolicy.Enabled {
return true
}
}
var nodeId string
if node.IsStatic {
nodeId = node.StaticNode.ClientID
node = node.StaticNode.ConvertToStaticNode()
} else {
nodeId = node.ID.String()
}
nodeTags := make(map[models.TagID]struct{})
nodeTags[models.TagID(nodeId)] = struct{}{}
if node.IsGw {
nodeTags[models.TagID(fmt.Sprintf("%s.%s", node.Network, models.GwTagName))] = struct{}{}
}
// list device policies
policies := ListDevicePolicies(models.NetworkID(node.Network))
srcMap := make(map[string]struct{})
dstMap := make(map[string]struct{})
defer func() {
srcMap = nil
dstMap = nil
}()
for _, policy := range policies {
if !policy.Enabled {
continue
}
srcMap = ConvAclTagToValueMap(policy.Src)
dstMap = ConvAclTagToValueMap(policy.Dst)
_, srcAll := srcMap["*"]
_, dstAll := dstMap["*"]
for tagID := range nodeTags {
if srcAll {
if _, ok := dstMap[tagID.String()]; ok {
return true
}
}
if dstAll {
if _, ok := srcMap[tagID.String()]; ok {
return true
}
}
}
}
return false
}
// IsNodeAllowedToCommunicate - check node is allowed to communicate with the peer // ADD ALLOWED DIRECTION - 0 => node -> peer, 1 => peer-> node,
func isNodeAllowedToCommunicate(node, peer models.Node, checkDefaultPolicy bool) (bool, []models.Acl) {
var nodeId, peerId string

View file

@ -729,12 +729,7 @@ func GetStaticNodesByNetwork(network models.NetworkID, onlyWg bool) (staticNode
if onlyWg && extI.RemoteAccessClientID != "" {
continue
}
n := models.Node{
IsStatic: true,
StaticNode: extI,
IsUserNode: extI.RemoteAccessClientID != "",
}
staticNode = append(staticNode, n)
staticNode = append(staticNode, extI.ConvertToStaticNode())
}
}

View file

@ -17,6 +17,27 @@ func GetFwRulesForUserNodesOnGw(node models.Node, nodes []models.Node) (rules []
defaultUserPolicy, _ := logic.GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy)
userNodes := logic.GetStaticUserNodesByNetwork(models.NetworkID(node.Network))
for _, userNodeI := range userNodes {
if defaultUserPolicy.Enabled {
if userNodeI.StaticNode.Address != "" {
rules = append(rules, models.FwRule{
SrcIP: userNodeI.StaticNode.AddressIPNet4(),
DstIP: net.IPNet{},
AllowedProtocol: models.ALL,
AllowedPorts: []string{},
Allow: true,
})
}
if userNodeI.StaticNode.Address6 != "" {
rules = append(rules, models.FwRule{
SrcIP: userNodeI.StaticNode.AddressIPNet6(),
DstIP: net.IPNet{},
AllowedProtocol: models.ALL,
AllowedPorts: []string{},
Allow: true,
})
}
continue
}
for _, peer := range nodes {
if peer.IsUserNode {
continue
@ -26,7 +47,6 @@ func GetFwRulesForUserNodesOnGw(node models.Node, nodes []models.Node) (rules []
if peer.IsStatic {
peer = peer.StaticNode.ConvertToStaticNode()
}
if !defaultUserPolicy.Enabled {
for _, policy := range allowedPolicies {
if userNodeI.StaticNode.Address != "" {
rules = append(rules, models.FwRule{
@ -55,6 +75,16 @@ func GetFwRulesForUserNodesOnGw(node models.Node, nodes []models.Node) (rules []
// add egress ranges
for _, dstI := range policy.Dst {
if dstI.Value == "*" {
rules = append(rules, models.FwRule{
SrcIP: userNodeI.StaticNode.AddressIPNet4(),
DstIP: net.IPNet{},
AllowedProtocol: policy.Proto,
AllowedPorts: policy.Port,
Allow: true,
})
break
}
if dstI.ID == models.EgressID {
e := schema.Egress{ID: dstI.Value}
@ -88,7 +118,6 @@ func GetFwRulesForUserNodesOnGw(node models.Node, nodes []models.Node) (rules []
}
}
}
}
}
@ -922,6 +951,8 @@ func getEgressUserRulesForNode(targetnode *models.Node,
if len(egs) == 0 {
return rules
}
defaultPolicy, _ := logic.GetDefaultPolicy(models.NetworkID(targetnode.Network), models.UserPolicy)
for _, egI := range egs {
if !egI.Status {
continue
@ -931,6 +962,7 @@ func getEgressUserRulesForNode(targetnode *models.Node,
targetNodeTags[models.TagID(egI.ID)] = struct{}{}
}
}
if !defaultPolicy.Enabled {
for _, acl := range acls {
if !acl.Enabled {
continue
@ -978,11 +1010,36 @@ func getEgressUserRulesForNode(targetnode *models.Node,
}
}
}
if defaultPolicy.Enabled {
r := models.AclRule{
ID: defaultPolicy.ID,
AllowedProtocol: defaultPolicy.Proto,
AllowedPorts: defaultPolicy.Port,
Direction: defaultPolicy.AllowedDirection,
Allowed: true,
}
for _, userNode := range userNodes {
if !userNode.StaticNode.Enabled {
continue
}
// Get peers in the tags and add allowed rules
if userNode.StaticNode.Address != "" {
r.IPList = append(r.IPList, userNode.StaticNode.AddressIPNet4())
}
if userNode.StaticNode.Address6 != "" {
r.IP6List = append(r.IP6List, userNode.StaticNode.AddressIPNet6())
}
}
rules[defaultPolicy.ID] = r
} else {
for _, userNode := range userNodes {
if !userNode.StaticNode.Enabled {
continue
}
acls, ok := allowedUsers[userNode.StaticNode.OwnerID]
if !ok {
continue
@ -1035,7 +1092,10 @@ func getEgressUserRulesForNode(targetnode *models.Node,
rules[acl.ID] = r
}
}
}
}
return rules
}
@ -1056,7 +1116,9 @@ func getUserAclRulesForNode(targetnode *models.Node,
if targetNodeTags == nil {
targetNodeTags = make(map[models.TagID]struct{})
}
defaultPolicy, _ := logic.GetDefaultPolicy(models.NetworkID(targetnode.Network), models.UserPolicy)
targetNodeTags[models.TagID(targetnode.ID.String())] = struct{}{}
if !defaultPolicy.Enabled {
for _, acl := range acls {
if !acl.Enabled {
continue
@ -1092,7 +1154,30 @@ func getUserAclRulesForNode(targetnode *models.Node,
}
}
}
if defaultPolicy.Enabled {
r := models.AclRule{
ID: defaultPolicy.ID,
AllowedProtocol: defaultPolicy.Proto,
AllowedPorts: defaultPolicy.Port,
Direction: defaultPolicy.AllowedDirection,
Allowed: true,
}
for _, userNode := range userNodes {
if !userNode.StaticNode.Enabled {
continue
}
// Get peers in the tags and add allowed rules
if userNode.StaticNode.Address != "" {
r.IPList = append(r.IPList, userNode.StaticNode.AddressIPNet4())
}
if userNode.StaticNode.Address6 != "" {
r.IP6List = append(r.IP6List, userNode.StaticNode.AddressIPNet6())
}
}
rules[defaultPolicy.ID] = r
} else {
for _, userNode := range userNodes {
if !userNode.StaticNode.Enabled {
continue
@ -1133,6 +1218,7 @@ func getUserAclRulesForNode(targetnode *models.Node,
}
}
}
}
return rules
}
@ -1228,9 +1314,9 @@ func CheckIfAnyPolicyisUniDirectional(targetNode models.Node, acls []models.Acl)
func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRule) {
targetnode := *targetnodeI
defer func() {
if !targetnode.IsIngressGateway {
//if !targetnode.IsIngressGateway {
rules = getUserAclRulesForNode(&targetnode, rules)
}
//}
}()
rules = make(map[string]models.AclRule)
var taggedNodes map[models.TagID][]models.Node

View file

@ -5,6 +5,7 @@ package pro
import (
"encoding/base64"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/logic"