mirror of
https://github.com/gravitl/netmaker.git
synced 2025-09-26 21:01:32 +08:00

* add support for egress domain routing * add domain info to egress range * fix egress domain update * send peer update domain resolution update * add egress domain update in the peer update * use range field for domain check * add egress domain to host pull * add egress domain model to egress host update * add egress domain model to egress host update * update egress domain model on acls * add check of range if domain is set * sync egress domains to dns system * add egress domain to match domain list, fix egress nat rule for domains * fix all rsrcs comms * fix static checks * fix egress acls on CE * check for all resources access on a node * simplify egress acl rules * merged ce and pro acl rule func * fix uni direction acl rule for static nodes * allow relayed nodes traffic * resolve merge conflicts * remove anywhere dst rule on user node acls * fix: broadcast user groups update for acl changes * add egress domain ans routes to nodes * add egress ranges to DST * add all egress ranges for all resources * fix DNS routing acls rules
1397 lines
37 KiB
Go
1397 lines
37 KiB
Go
package logic
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"maps"
|
|
"net"
|
|
|
|
"github.com/gravitl/netmaker/db"
|
|
"github.com/gravitl/netmaker/logic"
|
|
"github.com/gravitl/netmaker/models"
|
|
"github.com/gravitl/netmaker/schema"
|
|
)
|
|
|
|
func getStaticUserNodesByNetwork(network models.NetworkID) (staticNode []models.Node) {
|
|
extClients, err := logic.GetAllExtClients()
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, extI := range extClients {
|
|
if extI.Network == network.String() {
|
|
if extI.RemoteAccessClientID != "" {
|
|
n := extI.ConvertToStaticNode()
|
|
staticNode = append(staticNode, n)
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func GetFwRulesForUserNodesOnGw(node models.Node, nodes []models.Node) (rules []models.FwRule) {
|
|
defaultUserPolicy, _ := logic.GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy)
|
|
userNodes := getStaticUserNodesByNetwork(models.NetworkID(node.Network))
|
|
for _, userNodeI := range userNodes {
|
|
if !userNodeI.StaticNode.Enabled {
|
|
continue
|
|
}
|
|
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
|
|
}
|
|
|
|
if ok, allowedPolicies := IsUserAllowedToCommunicate(userNodeI.StaticNode.OwnerID, peer); ok {
|
|
if peer.IsStatic {
|
|
peer = peer.StaticNode.ConvertToStaticNode()
|
|
}
|
|
for _, policy := range allowedPolicies {
|
|
if userNodeI.StaticNode.Address != "" {
|
|
rules = append(rules, models.FwRule{
|
|
SrcIP: userNodeI.StaticNode.AddressIPNet4(),
|
|
DstIP: net.IPNet{
|
|
IP: peer.Address.IP,
|
|
Mask: net.CIDRMask(32, 32),
|
|
},
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
Allow: true,
|
|
})
|
|
}
|
|
if userNodeI.StaticNode.Address6 != "" {
|
|
rules = append(rules, models.FwRule{
|
|
SrcIP: userNodeI.StaticNode.AddressIPNet6(),
|
|
DstIP: net.IPNet{
|
|
IP: peer.Address6.IP,
|
|
Mask: net.CIDRMask(128, 128),
|
|
},
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
Allow: true,
|
|
})
|
|
}
|
|
|
|
// 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}
|
|
err := e.Get(db.WithContext(context.TODO()))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if e.Range != "" {
|
|
dstI.Value = e.Range
|
|
|
|
ip, cidr, err := net.ParseCIDR(dstI.Value)
|
|
if err == nil {
|
|
if ip.To4() != nil && userNodeI.StaticNode.Address != "" {
|
|
rules = append(rules, models.FwRule{
|
|
SrcIP: userNodeI.StaticNode.AddressIPNet4(),
|
|
DstIP: *cidr,
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
Allow: true,
|
|
})
|
|
} else if ip.To16() != nil && userNodeI.StaticNode.Address6 != "" {
|
|
rules = append(rules, models.FwRule{
|
|
SrcIP: userNodeI.StaticNode.AddressIPNet6(),
|
|
DstIP: *cidr,
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
Allow: true,
|
|
})
|
|
}
|
|
}
|
|
} else if len(e.DomainAns) > 0 {
|
|
for _, domainAns := range e.DomainAns {
|
|
dstI.Value = domainAns
|
|
|
|
ip, cidr, err := net.ParseCIDR(dstI.Value)
|
|
if err == nil {
|
|
if ip.To4() != nil && userNodeI.StaticNode.Address != "" {
|
|
rules = append(rules, models.FwRule{
|
|
SrcIP: userNodeI.StaticNode.AddressIPNet4(),
|
|
DstIP: *cidr,
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
Allow: true,
|
|
})
|
|
} else if ip.To16() != nil && userNodeI.StaticNode.Address6 != "" {
|
|
rules = append(rules, models.FwRule{
|
|
SrcIP: userNodeI.StaticNode.AddressIPNet6(),
|
|
DstIP: *cidr,
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
Allow: true,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
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),
|
|
},
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
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),
|
|
},
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
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),
|
|
},
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
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),
|
|
},
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
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
|
|
}
|
|
if e.Range != "" {
|
|
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,
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
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,
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
Allow: true,
|
|
})
|
|
}
|
|
}
|
|
|
|
}
|
|
} else if len(e.DomainAns) > 0 {
|
|
for _, domainAnsI := range e.DomainAns {
|
|
dstI.Value = domainAnsI
|
|
|
|
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,
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
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,
|
|
AllowedProtocol: policy.Proto,
|
|
AllowedPorts: policy.Port,
|
|
Allow: true,
|
|
})
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func checkIfAclTagisValid(a models.Acl, t models.AclPolicyTag, isSrc bool) (err error) {
|
|
switch t.ID {
|
|
case models.NodeTagID:
|
|
if a.RuleType == models.UserPolicy && isSrc {
|
|
return errors.New("user policy source mismatch")
|
|
}
|
|
// check if tag is valid
|
|
_, err := GetTag(models.TagID(t.Value))
|
|
if err != nil {
|
|
return errors.New("invalid tag " + t.Value)
|
|
}
|
|
case models.NodeID:
|
|
if a.RuleType == models.UserPolicy && isSrc {
|
|
return errors.New("user policy source mismatch")
|
|
}
|
|
_, nodeErr := logic.GetNodeByID(t.Value)
|
|
if nodeErr != nil {
|
|
_, staticNodeErr := logic.GetExtClient(t.Value, a.NetworkID.String())
|
|
if staticNodeErr != nil {
|
|
return errors.New("invalid node " + t.Value)
|
|
}
|
|
}
|
|
case models.EgressID, models.EgressRange:
|
|
e := schema.Egress{
|
|
ID: t.Value,
|
|
}
|
|
err := e.Get(db.WithContext(context.TODO()))
|
|
if err != nil {
|
|
return errors.New("invalid egress")
|
|
}
|
|
|
|
case models.UserAclID:
|
|
if a.RuleType == models.DevicePolicy {
|
|
return errors.New("device policy source mismatch")
|
|
}
|
|
if !isSrc {
|
|
return errors.New("user cannot be added to destination")
|
|
}
|
|
_, err := logic.GetUser(t.Value)
|
|
if err != nil {
|
|
return errors.New("invalid user " + t.Value)
|
|
}
|
|
case models.UserGroupAclID:
|
|
if a.RuleType == models.DevicePolicy {
|
|
return errors.New("device policy source mismatch")
|
|
}
|
|
if !isSrc {
|
|
return errors.New("user cannot be added to destination")
|
|
}
|
|
err := IsGroupValid(models.UserGroupID(t.Value))
|
|
if err != nil {
|
|
return errors.New("invalid user group " + t.Value)
|
|
}
|
|
// check if group belongs to this network
|
|
netGrps := GetUserGroupsInNetwork(a.NetworkID)
|
|
if _, ok := netGrps[models.UserGroupID(t.Value)]; !ok {
|
|
return errors.New("invalid user group " + t.Value)
|
|
}
|
|
default:
|
|
return errors.New("invalid policy")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// IsAclPolicyValid - validates if acl policy is valid
|
|
func IsAclPolicyValid(acl models.Acl) (err error) {
|
|
//check if src and dst are valid
|
|
if acl.AllowedDirection != models.TrafficDirectionBi &&
|
|
acl.AllowedDirection != models.TrafficDirectionUni {
|
|
return errors.New("invalid traffic direction")
|
|
}
|
|
switch acl.RuleType {
|
|
case models.UserPolicy:
|
|
// src list should only contain users
|
|
for _, srcI := range acl.Src {
|
|
|
|
if srcI.Value == "*" {
|
|
continue
|
|
}
|
|
// check if user group is valid
|
|
if err = checkIfAclTagisValid(acl, srcI, true); err != nil {
|
|
return
|
|
}
|
|
}
|
|
for _, dstI := range acl.Dst {
|
|
|
|
if dstI.Value == "*" {
|
|
continue
|
|
}
|
|
|
|
// check if user group is valid
|
|
if err = checkIfAclTagisValid(acl, dstI, false); err != nil {
|
|
return
|
|
}
|
|
}
|
|
case models.DevicePolicy:
|
|
for _, srcI := range acl.Src {
|
|
if srcI.Value == "*" {
|
|
continue
|
|
}
|
|
// check if user group is valid
|
|
if err = checkIfAclTagisValid(acl, srcI, true); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for _, dstI := range acl.Dst {
|
|
|
|
if dstI.Value == "*" {
|
|
continue
|
|
}
|
|
// check if user group is valid
|
|
if err = checkIfAclTagisValid(acl, dstI, false); err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ListUserPolicies - lists all acl policies enforced on an user
|
|
func ListUserPolicies(u models.User) []models.Acl {
|
|
allAcls := logic.ListAcls()
|
|
userAcls := []models.Acl{}
|
|
for _, acl := range allAcls {
|
|
|
|
if acl.RuleType == models.UserPolicy {
|
|
srcMap := logic.ConvAclTagToValueMap(acl.Src)
|
|
if _, ok := srcMap[u.UserName]; ok {
|
|
userAcls = append(userAcls, acl)
|
|
} else {
|
|
// check for user groups
|
|
for gID := range u.UserGroups {
|
|
if _, ok := srcMap[gID.String()]; ok {
|
|
userAcls = append(userAcls, acl)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
return userAcls
|
|
}
|
|
|
|
// listPoliciesOfUser - lists all user acl policies applied to user in an network
|
|
func listPoliciesOfUser(user models.User, netID models.NetworkID) []models.Acl {
|
|
allAcls := logic.ListAcls()
|
|
userAcls := []models.Acl{}
|
|
if _, ok := user.UserGroups[globalNetworksAdminGroupID]; ok {
|
|
user.UserGroups[GetDefaultNetworkAdminGroupID(netID)] = struct{}{}
|
|
}
|
|
if _, ok := user.UserGroups[globalNetworksUserGroupID]; ok {
|
|
user.UserGroups[GetDefaultNetworkUserGroupID(netID)] = struct{}{}
|
|
}
|
|
if user.PlatformRoleID == models.AdminRole || user.PlatformRoleID == models.SuperAdminRole {
|
|
user.UserGroups[GetDefaultNetworkAdminGroupID(netID)] = struct{}{}
|
|
}
|
|
for _, acl := range allAcls {
|
|
if acl.NetworkID == netID && acl.RuleType == models.UserPolicy {
|
|
srcMap := logic.ConvAclTagToValueMap(acl.Src)
|
|
if _, ok := srcMap[user.UserName]; ok {
|
|
userAcls = append(userAcls, acl)
|
|
continue
|
|
}
|
|
for netRole := range user.NetworkRoles {
|
|
if _, ok := srcMap[netRole.String()]; ok {
|
|
userAcls = append(userAcls, acl)
|
|
continue
|
|
}
|
|
}
|
|
for userG := range user.UserGroups {
|
|
if _, ok := srcMap[userG.String()]; ok {
|
|
userAcls = append(userAcls, acl)
|
|
continue
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
return userAcls
|
|
}
|
|
|
|
// listUserPolicies - lists all user policies in a network
|
|
func listUserPolicies(netID models.NetworkID) []models.Acl {
|
|
allAcls := logic.ListAcls()
|
|
deviceAcls := []models.Acl{}
|
|
for _, acl := range allAcls {
|
|
if acl.NetworkID == netID && acl.RuleType == models.UserPolicy {
|
|
deviceAcls = append(deviceAcls, acl)
|
|
}
|
|
}
|
|
return deviceAcls
|
|
}
|
|
|
|
// IsUserAllowedToCommunicate - check if user is allowed to communicate with peer
|
|
func IsUserAllowedToCommunicate(userName string, peer models.Node) (bool, []models.Acl) {
|
|
var peerId string
|
|
if peer.IsStatic {
|
|
peerId = peer.StaticNode.ClientID
|
|
peer = peer.StaticNode.ConvertToStaticNode()
|
|
} else {
|
|
peerId = peer.ID.String()
|
|
}
|
|
|
|
var peerTags map[models.TagID]struct{}
|
|
if peer.Mutex != nil {
|
|
peer.Mutex.Lock()
|
|
peerTags = maps.Clone(peer.Tags)
|
|
peer.Mutex.Unlock()
|
|
} else {
|
|
peerTags = peer.Tags
|
|
}
|
|
if peerTags == nil {
|
|
peerTags = make(map[models.TagID]struct{})
|
|
}
|
|
peerTags[models.TagID(peerId)] = struct{}{}
|
|
peerTags[models.TagID("*")] = struct{}{}
|
|
acl, _ := logic.GetDefaultPolicy(models.NetworkID(peer.Network), models.UserPolicy)
|
|
if acl.Enabled {
|
|
return true, []models.Acl{acl}
|
|
}
|
|
user, err := logic.GetUser(userName)
|
|
if err != nil {
|
|
return false, []models.Acl{}
|
|
}
|
|
allowedPolicies := []models.Acl{}
|
|
policies := listPoliciesOfUser(*user, models.NetworkID(peer.Network))
|
|
for _, policy := range policies {
|
|
if !policy.Enabled {
|
|
continue
|
|
}
|
|
dstMap := logic.ConvAclTagToValueMap(policy.Dst)
|
|
for _, dst := range policy.Dst {
|
|
if dst.ID == models.EgressID {
|
|
e := schema.Egress{ID: dst.Value}
|
|
err := e.Get(db.WithContext(context.TODO()))
|
|
if err == nil && e.Status {
|
|
for nodeID := range e.Nodes {
|
|
dstMap[nodeID] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if _, ok := dstMap["*"]; ok {
|
|
allowedPolicies = append(allowedPolicies, policy)
|
|
continue
|
|
}
|
|
if _, ok := dstMap[peer.ID.String()]; ok {
|
|
allowedPolicies = append(allowedPolicies, policy)
|
|
continue
|
|
}
|
|
for tagID := range peerTags {
|
|
if _, ok := dstMap[tagID.String()]; ok {
|
|
allowedPolicies = append(allowedPolicies, policy)
|
|
break
|
|
}
|
|
}
|
|
|
|
}
|
|
if len(allowedPolicies) > 0 {
|
|
return true, allowedPolicies
|
|
}
|
|
return false, []models.Acl{}
|
|
}
|
|
|
|
// IsPeerAllowed - checks if peer needs to be added to the interface
|
|
func IsPeerAllowed(node, peer models.Node, checkDefaultPolicy bool) bool {
|
|
var nodeId, peerId string
|
|
// if peer.IsFailOver && node.FailedOverBy != uuid.Nil && node.FailedOverBy == peer.ID {
|
|
// return true
|
|
// }
|
|
// if node.IsFailOver && peer.FailedOverBy != uuid.Nil && peer.FailedOverBy == node.ID {
|
|
// return true
|
|
// }
|
|
// if node.IsGw && peer.IsRelayed && peer.RelayedBy == node.ID.String() {
|
|
// return true
|
|
// }
|
|
// if peer.IsGw && node.IsRelayed && node.RelayedBy == peer.ID.String() {
|
|
// return true
|
|
// }
|
|
if node.IsStatic {
|
|
nodeId = node.StaticNode.ClientID
|
|
node = node.StaticNode.ConvertToStaticNode()
|
|
} else {
|
|
nodeId = node.ID.String()
|
|
}
|
|
if peer.IsStatic {
|
|
peerId = peer.StaticNode.ClientID
|
|
peer = peer.StaticNode.ConvertToStaticNode()
|
|
} else {
|
|
peerId = peer.ID.String()
|
|
}
|
|
|
|
var nodeTags, peerTags map[models.TagID]struct{}
|
|
if node.Mutex != nil {
|
|
node.Mutex.Lock()
|
|
nodeTags = maps.Clone(node.Tags)
|
|
node.Mutex.Unlock()
|
|
} else {
|
|
nodeTags = node.Tags
|
|
}
|
|
if peer.Mutex != nil {
|
|
peer.Mutex.Lock()
|
|
peerTags = maps.Clone(peer.Tags)
|
|
peer.Mutex.Unlock()
|
|
} else {
|
|
peerTags = peer.Tags
|
|
}
|
|
if nodeTags == nil {
|
|
nodeTags = make(map[models.TagID]struct{})
|
|
}
|
|
if peerTags == nil {
|
|
peerTags = make(map[models.TagID]struct{})
|
|
}
|
|
nodeTags[models.TagID(nodeId)] = struct{}{}
|
|
peerTags[models.TagID(peerId)] = struct{}{}
|
|
if checkDefaultPolicy {
|
|
// check default policy if all allowed return true
|
|
defaultPolicy, err := logic.GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
|
|
if err == nil {
|
|
if defaultPolicy.Enabled {
|
|
return true
|
|
}
|
|
}
|
|
|
|
}
|
|
// list device policies
|
|
policies := logic.ListDevicePolicies(models.NetworkID(peer.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 = logic.ConvAclTagToValueMap(policy.Src)
|
|
dstMap = logic.ConvAclTagToValueMap(policy.Dst)
|
|
for _, dst := range policy.Dst {
|
|
if dst.ID == models.EgressID {
|
|
e := schema.Egress{ID: dst.Value}
|
|
err := e.Get(db.WithContext(context.TODO()))
|
|
if err == nil && e.Status {
|
|
for nodeID := range e.Nodes {
|
|
dstMap[nodeID] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if logic.CheckTagGroupPolicy(srcMap, dstMap, node, peer, nodeTags, peerTags) {
|
|
return true
|
|
}
|
|
|
|
}
|
|
return false
|
|
}
|
|
|
|
func RemoveUserFromAclPolicy(userName string) {
|
|
acls := logic.ListAcls()
|
|
for _, acl := range acls {
|
|
delete := false
|
|
update := false
|
|
if acl.RuleType == models.UserPolicy {
|
|
for i := len(acl.Src) - 1; i >= 0; i-- {
|
|
if acl.Src[i].ID == models.UserAclID && acl.Src[i].Value == userName {
|
|
if len(acl.Src) == 1 {
|
|
// delete policy
|
|
delete = true
|
|
break
|
|
} else {
|
|
acl.Src = append(acl.Src[:i], acl.Src[i+1:]...)
|
|
update = true
|
|
}
|
|
}
|
|
}
|
|
if delete {
|
|
logic.DeleteAcl(acl)
|
|
continue
|
|
}
|
|
if update {
|
|
logic.UpsertAcl(acl)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// UpdateDeviceTag - updates device tag on acl policies
|
|
func UpdateDeviceTag(OldID, newID models.TagID, netID models.NetworkID) {
|
|
acls := logic.ListDevicePolicies(netID)
|
|
update := false
|
|
for _, acl := range acls {
|
|
for i, srcTagI := range acl.Src {
|
|
if srcTagI.ID == models.NodeTagID {
|
|
if OldID.String() == srcTagI.Value {
|
|
acl.Src[i].Value = newID.String()
|
|
update = true
|
|
}
|
|
}
|
|
}
|
|
for i, dstTagI := range acl.Dst {
|
|
if dstTagI.ID == models.NodeTagID {
|
|
if OldID.String() == dstTagI.Value {
|
|
acl.Dst[i].Value = newID.String()
|
|
update = true
|
|
}
|
|
}
|
|
}
|
|
if update {
|
|
logic.UpsertAcl(acl)
|
|
}
|
|
}
|
|
}
|
|
|
|
func CheckIfTagAsActivePolicy(tagID models.TagID, netID models.NetworkID) bool {
|
|
acls := logic.ListDevicePolicies(netID)
|
|
for _, acl := range acls {
|
|
for _, srcTagI := range acl.Src {
|
|
if srcTagI.ID == models.NodeTagID {
|
|
if tagID.String() == srcTagI.Value {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
for _, dstTagI := range acl.Dst {
|
|
if dstTagI.ID == models.NodeTagID {
|
|
if tagID.String() == dstTagI.Value {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// RemoveDeviceTagFromAclPolicies - remove device tag from acl policies
|
|
func RemoveDeviceTagFromAclPolicies(tagID models.TagID, netID models.NetworkID) error {
|
|
acls := logic.ListDevicePolicies(netID)
|
|
update := false
|
|
for _, acl := range acls {
|
|
for i := len(acl.Src) - 1; i >= 0; i-- {
|
|
if acl.Src[i].ID == models.NodeTagID {
|
|
if tagID.String() == acl.Src[i].Value {
|
|
acl.Src = append(acl.Src[:i], acl.Src[i+1:]...)
|
|
update = true
|
|
}
|
|
}
|
|
}
|
|
for i := len(acl.Dst) - 1; i >= 0; i-- {
|
|
if acl.Dst[i].ID == models.NodeTagID {
|
|
if tagID.String() == acl.Dst[i].Value {
|
|
acl.Dst = append(acl.Dst[:i], acl.Dst[i+1:]...)
|
|
update = true
|
|
}
|
|
}
|
|
}
|
|
if update {
|
|
logic.UpsertAcl(acl)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func GetEgressUserRulesForNode(targetnode *models.Node,
|
|
rules map[string]models.AclRule) map[string]models.AclRule {
|
|
userNodes := getStaticUserNodesByNetwork(models.NetworkID(targetnode.Network))
|
|
userGrpMap := GetUserGrpMap()
|
|
allowedUsers := make(map[string][]models.Acl)
|
|
acls := listUserPolicies(models.NetworkID(targetnode.Network))
|
|
var targetNodeTags = make(map[models.TagID]struct{})
|
|
targetNodeTags["*"] = struct{}{}
|
|
egs, _ := (&schema.Egress{Network: targetnode.Network}).ListByNetwork(db.WithContext(context.TODO()))
|
|
if len(egs) == 0 {
|
|
return rules
|
|
}
|
|
defaultPolicy, _ := logic.GetDefaultPolicy(models.NetworkID(targetnode.Network), models.UserPolicy)
|
|
|
|
for _, egI := range egs {
|
|
if !egI.Status {
|
|
continue
|
|
}
|
|
if _, ok := egI.Nodes[targetnode.ID.String()]; ok {
|
|
if egI.Range != "" {
|
|
targetNodeTags[models.TagID(egI.Range)] = struct{}{}
|
|
} else if len(egI.DomainAns) > 0 {
|
|
for _, domainAnsI := range egI.DomainAns {
|
|
targetNodeTags[models.TagID(domainAnsI)] = struct{}{}
|
|
}
|
|
}
|
|
|
|
targetNodeTags[models.TagID(egI.ID)] = struct{}{}
|
|
}
|
|
}
|
|
if !defaultPolicy.Enabled {
|
|
for _, acl := range acls {
|
|
if !acl.Enabled {
|
|
continue
|
|
}
|
|
dstTags := logic.ConvAclTagToValueMap(acl.Dst)
|
|
for _, dst := range acl.Dst {
|
|
if dst.ID == models.EgressID {
|
|
e := schema.Egress{ID: dst.Value}
|
|
err := e.Get(db.WithContext(context.TODO()))
|
|
if err == nil && e.Status {
|
|
for nodeID := range e.Nodes {
|
|
dstTags[nodeID] = struct{}{}
|
|
}
|
|
if e.Range != "" {
|
|
dstTags[e.Range] = struct{}{}
|
|
} else if len(e.DomainAns) > 0 {
|
|
for _, domainAnsI := range e.DomainAns {
|
|
dstTags[domainAnsI] = struct{}{}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
_, all := dstTags["*"]
|
|
addUsers := false
|
|
if !all {
|
|
for nodeTag := range targetNodeTags {
|
|
if _, ok := dstTags[nodeTag.String()]; ok {
|
|
addUsers = true
|
|
break
|
|
}
|
|
}
|
|
} else {
|
|
addUsers = true
|
|
}
|
|
|
|
if addUsers {
|
|
// get all src tags
|
|
for _, srcAcl := range acl.Src {
|
|
if srcAcl.ID == models.UserAclID {
|
|
allowedUsers[srcAcl.Value] = append(allowedUsers[srcAcl.Value], acl)
|
|
} else if srcAcl.ID == models.UserGroupAclID {
|
|
// fetch all users in the group
|
|
if usersMap, ok := userGrpMap[models.UserGroupID(srcAcl.Value)]; ok {
|
|
for userName := range usersMap {
|
|
allowedUsers[userName] = append(allowedUsers[userName], acl)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
for _, acl := range acls {
|
|
|
|
if !acl.Enabled {
|
|
continue
|
|
}
|
|
r := models.AclRule{
|
|
ID: acl.ID,
|
|
AllowedProtocol: acl.Proto,
|
|
AllowedPorts: acl.Port,
|
|
Direction: acl.AllowedDirection,
|
|
Allowed: true,
|
|
}
|
|
// 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())
|
|
}
|
|
for _, dstI := range acl.Dst {
|
|
if dstI.ID == models.EgressID {
|
|
e := schema.Egress{ID: dstI.Value}
|
|
err := e.Get(db.WithContext(context.TODO()))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if e.Range != "" {
|
|
ip, cidr, err := net.ParseCIDR(e.Range)
|
|
if err == nil {
|
|
if ip.To4() != nil {
|
|
r.Dst = append(r.Dst, *cidr)
|
|
} else {
|
|
r.Dst6 = append(r.Dst6, *cidr)
|
|
}
|
|
|
|
}
|
|
} else if len(e.DomainAns) > 0 {
|
|
for _, domainAnsI := range e.DomainAns {
|
|
ip, cidr, err := net.ParseCIDR(domainAnsI)
|
|
if err == nil {
|
|
if ip.To4() != nil {
|
|
r.Dst = append(r.Dst, *cidr)
|
|
} else {
|
|
r.Dst6 = append(r.Dst6, *cidr)
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
if userNode.StaticNode.Address6 != "" {
|
|
r.IP6List = append(r.IP6List, userNode.StaticNode.AddressIPNet6())
|
|
}
|
|
if aclRule, ok := rules[acl.ID]; ok {
|
|
|
|
aclRule.IPList = append(aclRule.IPList, r.IPList...)
|
|
aclRule.IP6List = append(aclRule.IP6List, r.IP6List...)
|
|
|
|
aclRule.Dst = append(aclRule.Dst, r.Dst...)
|
|
aclRule.Dst6 = append(aclRule.Dst6, r.Dst6...)
|
|
|
|
aclRule.IPList = logic.UniqueIPNetList(aclRule.IPList)
|
|
aclRule.IP6List = logic.UniqueIPNetList(aclRule.IP6List)
|
|
|
|
aclRule.Dst = logic.UniqueIPNetList(aclRule.Dst)
|
|
aclRule.Dst6 = logic.UniqueIPNetList(aclRule.Dst6)
|
|
|
|
rules[acl.ID] = aclRule
|
|
} else {
|
|
r.IPList = logic.UniqueIPNetList(r.IPList)
|
|
r.IP6List = logic.UniqueIPNetList(r.IP6List)
|
|
|
|
r.Dst = logic.UniqueIPNetList(r.Dst)
|
|
r.Dst6 = logic.UniqueIPNetList(r.Dst6)
|
|
rules[acl.ID] = r
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return rules
|
|
}
|
|
|
|
func GetUserAclRulesForNode(targetnode *models.Node,
|
|
rules map[string]models.AclRule) map[string]models.AclRule {
|
|
userNodes := getStaticUserNodesByNetwork(models.NetworkID(targetnode.Network))
|
|
userGrpMap := GetUserGrpMap()
|
|
allowedUsers := make(map[string][]models.Acl)
|
|
acls := listUserPolicies(models.NetworkID(targetnode.Network))
|
|
var targetNodeTags = make(map[models.TagID]struct{})
|
|
if targetnode.Mutex != nil {
|
|
targetnode.Mutex.Lock()
|
|
targetNodeTags = maps.Clone(targetnode.Tags)
|
|
targetnode.Mutex.Unlock()
|
|
} else {
|
|
targetNodeTags = maps.Clone(targetnode.Tags)
|
|
}
|
|
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
|
|
}
|
|
dstTags := logic.ConvAclTagToValueMap(acl.Dst)
|
|
_, all := dstTags["*"]
|
|
addUsers := false
|
|
if !all {
|
|
for _, dst := range acl.Dst {
|
|
if dst.ID == models.EgressID {
|
|
e := schema.Egress{ID: dst.Value}
|
|
err := e.Get(db.WithContext(context.TODO()))
|
|
if err == nil && e.Status && len(e.Nodes) > 0 {
|
|
if _, ok := e.Nodes[targetnode.ID.String()]; ok {
|
|
dstTags[targetnode.ID.String()] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for nodeTag := range targetNodeTags {
|
|
if _, ok := dstTags[nodeTag.String()]; ok {
|
|
addUsers = true
|
|
break
|
|
}
|
|
}
|
|
} else {
|
|
addUsers = true
|
|
}
|
|
|
|
if addUsers {
|
|
// get all src tags
|
|
for _, srcAcl := range acl.Src {
|
|
if srcAcl.ID == models.UserAclID {
|
|
allowedUsers[srcAcl.Value] = append(allowedUsers[srcAcl.Value], acl)
|
|
} else if srcAcl.ID == models.UserGroupAclID {
|
|
// fetch all users in the group
|
|
if usersMap, ok := userGrpMap[models.UserGroupID(srcAcl.Value)]; ok {
|
|
for userName := range usersMap {
|
|
allowedUsers[userName] = append(allowedUsers[userName], acl)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
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
|
|
}
|
|
for _, acl := range acls {
|
|
|
|
if !acl.Enabled {
|
|
continue
|
|
}
|
|
egressRanges4 := []net.IPNet{}
|
|
egressRanges6 := []net.IPNet{}
|
|
|
|
for _, dst := range acl.Dst {
|
|
if dst.Value == "*" {
|
|
e := schema.Egress{Network: targetnode.Network}
|
|
eli, _ := e.ListByNetwork(db.WithContext(context.Background()))
|
|
for _, eI := range eli {
|
|
if !eI.Status || len(eI.Nodes) == 0 {
|
|
continue
|
|
}
|
|
if _, ok := eI.Nodes[targetnode.ID.String()]; ok {
|
|
if eI.Range != "" {
|
|
_, cidr, err := net.ParseCIDR(eI.Range)
|
|
if err == nil {
|
|
if cidr.IP.To4() != nil {
|
|
egressRanges4 = append(egressRanges4, *cidr)
|
|
} else {
|
|
egressRanges6 = append(egressRanges6, *cidr)
|
|
}
|
|
}
|
|
} else if len(eI.DomainAns) > 0 {
|
|
for _, domainAnsI := range eI.DomainAns {
|
|
_, cidr, err := net.ParseCIDR(domainAnsI)
|
|
if err == nil {
|
|
if cidr.IP.To4() != nil {
|
|
egressRanges4 = append(egressRanges4, *cidr)
|
|
} else {
|
|
egressRanges6 = append(egressRanges6, *cidr)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
break
|
|
}
|
|
if dst.ID == models.EgressID {
|
|
e := schema.Egress{ID: dst.Value}
|
|
err := e.Get(db.WithContext(context.TODO()))
|
|
if err == nil && e.Status && len(e.Nodes) > 0 {
|
|
if _, ok := e.Nodes[targetnode.ID.String()]; ok {
|
|
if e.Range != "" {
|
|
_, cidr, err := net.ParseCIDR(e.Range)
|
|
if err == nil {
|
|
if cidr.IP.To4() != nil {
|
|
egressRanges4 = append(egressRanges4, *cidr)
|
|
} else {
|
|
egressRanges6 = append(egressRanges6, *cidr)
|
|
}
|
|
}
|
|
} else if len(e.DomainAns) > 0 {
|
|
for _, domainAnsI := range e.DomainAns {
|
|
_, cidr, err := net.ParseCIDR(domainAnsI)
|
|
if err == nil {
|
|
if cidr.IP.To4() != nil {
|
|
egressRanges4 = append(egressRanges4, *cidr)
|
|
} else {
|
|
egressRanges6 = append(egressRanges6, *cidr)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
r := models.AclRule{
|
|
ID: acl.ID,
|
|
AllowedProtocol: acl.Proto,
|
|
AllowedPorts: acl.Port,
|
|
Direction: acl.AllowedDirection,
|
|
Dst: []net.IPNet{targetnode.AddressIPNet4()},
|
|
Dst6: []net.IPNet{targetnode.AddressIPNet6()},
|
|
Allowed: true,
|
|
}
|
|
if len(egressRanges4) > 0 {
|
|
r.Dst = append(r.Dst, egressRanges4...)
|
|
}
|
|
if len(egressRanges6) > 0 {
|
|
r.Dst6 = append(r.Dst6, egressRanges6...)
|
|
}
|
|
// 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())
|
|
}
|
|
if aclRule, ok := rules[acl.ID]; ok {
|
|
|
|
aclRule.IPList = append(aclRule.IPList, r.IPList...)
|
|
aclRule.IP6List = append(aclRule.IP6List, r.IP6List...)
|
|
|
|
aclRule.Dst = append(aclRule.Dst, r.Dst...)
|
|
aclRule.Dst6 = append(aclRule.Dst6, r.Dst6...)
|
|
|
|
aclRule.IPList = logic.UniqueIPNetList(aclRule.IPList)
|
|
aclRule.IP6List = logic.UniqueIPNetList(aclRule.IP6List)
|
|
|
|
aclRule.Dst = logic.UniqueIPNetList(aclRule.Dst)
|
|
aclRule.Dst6 = logic.UniqueIPNetList(aclRule.Dst6)
|
|
|
|
rules[acl.ID] = aclRule
|
|
} else {
|
|
r.IPList = logic.UniqueIPNetList(r.IPList)
|
|
r.IP6List = logic.UniqueIPNetList(r.IP6List)
|
|
|
|
r.Dst = logic.UniqueIPNetList(r.Dst)
|
|
r.Dst6 = logic.UniqueIPNetList(r.Dst6)
|
|
rules[acl.ID] = r
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return rules
|
|
}
|
|
|
|
func CheckIfAnyPolicyisUniDirectional(targetNode models.Node, acls []models.Acl) bool {
|
|
var targetNodeTags = make(map[models.TagID]struct{})
|
|
if targetNode.Mutex != nil {
|
|
targetNode.Mutex.Lock()
|
|
targetNodeTags = maps.Clone(targetNode.Tags)
|
|
targetNode.Mutex.Unlock()
|
|
} else {
|
|
targetNodeTags = maps.Clone(targetNode.Tags)
|
|
}
|
|
if targetNodeTags == nil {
|
|
targetNodeTags = make(map[models.TagID]struct{})
|
|
}
|
|
targetNodeTags[models.TagID(targetNode.ID.String())] = struct{}{}
|
|
targetNodeTags["*"] = struct{}{}
|
|
for _, acl := range acls {
|
|
if !acl.Enabled {
|
|
continue
|
|
}
|
|
if acl.AllowedDirection == models.TrafficDirectionBi && acl.Proto == models.ALL && acl.ServiceType == models.Any {
|
|
continue
|
|
}
|
|
if acl.Proto != models.ALL || acl.ServiceType != models.Any {
|
|
return true
|
|
}
|
|
srcTags := logic.ConvAclTagToValueMap(acl.Src)
|
|
dstTags := logic.ConvAclTagToValueMap(acl.Dst)
|
|
for nodeTag := range targetNodeTags {
|
|
if acl.RuleType == models.DevicePolicy {
|
|
if _, ok := srcTags[nodeTag.String()]; ok {
|
|
return true
|
|
}
|
|
if _, ok := srcTags[targetNode.ID.String()]; ok {
|
|
return true
|
|
}
|
|
}
|
|
|
|
if _, ok := dstTags[nodeTag.String()]; ok {
|
|
return true
|
|
}
|
|
if _, ok := dstTags[targetNode.ID.String()]; ok {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func GetTagMapWithNodesByNetwork(netID models.NetworkID, withStaticNodes bool) (tagNodesMap map[models.TagID][]models.Node) {
|
|
tagNodesMap = make(map[models.TagID][]models.Node)
|
|
nodes, _ := logic.GetNetworkNodes(netID.String())
|
|
for _, nodeI := range nodes {
|
|
tagNodesMap[models.TagID(nodeI.ID.String())] = []models.Node{
|
|
nodeI,
|
|
}
|
|
if nodeI.Tags == nil {
|
|
continue
|
|
}
|
|
if nodeI.Mutex != nil {
|
|
nodeI.Mutex.Lock()
|
|
}
|
|
for nodeTagID := range nodeI.Tags {
|
|
if nodeTagID == models.TagID(nodeI.ID.String()) {
|
|
continue
|
|
}
|
|
tagNodesMap[nodeTagID] = append(tagNodesMap[nodeTagID], nodeI)
|
|
}
|
|
if nodeI.Mutex != nil {
|
|
nodeI.Mutex.Unlock()
|
|
}
|
|
}
|
|
tagNodesMap["*"] = nodes
|
|
if !withStaticNodes {
|
|
return
|
|
}
|
|
return AddTagMapWithStaticNodes(netID, tagNodesMap)
|
|
}
|
|
|
|
func AddTagMapWithStaticNodes(netID models.NetworkID,
|
|
tagNodesMap map[models.TagID][]models.Node) map[models.TagID][]models.Node {
|
|
extclients, err := logic.GetNetworkExtClients(netID.String())
|
|
if err != nil {
|
|
return tagNodesMap
|
|
}
|
|
for _, extclient := range extclients {
|
|
if extclient.RemoteAccessClientID != "" {
|
|
continue
|
|
}
|
|
tagNodesMap[models.TagID(extclient.ClientID)] = []models.Node{
|
|
{
|
|
IsStatic: true,
|
|
StaticNode: extclient,
|
|
},
|
|
}
|
|
if extclient.Tags == nil {
|
|
continue
|
|
}
|
|
|
|
if extclient.Mutex != nil {
|
|
extclient.Mutex.Lock()
|
|
}
|
|
for tagID := range extclient.Tags {
|
|
if tagID == models.TagID(extclient.ClientID) {
|
|
continue
|
|
}
|
|
tagNodesMap[tagID] = append(tagNodesMap[tagID], extclient.ConvertToStaticNode())
|
|
tagNodesMap["*"] = append(tagNodesMap["*"], extclient.ConvertToStaticNode())
|
|
}
|
|
if extclient.Mutex != nil {
|
|
extclient.Mutex.Unlock()
|
|
}
|
|
}
|
|
return tagNodesMap
|
|
}
|