|
@@ -1,6 +1,7 @@
|
|
package logic
|
|
package logic
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
+ "context"
|
|
"encoding/json"
|
|
"encoding/json"
|
|
"errors"
|
|
"errors"
|
|
"fmt"
|
|
"fmt"
|
|
@@ -12,10 +13,23 @@ import (
|
|
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/google/uuid"
|
|
"github.com/gravitl/netmaker/database"
|
|
"github.com/gravitl/netmaker/database"
|
|
|
|
+ "github.com/gravitl/netmaker/db"
|
|
"github.com/gravitl/netmaker/models"
|
|
"github.com/gravitl/netmaker/models"
|
|
|
|
+ "github.com/gravitl/netmaker/schema"
|
|
"github.com/gravitl/netmaker/servercfg"
|
|
"github.com/gravitl/netmaker/servercfg"
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+TODO: EGRESS
|
|
|
|
+1. allow only selection of egress ranges in a policy
|
|
|
|
+ranges should be replaced by egress identifier
|
|
|
|
+
|
|
|
|
+2. check logic required for MAC exit node
|
|
|
|
+
|
|
|
|
+3.
|
|
|
|
+
|
|
|
|
+*/
|
|
|
|
+
|
|
var (
|
|
var (
|
|
aclCacheMutex = &sync.RWMutex{}
|
|
aclCacheMutex = &sync.RWMutex{}
|
|
aclCacheMap = make(map[string]models.Acl)
|
|
aclCacheMap = make(map[string]models.Acl)
|
|
@@ -236,10 +250,10 @@ func GetEgressRanges(netID models.NetworkID) (map[string][]string, map[string]st
|
|
if currentNode.Network != netID.String() {
|
|
if currentNode.Network != netID.String() {
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
- if currentNode.IsEgressGateway { // add the egress gateway range(s) to the result
|
|
|
|
- if len(currentNode.EgressGatewayRanges) > 0 {
|
|
|
|
- nodeEgressMap[currentNode.ID.String()] = currentNode.EgressGatewayRanges
|
|
|
|
- for _, egressRangeI := range currentNode.EgressGatewayRanges {
|
|
|
|
|
|
+ if currentNode.EgressDetails.IsEgressGateway { // add the egress gateway range(s) to the result
|
|
|
|
+ if len(currentNode.EgressDetails.EgressGatewayRanges) > 0 {
|
|
|
|
+ nodeEgressMap[currentNode.ID.String()] = currentNode.EgressDetails.EgressGatewayRanges
|
|
|
|
+ for _, egressRangeI := range currentNode.EgressDetails.EgressGatewayRanges {
|
|
resultMap[egressRangeI] = struct{}{}
|
|
resultMap[egressRangeI] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -257,78 +271,102 @@ func GetEgressRanges(netID models.NetworkID) (map[string][]string, map[string]st
|
|
return nodeEgressMap, resultMap, nil
|
|
return nodeEgressMap, resultMap, nil
|
|
}
|
|
}
|
|
|
|
|
|
-func checkIfAclTagisValid(t models.AclPolicyTag, netID models.NetworkID, policyType models.AclPolicyType, isSrc bool) bool {
|
|
|
|
|
|
+func checkIfAclTagisValid(a models.Acl, t models.AclPolicyTag, isSrc bool) (err error) {
|
|
switch t.ID {
|
|
switch t.ID {
|
|
case models.NodeTagID:
|
|
case models.NodeTagID:
|
|
- if policyType == models.UserPolicy && isSrc {
|
|
|
|
- return false
|
|
|
|
|
|
+ if a.RuleType == models.UserPolicy && isSrc {
|
|
|
|
+ return errors.New("user policy source mismatch")
|
|
}
|
|
}
|
|
// check if tag is valid
|
|
// check if tag is valid
|
|
_, err := GetTag(models.TagID(t.Value))
|
|
_, err := GetTag(models.TagID(t.Value))
|
|
if err != nil {
|
|
if err != nil {
|
|
- return false
|
|
|
|
|
|
+ return errors.New("invalid tag " + t.Value)
|
|
}
|
|
}
|
|
case models.NodeID:
|
|
case models.NodeID:
|
|
- if policyType == models.UserPolicy && isSrc {
|
|
|
|
- return false
|
|
|
|
|
|
+ if a.RuleType == models.UserPolicy && isSrc {
|
|
|
|
+ return errors.New("user policy source mismatch")
|
|
}
|
|
}
|
|
_, nodeErr := GetNodeByID(t.Value)
|
|
_, nodeErr := GetNodeByID(t.Value)
|
|
if nodeErr != nil {
|
|
if nodeErr != nil {
|
|
- _, staticNodeErr := GetExtClient(t.Value, netID.String())
|
|
|
|
|
|
+ _, staticNodeErr := GetExtClient(t.Value, a.NetworkID.String())
|
|
if staticNodeErr != nil {
|
|
if staticNodeErr != nil {
|
|
- return false
|
|
|
|
|
|
+ return errors.New("invalid node " + t.Value)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- case models.EgressRange:
|
|
|
|
- if isSrc {
|
|
|
|
- return false
|
|
|
|
|
|
+ case models.EgressID, models.EgressRange:
|
|
|
|
+ e := schema.Egress{
|
|
|
|
+ ID: t.Value,
|
|
}
|
|
}
|
|
- // _, rangesMap, err := GetEgressRanges(netID)
|
|
|
|
- // if err != nil {
|
|
|
|
- // return false
|
|
|
|
- // }
|
|
|
|
- // if _, ok := rangesMap[t.Value]; !ok {
|
|
|
|
- // return false
|
|
|
|
- // }
|
|
|
|
|
|
+ err := e.Get(db.WithContext(context.TODO()))
|
|
|
|
+ if err != nil {
|
|
|
|
+ return errors.New("invalid egress")
|
|
|
|
+ }
|
|
|
|
+ if e.IsInetGw {
|
|
|
|
+ req := models.InetNodeReq{}
|
|
|
|
+ for _, srcI := range a.Src {
|
|
|
|
+ if srcI.ID == models.NodeTagID {
|
|
|
|
+ nodesMap := GetNodesWithTag(models.TagID(srcI.Value))
|
|
|
|
+ for _, node := range nodesMap {
|
|
|
|
+ req.InetNodeClientIDs = append(req.InetNodeClientIDs, node.ID.String())
|
|
|
|
+ }
|
|
|
|
+ } else if srcI.ID == models.NodeID {
|
|
|
|
+ req.InetNodeClientIDs = append(req.InetNodeClientIDs, srcI.Value)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if len(e.Nodes) > 0 {
|
|
|
|
+ for k := range e.Nodes {
|
|
|
|
+ inetNode, err := GetNodeByID(k)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return errors.New("invalid node " + t.Value)
|
|
|
|
+ }
|
|
|
|
+ if err = ValidateInetGwReq(inetNode, req, false); err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
case models.UserAclID:
|
|
case models.UserAclID:
|
|
- if policyType == models.DevicePolicy {
|
|
|
|
- return false
|
|
|
|
|
|
+ if a.RuleType == models.DevicePolicy {
|
|
|
|
+ return errors.New("device policy source mismatch")
|
|
}
|
|
}
|
|
if !isSrc {
|
|
if !isSrc {
|
|
- return false
|
|
|
|
|
|
+ return errors.New("user cannot be added to destination")
|
|
}
|
|
}
|
|
_, err := GetUser(t.Value)
|
|
_, err := GetUser(t.Value)
|
|
if err != nil {
|
|
if err != nil {
|
|
- return false
|
|
|
|
|
|
+ return errors.New("invalid user " + t.Value)
|
|
}
|
|
}
|
|
case models.UserGroupAclID:
|
|
case models.UserGroupAclID:
|
|
- if policyType == models.DevicePolicy {
|
|
|
|
- return false
|
|
|
|
|
|
+ if a.RuleType == models.DevicePolicy {
|
|
|
|
+ return errors.New("device policy source mismatch")
|
|
}
|
|
}
|
|
if !isSrc {
|
|
if !isSrc {
|
|
- return false
|
|
|
|
|
|
+ return errors.New("user cannot be added to destination")
|
|
}
|
|
}
|
|
err := IsGroupValid(models.UserGroupID(t.Value))
|
|
err := IsGroupValid(models.UserGroupID(t.Value))
|
|
if err != nil {
|
|
if err != nil {
|
|
- return false
|
|
|
|
|
|
+ return errors.New("invalid user group " + t.Value)
|
|
}
|
|
}
|
|
// check if group belongs to this network
|
|
// check if group belongs to this network
|
|
- netGrps := GetUserGroupsInNetwork(netID)
|
|
|
|
|
|
+ netGrps := GetUserGroupsInNetwork(a.NetworkID)
|
|
if _, ok := netGrps[models.UserGroupID(t.Value)]; !ok {
|
|
if _, ok := netGrps[models.UserGroupID(t.Value)]; !ok {
|
|
- return false
|
|
|
|
|
|
+ return errors.New("invalid user group " + t.Value)
|
|
}
|
|
}
|
|
default:
|
|
default:
|
|
- return false
|
|
|
|
|
|
+ return errors.New("invalid policy")
|
|
}
|
|
}
|
|
- return true
|
|
|
|
|
|
+ return nil
|
|
}
|
|
}
|
|
|
|
|
|
// IsAclPolicyValid - validates if acl policy is valid
|
|
// IsAclPolicyValid - validates if acl policy is valid
|
|
-func IsAclPolicyValid(acl models.Acl) bool {
|
|
|
|
|
|
+func IsAclPolicyValid(acl models.Acl) (err error) {
|
|
//check if src and dst are valid
|
|
//check if src and dst are valid
|
|
if acl.AllowedDirection != models.TrafficDirectionBi &&
|
|
if acl.AllowedDirection != models.TrafficDirectionBi &&
|
|
acl.AllowedDirection != models.TrafficDirectionUni {
|
|
acl.AllowedDirection != models.TrafficDirectionUni {
|
|
- return false
|
|
|
|
|
|
+ return errors.New("invalid traffic direction")
|
|
}
|
|
}
|
|
switch acl.RuleType {
|
|
switch acl.RuleType {
|
|
case models.UserPolicy:
|
|
case models.UserPolicy:
|
|
@@ -339,8 +377,8 @@ func IsAclPolicyValid(acl models.Acl) bool {
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
// check if user group is valid
|
|
// check if user group is valid
|
|
- if !checkIfAclTagisValid(srcI, acl.NetworkID, acl.RuleType, true) {
|
|
|
|
- return false
|
|
|
|
|
|
+ if err = checkIfAclTagisValid(acl, srcI, true); err != nil {
|
|
|
|
+ return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for _, dstI := range acl.Dst {
|
|
for _, dstI := range acl.Dst {
|
|
@@ -350,8 +388,8 @@ func IsAclPolicyValid(acl models.Acl) bool {
|
|
}
|
|
}
|
|
|
|
|
|
// check if user group is valid
|
|
// check if user group is valid
|
|
- if !checkIfAclTagisValid(dstI, acl.NetworkID, acl.RuleType, false) {
|
|
|
|
- return false
|
|
|
|
|
|
+ if err = checkIfAclTagisValid(acl, dstI, false); err != nil {
|
|
|
|
+ return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
case models.DevicePolicy:
|
|
case models.DevicePolicy:
|
|
@@ -360,8 +398,8 @@ func IsAclPolicyValid(acl models.Acl) bool {
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
// check if user group is valid
|
|
// check if user group is valid
|
|
- if !checkIfAclTagisValid(srcI, acl.NetworkID, acl.RuleType, true) {
|
|
|
|
- return false
|
|
|
|
|
|
+ if err = checkIfAclTagisValid(acl, srcI, true); err != nil {
|
|
|
|
+ return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for _, dstI := range acl.Dst {
|
|
for _, dstI := range acl.Dst {
|
|
@@ -370,12 +408,26 @@ func IsAclPolicyValid(acl models.Acl) bool {
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
// check if user group is valid
|
|
// check if user group is valid
|
|
- if !checkIfAclTagisValid(dstI, acl.NetworkID, acl.RuleType, false) {
|
|
|
|
- return false
|
|
|
|
|
|
+ if err = checkIfAclTagisValid(acl, dstI, false); err != nil {
|
|
|
|
+ return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return true
|
|
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func UniqueAclPolicyTags(tags []models.AclPolicyTag) []models.AclPolicyTag {
|
|
|
|
+ seen := make(map[string]bool)
|
|
|
|
+ var result []models.AclPolicyTag
|
|
|
|
+
|
|
|
|
+ for _, tag := range tags {
|
|
|
|
+ key := fmt.Sprintf("%v-%s", tag.ID, tag.Value)
|
|
|
|
+ if !seen[key] {
|
|
|
|
+ seen[key] = true
|
|
|
|
+ result = append(result, tag)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return result
|
|
}
|
|
}
|
|
|
|
|
|
// UpdateAcl - updates allowed fields on acls and commits to DB
|
|
// UpdateAcl - updates allowed fields on acls and commits to DB
|
|
@@ -623,6 +675,17 @@ func IsUserAllowedToCommunicate(userName string, peer models.Node) (bool, []mode
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
dstMap := convAclTagToValueMap(policy.Dst)
|
|
dstMap := 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 {
|
|
if _, ok := dstMap["*"]; ok {
|
|
allowedPolicies = append(allowedPolicies, policy)
|
|
allowedPolicies = append(allowedPolicies, policy)
|
|
continue
|
|
continue
|
|
@@ -712,8 +775,20 @@ func IsPeerAllowed(node, peer models.Node, checkDefaultPolicy bool) bool {
|
|
if !policy.Enabled {
|
|
if !policy.Enabled {
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
|
|
+
|
|
srcMap = convAclTagToValueMap(policy.Src)
|
|
srcMap = convAclTagToValueMap(policy.Src)
|
|
dstMap = convAclTagToValueMap(policy.Dst)
|
|
dstMap = 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 checkTagGroupPolicy(srcMap, dstMap, node, peer, nodeTags, peerTags) {
|
|
if checkTagGroupPolicy(srcMap, dstMap, node, peer, nodeTags, peerTags) {
|
|
return true
|
|
return true
|
|
}
|
|
}
|
|
@@ -975,6 +1050,17 @@ func IsNodeAllowedToCommunicateV1(node, peer models.Node, checkDefaultPolicy boo
|
|
allowed := false
|
|
allowed := false
|
|
srcMap = convAclTagToValueMap(policy.Src)
|
|
srcMap = convAclTagToValueMap(policy.Src)
|
|
dstMap = convAclTagToValueMap(policy.Dst)
|
|
dstMap = 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{}{}
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
_, srcAll := srcMap["*"]
|
|
_, srcAll := srcMap["*"]
|
|
_, dstAll := dstMap["*"]
|
|
_, dstAll := dstMap["*"]
|
|
if policy.AllowedDirection == models.TrafficDirectionBi {
|
|
if policy.AllowedDirection == models.TrafficDirectionBi {
|
|
@@ -1158,7 +1244,7 @@ func getEgressUserRulesForNode(targetnode *models.Node,
|
|
acls := listUserPolicies(models.NetworkID(targetnode.Network))
|
|
acls := listUserPolicies(models.NetworkID(targetnode.Network))
|
|
var targetNodeTags = make(map[models.TagID]struct{})
|
|
var targetNodeTags = make(map[models.TagID]struct{})
|
|
targetNodeTags["*"] = struct{}{}
|
|
targetNodeTags["*"] = struct{}{}
|
|
- for _, rangeI := range targetnode.EgressGatewayRanges {
|
|
|
|
|
|
+ for _, rangeI := range targetnode.EgressDetails.EgressGatewayRanges {
|
|
targetNodeTags[models.TagID(rangeI)] = struct{}{}
|
|
targetNodeTags[models.TagID(rangeI)] = struct{}{}
|
|
}
|
|
}
|
|
for _, acl := range acls {
|
|
for _, acl := range acls {
|
|
@@ -1166,6 +1252,18 @@ func getEgressUserRulesForNode(targetnode *models.Node,
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
dstTags := convAclTagToValueMap(acl.Dst)
|
|
dstTags := 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{}{}
|
|
|
|
+ }
|
|
|
|
+ dstTags[e.Range] = struct{}{}
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
_, all := dstTags["*"]
|
|
_, all := dstTags["*"]
|
|
addUsers := false
|
|
addUsers := false
|
|
if !all {
|
|
if !all {
|
|
@@ -1225,16 +1323,34 @@ func getEgressUserRulesForNode(targetnode *models.Node,
|
|
r.IP6List = append(r.IP6List, userNode.StaticNode.AddressIPNet6())
|
|
r.IP6List = append(r.IP6List, userNode.StaticNode.AddressIPNet6())
|
|
}
|
|
}
|
|
for _, dstI := range acl.Dst {
|
|
for _, dstI := range acl.Dst {
|
|
- if dstI.ID == models.EgressRange {
|
|
|
|
- ip, cidr, err := net.ParseCIDR(dstI.Value)
|
|
|
|
- if err == nil {
|
|
|
|
- if ip.To4() != nil {
|
|
|
|
- r.Dst = append(r.Dst, *cidr)
|
|
|
|
- } else {
|
|
|
|
- r.Dst6 = append(r.Dst6, *cidr)
|
|
|
|
- }
|
|
|
|
|
|
+ if dstI.ID == models.EgressID {
|
|
|
|
+ e := schema.Egress{ID: dstI.Value}
|
|
|
|
+ err := e.Get(db.WithContext(context.TODO()))
|
|
|
|
+ if err != nil {
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ if e.IsInetGw {
|
|
|
|
+ r.Dst = append(r.Dst, net.IPNet{
|
|
|
|
+ IP: net.IPv4zero,
|
|
|
|
+ Mask: net.CIDRMask(0, 32),
|
|
|
|
+ })
|
|
|
|
+ r.Dst6 = append(r.Dst6, net.IPNet{
|
|
|
|
+ IP: net.IPv6zero,
|
|
|
|
+ Mask: net.CIDRMask(0, 128),
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ 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)
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
@@ -1348,7 +1464,7 @@ func getUserAclRulesForNode(targetnode *models.Node,
|
|
}
|
|
}
|
|
|
|
|
|
func checkIfAnyActiveEgressPolicy(targetNode models.Node) bool {
|
|
func checkIfAnyActiveEgressPolicy(targetNode models.Node) bool {
|
|
- if !targetNode.IsEgressGateway {
|
|
|
|
|
|
+ if !targetNode.EgressDetails.IsEgressGateway {
|
|
return false
|
|
return false
|
|
}
|
|
}
|
|
var targetNodeTags = make(map[models.TagID]struct{})
|
|
var targetNodeTags = make(map[models.TagID]struct{})
|
|
@@ -1371,8 +1487,20 @@ func checkIfAnyActiveEgressPolicy(targetNode models.Node) bool {
|
|
}
|
|
}
|
|
srcTags := convAclTagToValueMap(acl.Src)
|
|
srcTags := convAclTagToValueMap(acl.Src)
|
|
dstTags := convAclTagToValueMap(acl.Dst)
|
|
dstTags := 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{}{}
|
|
|
|
+ }
|
|
|
|
+ dstTags[e.Range] = struct{}{}
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
for nodeTag := range targetNodeTags {
|
|
for nodeTag := range targetNodeTags {
|
|
- if acl.RuleType == models.DevicePolicy {
|
|
|
|
|
|
+ if acl.RuleType == models.DevicePolicy && acl.AllowedDirection == models.TrafficDirectionBi {
|
|
if _, ok := srcTags[nodeTag.String()]; ok {
|
|
if _, ok := srcTags[nodeTag.String()]; ok {
|
|
return true
|
|
return true
|
|
}
|
|
}
|
|
@@ -1440,6 +1568,60 @@ func checkIfAnyPolicyisUniDirectional(targetNode models.Node) bool {
|
|
return false
|
|
return false
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func checkIfNodeHasAccessToAllResources(targetnode *models.Node) bool {
|
|
|
|
+ acls := listDevicePolicies(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{})
|
|
|
|
+ }
|
|
|
|
+ targetNodeTags[models.TagID(targetnode.ID.String())] = struct{}{}
|
|
|
|
+ targetNodeTags["*"] = struct{}{}
|
|
|
|
+ for _, acl := range acls {
|
|
|
|
+ if !acl.Enabled {
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ srcTags := convAclTagToValueMap(acl.Src)
|
|
|
|
+ dstTags := convAclTagToValueMap(acl.Dst)
|
|
|
|
+ _, srcAll := srcTags["*"]
|
|
|
|
+ _, dstAll := dstTags["*"]
|
|
|
|
+ for nodeTag := range targetNodeTags {
|
|
|
|
+
|
|
|
|
+ var existsInSrcTag bool
|
|
|
|
+ var existsInDstTag bool
|
|
|
|
+
|
|
|
|
+ if _, ok := srcTags[nodeTag.String()]; ok {
|
|
|
|
+ existsInSrcTag = true
|
|
|
|
+ }
|
|
|
|
+ if _, ok := srcTags[targetnode.ID.String()]; ok {
|
|
|
|
+ existsInSrcTag = true
|
|
|
|
+ }
|
|
|
|
+ if _, ok := dstTags[nodeTag.String()]; ok {
|
|
|
|
+ existsInDstTag = true
|
|
|
|
+ }
|
|
|
|
+ if _, ok := dstTags[targetnode.ID.String()]; ok {
|
|
|
|
+ existsInDstTag = true
|
|
|
|
+ }
|
|
|
|
+ if acl.AllowedDirection == models.TrafficDirectionBi {
|
|
|
|
+ if existsInSrcTag && dstAll || existsInDstTag && srcAll {
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if existsInDstTag && srcAll {
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return false
|
|
|
|
+}
|
|
|
|
+
|
|
func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRule) {
|
|
func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRule) {
|
|
targetnode := *targetnodeI
|
|
targetnode := *targetnodeI
|
|
defer func() {
|
|
defer func() {
|
|
@@ -1454,7 +1636,6 @@ func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRu
|
|
} else {
|
|
} else {
|
|
taggedNodes = GetTagMapWithNodesByNetwork(models.NetworkID(targetnode.Network), true)
|
|
taggedNodes = GetTagMapWithNodesByNetwork(models.NetworkID(targetnode.Network), true)
|
|
}
|
|
}
|
|
-
|
|
|
|
acls := listDevicePolicies(models.NetworkID(targetnode.Network))
|
|
acls := listDevicePolicies(models.NetworkID(targetnode.Network))
|
|
var targetNodeTags = make(map[models.TagID]struct{})
|
|
var targetNodeTags = make(map[models.TagID]struct{})
|
|
if targetnode.Mutex != nil {
|
|
if targetnode.Mutex != nil {
|
|
@@ -1475,6 +1656,17 @@ func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRu
|
|
}
|
|
}
|
|
srcTags := convAclTagToValueMap(acl.Src)
|
|
srcTags := convAclTagToValueMap(acl.Src)
|
|
dstTags := convAclTagToValueMap(acl.Dst)
|
|
dstTags := 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{}{}
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
_, srcAll := srcTags["*"]
|
|
_, srcAll := srcTags["*"]
|
|
_, dstAll := dstTags["*"]
|
|
_, dstAll := dstTags["*"]
|
|
aclRule := models.AclRule{
|
|
aclRule := models.AclRule{
|
|
@@ -1502,7 +1694,7 @@ func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRu
|
|
existsInDstTag = true
|
|
existsInDstTag = true
|
|
}
|
|
}
|
|
|
|
|
|
- if existsInSrcTag && !existsInDstTag {
|
|
|
|
|
|
+ if existsInSrcTag /* && !existsInDstTag*/ {
|
|
// get all dst tags
|
|
// get all dst tags
|
|
for dst := range dstTags {
|
|
for dst := range dstTags {
|
|
if dst == nodeTag.String() {
|
|
if dst == nodeTag.String() {
|
|
@@ -1539,7 +1731,7 @@ func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRu
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if existsInDstTag && !existsInSrcTag {
|
|
|
|
|
|
+ if existsInDstTag /*&& !existsInSrcTag*/ {
|
|
// get all src tags
|
|
// get all src tags
|
|
for src := range srcTags {
|
|
for src := range srcTags {
|
|
if src == nodeTag.String() {
|
|
if src == nodeTag.String() {
|
|
@@ -1575,47 +1767,47 @@ func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRu
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if existsInDstTag && existsInSrcTag {
|
|
|
|
- nodes := taggedNodes[nodeTag]
|
|
|
|
- for srcID := range srcTags {
|
|
|
|
- if srcID == targetnode.ID.String() {
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- node, err := GetNodeByID(srcID)
|
|
|
|
- if err == nil {
|
|
|
|
- nodes = append(nodes, node)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- for dstID := range dstTags {
|
|
|
|
- if dstID == targetnode.ID.String() {
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- node, err := GetNodeByID(dstID)
|
|
|
|
- if err == nil {
|
|
|
|
- nodes = append(nodes, node)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- for _, node := range nodes {
|
|
|
|
- if node.ID == targetnode.ID {
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- if node.IsStatic && node.StaticNode.IngressGatewayID == targetnode.ID.String() {
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- if node.Address.IP != nil {
|
|
|
|
- aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
|
|
|
|
- }
|
|
|
|
- if node.Address6.IP != nil {
|
|
|
|
- aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
|
|
|
|
- }
|
|
|
|
- if node.IsStatic && node.StaticNode.Address != "" {
|
|
|
|
- aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
|
|
|
|
- }
|
|
|
|
- if node.IsStatic && node.StaticNode.Address6 != "" {
|
|
|
|
- aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ // if existsInDstTag && existsInSrcTag {
|
|
|
|
+ // nodes := taggedNodes[nodeTag]
|
|
|
|
+ // for srcID := range srcTags {
|
|
|
|
+ // if srcID == targetnode.ID.String() {
|
|
|
|
+ // continue
|
|
|
|
+ // }
|
|
|
|
+ // node, err := GetNodeByID(srcID)
|
|
|
|
+ // if err == nil {
|
|
|
|
+ // nodes = append(nodes, node)
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // for dstID := range dstTags {
|
|
|
|
+ // if dstID == targetnode.ID.String() {
|
|
|
|
+ // continue
|
|
|
|
+ // }
|
|
|
|
+ // node, err := GetNodeByID(dstID)
|
|
|
|
+ // if err == nil {
|
|
|
|
+ // nodes = append(nodes, node)
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // for _, node := range nodes {
|
|
|
|
+ // if node.ID == targetnode.ID {
|
|
|
|
+ // continue
|
|
|
|
+ // }
|
|
|
|
+ // if node.IsStatic && node.StaticNode.IngressGatewayID == targetnode.ID.String() {
|
|
|
|
+ // continue
|
|
|
|
+ // }
|
|
|
|
+ // if node.Address.IP != nil {
|
|
|
|
+ // aclRule.IPList = append(aclRule.IPList, node.AddressIPNet4())
|
|
|
|
+ // }
|
|
|
|
+ // if node.Address6.IP != nil {
|
|
|
|
+ // aclRule.IP6List = append(aclRule.IP6List, node.AddressIPNet6())
|
|
|
|
+ // }
|
|
|
|
+ // if node.IsStatic && node.StaticNode.Address != "" {
|
|
|
|
+ // aclRule.IPList = append(aclRule.IPList, node.StaticNode.AddressIPNet4())
|
|
|
|
+ // }
|
|
|
|
+ // if node.IsStatic && node.StaticNode.Address6 != "" {
|
|
|
|
+ // aclRule.IP6List = append(aclRule.IP6List, node.StaticNode.AddressIPNet6())
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
} else {
|
|
} else {
|
|
_, all := dstTags["*"]
|
|
_, all := dstTags["*"]
|
|
if _, ok := dstTags[nodeTag.String()]; ok || all {
|
|
if _, ok := dstTags[nodeTag.String()]; ok || all {
|
|
@@ -1677,9 +1869,23 @@ func GetEgressRulesForNode(targetnode models.Node) (rules map[string]models.AclR
|
|
if acl policy has egress route and it is present in target node egress ranges
|
|
if acl policy has egress route and it is present in target node egress ranges
|
|
fetch all the nodes in that policy and add rules
|
|
fetch all the nodes in that policy and add rules
|
|
*/
|
|
*/
|
|
-
|
|
|
|
- for _, rangeI := range targetnode.EgressGatewayRanges {
|
|
|
|
- targetNodeTags[models.TagID(rangeI)] = struct{}{}
|
|
|
|
|
|
+ egs, _ := (&schema.Egress{Network: targetnode.Network}).ListByNetwork(db.WithContext(context.TODO()))
|
|
|
|
+ if len(egs) == 0 {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ for _, egI := range egs {
|
|
|
|
+ if !egI.Status {
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ if _, ok := egI.Nodes[targetnode.ID.String()]; ok {
|
|
|
|
+ if egI.Range == "*" {
|
|
|
|
+ targetNodeTags[models.TagID("0.0.0.0/0")] = struct{}{}
|
|
|
|
+ targetNodeTags[models.TagID("::/0")] = struct{}{}
|
|
|
|
+ } else {
|
|
|
|
+ targetNodeTags[models.TagID(egI.Range)] = struct{}{}
|
|
|
|
+ }
|
|
|
|
+ targetNodeTags[models.TagID(egI.ID)] = struct{}{}
|
|
|
|
+ }
|
|
}
|
|
}
|
|
for _, acl := range acls {
|
|
for _, acl := range acls {
|
|
if !acl.Enabled {
|
|
if !acl.Enabled {
|
|
@@ -1689,46 +1895,43 @@ func GetEgressRulesForNode(targetnode models.Node) (rules map[string]models.AclR
|
|
dstTags := convAclTagToValueMap(acl.Dst)
|
|
dstTags := convAclTagToValueMap(acl.Dst)
|
|
_, srcAll := srcTags["*"]
|
|
_, srcAll := srcTags["*"]
|
|
_, dstAll := dstTags["*"]
|
|
_, dstAll := dstTags["*"]
|
|
|
|
+ aclRule := models.AclRule{
|
|
|
|
+ ID: acl.ID,
|
|
|
|
+ AllowedProtocol: acl.Proto,
|
|
|
|
+ AllowedPorts: acl.Port,
|
|
|
|
+ Direction: acl.AllowedDirection,
|
|
|
|
+ Allowed: true,
|
|
|
|
+ }
|
|
for nodeTag := range targetNodeTags {
|
|
for nodeTag := range targetNodeTags {
|
|
- aclRule := models.AclRule{
|
|
|
|
- ID: acl.ID,
|
|
|
|
- AllowedProtocol: acl.Proto,
|
|
|
|
- AllowedPorts: acl.Port,
|
|
|
|
- Direction: acl.AllowedDirection,
|
|
|
|
- Allowed: true,
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
if nodeTag != "*" {
|
|
if nodeTag != "*" {
|
|
ip, cidr, err := net.ParseCIDR(nodeTag.String())
|
|
ip, cidr, err := net.ParseCIDR(nodeTag.String())
|
|
- if err != nil {
|
|
|
|
- continue
|
|
|
|
- }
|
|
|
|
- if ip.To4() != nil {
|
|
|
|
- aclRule.Dst = append(aclRule.Dst, *cidr)
|
|
|
|
- } else {
|
|
|
|
- aclRule.Dst6 = append(aclRule.Dst6, *cidr)
|
|
|
|
|
|
+ if err == nil {
|
|
|
|
+ if ip.To4() != nil {
|
|
|
|
+ aclRule.Dst = append(aclRule.Dst, *cidr)
|
|
|
|
+ } else {
|
|
|
|
+ aclRule.Dst6 = append(aclRule.Dst6, *cidr)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
- } else {
|
|
|
|
- aclRule.Dst = append(aclRule.Dst, net.IPNet{
|
|
|
|
- IP: net.IPv4zero, // 0.0.0.0
|
|
|
|
- Mask: net.CIDRMask(0, 32), // /0 means match all IPv4
|
|
|
|
- })
|
|
|
|
- aclRule.Dst6 = append(aclRule.Dst6, net.IPNet{
|
|
|
|
- IP: net.IPv6zero, // ::
|
|
|
|
- Mask: net.CIDRMask(0, 128), // /0 means match all IPv6
|
|
|
|
- })
|
|
|
|
}
|
|
}
|
|
if acl.AllowedDirection == models.TrafficDirectionBi {
|
|
if acl.AllowedDirection == models.TrafficDirectionBi {
|
|
var existsInSrcTag bool
|
|
var existsInSrcTag bool
|
|
var existsInDstTag bool
|
|
var existsInDstTag bool
|
|
-
|
|
|
|
if _, ok := srcTags[nodeTag.String()]; ok || srcAll {
|
|
if _, ok := srcTags[nodeTag.String()]; ok || srcAll {
|
|
existsInSrcTag = true
|
|
existsInSrcTag = true
|
|
}
|
|
}
|
|
if _, ok := dstTags[nodeTag.String()]; ok || dstAll {
|
|
if _, ok := dstTags[nodeTag.String()]; ok || dstAll {
|
|
existsInDstTag = true
|
|
existsInDstTag = true
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+ if srcAll || dstAll {
|
|
|
|
+ if targetnode.NetworkRange.IP != nil {
|
|
|
|
+ aclRule.IPList = append(aclRule.IPList, targetnode.NetworkRange)
|
|
|
|
+ }
|
|
|
|
+ if targetnode.NetworkRange6.IP != nil {
|
|
|
|
+ aclRule.IP6List = append(aclRule.IP6List, targetnode.NetworkRange6)
|
|
|
|
+ }
|
|
|
|
+ break
|
|
|
|
+ }
|
|
if existsInSrcTag && !existsInDstTag {
|
|
if existsInSrcTag && !existsInDstTag {
|
|
// get all dst tags
|
|
// get all dst tags
|
|
for dst := range dstTags {
|
|
for dst := range dstTags {
|
|
@@ -1835,8 +2038,16 @@ func GetEgressRulesForNode(targetnode models.Node) (rules map[string]models.AclR
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- _, all := dstTags["*"]
|
|
|
|
- if _, ok := dstTags[nodeTag.String()]; ok || all {
|
|
|
|
|
|
+ if dstAll {
|
|
|
|
+ if targetnode.NetworkRange.IP != nil {
|
|
|
|
+ aclRule.IPList = append(aclRule.IPList, targetnode.NetworkRange)
|
|
|
|
+ }
|
|
|
|
+ if targetnode.NetworkRange6.IP != nil {
|
|
|
|
+ aclRule.IP6List = append(aclRule.IP6List, targetnode.NetworkRange6)
|
|
|
|
+ }
|
|
|
|
+ break
|
|
|
|
+ }
|
|
|
|
+ if _, ok := dstTags[nodeTag.String()]; ok || dstAll {
|
|
// get all src tags
|
|
// get all src tags
|
|
for src := range srcTags {
|
|
for src := range srcTags {
|
|
if src == nodeTag.String() {
|
|
if src == nodeTag.String() {
|
|
@@ -1864,13 +2075,13 @@ func GetEgressRulesForNode(targetnode models.Node) (rules map[string]models.AclR
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if len(aclRule.IPList) > 0 || len(aclRule.IP6List) > 0 {
|
|
|
|
- aclRule.IPList = UniqueIPNetList(aclRule.IPList)
|
|
|
|
- aclRule.IP6List = UniqueIPNetList(aclRule.IP6List)
|
|
|
|
- rules[acl.ID] = aclRule
|
|
|
|
- }
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
+ if len(aclRule.IPList) > 0 || len(aclRule.IP6List) > 0 {
|
|
|
|
+ aclRule.IPList = UniqueIPNetList(aclRule.IPList)
|
|
|
|
+ aclRule.IP6List = UniqueIPNetList(aclRule.IP6List)
|
|
|
|
+ rules[acl.ID] = aclRule
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
return
|
|
return
|