mirror of
https://github.com/gravitl/netmaker.git
synced 2025-09-04 04:04:17 +08:00
NET-1910: Acl controls for Egress Traffic (#3377)
* add support for egress ranges on acl policy * add egress ranges to acl rules * add egress ranges to acl policies * Add egress ranges to acl rules * add egress ranges to fw update * fetch acl rules for egress networks * apply egress policies for devices * configure user policies for egresss routes * fix gw tag name migration * fix egress acl rules for static nodes * add egress ranges for static nodes on ingress gw * fileter acl IPs to be unique * cleanup IOT logic from peer update * make acl Rule Dst List * cleanup egress ranges from acl policies * create user group default acl policy for gateways * remove remote access name ids * rm egress ranges removal from acl policies * simplify user permissions on nodes * add additional nameservers to extclient dns * remove debug logs * fix static checks
This commit is contained in:
parent
372c797e60
commit
3d765f9cf1
18 changed files with 737 additions and 436 deletions
|
@ -4,7 +4,7 @@ ARG tags
|
|||
WORKDIR /app
|
||||
COPY . .
|
||||
|
||||
RUN GOOS=linux CGO_ENABLED=1 go build -ldflags="-s -w " -tags ${tags} .
|
||||
RUN GOOS=linux CGO_ENABLED=1 go build -race -ldflags="-s -w " -tags ${tags} .
|
||||
# RUN go build -tags=ee . -o netmaker main.go
|
||||
FROM alpine:3.21.2
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ func aclPolicyTypes(w http.ResponseWriter, r *http.Request) {
|
|||
DstGroupTypes: []models.AclGroupType{
|
||||
models.NodeTagID,
|
||||
models.NodeID,
|
||||
models.EgressRange,
|
||||
// models.NetmakerIPAclID,
|
||||
// models.NetmakerSubNetRangeAClID,
|
||||
},
|
||||
|
|
|
@ -475,7 +475,18 @@ func getExtClientHAConf(w http.ResponseWriter, r *http.Request) {
|
|||
// models.RemoteAccessTagName))] = struct{}{}
|
||||
// set extclient dns to ingressdns if extclient dns is not explicitly set
|
||||
if (extclient.DNS == "") && (gwnode.IngressDNS != "") {
|
||||
extclient.DNS = gwnode.IngressDNS
|
||||
network, _ := logic.GetNetwork(gwnode.Network)
|
||||
dns := gwnode.IngressDNS
|
||||
if len(network.NameServers) > 0 {
|
||||
if dns == "" {
|
||||
dns = strings.Join(network.NameServers, ",")
|
||||
} else {
|
||||
dns += "," + strings.Join(network.NameServers, ",")
|
||||
}
|
||||
|
||||
}
|
||||
extclient.DNS = dns
|
||||
|
||||
}
|
||||
|
||||
listenPort := logic.GetPeerListenPort(host)
|
||||
|
|
|
@ -140,60 +140,12 @@ func upgradeHost(w http.ResponseWriter, r *http.Request) {
|
|||
// @Failure 500 {object} models.ErrorResponse
|
||||
func getHosts(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
currentHosts := []models.Host{}
|
||||
var err error
|
||||
if r.Header.Get("ismaster") == "yes" {
|
||||
currentHosts, err = logic.GetAllHosts()
|
||||
if err != nil {
|
||||
logger.Log(0, r.Header.Get("user"), "failed to fetch hosts: ", err.Error())
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
username := r.Header.Get("user")
|
||||
user, err := logic.GetUser(username)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
userPlatformRole, err := logic.GetRole(user.PlatformRoleID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
respHostsMap := make(map[string]struct{})
|
||||
if !userPlatformRole.FullAccess {
|
||||
nodes, err := logic.GetAllNodes()
|
||||
if err != nil {
|
||||
logger.Log(0, "error fetching all nodes info: ", err.Error())
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
filteredNodes := logic.GetFilteredNodesByUserAccess(*user, nodes)
|
||||
if len(filteredNodes) > 0 {
|
||||
currentHostsMap, err := logic.GetHostsMap()
|
||||
if err != nil {
|
||||
logger.Log(0, r.Header.Get("user"), "failed to fetch hosts: ", err.Error())
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
for _, node := range filteredNodes {
|
||||
if _, ok := respHostsMap[node.HostID.String()]; ok {
|
||||
continue
|
||||
}
|
||||
if host, ok := currentHostsMap[node.HostID.String()]; ok {
|
||||
currentHosts = append(currentHosts, host)
|
||||
respHostsMap[host.ID.String()] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
currentHosts, err = logic.GetAllHosts()
|
||||
if err != nil {
|
||||
logger.Log(0, r.Header.Get("user"), "failed to fetch hosts: ", err.Error())
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
}
|
||||
currentHosts, err := logic.GetAllHosts()
|
||||
if err != nil {
|
||||
logger.Log(0, r.Header.Get("user"), "failed to fetch hosts: ", err.Error())
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
|
||||
apiHosts := logic.GetAllHostsAPI(currentHosts[:])
|
||||
|
|
|
@ -41,6 +41,7 @@ func networkHandlers(r *mux.Router) {
|
|||
Methods(http.MethodPut)
|
||||
r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(getNetworkACL))).
|
||||
Methods(http.MethodGet)
|
||||
r.HandleFunc("/api/networks/{networkname}/egress_routes", logic.SecurityCheck(true, http.HandlerFunc(getNetworkEgressRoutes)))
|
||||
}
|
||||
|
||||
// @Summary Lists all networks
|
||||
|
@ -429,6 +430,33 @@ func getNetworkACL(w http.ResponseWriter, r *http.Request) {
|
|||
json.NewEncoder(w).Encode(networkACL)
|
||||
}
|
||||
|
||||
// @Summary Get a network Egress routes
|
||||
// @Router /api/networks/{networkname}/egress_routes [get]
|
||||
// @Tags Networks
|
||||
// @Security oauth
|
||||
// @Param networkname path string true "Network name"
|
||||
// @Produce json
|
||||
// @Success 200 {object} acls.SuccessResponse
|
||||
// @Failure 500 {object} models.ErrorResponse
|
||||
func getNetworkEgressRoutes(w http.ResponseWriter, r *http.Request) {
|
||||
var params = mux.Vars(r)
|
||||
netname := params["networkname"]
|
||||
// check if network exists
|
||||
_, err := logic.GetNetwork(netname)
|
||||
if err != nil {
|
||||
logger.Log(0, r.Header.Get("user"),
|
||||
fmt.Sprintf("failed to fetch ACLs for network [%s]: %v", netname, err))
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
|
||||
return
|
||||
}
|
||||
nodeEgressRoutes, _, err := logic.GetEgressRanges(models.NetworkID(netname))
|
||||
if err != nil {
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
|
||||
return
|
||||
}
|
||||
logic.ReturnSuccessResponseWithJson(w, r, nodeEgressRoutes, "fetched network egress routes")
|
||||
}
|
||||
|
||||
// @Summary Delete a network
|
||||
// @Router /api/networks/{networkname} [delete]
|
||||
// @Tags Networks
|
||||
|
|
600
logic/acls.go
600
logic/acls.go
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"net"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -222,6 +223,104 @@ func IsAclExists(aclID string) bool {
|
|||
_, err := GetAcl(aclID)
|
||||
return err == nil
|
||||
}
|
||||
func GetEgressRanges(netID models.NetworkID) (map[string][]string, map[string]struct{}, error) {
|
||||
|
||||
resultMap := make(map[string]struct{})
|
||||
nodeEgressMap := make(map[string][]string)
|
||||
networkNodes, err := GetNetworkNodes(netID.String())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
for _, currentNode := range networkNodes {
|
||||
if currentNode.Network != netID.String() {
|
||||
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 {
|
||||
resultMap[egressRangeI] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
extclients, _ := GetNetworkExtClients(netID.String())
|
||||
for _, extclient := range extclients {
|
||||
if len(extclient.ExtraAllowedIPs) > 0 {
|
||||
nodeEgressMap[extclient.ClientID] = extclient.ExtraAllowedIPs
|
||||
for _, extraAllowedIP := range extclient.ExtraAllowedIPs {
|
||||
resultMap[extraAllowedIP] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodeEgressMap, resultMap, nil
|
||||
}
|
||||
|
||||
func checkIfAclTagisValid(t models.AclPolicyTag, netID models.NetworkID, policyType models.AclPolicyType, isSrc bool) bool {
|
||||
switch t.ID {
|
||||
case models.NodeTagID:
|
||||
if policyType == models.UserPolicy && isSrc {
|
||||
return false
|
||||
}
|
||||
// check if tag is valid
|
||||
_, err := GetTag(models.TagID(t.Value))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
case models.NodeID:
|
||||
if policyType == models.UserPolicy && isSrc {
|
||||
return false
|
||||
}
|
||||
_, nodeErr := GetNodeByID(t.Value)
|
||||
if nodeErr != nil {
|
||||
_, staticNodeErr := GetExtClient(t.Value, netID.String())
|
||||
if staticNodeErr != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
case models.EgressRange:
|
||||
if isSrc {
|
||||
return false
|
||||
}
|
||||
// _, rangesMap, err := GetEgressRanges(netID)
|
||||
// if err != nil {
|
||||
// return false
|
||||
// }
|
||||
// if _, ok := rangesMap[t.Value]; !ok {
|
||||
// return false
|
||||
// }
|
||||
case models.UserAclID:
|
||||
if policyType == models.DevicePolicy {
|
||||
return false
|
||||
}
|
||||
if !isSrc {
|
||||
return false
|
||||
}
|
||||
_, err := GetUser(t.Value)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
case models.UserGroupAclID:
|
||||
if policyType == models.DevicePolicy {
|
||||
return false
|
||||
}
|
||||
if !isSrc {
|
||||
return false
|
||||
}
|
||||
err := IsGroupValid(models.UserGroupID(t.Value))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
// check if group belongs to this network
|
||||
netGrps := GetUserGroupsInNetwork(netID)
|
||||
if _, ok := netGrps[models.UserGroupID(t.Value)]; !ok {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsAclPolicyValid - validates if acl policy is valid
|
||||
func IsAclPolicyValid(acl models.Acl) bool {
|
||||
|
@ -235,115 +334,43 @@ func IsAclPolicyValid(acl models.Acl) bool {
|
|||
// src list should only contain users
|
||||
for _, srcI := range acl.Src {
|
||||
|
||||
if srcI.ID == "" || srcI.Value == "" {
|
||||
return false
|
||||
}
|
||||
if srcI.Value == "*" {
|
||||
continue
|
||||
}
|
||||
if srcI.ID != models.UserAclID && srcI.ID != models.UserGroupAclID {
|
||||
// check if user group is valid
|
||||
if !checkIfAclTagisValid(srcI, acl.NetworkID, acl.RuleType, true) {
|
||||
return false
|
||||
}
|
||||
// check if user group is valid
|
||||
if srcI.ID == models.UserAclID {
|
||||
_, err := GetUser(srcI.Value)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
} else if srcI.ID == models.UserGroupAclID {
|
||||
err := IsGroupValid(models.UserGroupID(srcI.Value))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
// check if group belongs to this network
|
||||
netGrps := GetUserGroupsInNetwork(acl.NetworkID)
|
||||
if _, ok := netGrps[models.UserGroupID(srcI.Value)]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
for _, dstI := range acl.Dst {
|
||||
|
||||
if dstI.ID == "" || dstI.Value == "" {
|
||||
return false
|
||||
}
|
||||
if dstI.ID != models.NodeTagID && dstI.ID != models.NodeID {
|
||||
return false
|
||||
}
|
||||
if dstI.Value == "*" {
|
||||
continue
|
||||
}
|
||||
if dstI.ID == models.NodeTagID {
|
||||
// check if tag is valid
|
||||
_, err := GetTag(models.TagID(dstI.Value))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
_, nodeErr := GetNodeByID(dstI.Value)
|
||||
if nodeErr != nil {
|
||||
_, staticNodeErr := GetExtClient(dstI.Value, acl.NetworkID.String())
|
||||
if staticNodeErr != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// check if user group is valid
|
||||
if !checkIfAclTagisValid(dstI, acl.NetworkID, acl.RuleType, false) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
case models.DevicePolicy:
|
||||
for _, srcI := range acl.Src {
|
||||
if srcI.ID == "" || srcI.Value == "" {
|
||||
return false
|
||||
}
|
||||
if srcI.ID != models.NodeTagID && srcI.ID != models.NodeID {
|
||||
return false
|
||||
}
|
||||
if srcI.Value == "*" {
|
||||
continue
|
||||
}
|
||||
if srcI.ID == models.NodeTagID {
|
||||
// check if tag is valid
|
||||
_, err := GetTag(models.TagID(srcI.Value))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
_, nodeErr := GetNodeByID(srcI.Value)
|
||||
if nodeErr != nil {
|
||||
_, staticNodeErr := GetExtClient(srcI.Value, acl.NetworkID.String())
|
||||
if staticNodeErr != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// check if user group is valid
|
||||
if !checkIfAclTagisValid(srcI, acl.NetworkID, acl.RuleType, true) {
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
for _, dstI := range acl.Dst {
|
||||
|
||||
if dstI.ID == "" || dstI.Value == "" {
|
||||
return false
|
||||
}
|
||||
if dstI.ID != models.NodeTagID && dstI.ID != models.NodeID {
|
||||
return false
|
||||
}
|
||||
if dstI.Value == "*" {
|
||||
continue
|
||||
}
|
||||
if dstI.ID == models.NodeTagID {
|
||||
// check if tag is valid
|
||||
_, err := GetTag(models.TagID(dstI.Value))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
_, nodeErr := GetNodeByID(dstI.Value)
|
||||
if nodeErr != nil {
|
||||
_, staticNodeErr := GetExtClient(dstI.Value, acl.NetworkID.String())
|
||||
if staticNodeErr != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// check if user group is valid
|
||||
if !checkIfAclTagisValid(dstI, acl.NetworkID, acl.RuleType, false) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -688,8 +715,8 @@ func RemoveUserFromAclPolicy(userName string) {
|
|||
delete := false
|
||||
update := false
|
||||
if acl.RuleType == models.UserPolicy {
|
||||
for i, srcI := range acl.Src {
|
||||
if srcI.ID == models.UserAclID && srcI.Value == userName {
|
||||
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
|
||||
|
@ -723,8 +750,8 @@ func RemoveNodeFromAclPolicy(node models.Node) {
|
|||
delete := false
|
||||
update := false
|
||||
if acl.RuleType == models.DevicePolicy {
|
||||
for i, srcI := range acl.Src {
|
||||
if srcI.ID == models.NodeID && srcI.Value == nodeID {
|
||||
for i := len(acl.Src) - 1; i >= 0; i-- {
|
||||
if acl.Src[i].ID == models.NodeID && acl.Src[i].Value == nodeID {
|
||||
if len(acl.Src) == 1 {
|
||||
// delete policy
|
||||
delete = true
|
||||
|
@ -739,8 +766,8 @@ func RemoveNodeFromAclPolicy(node models.Node) {
|
|||
DeleteAcl(acl)
|
||||
continue
|
||||
}
|
||||
for i, dstI := range acl.Dst {
|
||||
if dstI.ID == models.NodeID && dstI.Value == nodeID {
|
||||
for i := len(acl.Dst) - 1; i >= 0; i-- {
|
||||
if acl.Dst[i].ID == models.NodeID && acl.Dst[i].Value == nodeID {
|
||||
if len(acl.Dst) == 1 {
|
||||
// delete policy
|
||||
delete = true
|
||||
|
@ -761,8 +788,8 @@ func RemoveNodeFromAclPolicy(node models.Node) {
|
|||
|
||||
}
|
||||
if acl.RuleType == models.UserPolicy {
|
||||
for i, dstI := range acl.Dst {
|
||||
if dstI.ID == models.NodeID && dstI.Value == nodeID {
|
||||
for i := len(acl.Dst) - 1; i >= 0; i-- {
|
||||
if acl.Dst[i].ID == models.NodeID && acl.Dst[i].Value == nodeID {
|
||||
if len(acl.Dst) == 1 {
|
||||
// delete policy
|
||||
delete = true
|
||||
|
@ -1239,17 +1266,17 @@ func RemoveDeviceTagFromAclPolicies(tagID models.TagID, netID models.NetworkID)
|
|||
acls := listDevicePolicies(netID)
|
||||
update := false
|
||||
for _, acl := range acls {
|
||||
for i, srcTagI := range acl.Src {
|
||||
if srcTagI.ID == models.NodeTagID {
|
||||
if tagID.String() == srcTagI.Value {
|
||||
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, dstTagI := range acl.Dst {
|
||||
if dstTagI.ID == models.NodeTagID {
|
||||
if tagID.String() == dstTagI.Value {
|
||||
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
|
||||
}
|
||||
|
@ -1262,19 +1289,16 @@ func RemoveDeviceTagFromAclPolicies(tagID models.TagID, netID models.NetworkID)
|
|||
return nil
|
||||
}
|
||||
|
||||
func getUserAclRulesForNode(targetnode *models.Node,
|
||||
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{})
|
||||
if targetnode.Mutex != nil {
|
||||
targetnode.Mutex.Lock()
|
||||
targetNodeTags = maps.Clone(targetnode.Tags)
|
||||
targetnode.Mutex.Unlock()
|
||||
} else {
|
||||
targetNodeTags = maps.Clone(targetnode.Tags)
|
||||
targetNodeTags["*"] = struct{}{}
|
||||
for _, rangeI := range targetnode.EgressGatewayRanges {
|
||||
targetNodeTags[models.TagID(rangeI)] = struct{}{}
|
||||
}
|
||||
for _, acl := range acls {
|
||||
if !acl.Enabled {
|
||||
|
@ -1285,10 +1309,9 @@ func getUserAclRulesForNode(targetnode *models.Node,
|
|||
addUsers := false
|
||||
if !all {
|
||||
for nodeTag := range targetNodeTags {
|
||||
if _, ok := dstTags[nodeTag.String()]; !ok {
|
||||
if _, ok = dstTags[targetnode.ID.String()]; !ok {
|
||||
break
|
||||
}
|
||||
if _, ok := dstTags[nodeTag.String()]; ok {
|
||||
addUsers = true
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1326,7 +1349,110 @@ func getUserAclRulesForNode(targetnode *models.Node,
|
|||
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.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 aclRule, ok := rules[acl.ID]; ok {
|
||||
aclRule.IPList = append(aclRule.IPList, r.IPList...)
|
||||
aclRule.IP6List = append(aclRule.IP6List, r.IP6List...)
|
||||
rules[acl.ID] = aclRule
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
targetNodeTags[models.TagID(targetnode.ID.String())] = struct{}{}
|
||||
for _, acl := range acls {
|
||||
if !acl.Enabled {
|
||||
continue
|
||||
}
|
||||
dstTags := convAclTagToValueMap(acl.Dst)
|
||||
_, 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -1354,7 +1480,16 @@ func getUserAclRulesForNode(targetnode *models.Node,
|
|||
}
|
||||
|
||||
func checkIfAnyPolicyisUniDirectional(targetNode models.Node) bool {
|
||||
targetNode.Tags[models.TagID(targetNode.ID.String())] = struct{}{}
|
||||
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)
|
||||
}
|
||||
targetNodeTags[models.TagID(targetNode.ID.String())] = struct{}{}
|
||||
targetNodeTags["*"] = struct{}{}
|
||||
acls := listDevicePolicies(models.NetworkID(targetNode.Network))
|
||||
for _, acl := range acls {
|
||||
if !acl.Enabled {
|
||||
|
@ -1363,9 +1498,12 @@ func checkIfAnyPolicyisUniDirectional(targetNode models.Node) bool {
|
|||
if acl.AllowedDirection == models.TrafficDirectionBi {
|
||||
continue
|
||||
}
|
||||
if acl.Proto != models.ALL || acl.ServiceType != models.Any {
|
||||
return true
|
||||
}
|
||||
srcTags := convAclTagToValueMap(acl.Src)
|
||||
dstTags := convAclTagToValueMap(acl.Dst)
|
||||
for nodeTag := range targetNode.Tags {
|
||||
for nodeTag := range targetNodeTags {
|
||||
if _, ok := srcTags[nodeTag.String()]; ok {
|
||||
return true
|
||||
}
|
||||
|
@ -1385,12 +1523,10 @@ func checkIfAnyPolicyisUniDirectional(targetNode models.Node) bool {
|
|||
|
||||
func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRule) {
|
||||
targetnode := *targetnodeI
|
||||
targetnode.Tags[models.TagID(targetnode.ID.String())] = struct{}{}
|
||||
defer func() {
|
||||
if !targetnode.IsIngressGateway {
|
||||
rules = getUserAclRulesForNode(&targetnode, rules)
|
||||
}
|
||||
|
||||
}()
|
||||
rules = make(map[string]models.AclRule)
|
||||
var taggedNodes map[models.TagID][]models.Node
|
||||
|
@ -1409,8 +1545,8 @@ func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRu
|
|||
} else {
|
||||
targetNodeTags = maps.Clone(targetnode.Tags)
|
||||
}
|
||||
targetNodeTags[models.TagID(targetnode.ID.String())] = struct{}{}
|
||||
targetNodeTags["*"] = struct{}{}
|
||||
|
||||
for _, acl := range acls {
|
||||
if !acl.Enabled {
|
||||
continue
|
||||
|
@ -1593,9 +1729,245 @@ func GetAclRulesForNode(targetnodeI *models.Node) (rules map[string]models.AclRu
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
if len(aclRule.IPList) > 0 || len(aclRule.IP6List) > 0 {
|
||||
aclRule.IPList = UniqueIPNetList(aclRule.IPList)
|
||||
aclRule.IP6List = UniqueIPNetList(aclRule.IP6List)
|
||||
rules[acl.ID] = aclRule
|
||||
}
|
||||
}
|
||||
return rules
|
||||
}
|
||||
func UniqueIPNetList(ipnets []net.IPNet) []net.IPNet {
|
||||
uniqueMap := make(map[string]net.IPNet)
|
||||
|
||||
for _, ipnet := range ipnets {
|
||||
key := ipnet.String() // Uses CIDR notation as a unique key
|
||||
if _, exists := uniqueMap[key]; !exists {
|
||||
uniqueMap[key] = ipnet
|
||||
}
|
||||
}
|
||||
|
||||
// Convert map back to slice
|
||||
uniqueList := make([]net.IPNet, 0, len(uniqueMap))
|
||||
for _, ipnet := range uniqueMap {
|
||||
uniqueList = append(uniqueList, ipnet)
|
||||
}
|
||||
|
||||
return uniqueList
|
||||
}
|
||||
|
||||
func GetEgressRulesForNode(targetnode models.Node) (rules map[string]models.AclRule) {
|
||||
rules = make(map[string]models.AclRule)
|
||||
defer func() {
|
||||
rules = getEgressUserRulesForNode(&targetnode, rules)
|
||||
}()
|
||||
taggedNodes := GetTagMapWithNodesByNetwork(models.NetworkID(targetnode.Network), true)
|
||||
|
||||
acls := listDevicePolicies(models.NetworkID(targetnode.Network))
|
||||
var targetNodeTags = make(map[models.TagID]struct{})
|
||||
targetNodeTags["*"] = struct{}{}
|
||||
|
||||
/*
|
||||
if target node is egress gateway
|
||||
if acl policy has egress route and it is present in target node egress ranges
|
||||
fetches all the nodes in that policy and add rules
|
||||
*/
|
||||
|
||||
for _, rangeI := range targetnode.EgressGatewayRanges {
|
||||
targetNodeTags[models.TagID(rangeI)] = 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 {
|
||||
aclRule := models.AclRule{
|
||||
ID: acl.ID,
|
||||
AllowedProtocol: acl.Proto,
|
||||
AllowedPorts: acl.Port,
|
||||
Direction: acl.AllowedDirection,
|
||||
Allowed: true,
|
||||
}
|
||||
if nodeTag != "*" {
|
||||
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)
|
||||
}
|
||||
|
||||
} 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 {
|
||||
var existsInSrcTag bool
|
||||
var existsInDstTag bool
|
||||
|
||||
if _, ok := srcTags[nodeTag.String()]; ok || srcAll {
|
||||
existsInSrcTag = true
|
||||
}
|
||||
if _, ok := dstTags[nodeTag.String()]; ok || dstAll {
|
||||
existsInDstTag = true
|
||||
}
|
||||
|
||||
if existsInSrcTag && !existsInDstTag {
|
||||
// get all dst tags
|
||||
for dst := range dstTags {
|
||||
if dst == nodeTag.String() {
|
||||
continue
|
||||
}
|
||||
// Get peers in the tags and add allowed rules
|
||||
nodes := taggedNodes[models.TagID(dst)]
|
||||
if dst != targetnode.ID.String() {
|
||||
node, err := GetNodeByID(dst)
|
||||
if err == nil {
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
}
|
||||
|
||||
for _, node := range nodes {
|
||||
if node.ID == targetnode.ID {
|
||||
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 {
|
||||
// get all src tags
|
||||
for src := range srcTags {
|
||||
if src == nodeTag.String() {
|
||||
continue
|
||||
}
|
||||
// Get peers in the tags and add allowed rules
|
||||
nodes := taggedNodes[models.TagID(src)]
|
||||
if src != targetnode.ID.String() {
|
||||
node, err := GetNodeByID(src)
|
||||
if err == nil {
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
}
|
||||
for _, node := range nodes {
|
||||
if node.ID == targetnode.ID {
|
||||
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.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 {
|
||||
_, all := dstTags["*"]
|
||||
if _, ok := dstTags[nodeTag.String()]; ok || all {
|
||||
// get all src tags
|
||||
for src := range srcTags {
|
||||
if src == nodeTag.String() {
|
||||
continue
|
||||
}
|
||||
// Get peers in the tags and add allowed rules
|
||||
nodes := taggedNodes[models.TagID(src)]
|
||||
for _, node := range nodes {
|
||||
if node.ID == targetnode.ID {
|
||||
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 len(aclRule.IPList) > 0 || len(aclRule.IP6List) > 0 {
|
||||
aclRule.IPList = UniqueIPNetList(aclRule.IPList)
|
||||
aclRule.IP6List = UniqueIPNetList(aclRule.IP6List)
|
||||
rules[acl.ID] = aclRule
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -591,132 +591,130 @@ func getFwRulesForNodeAndPeerOnGw(node, peer models.Node, allowedPolicies []mode
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
// add egress range rules
|
||||
for _, dstI := range policy.Dst {
|
||||
if dstI.ID == models.EgressRange {
|
||||
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 GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) {
|
||||
// fetch user access to static clients via policies
|
||||
func getFwRulesForUserNodesOnGw(node models.Node, nodes []models.Node) (rules []models.FwRule) {
|
||||
defaultUserPolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy)
|
||||
defaultDevicePolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
|
||||
nodes, _ := GetNetworkNodes(node.Network)
|
||||
nodes = append(nodes, GetStaticNodesByNetwork(models.NetworkID(node.Network), true)...)
|
||||
userNodes := GetStaticUserNodesByNetwork(models.NetworkID(node.Network))
|
||||
for _, userNodeI := range userNodes {
|
||||
for _, peer := range nodes {
|
||||
if peer.IsUserNode {
|
||||
continue
|
||||
}
|
||||
|
||||
if ok, allowedPolicies := IsUserAllowedToCommunicate(userNodeI.StaticNode.OwnerID, peer); ok {
|
||||
if peer.IsStatic {
|
||||
if userNodeI.StaticNode.Address != "" {
|
||||
if !defaultUserPolicy.Enabled {
|
||||
for _, policy := range allowedPolicies {
|
||||
rules = append(rules, models.FwRule{
|
||||
SrcIP: userNodeI.StaticNode.AddressIPNet4(),
|
||||
DstIP: peer.StaticNode.AddressIPNet4(),
|
||||
AllowedProtocol: policy.Proto,
|
||||
AllowedPorts: policy.Port,
|
||||
Allow: true,
|
||||
})
|
||||
rules = append(rules, models.FwRule{
|
||||
SrcIP: peer.StaticNode.AddressIPNet4(),
|
||||
DstIP: userNodeI.StaticNode.AddressIPNet4(),
|
||||
AllowedProtocol: policy.Proto,
|
||||
AllowedPorts: policy.Port,
|
||||
Allow: true,
|
||||
})
|
||||
peer = peer.StaticNode.ConvertToStaticNode()
|
||||
}
|
||||
if !defaultUserPolicy.Enabled {
|
||||
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.ID == models.EgressRange {
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if userNodeI.StaticNode.Address6 != "" {
|
||||
if !defaultUserPolicy.Enabled {
|
||||
for _, policy := range allowedPolicies {
|
||||
rules = append(rules, models.FwRule{
|
||||
SrcIP: userNodeI.StaticNode.AddressIPNet6(),
|
||||
DstIP: peer.StaticNode.AddressIPNet6(),
|
||||
Allow: true,
|
||||
AllowedProtocol: policy.Proto,
|
||||
AllowedPorts: policy.Port,
|
||||
})
|
||||
rules = append(rules, models.FwRule{
|
||||
SrcIP: peer.StaticNode.AddressIPNet6(),
|
||||
DstIP: userNodeI.StaticNode.AddressIPNet6(),
|
||||
AllowedProtocol: policy.Proto,
|
||||
AllowedPorts: policy.Port,
|
||||
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 {
|
||||
rules = append(rules, models.FwRule{
|
||||
SrcIP: userNodeI.StaticNode.AddressIPNet4(),
|
||||
DstIP: *ipNet,
|
||||
Allow: true,
|
||||
})
|
||||
} else {
|
||||
rules = append(rules, models.FwRule{
|
||||
SrcIP: userNodeI.StaticNode.AddressIPNet6(),
|
||||
DstIP: *ipNet,
|
||||
Allow: true,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
if userNodeI.StaticNode.Address != "" {
|
||||
if !defaultUserPolicy.Enabled {
|
||||
for _, policy := range allowedPolicies {
|
||||
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 != "" {
|
||||
if !defaultUserPolicy.Enabled {
|
||||
for _, policy := range allowedPolicies {
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) {
|
||||
// fetch user access to static clients via policies
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -739,17 +737,34 @@ func GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) {
|
|||
if peer.IsStatic {
|
||||
peer = peer.StaticNode.ConvertToStaticNode()
|
||||
}
|
||||
if ok, allowedPolicies := IsNodeAllowedToCommunicateV1(nodeI.StaticNode.ConvertToStaticNode(), peer, true); ok {
|
||||
rules = append(rules, getFwRulesForNodeAndPeerOnGw(nodeI.StaticNode.ConvertToStaticNode(), peer, allowedPolicies)...)
|
||||
var allowedPolicies1 []models.Acl
|
||||
var ok bool
|
||||
if ok, allowedPolicies1 = IsNodeAllowedToCommunicateV1(nodeI.StaticNode.ConvertToStaticNode(), peer, true); ok {
|
||||
rules = append(rules, getFwRulesForNodeAndPeerOnGw(nodeI.StaticNode.ConvertToStaticNode(), peer, allowedPolicies1)...)
|
||||
}
|
||||
if ok, allowedPolicies := IsNodeAllowedToCommunicateV1(peer, nodeI.StaticNode.ConvertToStaticNode(), true); ok {
|
||||
rules = append(rules, getFwRulesForNodeAndPeerOnGw(peer, nodeI.StaticNode.ConvertToStaticNode(), allowedPolicies)...)
|
||||
if ok, allowedPolicies2 := IsNodeAllowedToCommunicateV1(peer, nodeI.StaticNode.ConvertToStaticNode(), true); ok {
|
||||
rules = append(rules,
|
||||
getFwRulesForNodeAndPeerOnGw(peer, nodeI.StaticNode.ConvertToStaticNode(),
|
||||
GetUniquePolicies(allowedPolicies1, allowedPolicies2))...)
|
||||
}
|
||||
}
|
||||
}
|
||||
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 GetExtPeers(node, peer *models.Node) ([]wgtypes.PeerConfig, []models.IDandAddr, []models.EgressNetworkRoutes, error) {
|
||||
var peers []wgtypes.PeerConfig
|
||||
var idsAndAddr []models.IDandAddr
|
||||
|
@ -764,13 +779,11 @@ func GetExtPeers(node, peer *models.Node) ([]wgtypes.PeerConfig, []models.IDandA
|
|||
}
|
||||
for _, extPeer := range extPeers {
|
||||
extPeer := extPeer
|
||||
fmt.Println("=====> checking EXT peer: ", extPeer.ClientID)
|
||||
if !IsClientNodeAllowed(&extPeer, peer.ID.String()) {
|
||||
continue
|
||||
}
|
||||
if extPeer.RemoteAccessClientID == "" {
|
||||
if ok := IsPeerAllowed(extPeer.ConvertToStaticNode(), *peer, true); !ok {
|
||||
fmt.Println("=====>1 checking EXT peer: ", extPeer.ClientID)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
|
@ -934,16 +947,11 @@ func GetStaticUserNodesByNetwork(network models.NetworkID) (staticNode []models.
|
|||
for _, extI := range extClients {
|
||||
if extI.Network == network.String() {
|
||||
if extI.RemoteAccessClientID != "" {
|
||||
n := models.Node{
|
||||
IsStatic: true,
|
||||
StaticNode: extI,
|
||||
IsUserNode: extI.RemoteAccessClientID != "",
|
||||
}
|
||||
n := extI.ConvertToStaticNode()
|
||||
staticNode = append(staticNode, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -866,6 +866,9 @@ func GetTagMapWithNodesByNetwork(netID models.NetworkID, withStaticNodes bool) (
|
|||
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 {
|
||||
|
@ -903,6 +906,9 @@ func AddTagMapWithStaticNodes(netID models.NetworkID,
|
|||
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())
|
||||
}
|
||||
|
|
|
@ -181,6 +181,7 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
|
|||
slog.Debug("peer update for host", "hostId", host.ID.String())
|
||||
peerIndexMap := make(map[string]int)
|
||||
for _, nodeID := range host.Nodes {
|
||||
networkAllowAll := true
|
||||
nodeID := nodeID
|
||||
node, err := GetNodeByID(nodeID)
|
||||
if err != nil {
|
||||
|
@ -190,60 +191,6 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
|
|||
if !node.Connected || node.PendingDelete || node.Action == models.NODE_DELETE {
|
||||
continue
|
||||
}
|
||||
if host.OS == models.OS_Types.IoT {
|
||||
hostPeerUpdate.NodeAddrs = append(hostPeerUpdate.NodeAddrs, node.PrimaryAddressIPNet())
|
||||
if node.IsRelayed {
|
||||
relayNode, err := GetNodeByID(node.RelayedBy)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
relayHost, err := GetHost(relayNode.HostID.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
relayPeer := wgtypes.PeerConfig{
|
||||
PublicKey: relayHost.PublicKey,
|
||||
PersistentKeepaliveInterval: &relayHost.PersistentKeepalive,
|
||||
ReplaceAllowedIPs: true,
|
||||
AllowedIPs: GetAllowedIPs(&node, &relayNode, nil),
|
||||
}
|
||||
uselocal := false
|
||||
if host.EndpointIP.String() == relayHost.EndpointIP.String() {
|
||||
// peer is on same network
|
||||
// set to localaddress
|
||||
uselocal = true
|
||||
if node.LocalAddress.IP == nil {
|
||||
// use public endpint
|
||||
uselocal = false
|
||||
}
|
||||
if node.LocalAddress.String() == relayNode.LocalAddress.String() {
|
||||
uselocal = false
|
||||
}
|
||||
}
|
||||
relayPeer.Endpoint = &net.UDPAddr{
|
||||
IP: relayHost.EndpointIP,
|
||||
Port: GetPeerListenPort(relayHost),
|
||||
}
|
||||
|
||||
if uselocal {
|
||||
relayPeer.Endpoint.IP = relayNode.LocalAddress.IP
|
||||
relayPeer.Endpoint.Port = relayHost.ListenPort
|
||||
}
|
||||
|
||||
hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, relayPeer)
|
||||
} else if deletedNode != nil && deletedNode.IsRelay {
|
||||
relayHost, err := GetHost(deletedNode.HostID.String())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
relayPeer := wgtypes.PeerConfig{
|
||||
PublicKey: relayHost.PublicKey,
|
||||
Remove: true,
|
||||
}
|
||||
hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, relayPeer)
|
||||
}
|
||||
continue
|
||||
}
|
||||
hostPeerUpdate = SetDefaultGw(node, hostPeerUpdate)
|
||||
if !hostPeerUpdate.IsInternetGw {
|
||||
hostPeerUpdate.IsInternetGw = IsInternetGw(node)
|
||||
|
@ -259,6 +206,7 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
|
|||
hostPeerUpdate.FwUpdate.AllowedNetworks = append(hostPeerUpdate.FwUpdate.AllowedNetworks, node.NetworkRange6)
|
||||
}
|
||||
} else {
|
||||
networkAllowAll = false
|
||||
hostPeerUpdate.FwUpdate.AllowAll = false
|
||||
rules := GetAclRulesForNode(&node)
|
||||
if len(hostPeerUpdate.FwUpdate.AclRules) == 0 {
|
||||
|
@ -370,7 +318,6 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
|
|||
}
|
||||
|
||||
if uselocal {
|
||||
peerConfig.Endpoint.IP = peer.LocalAddress.IP
|
||||
peerConfig.Endpoint.Port = peerHost.ListenPort
|
||||
}
|
||||
var allowedToComm bool
|
||||
|
@ -438,7 +385,6 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
|
|||
IngressID: node.ID.String(),
|
||||
Network: node.NetworkRange,
|
||||
Network6: node.NetworkRange6,
|
||||
AllowAll: defaultDevicePolicy.Enabled && defaultUserPolicy.Default,
|
||||
StaticNodeIps: GetStaticNodeIps(node),
|
||||
Rules: GetFwRulesOnIngressGateway(node),
|
||||
}
|
||||
|
@ -472,10 +418,23 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
|
|||
IP: node.Address6.IP,
|
||||
Mask: getCIDRMaskFromAddr(node.Address6.IP.String()),
|
||||
},
|
||||
EgressGWCfg: node.EgressGatewayRequest,
|
||||
EgressGWCfg: node.EgressGatewayRequest,
|
||||
EgressFwRules: make(map[string]models.AclRule),
|
||||
}
|
||||
|
||||
}
|
||||
if node.IsEgressGateway {
|
||||
if !networkAllowAll {
|
||||
egressInfo := hostPeerUpdate.FwUpdate.EgressInfo[node.ID.String()]
|
||||
if egressInfo.EgressFwRules == nil {
|
||||
egressInfo.EgressFwRules = make(map[string]models.AclRule)
|
||||
}
|
||||
egressInfo.EgressFwRules = GetEgressRulesForNode(node)
|
||||
hostPeerUpdate.FwUpdate.EgressInfo[node.ID.String()] = egressInfo
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if IsInternetGw(node) {
|
||||
hostPeerUpdate.FwUpdate.IsEgressGw = true
|
||||
egressrange := []string{"0.0.0.0/0"}
|
||||
|
|
|
@ -278,7 +278,7 @@ func CheckIDSyntax(id string) error {
|
|||
}
|
||||
|
||||
func CreateDefaultTags(netID models.NetworkID) {
|
||||
// create tag for remote access gws in the network
|
||||
// create tag for gws in the network
|
||||
tag := models.Tag{
|
||||
ID: models.TagID(fmt.Sprintf("%s.%s", netID.String(), models.GwTagName)),
|
||||
TagName: models.GwTagName,
|
||||
|
@ -292,7 +292,7 @@ func CreateDefaultTags(netID models.NetworkID) {
|
|||
}
|
||||
err = InsertTag(tag)
|
||||
if err != nil {
|
||||
slog.Error("failed to create remote access gw tag", "error", err.Error())
|
||||
slog.Error("failed to create gw tag", "error", err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -468,14 +468,14 @@ func migrateToGws() {
|
|||
upsert := false
|
||||
for i, srcI := range acl.Src {
|
||||
if srcI.ID == models.NodeTagID && srcI.Value == fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.OldRemoteAccessTagName) {
|
||||
srcI.Value = models.GwTagName
|
||||
srcI.Value = fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.GwTagName)
|
||||
acl.Src[i] = srcI
|
||||
upsert = true
|
||||
}
|
||||
}
|
||||
for i, dstI := range acl.Dst {
|
||||
if dstI.ID == models.NodeTagID && dstI.Value == fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.OldRemoteAccessTagName) {
|
||||
dstI.Value = models.GwTagName
|
||||
dstI.Value = fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.GwTagName)
|
||||
acl.Dst[i] = dstI
|
||||
upsert = true
|
||||
}
|
||||
|
|
|
@ -117,5 +117,7 @@ type AclRule struct {
|
|||
AllowedProtocol Protocol `json:"allowed_protocols"` // tcp, udp, etc.
|
||||
AllowedPorts []string `json:"allowed_ports"`
|
||||
Direction AllowedTrafficDirection `json:"direction"` // single or two-way
|
||||
Dst []net.IPNet `json:"dst"`
|
||||
Dst6 []net.IPNet `json:"dst6"`
|
||||
Allowed bool
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ func (ext *ExtClient) ConvertToStaticNode() Node {
|
|||
Tags: ext.Tags,
|
||||
IsStatic: true,
|
||||
StaticNode: *ext,
|
||||
IsUserNode: ext.RemoteAccessClientID != "",
|
||||
Mutex: ext.Mutex,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ type IngressInfo struct {
|
|||
Network6 net.IPNet `json:"network6"`
|
||||
StaticNodeIps []net.IP `json:"static_node_ips"`
|
||||
Rules []FwRule `json:"rules"`
|
||||
AllowAll bool `json:"allow_all"`
|
||||
EgressRanges []net.IPNet `json:"egress_ranges"`
|
||||
EgressRanges6 []net.IPNet `json:"egress_ranges6"`
|
||||
}
|
||||
|
@ -66,6 +65,7 @@ type EgressInfo struct {
|
|||
Network6 net.IPNet `json:"network6" yaml:"network6"`
|
||||
EgressGwAddr6 net.IPNet `json:"egress_gw_addr6" yaml:"egress_gw_addr6"`
|
||||
EgressGWCfg EgressGatewayRequest `json:"egress_gateway_cfg" yaml:"egress_gateway_cfg"`
|
||||
EgressFwRules map[string]AclRule `json:"egress_fw_rules"`
|
||||
}
|
||||
|
||||
// EgressNetworkRoutes - struct for egress network routes for adding routes to peer's interface
|
||||
|
|
|
@ -98,7 +98,7 @@ var oauthNotConfigured = fmt.Sprintf(htmlBaseTemplate, `<h2>Your Netmaker server
|
|||
var oauthStateInvalid = fmt.Sprintf(htmlBaseTemplate, `<h2>Invalid OAuth Session. Please re-try again.</h2>`)
|
||||
|
||||
var userNotAllowed = fmt.Sprintf(htmlBaseTemplate, `<h2>Your account does not have access to the dashboard. Please contact your administrator for more information about your account.</h2>
|
||||
<p>Non-Admins can access the netmaker networks using <a href="https://docs.netmaker.io/docs/remote-access-client-rac#downloadinstallation" target="_blank" rel="noopener">our Remote Access Client.</a></p>`)
|
||||
<p>Non-Admins can access the netmaker networks using <a href="https://docs.netmaker.io/docs/remote-access-client-rac#downloadinstallation" target="_blank" rel="noopener">our Netmaker Desktop App.</a></p>`)
|
||||
|
||||
var userFirstTimeSignUp = fmt.Sprintf(htmlBaseTemplate, `<h2>Thank you for signing up. Please contact your administrator for access.</h2>`)
|
||||
|
||||
|
|
|
@ -8,7 +8,9 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gravitl/netmaker/database"
|
||||
"github.com/gravitl/netmaker/logger"
|
||||
|
@ -411,6 +413,44 @@ func createUserGroup(w http.ResponseWriter, r *http.Request) {
|
|||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
networks, err := logic.GetNetworks()
|
||||
if err != nil {
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
for _, network := range networks {
|
||||
acl := models.Acl{
|
||||
ID: uuid.New().String(),
|
||||
Name: fmt.Sprintf("%s group", userGroupReq.Group.Name),
|
||||
MetaData: "This Policy allows user group to communicate with all gateways",
|
||||
Default: true,
|
||||
ServiceType: models.Any,
|
||||
NetworkID: models.NetworkID(network.NetID),
|
||||
Proto: models.ALL,
|
||||
RuleType: models.UserPolicy,
|
||||
Src: []models.AclPolicyTag{
|
||||
{
|
||||
ID: models.UserGroupAclID,
|
||||
Value: userGroupReq.Group.ID.String(),
|
||||
},
|
||||
},
|
||||
Dst: []models.AclPolicyTag{
|
||||
{
|
||||
ID: models.NodeTagID,
|
||||
Value: fmt.Sprintf("%s.%s", models.NetworkID(network.NetID), models.GwTagName),
|
||||
}},
|
||||
AllowedDirection: models.TrafficDirectionUni,
|
||||
Enabled: true,
|
||||
CreatedBy: "auto",
|
||||
CreatedAt: time.Now().UTC(),
|
||||
}
|
||||
err = logic.InsertAcl(acl)
|
||||
if err != nil {
|
||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, userID := range userGroupReq.Members {
|
||||
user, err := logic.GetUser(userID)
|
||||
if err != nil {
|
||||
|
|
|
@ -2,6 +2,7 @@ package email
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gravitl/netmaker/models"
|
||||
proLogic "github.com/gravitl/netmaker/pro/logic"
|
||||
"github.com/gravitl/netmaker/servercfg"
|
||||
|
@ -31,11 +32,11 @@ func (invite UserInvitedMail) GetBody(info Notification) string {
|
|||
|
||||
content := invite.BodyBuilder.
|
||||
WithParagraph("Hi,").
|
||||
WithParagraph("You've been invited to access a secure network via Netmaker's Remote Access Client (RAC). Follow these simple steps to get connected:").
|
||||
WithParagraph("You've been invited to access a secure network via Netmaker Desktop App. Follow these simple steps to get connected:").
|
||||
WithHtml("<ol>").
|
||||
WithHtml(fmt.Sprintf("<li>Click <a href=\"%s\">here</a> to accept your invitation and setup your account.</li>", invite.InviteURL)).
|
||||
WithHtml("<br>").
|
||||
WithHtml(fmt.Sprintf("<li><a href=\"%s\">Download the Remote Access Client (RAC)</a>.</li>", downloadLink))
|
||||
WithHtml(fmt.Sprintf("<li><a href=\"%s\">Download the Netmaker Desktop App</a>.</li>", downloadLink))
|
||||
|
||||
if invite.PlatformRoleID == models.AdminRole.String() || invite.PlatformRoleID == models.PlatformUser.String() {
|
||||
content = content.
|
||||
|
|
|
@ -40,7 +40,7 @@ var NetworkAdminAllPermissionTemplate = models.UserRolePermissionTemplate{
|
|||
var NetworkUserAllPermissionTemplate = models.UserRolePermissionTemplate{
|
||||
ID: models.UserRoleID(fmt.Sprintf("global-%s", models.NetworkUser)),
|
||||
Name: "Network Users",
|
||||
MetaData: "Can connect to nodes in your networks via Remote Access Client.",
|
||||
MetaData: "Can connect to nodes in your networks via Netmaker Desktop App.",
|
||||
Default: true,
|
||||
FullAccess: false,
|
||||
NetworkID: models.AllNetworks,
|
||||
|
@ -131,7 +131,7 @@ func UserGroupsInit() {
|
|||
models.UserRoleID(fmt.Sprintf("global-%s", models.NetworkUser)): {},
|
||||
},
|
||||
},
|
||||
MetaData: "Provides read-only dashboard access to platform users and allows connection to network nodes via the Remote Access Client.",
|
||||
MetaData: "Provides read-only dashboard access to platform users and allows connection to network nodes via the Netmaker Desktop App.",
|
||||
}
|
||||
d, _ := json.Marshal(NetworkGlobalAdminGroup)
|
||||
database.Insert(NetworkGlobalAdminGroup.ID.String(), string(d), database.USER_GROUPS_TABLE_NAME)
|
||||
|
@ -156,7 +156,7 @@ func CreateDefaultNetworkRolesAndGroups(netID models.NetworkID) {
|
|||
var NetworkUserPermissionTemplate = models.UserRolePermissionTemplate{
|
||||
ID: models.UserRoleID(fmt.Sprintf("%s-%s", netID, models.NetworkUser)),
|
||||
Name: fmt.Sprintf("%s User", netID),
|
||||
MetaData: fmt.Sprintf("Can connect to nodes in your network `%s` via Remote Access Client.", netID),
|
||||
MetaData: fmt.Sprintf("Can connect to nodes in your network `%s` via Netmaker Desktop App.", netID),
|
||||
Default: true,
|
||||
FullAccess: false,
|
||||
NetworkID: netID,
|
||||
|
@ -235,7 +235,7 @@ func CreateDefaultNetworkRolesAndGroups(netID models.NetworkID) {
|
|||
models.UserRoleID(fmt.Sprintf("%s-%s", netID, models.NetworkUser)): {},
|
||||
},
|
||||
},
|
||||
MetaData: fmt.Sprintf("Can connect to nodes in your network `%s` via Remote Access Client. Platform users will have read-only access to the the dashboard.", netID),
|
||||
MetaData: fmt.Sprintf("Can connect to nodes in your network `%s` via Netmaker Desktop App. Platform users will have read-only access to the the dashboard.", netID),
|
||||
}
|
||||
d, _ = json.Marshal(NetworkAdminGroup)
|
||||
database.Insert(NetworkAdminGroup.ID.String(), string(d), database.USER_GROUPS_TABLE_NAME)
|
||||
|
@ -810,87 +810,7 @@ func GetUserNetworkRolesWithRemoteVPNAccess(user models.User) (gwAccess map[mode
|
|||
}
|
||||
|
||||
func GetFilteredNodesByUserAccess(user models.User, nodes []models.Node) (filteredNodes []models.Node) {
|
||||
|
||||
nodesMap := make(map[string]struct{})
|
||||
allNetworkRoles := make(map[models.UserRoleID]struct{})
|
||||
defer func() {
|
||||
filteredNodes = logic.AddStaticNodestoList(filteredNodes)
|
||||
}()
|
||||
if len(user.NetworkRoles) > 0 {
|
||||
for _, netRoles := range user.NetworkRoles {
|
||||
for netRoleI := range netRoles {
|
||||
allNetworkRoles[netRoleI] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, ok := user.NetworkRoles[models.AllNetworks]; ok {
|
||||
filteredNodes = nodes
|
||||
return
|
||||
}
|
||||
if len(user.UserGroups) > 0 {
|
||||
for userGID := range user.UserGroups {
|
||||
userG, err := GetUserGroup(userGID)
|
||||
if err == nil {
|
||||
if len(userG.NetworkRoles) > 0 {
|
||||
if _, ok := userG.NetworkRoles[models.AllNetworks]; ok {
|
||||
filteredNodes = nodes
|
||||
return
|
||||
}
|
||||
for _, netRoles := range userG.NetworkRoles {
|
||||
for netRoleI := range netRoles {
|
||||
allNetworkRoles[netRoleI] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for networkRoleID := range allNetworkRoles {
|
||||
userPermTemplate, err := logic.GetRole(networkRoleID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
networkNodes := logic.GetNetworkNodesMemory(nodes, userPermTemplate.NetworkID.String())
|
||||
if userPermTemplate.FullAccess {
|
||||
for _, node := range networkNodes {
|
||||
if _, ok := nodesMap[node.ID.String()]; ok {
|
||||
continue
|
||||
}
|
||||
nodesMap[node.ID.String()] = struct{}{}
|
||||
filteredNodes = append(filteredNodes, node)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
if rsrcPerms, ok := userPermTemplate.NetworkLevelAccess[models.RemoteAccessGwRsrc]; ok {
|
||||
if _, ok := rsrcPerms[models.AllRemoteAccessGwRsrcID]; ok {
|
||||
for _, node := range networkNodes {
|
||||
if _, ok := nodesMap[node.ID.String()]; ok {
|
||||
continue
|
||||
}
|
||||
if node.IsIngressGateway {
|
||||
nodesMap[node.ID.String()] = struct{}{}
|
||||
filteredNodes = append(filteredNodes, node)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for gwID, scope := range rsrcPerms {
|
||||
if _, ok := nodesMap[gwID.String()]; ok {
|
||||
continue
|
||||
}
|
||||
if scope.Read {
|
||||
gwNode, err := logic.GetNodeByID(gwID.String())
|
||||
if err == nil && gwNode.IsIngressGateway {
|
||||
nodesMap[gwNode.ID.String()] = struct{}{}
|
||||
filteredNodes = append(filteredNodes, gwNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
return filteredNodes
|
||||
}
|
||||
|
||||
func FilterNetworksByRole(allnetworks []models.Network, user models.User) []models.Network {
|
||||
|
@ -1211,7 +1131,7 @@ func CreateDefaultUserPolicies(netID models.NetworkID) {
|
|||
defaultUserAcl := models.Acl{
|
||||
ID: fmt.Sprintf("%s.%s-grp", netID, models.NetworkAdmin),
|
||||
Name: "Network Admin",
|
||||
MetaData: "This Policy allows all network admins to communicate with all remote access gateways",
|
||||
MetaData: "This Policy allows all network admins to communicate with all gateways",
|
||||
Default: true,
|
||||
ServiceType: models.Any,
|
||||
NetworkID: netID,
|
||||
|
@ -1244,7 +1164,7 @@ func CreateDefaultUserPolicies(netID models.NetworkID) {
|
|||
defaultUserAcl := models.Acl{
|
||||
ID: fmt.Sprintf("%s.%s-grp", netID, models.NetworkUser),
|
||||
Name: "Network User",
|
||||
MetaData: "This Policy allows all network users to communicate with all remote access gateways",
|
||||
MetaData: "This Policy allows all network users to communicate with all gateways",
|
||||
Default: true,
|
||||
ServiceType: models.Any,
|
||||
NetworkID: netID,
|
||||
|
|
Loading…
Add table
Reference in a new issue