NET-1932: sort out acls into CE and PRO (#3460)

* move relevant acl and tag code to CE and Pro pkgs

* intialise pro acl funcs

* list gateways by user access

* check user gw access by policies

* filter out user policies on CE

* filter out tagged policies on CE

* fix ce acl comms

* allow gateways tag

* allow gateway tag  on CE, remove failover and gw check on acl policy

* add gw rules func to pro

* add inet gw support on CE

* add egress acl API

* add egress acl API

* fix(go): set is_gw when converting api node to server node;

* fix(go): set is_gw when converting api node to server node;

* fix policy validity checker for inet gws

* move dns option to host model

* fix node removal from egress policy on delete

* add migration logic for ManageDNS

* fix dns json field

* fix nil error on node tags

* add egress info to relayed nodes

---------

Co-authored-by: Vishal Dalwadi <dalwadivishal26@gmail.com>
This commit is contained in:
Abhishek K
2025-06-02 13:05:10 +05:30
committed by GitHub
parent f0affca56b
commit 5849e0e2e1
29 changed files with 3467 additions and 2675 deletions

View File

@@ -9,15 +9,19 @@ import (
"github.com/google/uuid"
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/db"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mq"
"github.com/gravitl/netmaker/schema"
)
func aclHandlers(r *mux.Router) {
r.HandleFunc("/api/v1/acls", logic.SecurityCheck(true, http.HandlerFunc(getAcls))).
Methods(http.MethodGet)
r.HandleFunc("/api/v1/acls/egress", logic.SecurityCheck(true, http.HandlerFunc(getEgressAcls))).
Methods(http.MethodGet)
r.HandleFunc("/api/v1/acls/policy_types", logic.SecurityCheck(true, http.HandlerFunc(aclPolicyTypes))).
Methods(http.MethodGet)
r.HandleFunc("/api/v1/acls", logic.SecurityCheck(true, http.HandlerFunc(createAcl))).
@@ -174,7 +178,7 @@ func aclDebug(w http.ResponseWriter, r *http.Request) {
NodeAllPolicy bool
}
allowed, ps := logic.IsNodeAllowedToCommunicateV1(node, peer, true)
allowed, ps := logic.IsNodeAllowedToCommunicate(node, peer, true)
isallowed := logic.IsPeerAllowed(node, peer, true)
re := resp{
IsNodeAllowed: allowed,
@@ -218,6 +222,35 @@ func getAcls(w http.ResponseWriter, r *http.Request) {
logic.ReturnSuccessResponseWithJson(w, r, acls, "fetched all acls in the network "+netID)
}
// @Summary List Egress Acls in a network
// @Router /api/v1/acls [get]
// @Tags ACL
// @Accept json
// @Success 200 {array} models.SuccessResponse
// @Failure 500 {object} models.ErrorResponse
func getEgressAcls(w http.ResponseWriter, r *http.Request) {
eID := r.URL.Query().Get("egress_id")
if eID == "" {
logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("egress id param is missing"), "badrequest"))
return
}
e := schema.Egress{ID: eID}
// check if network exists
err := e.Get(db.WithContext(r.Context()))
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
acls, err := logic.ListEgressAcls(eID)
if err != nil {
logger.Log(0, r.Header.Get("user"), "failed to get all network acl entries: ", err.Error())
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
logic.SortAclEntrys(acls[:])
logic.ReturnSuccessResponseWithJson(w, r, acls, "fetched acls for egress"+e.Name)
}
// @Summary Create Acl
// @Router /api/v1/acls [post]
// @Tags ACL

View File

@@ -3,13 +3,14 @@ package controller
import (
"context"
"fmt"
"github.com/gravitl/netmaker/db"
"net/http"
"os"
"strings"
"sync"
"time"
"github.com/gravitl/netmaker/db"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/logger"
@@ -37,7 +38,6 @@ var HttpHandlers = []interface{}{
loggerHandlers,
hostHandlers,
enrollmentKeyHandlers,
tagHandlers,
aclHandlers,
egressHandlers,
legacyHandlers,

View File

@@ -65,7 +65,6 @@ func TestGetNodeDNS(t *testing.T) {
ID: uuid.New(),
Network: "skynet",
Address: *ipnet,
DNSOn: true,
}
createnode := models.Node{
CommonNode: tmpCNode,
@@ -82,7 +81,6 @@ func TestGetNodeDNS(t *testing.T) {
ID: uuid.New(),
Network: "skynet",
Address: *ipnet,
DNSOn: true,
}
createnode := models.Node{
CommonNode: tmpCNode,

View File

@@ -109,6 +109,8 @@ func createGateway(w http.ResponseWriter, r *http.Request) {
},
Origin: models.Dashboard,
})
host.IsStaticPort = true
logic.UpsertHost(host)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(apiNode)
go func() {

View File

@@ -207,7 +207,6 @@ func convertLegacyNode(legacy models.LegacyNode, hostID uuid.UUID) models.Node {
node.IsRelayed = false
node.IsRelay = false
node.RelayedNodes = []string{}
node.DNSOn = models.ParseBool(legacy.DNSOn)
node.LastModified = time.Now().UTC()
node.ExpirationDateTime = time.Unix(legacy.ExpirationDateTime, 0)
node.EgressGatewayNatEnabled = models.ParseBool(legacy.EgressGatewayNatEnabled)

View File

@@ -143,7 +143,6 @@ func createNodeWithParams(network, address string) *models.Node {
ID: uuid.New(),
Network: "skynet",
Address: *ipnet,
DNSOn: true,
}
if len(network) > 0 {
tmpCNode.Network = network

File diff suppressed because it is too large Load Diff

View File

@@ -63,93 +63,6 @@ func ValidateEgressReq(e *schema.Egress) error {
return nil
}
func GetInetClientsFromAclPolicies(eID string) (inetClientIDs []string) {
e := schema.Egress{ID: eID}
err := e.Get(db.WithContext(context.TODO()))
if err != nil || !e.Status {
return
}
acls, _ := ListAclsByNetwork(models.NetworkID(e.Network))
for _, acl := range acls {
for _, dstI := range acl.Dst {
if dstI.ID == models.EgressID {
if dstI.Value != eID {
continue
}
for _, srcI := range acl.Src {
if srcI.Value == "*" {
continue
}
if srcI.ID == models.NodeID {
inetClientIDs = append(inetClientIDs, srcI.Value)
}
if srcI.ID == models.NodeTagID {
inetClientIDs = append(inetClientIDs, GetNodeIDsWithTag(models.TagID(srcI.Value))...)
}
}
}
}
}
return
}
func isNodeUsingInternetGw(node *models.Node) {
host, err := GetHost(node.HostID.String())
if err != nil {
return
}
if host.IsDefault || node.IsFailOver {
return
}
nodeTags := maps.Clone(node.Tags)
nodeTags[models.TagID(node.ID.String())] = struct{}{}
acls, _ := ListAclsByNetwork(models.NetworkID(node.Network))
var isUsing bool
for _, acl := range acls {
if !acl.Enabled {
continue
}
srcVal := convAclTagToValueMap(acl.Src)
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 || !e.Status {
continue
}
if e.IsInetGw {
if _, ok := srcVal[node.ID.String()]; ok {
for nodeID := range e.Nodes {
if nodeID == node.ID.String() {
continue
}
node.EgressDetails.InternetGwID = nodeID
isUsing = true
return
}
}
for tagID := range nodeTags {
if _, ok := srcVal[tagID.String()]; ok {
for nodeID := range e.Nodes {
if nodeID == node.ID.String() {
continue
}
node.EgressDetails.InternetGwID = nodeID
isUsing = true
return
}
}
}
}
}
}
}
if !isUsing {
node.EgressDetails.InternetGwID = ""
}
}
func DoesNodeHaveAccessToEgress(node *models.Node, e *schema.Egress) bool {
nodeTags := maps.Clone(node.Tags)
nodeTags[models.TagID(node.ID.String())] = struct{}{}
@@ -167,7 +80,7 @@ func DoesNodeHaveAccessToEgress(node *models.Node, e *schema.Egress) bool {
if !acl.Enabled {
continue
}
srcVal := convAclTagToValueMap(acl.Src)
srcVal := ConvAclTagToValueMap(acl.Src)
if !e.IsInetGw && acl.AllowedDirection == models.TrafficDirectionBi {
if _, ok := srcVal["*"]; ok {
return true
@@ -216,7 +129,7 @@ func AddEgressInfoToPeerByAccess(node, targetNode *models.Node) {
if targetNode.Mutex != nil {
targetNode.Mutex.Lock()
}
isNodeUsingInternetGw(targetNode)
IsNodeUsingInternetGw(targetNode)
if targetNode.Mutex != nil {
targetNode.Mutex.Unlock()
}
@@ -296,7 +209,7 @@ func GetNodeEgressInfo(targetNode *models.Node) {
if targetNode.Mutex != nil {
targetNode.Mutex.Lock()
}
isNodeUsingInternetGw(targetNode)
IsNodeUsingInternetGw(targetNode)
if targetNode.Mutex != nil {
targetNode.Mutex.Unlock()
}
@@ -355,7 +268,9 @@ func GetNodeEgressInfo(targetNode *models.Node) {
}
func RemoveNodeFromEgress(node models.Node) {
egs, _ := (&schema.Egress{}).ListByNetwork(db.WithContext(context.TODO()))
egs, _ := (&schema.Egress{
Network: node.Network,
}).ListByNetwork(db.WithContext(context.TODO()))
for _, egI := range egs {
if _, ok := egI.Nodes[node.ID.String()]; ok {
delete(egI.Nodes, node.ID.String())
@@ -364,3 +279,36 @@ func RemoveNodeFromEgress(node models.Node) {
}
}
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.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{}{}
}
}
}
}
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
}

View File

@@ -1,7 +1,6 @@
package logic
import (
"context"
"encoding/json"
"errors"
"fmt"
@@ -14,11 +13,9 @@ import (
"github.com/goombaio/namegenerator"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/db"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/logic/acls"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/schema"
"github.com/gravitl/netmaker/servercfg"
"golang.org/x/exp/slog"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
@@ -84,7 +81,6 @@ func GetEgressRangesOnNetwork(client *models.ExtClient) ([]string, error) {
continue
}
if currentNode.EgressDetails.IsEgressGateway { // add the egress gateway range(s) to the result
fmt.Println("EGRESSS EXTCLEINT: ", currentNode.EgressDetails)
if len(currentNode.EgressDetails.EgressGatewayRanges) > 0 {
result = append(result, currentNode.EgressDetails.EgressGatewayRanges...)
}
@@ -98,7 +94,30 @@ func GetEgressRangesOnNetwork(client *models.ExtClient) ([]string, error) {
result = append(result, extclient.ExtraAllowedIPs...)
}
return result, nil
return UniqueIPNetStrList(result), nil
}
// UniqueIPNetList deduplicates and sorts a list of CIDR strings.
func UniqueIPNetStrList(ipnets []string) []string {
uniqueMap := make(map[string]struct{})
for _, cidr := range ipnets {
_, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
continue // skip invalid CIDR strings
}
key := ipnet.String() // normalized CIDR
uniqueMap[key] = struct{}{}
}
// Convert map keys to slice
uniqueList := make([]string, 0, len(uniqueMap))
for cidr := range uniqueMap {
uniqueList = append(uniqueList, cidr)
}
sort.Strings(uniqueList)
return uniqueList
}
// DeleteExtClient - deletes an existing ext client
@@ -493,362 +512,6 @@ func ToggleExtClientConnectivity(client *models.ExtClient, enable bool) (models.
return newClient, nil
}
// Sort a slice of net.IP addresses
func sortIPs(ips []net.IP) {
sort.Slice(ips, func(i, j int) bool {
ip1, ip2 := ips[i].To16(), ips[j].To16()
return string(ip1) < string(ip2) // Compare as byte slices
})
}
func GetStaticNodeIps(node models.Node) (ips []net.IP) {
defer func() {
sortIPs(ips)
}()
defaultUserPolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy)
defaultDevicePolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
extclients := GetStaticNodesByNetwork(models.NetworkID(node.Network), false)
for _, extclient := range extclients {
if extclient.IsUserNode && defaultUserPolicy.Enabled {
continue
}
if !extclient.IsUserNode && defaultDevicePolicy.Enabled {
continue
}
if extclient.StaticNode.Address != "" {
ips = append(ips, extclient.StaticNode.AddressIPNet4().IP)
}
if extclient.StaticNode.Address6 != "" {
ips = append(ips, extclient.StaticNode.AddressIPNet6().IP)
}
}
return
}
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
}
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,
})
}
}
}
}
}
}
return
}
func getFwRulesForUserNodesOnGw(node models.Node, nodes []models.Node) (rules []models.FwRule) {
defaultUserPolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy)
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 {
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.EgressID {
e := schema.Egress{ID: dstI.Value}
err := e.Get(db.WithContext(context.TODO()))
if err != nil {
continue
}
dstI.Value = e.Range
ip, cidr, err := net.ParseCIDR(dstI.Value)
if err == nil {
if ip.To4() != nil && 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 GetFwRulesOnIngressGateway(node models.Node) (rules []models.FwRule) {
// fetch user access to static clients via policies
defer func() {
sort.Slice(rules, func(i, j int) bool {
if !rules[i].SrcIP.IP.Equal(rules[j].SrcIP.IP) {
return string(rules[i].SrcIP.IP.To16()) < string(rules[j].SrcIP.IP.To16())
}
return string(rules[i].DstIP.IP.To16()) < string(rules[j].DstIP.IP.To16())
})
}()
defaultDevicePolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
nodes, _ := GetNetworkNodes(node.Network)
nodes = append(nodes, GetStaticNodesByNetwork(models.NetworkID(node.Network), true)...)
rules = getFwRulesForUserNodesOnGw(node, nodes)
if defaultDevicePolicy.Enabled {
return
}
for _, nodeI := range nodes {
if !nodeI.IsStatic || nodeI.IsUserNode {
continue
}
// if nodeI.StaticNode.IngressGatewayID != node.ID.String() {
// continue
// }
for _, peer := range nodes {
if peer.StaticNode.ClientID == nodeI.StaticNode.ClientID || peer.IsUserNode {
continue
}
if nodeI.StaticNode.IngressGatewayID != node.ID.String() &&
((!peer.IsStatic && peer.ID.String() != node.ID.String()) ||
(peer.IsStatic && peer.StaticNode.IngressGatewayID != node.ID.String())) {
continue
}
if peer.IsStatic {
peer = peer.StaticNode.ConvertToStaticNode()
}
var allowedPolicies1 []models.Acl
var ok bool
if ok, allowedPolicies1 = IsNodeAllowedToCommunicateV1(nodeI.StaticNode.ConvertToStaticNode(), peer, true); ok {
rules = append(rules, getFwRulesForNodeAndPeerOnGw(nodeI.StaticNode.ConvertToStaticNode(), peer, allowedPolicies1)...)
}
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
@@ -964,7 +627,7 @@ func getExtpeerEgressRanges(node models.Node) (ranges, ranges6 []net.IPNet) {
if len(extPeer.ExtraAllowedIPs) == 0 {
continue
}
if ok, _ := IsNodeAllowedToCommunicateV1(extPeer.ConvertToStaticNode(), node, true); !ok {
if ok, _ := IsNodeAllowedToCommunicate(extPeer.ConvertToStaticNode(), node, true); !ok {
continue
}
for _, allowedRange := range extPeer.ExtraAllowedIPs {
@@ -991,7 +654,7 @@ func getExtpeersExtraRoutes(node models.Node) (egressRoutes []models.EgressNetwo
if len(extPeer.ExtraAllowedIPs) == 0 {
continue
}
if ok, _ := IsNodeAllowedToCommunicateV1(extPeer.ConvertToStaticNode(), node, true); !ok {
if ok, _ := IsNodeAllowedToCommunicate(extPeer.ConvertToStaticNode(), node, true); !ok {
continue
}
egressRoutes = append(egressRoutes, getExtPeerEgressRoute(node, extPeer)...)

View File

@@ -229,6 +229,12 @@ func CreateHost(h *models.Host) error {
}
h.HostPass = string(hash)
h.AutoUpdate = AutoUpdateEnabled()
if GetServerSettings().ManageDNS {
h.DNS = "on"
} else {
h.DNS = "off"
}
checkForZombieHosts(h)
return UpsertHost(h)
}

View File

@@ -30,6 +30,8 @@ var (
nodeNetworkCacheMutex = &sync.RWMutex{}
nodesCacheMap = make(map[string]models.Node)
nodesNetworkCacheMap = make(map[string]map[string]models.Node)
IPv4Network = "0.0.0.0/0"
IPv6Network = "::/0"
)
func getNodeFromCache(nodeID string) (node models.Node, ok bool) {
@@ -641,14 +643,6 @@ func createNode(node *models.Node) error {
return err
}
if !node.DNSOn {
if servercfg.IsDNSMode() {
node.DNSOn = true
} else {
node.DNSOn = false
}
}
SetNodeDefaults(node, true)
defaultACLVal := acls.Allowed
@@ -833,206 +827,156 @@ func GetAllFailOvers() ([]models.Node, error) {
return igs, nil
}
func GetTagMapWithNodes() (tagNodesMap map[models.TagID][]models.Node) {
tagNodesMap = make(map[models.TagID][]models.Node)
nodes, _ := GetAllNodes()
for _, nodeI := range nodes {
if nodeI.Tags == nil {
continue
}
if nodeI.Mutex != nil {
nodeI.Mutex.Lock()
}
for nodeTagID := range nodeI.Tags {
tagNodesMap[nodeTagID] = append(tagNodesMap[nodeTagID], nodeI)
}
if nodeI.Mutex != nil {
nodeI.Mutex.Unlock()
}
func ValidateInetGwReq(inetNode models.Node, req models.InetNodeReq, update bool) error {
inetHost, err := GetHost(inetNode.HostID.String())
if err != nil {
return err
}
if inetHost.FirewallInUse == models.FIREWALL_NONE {
return errors.New("iptables or nftables needs to be installed")
}
if inetNode.EgressDetails.InternetGwID != "" {
return fmt.Errorf("node %s is using a internet gateway already", inetHost.Name)
}
if inetNode.IsRelayed {
return fmt.Errorf("node %s is being relayed", inetHost.Name)
}
return
}
func GetTagMapWithNodesByNetwork(netID models.NetworkID, withStaticNodes bool) (tagNodesMap map[models.TagID][]models.Node) {
tagNodesMap = make(map[models.TagID][]models.Node)
nodes, _ := GetNetworkNodes(netID.String())
for _, nodeI := range nodes {
tagNodesMap[models.TagID(nodeI.ID.String())] = []models.Node{
nodeI,
for _, clientNodeID := range req.InetNodeClientIDs {
clientNode, err := GetNodeByID(clientNodeID)
if err != nil {
return err
}
if nodeI.Tags == nil {
continue
if clientNode.IsFailOver {
return errors.New("failover node cannot be set to use internet gateway")
}
if nodeI.Mutex != nil {
nodeI.Mutex.Lock()
clientHost, err := GetHost(clientNode.HostID.String())
if err != nil {
return err
}
for nodeTagID := range nodeI.Tags {
if nodeTagID == models.TagID(nodeI.ID.String()) {
if clientHost.IsDefault {
return errors.New("default host cannot be set to use internet gateway")
}
if clientHost.OS != models.OS_Types.Linux && clientHost.OS != models.OS_Types.Windows {
return errors.New("can only attach linux or windows machine to a internet gateway")
}
if clientNode.EgressDetails.IsInternetGateway {
return fmt.Errorf("node %s acting as internet gateway cannot use another internet gateway", clientHost.Name)
}
if update {
if clientNode.EgressDetails.InternetGwID != "" && clientNode.EgressDetails.InternetGwID != inetNode.ID.String() {
return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name)
}
} else {
if clientNode.EgressDetails.InternetGwID != "" {
return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name)
}
}
if clientNode.FailedOverBy != uuid.Nil {
ResetFailedOverPeer(&clientNode)
}
if clientNode.IsRelayed && clientNode.RelayedBy != inetNode.ID.String() {
return fmt.Errorf("node %s is being relayed", clientHost.Name)
}
for _, nodeID := range clientHost.Nodes {
node, err := GetNodeByID(nodeID)
if err != nil {
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 := 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
if node.EgressDetails.InternetGwID != "" && node.EgressDetails.InternetGwID != inetNode.ID.String() {
return errors.New("nodes on same host cannot use different internet gateway")
}
tagNodesMap[tagID] = append(tagNodesMap[tagID], extclient.ConvertToStaticNode())
tagNodesMap["*"] = append(tagNodesMap["*"], extclient.ConvertToStaticNode())
}
if extclient.Mutex != nil {
extclient.Mutex.Unlock()
}
}
return tagNodesMap
return nil
}
func AddTagMapWithStaticNodesWithUsers(netID models.NetworkID,
tagNodesMap map[models.TagID][]models.Node) map[models.TagID][]models.Node {
extclients, err := GetNetworkExtClients(netID.String())
if err != nil {
return tagNodesMap
}
for _, extclient := range extclients {
tagNodesMap[models.TagID(extclient.ClientID)] = []models.Node{
{
IsStatic: true,
StaticNode: extclient,
},
}
if extclient.Tags == nil {
// SetInternetGw - sets the node as internet gw based on flag bool
func SetInternetGw(node *models.Node, req models.InetNodeReq) {
node.EgressDetails.IsInternetGateway = true
node.EgressDetails.InetNodeReq = req
for _, clientNodeID := range req.InetNodeClientIDs {
clientNode, err := GetNodeByID(clientNodeID)
if err != nil {
continue
}
if extclient.Mutex != nil {
extclient.Mutex.Lock()
}
for tagID := range extclient.Tags {
tagNodesMap[tagID] = append(tagNodesMap[tagID], extclient.ConvertToStaticNode())
}
if extclient.Mutex != nil {
extclient.Mutex.Unlock()
}
clientNode.EgressDetails.InternetGwID = node.ID.String()
UpsertNode(&clientNode)
}
return tagNodesMap
}
func GetNodeIDsWithTag(tagID models.TagID) (ids []string) {
tag, err := GetTag(tagID)
func UnsetInternetGw(node *models.Node) {
nodes, err := GetNetworkNodes(node.Network)
if err != nil {
slog.Error("failed to get network nodes", "network", node.Network, "error", err)
return
}
nodes, _ := GetNetworkNodes(tag.Network.String())
for _, nodeI := range nodes {
if nodeI.Tags == nil {
continue
}
if nodeI.Mutex != nil {
nodeI.Mutex.Lock()
}
if _, ok := nodeI.Tags[tagID]; ok {
ids = append(ids, nodeI.ID.String())
}
if nodeI.Mutex != nil {
nodeI.Mutex.Unlock()
for _, clientNode := range nodes {
if node.ID.String() == clientNode.EgressDetails.InternetGwID {
clientNode.EgressDetails.InternetGwID = ""
UpsertNode(&clientNode)
}
}
return
node.EgressDetails.IsInternetGateway = false
node.EgressDetails.InetNodeReq = models.InetNodeReq{}
}
func GetNodesWithTag(tagID models.TagID) map[string]models.Node {
nMap := make(map[string]models.Node)
tag, err := GetTag(tagID)
if err != nil {
return nMap
func SetDefaultGwForRelayedUpdate(relayed, relay models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
if relay.EgressDetails.InternetGwID != "" {
relayedHost, err := GetHost(relayed.HostID.String())
if err != nil {
return peerUpdate
}
peerUpdate.ChangeDefaultGw = true
peerUpdate.DefaultGwIp = relay.Address.IP
if peerUpdate.DefaultGwIp == nil || relayedHost.EndpointIP == nil {
peerUpdate.DefaultGwIp = relay.Address6.IP
}
}
nodes, _ := GetNetworkNodes(tag.Network.String())
for _, nodeI := range nodes {
if nodeI.Tags == nil {
continue
}
if nodeI.Mutex != nil {
nodeI.Mutex.Lock()
}
if _, ok := nodeI.Tags[tagID]; ok {
nMap[nodeI.ID.String()] = nodeI
}
if nodeI.Mutex != nil {
nodeI.Mutex.Unlock()
}
}
return AddStaticNodesWithTag(tag, nMap)
return peerUpdate
}
func AddStaticNodesWithTag(tag models.Tag, nMap map[string]models.Node) map[string]models.Node {
extclients, err := GetNetworkExtClients(tag.Network.String())
if err != nil {
return nMap
}
for _, extclient := range extclients {
if extclient.RemoteAccessClientID != "" {
continue
func SetDefaultGw(node models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
if node.EgressDetails.InternetGwID != "" {
inetNode, err := GetNodeByID(node.EgressDetails.InternetGwID)
if err != nil {
return peerUpdate
}
if extclient.Mutex != nil {
extclient.Mutex.Lock()
host, err := GetHost(node.HostID.String())
if err != nil {
return peerUpdate
}
if _, ok := extclient.Tags[tag.ID]; ok {
nMap[extclient.ClientID] = extclient.ConvertToStaticNode()
}
if extclient.Mutex != nil {
extclient.Mutex.Unlock()
peerUpdate.ChangeDefaultGw = true
peerUpdate.DefaultGwIp = inetNode.Address.IP
if peerUpdate.DefaultGwIp == nil || host.EndpointIP == nil {
peerUpdate.DefaultGwIp = inetNode.Address6.IP
}
}
return nMap
return peerUpdate
}
func GetStaticNodeWithTag(tagID models.TagID) map[string]models.Node {
nMap := make(map[string]models.Node)
tag, err := GetTag(tagID)
if err != nil {
return nMap
// GetAllowedIpForInetNodeClient - get inet cidr for node using a inet gw
func GetAllowedIpForInetNodeClient(node, peer *models.Node) []net.IPNet {
var allowedips = []net.IPNet{}
if peer.Address.IP != nil {
_, ipnet, _ := net.ParseCIDR(IPv4Network)
allowedips = append(allowedips, *ipnet)
}
extclients, err := GetNetworkExtClients(tag.Network.String())
if err != nil {
return nMap
if peer.Address6.IP != nil {
_, ipnet, _ := net.ParseCIDR(IPv6Network)
allowedips = append(allowedips, *ipnet)
}
for _, extclient := range extclients {
nMap[extclient.ClientID] = extclient.ConvertToStaticNode()
}
return nMap
return allowedips
}

View File

@@ -39,29 +39,6 @@ var (
CreateFailOver = func(node models.Node) error {
return nil
}
// SetDefaulGw
SetDefaultGw = func(node models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
return peerUpdate
}
SetDefaultGwForRelayedUpdate = func(relayed, relay models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
return peerUpdate
}
// UnsetInternetGw
UnsetInternetGw = func(node *models.Node) {
node.EgressDetails.IsInternetGateway = false
}
// SetInternetGw
SetInternetGw = func(node *models.Node, req models.InetNodeReq) {
node.EgressDetails.IsInternetGateway = true
}
// GetAllowedIpForInetNodeClient
GetAllowedIpForInetNodeClient = func(node, peer *models.Node) []net.IPNet {
return []net.IPNet{}
}
ValidateInetGwReq = func(inetNode models.Node, req models.InetNodeReq, update bool) error {
return nil
}
)
// GetHostPeerInfo - fetches required peer info per network
@@ -111,7 +88,7 @@ func GetHostPeerInfo(host *models.Host) (models.HostPeerInfo, error) {
!peer.PendingDelete &&
peer.Connected &&
nodeacls.AreNodesAllowed(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), nodeacls.NodeID(peer.ID.String())) &&
(defaultDevicePolicy.Enabled || allowedToComm) {
(allowedToComm) {
networkPeersInfo[peerHost.PublicKey.String()] = models.IDandAddr{
ID: peer.ID.String(),
@@ -164,6 +141,9 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
HostNetworkInfo: models.HostInfoMap{},
ServerConfig: GetServerInfo(),
}
if host.DNS == "off" {
hostPeerUpdate.ManageDNS = false
}
defer func() {
if !hostPeerUpdate.FwUpdate.AllowAll {
@@ -203,10 +183,12 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
}
defaultUserPolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.UserPolicy)
defaultDevicePolicy, _ := GetDefaultPolicy(models.NetworkID(node.Network), models.DevicePolicy)
anyActiveEgressPolicy := CheckIfAnyActiveEgressPolicy(node)
nodeHasAccessToAllRsrcs := CheckIfNodeHasAccessToAllResources(&node)
anyUniDirectionPolicy := CheckIfAnyPolicyisUniDirectional(node)
if (defaultDevicePolicy.Enabled && defaultUserPolicy.Enabled) ||
(!checkIfAnyPolicyisUniDirectional(node) && !checkIfAnyActiveEgressPolicy(node)) ||
checkIfNodeHasAccessToAllResources(&node) {
(!anyUniDirectionPolicy && !anyActiveEgressPolicy) ||
nodeHasAccessToAllRsrcs {
aclRule := models.AclRule{
ID: fmt.Sprintf("%s-allowed-network-rules", node.ID.String()),
AllowedProtocol: models.ALL,
@@ -371,8 +353,8 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
!peer.PendingDelete &&
peer.Connected &&
nodeacls.AreNodesAllowed(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID.String()), nodeacls.NodeID(peer.ID.String())) &&
(defaultDevicePolicy.Enabled || allowedToComm) &&
(deletedNode == nil || (deletedNode != nil && peer.ID.String() != deletedNode.ID.String())) {
(allowedToComm) &&
(deletedNode == nil || (peer.ID.String() != deletedNode.ID.String())) {
peerConfig.AllowedIPs = GetAllowedIPs(&node, &peer, nil) // only append allowed IPs if valid connection
}

View File

@@ -222,6 +222,10 @@ func GetAllowedIpsForRelayed(relayed, relay *models.Node) (allowedIPs []net.IPNe
if peer.ID == relayed.ID || peer.ID == relay.ID {
continue
}
if !IsPeerAllowed(*relayed, peer, true) {
continue
}
GetNodeEgressInfo(&peer)
if nodeacls.AreNodesAllowed(nodeacls.NetworkID(relayed.Network), nodeacls.NodeID(relayed.ID.String()), nodeacls.NodeID(peer.ID.String())) {
allowedIPs = append(allowedIPs, GetAllowedIPs(relayed, &peer, nil)...)
}

View File

@@ -102,25 +102,6 @@ func ListPlatformRoles() ([]models.UserRolePermissionTemplate, error) {
return userRoles, nil
}
func GetUserGrpMap() map[models.UserGroupID]map[string]struct{} {
grpUsersMap := make(map[models.UserGroupID]map[string]struct{})
users, _ := GetUsersDB()
for _, user := range users {
for gID := range user.UserGroups {
if grpUsers, ok := grpUsersMap[gID]; ok {
grpUsers[user.UserName] = struct{}{}
grpUsersMap[gID] = grpUsers
} else {
grpUsersMap[gID] = make(map[string]struct{})
grpUsersMap[gID][user.UserName] = struct{}{}
}
}
}
return grpUsersMap
}
func userRolesInit() {
d, _ := json.Marshal(SuperAdminPermissionTemplate)
database.Insert(SuperAdminPermissionTemplate.ID.String(), string(d), database.USER_PERMISSIONS_TABLE_NAME)

View File

@@ -34,7 +34,7 @@ func Run() {
updateHosts()
updateNodes()
updateAcls()
migrateToGws()
logic.MigrateToGws()
migrateToEgressV1()
}
@@ -196,6 +196,13 @@ func updateHosts() {
continue
}
}
if host.DNS == "" {
if logic.GetServerSettings().ManageDNS {
host.DNS = "on"
} else {
host.DNS = "off"
}
}
}
}
@@ -465,51 +472,6 @@ func createDefaultTagsAndPolicies() {
logic.MigrateAclPolicies()
}
func migrateToGws() {
nodes, err := logic.GetAllNodes()
if err != nil {
return
}
for _, node := range nodes {
if node.IsIngressGateway || node.IsRelay {
node.IsGw = true
node.IsIngressGateway = true
node.IsRelay = true
if node.Tags == nil {
node.Tags = make(map[models.TagID]struct{})
}
node.Tags[models.TagID(fmt.Sprintf("%s.%s", node.Network, models.GwTagName))] = struct{}{}
delete(node.Tags, models.TagID(fmt.Sprintf("%s.%s", node.Network, models.OldRemoteAccessTagName)))
logic.UpsertNode(&node)
}
}
acls := logic.ListAcls()
for _, acl := range acls {
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 = 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 = fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.GwTagName)
acl.Dst[i] = dstI
upsert = true
}
}
if upsert {
logic.UpsertAcl(acl)
}
}
nets, _ := logic.GetNetworks()
for _, netI := range nets {
logic.DeleteTag(models.TagID(fmt.Sprintf("%s.%s", netI.NetID, models.OldRemoteAccessTagName)), true)
}
}
func migrateToEgressV1() {
nodes, _ := logic.GetAllNodes()
user, err := logic.GetSuperAdmin()

View File

@@ -31,6 +31,7 @@ type ApiHost struct {
NatType string `json:"nat_type" yaml:"nat_type"`
PersistentKeepalive int `json:"persistentkeepalive" yaml:"persistentkeepalive"`
AutoUpdate bool `json:"autoupdate" yaml:"autoupdate"`
DNS string `json:"dns" yaml:"dns"`
}
// ApiIface - the interface struct for API usage
@@ -78,6 +79,7 @@ func (h *Host) ConvertNMHostToAPI() *ApiHost {
a.NatType = h.NatType
a.PersistentKeepalive = int(h.PersistentKeepalive.Seconds())
a.AutoUpdate = h.AutoUpdate
a.DNS = h.DNS
return &a
}
@@ -123,5 +125,6 @@ func (a *ApiHost) ConvertAPIHostToNMHost(currentHost *Host) *Host {
h.TurnEndpoint = currentHost.TurnEndpoint
h.PersistentKeepalive = time.Duration(a.PersistentKeepalive) * time.Second
h.AutoUpdate = a.AutoUpdate
h.DNS = a.DNS
return &h
}

View File

@@ -32,6 +32,7 @@ type ApiNode struct {
NetworkRange6 string `json:"networkrange6"`
IsRelayed bool `json:"isrelayed"`
IsRelay bool `json:"isrelay"`
IsGw bool `json:"is_gw"`
RelayedBy string `json:"relayedby" bson:"relayedby" yaml:"relayedby"`
RelayedNodes []string `json:"relaynodes" yaml:"relayedNodes"`
IsEgressGateway bool `json:"isegressgateway"`
@@ -72,17 +73,16 @@ func (a *ApiNode) ConvertToServerNode(currentNode *Node) *Node {
convertedNode.Connected = a.Connected
convertedNode.ID, _ = uuid.Parse(a.ID)
convertedNode.HostID, _ = uuid.Parse(a.HostID)
convertedNode.IsRelay = a.IsRelay
//convertedNode.IsRelay = a.IsRelay
convertedNode.IsRelayed = a.IsRelayed
convertedNode.RelayedBy = a.RelayedBy
convertedNode.RelayedNodes = a.RelayedNodes
convertedNode.PendingDelete = a.PendingDelete
convertedNode.FailedOverBy = currentNode.FailedOverBy
convertedNode.FailOverPeers = currentNode.FailOverPeers
convertedNode.IsIngressGateway = a.IsIngressGateway
//convertedNode.IsIngressGateway = a.IsIngressGateway
convertedNode.IngressGatewayRange = currentNode.IngressGatewayRange
convertedNode.IngressGatewayRange6 = currentNode.IngressGatewayRange6
convertedNode.DNSOn = a.DNSOn
convertedNode.IngressDNS = a.IngressDns
convertedNode.IngressPersistentKeepalive = a.IngressPersistentKeepalive
convertedNode.IngressMTU = a.IngressMTU
@@ -132,6 +132,11 @@ func (a *ApiNode) ConvertToServerNode(currentNode *Node) *Node {
convertedNode.AdditionalRagIps = append(convertedNode.AdditionalRagIps, ragIp)
}
convertedNode.Tags = a.Tags
convertedNode.IsGw = a.IsGw
if convertedNode.IsGw {
convertedNode.IsRelay = true
convertedNode.IsIngressGateway = true
}
return &convertedNode
}
@@ -180,10 +185,10 @@ func (nm *Node) ConvertToAPINode() *ApiNode {
}
apiNode.IsRelayed = nm.IsRelayed
apiNode.IsRelay = nm.IsRelay
apiNode.IsGw = nm.IsGw
apiNode.RelayedBy = nm.RelayedBy
apiNode.RelayedNodes = nm.RelayedNodes
apiNode.IsIngressGateway = nm.IsIngressGateway
apiNode.DNSOn = nm.DNSOn
apiNode.IngressDns = nm.IngressDNS
apiNode.IngressPersistentKeepalive = nm.IngressPersistentKeepalive
apiNode.IngressMTU = nm.IngressMTU

View File

@@ -69,6 +69,7 @@ type Host struct {
IsStaticPort bool `json:"isstaticport" yaml:"isstaticport"`
IsStatic bool `json:"isstatic" yaml:"isstatic"`
IsDefault bool `json:"isdefault" yaml:"isdefault"`
DNS string `json:"dns_status" yaml:"dns_status"`
NatType string `json:"nat_type,omitempty" yaml:"nat_type,omitempty"`
TurnEndpoint *netip.AddrPort `json:"turn_endpoint,omitempty" yaml:"turn_endpoint,omitempty"`
PersistentKeepalive time.Duration `json:"persistentkeepalive" swaggertype:"primitive,integer" format:"int64" yaml:"persistentkeepalive"`

View File

@@ -87,7 +87,6 @@ type CommonNode struct {
IsGw bool `json:"is_gw" yaml:"is_gw"`
RelayedNodes []string `json:"relaynodes" yaml:"relayedNodes"`
IngressDNS string `json:"ingressdns" yaml:"ingressdns"`
DNSOn bool `json:"dnson" yaml:"dnson"`
}
// Node - a model of a network node
@@ -482,6 +481,12 @@ func (newNode *Node) Fill(
if newNode.IsFailOver != currentNode.IsFailOver {
newNode.IsFailOver = currentNode.IsFailOver
}
if newNode.Tags == nil {
if currentNode.Tags == nil {
currentNode.Tags = make(map[TagID]struct{})
}
newNode.Tags = currentNode.Tags
}
}
// StringWithCharset - returns random string inside defined charset
@@ -572,7 +577,6 @@ func (ln *LegacyNode) ConvertToNewNode() (*Host, *Node) {
}
node.Action = ln.Action
node.IsIngressGateway = parseBool(ln.IsIngressGateway)
node.DNSOn = parseBool(ln.DNSOn)
return &host, &node
}
@@ -613,7 +617,6 @@ func (n *Node) Legacy(h *Host, s *ServerConfig, net *Network) *LegacyNode {
//l.IngressGatewayRange6 = n.IngressGatewayRange6
l.IsStatic = formatBool(h.IsStatic)
l.UDPHolePunch = formatBool(true)
l.DNSOn = formatBool(n.DNSOn)
l.Action = n.Action
l.IPForwarding = formatBool(h.IPForwarding)
l.OS = h.OS

View File

@@ -70,12 +70,12 @@ func createInternetGw(w http.ResponseWriter, r *http.Request) {
)
return
}
err = proLogic.ValidateInetGwReq(node, request, false)
err = logic.ValidateInetGwReq(node, request, false)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
proLogic.SetInternetGw(&node, request)
logic.SetInternetGw(&node, request)
if servercfg.IsPro {
if _, exists := proLogic.FailOverExists(node.Network); exists {
go func() {
@@ -140,13 +140,13 @@ func updateInternetGw(w http.ResponseWriter, r *http.Request) {
)
return
}
err = proLogic.ValidateInetGwReq(node, request, true)
err = logic.ValidateInetGwReq(node, request, true)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
proLogic.UnsetInternetGw(&node)
proLogic.SetInternetGw(&node, request)
logic.UnsetInternetGw(&node)
logic.SetInternetGw(&node, request)
err = logic.UpsertNode(&node)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
@@ -185,7 +185,7 @@ func deleteInternetGw(w http.ResponseWriter, r *http.Request) {
return
}
proLogic.UnsetInternetGw(&node)
logic.UnsetInternetGw(&node)
err = logic.UpsertNode(&node)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))

View File

@@ -1,4 +1,4 @@
package controller
package controllers
import (
"encoding/json"
@@ -14,9 +14,10 @@ import (
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mq"
proLogic "github.com/gravitl/netmaker/pro/logic"
)
func tagHandlers(r *mux.Router) {
func TagHandlers(r *mux.Router) {
r.HandleFunc("/api/v1/tags", logic.SecurityCheck(true, http.HandlerFunc(getTags))).
Methods(http.MethodGet)
r.HandleFunc("/api/v1/tags", logic.SecurityCheck(true, http.HandlerFunc(createTag))).
@@ -46,13 +47,13 @@ func getTags(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
tags, err := logic.ListTagsWithNodes(models.NetworkID(netID))
tags, err := proLogic.ListTagsWithNodes(models.NetworkID(netID))
if err != nil {
logger.Log(0, r.Header.Get("user"), "failed to get all network tag entries: ", err.Error())
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
logic.SortTagEntrys(tags[:])
proLogic.SortTagEntrys(tags[:])
logic.ReturnSuccessResponseWithJson(w, r, tags, "fetched all tags in the network "+netID)
}
@@ -91,18 +92,18 @@ func createTag(w http.ResponseWriter, r *http.Request) {
ColorCode: req.ColorCode,
CreatedAt: time.Now().UTC(),
}
_, err = logic.GetTag(tag.ID)
_, err = proLogic.GetTag(tag.ID)
if err == nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("tag with id %s exists already", tag.TagName), "badrequest"))
return
}
// validate name
err = logic.CheckIDSyntax(tag.TagName)
err = proLogic.CheckIDSyntax(tag.TagName)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
err = logic.InsertTag(tag)
err = proLogic.InsertTag(tag)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
@@ -174,7 +175,7 @@ func updateTag(w http.ResponseWriter, r *http.Request) {
return
}
tag, err := logic.GetTag(updateTag.ID)
tag, err := proLogic.GetTag(updateTag.ID)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
@@ -202,7 +203,7 @@ func updateTag(w http.ResponseWriter, r *http.Request) {
var newID models.TagID
if updateTag.NewName != "" {
// validate name
err = logic.CheckIDSyntax(updateTag.NewName)
err = proLogic.CheckIDSyntax(updateTag.NewName)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
@@ -210,26 +211,26 @@ func updateTag(w http.ResponseWriter, r *http.Request) {
newID = models.TagID(fmt.Sprintf("%s.%s", tag.Network, updateTag.NewName))
tag.ID = newID
tag.TagName = updateTag.NewName
err = logic.InsertTag(tag)
err = proLogic.InsertTag(tag)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
// delete old Tag entry
logic.DeleteTag(updateTag.ID, false)
proLogic.DeleteTag(updateTag.ID, false)
}
if updateTag.ColorCode != "" && updateTag.ColorCode != tag.ColorCode {
tag.ColorCode = updateTag.ColorCode
err = logic.UpsertTag(tag)
err = proLogic.UpsertTag(tag)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
}
go func() {
logic.UpdateTag(updateTag, newID)
proLogic.UpdateTag(updateTag, newID)
if updateTag.NewName != "" {
logic.UpdateDeviceTag(updateTag.ID, newID, tag.Network)
proLogic.UpdateDeviceTag(updateTag.ID, newID, tag.Network)
}
mq.PublishPeerUpdate(false)
}()
@@ -256,24 +257,24 @@ func deleteTag(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("role is required"), "badrequest"))
return
}
tag, err := logic.GetTag(models.TagID(tagID))
tag, err := proLogic.GetTag(models.TagID(tagID))
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
// check if active policy is using the tag
if logic.CheckIfTagAsActivePolicy(tag.ID, tag.Network) {
if proLogic.CheckIfTagAsActivePolicy(tag.ID, tag.Network) {
logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("tag is currently in use by an active policy"), "badrequest"))
return
}
err = logic.DeleteTag(models.TagID(tagID), true)
err = proLogic.DeleteTag(models.TagID(tagID), true)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
go func() {
logic.RemoveDeviceTagFromAclPolicies(tag.ID, tag.Network)
proLogic.RemoveDeviceTagFromAclPolicies(tag.ID, tag.Network)
logic.RemoveTagFromEnrollmentKeys(tag.ID)
mq.PublishPeerUpdate(false)
}()

View File

@@ -35,6 +35,7 @@ func InitPro() {
proControllers.InetHandlers,
proControllers.RacHandlers,
proControllers.EventHandlers,
proControllers.TagHandlers,
)
controller.ListRoles = proControllers.ListRoles
logic.EnterpriseCheckFuncs = append(logic.EnterpriseCheckFuncs, func() {
@@ -112,12 +113,6 @@ func InitPro() {
logic.UpdateMetrics = proLogic.UpdateMetrics
logic.DeleteMetrics = proLogic.DeleteMetrics
logic.GetTrialEndDate = getTrialEndDate
logic.SetDefaultGw = proLogic.SetDefaultGw
logic.ValidateInetGwReq = proLogic.ValidateInetGwReq
logic.SetDefaultGwForRelayedUpdate = proLogic.SetDefaultGwForRelayedUpdate
logic.UnsetInternetGw = proLogic.UnsetInternetGw
logic.SetInternetGw = proLogic.SetInternetGw
logic.GetAllowedIpForInetNodeClient = proLogic.GetAllowedIpForInetNodeClient
mq.UpdateMetrics = proLogic.MQUpdateMetrics
mq.UpdateMetricsFallBack = proLogic.MQUpdateMetricsFallBack
logic.GetFilteredNodesByUserAccess = proLogic.GetFilteredNodesByUserAccess
@@ -146,6 +141,23 @@ func InitPro() {
logic.ResetIDPSyncHook = auth.ResetIDPSyncHook
logic.EmailInit = email.Init
logic.LogEvent = proLogic.LogEvent
logic.RemoveUserFromAclPolicy = proLogic.RemoveUserFromAclPolicy
logic.IsUserAllowedToCommunicate = proLogic.IsUserAllowedToCommunicate
logic.DeleteAllNetworkTags = proLogic.DeleteAllNetworkTags
logic.CreateDefaultTags = proLogic.CreateDefaultTags
logic.IsNodeUsingInternetGw = proLogic.IsNodeUsingInternetGw
logic.GetInetClientsFromAclPolicies = proLogic.GetInetClientsFromAclPolicies
logic.IsPeerAllowed = proLogic.IsPeerAllowed
logic.IsAclPolicyValid = proLogic.IsAclPolicyValid
logic.GetEgressRulesForNode = proLogic.GetEgressRulesForNode
logic.GetAclRulesForNode = proLogic.GetAclRulesForNode
logic.CheckIfAnyActiveEgressPolicy = proLogic.CheckIfAnyActiveEgressPolicy
logic.CheckIfAnyPolicyisUniDirectional = proLogic.CheckIfAnyPolicyisUniDirectional
logic.MigrateToGws = proLogic.MigrateToGws
logic.IsNodeAllowedToCommunicate = proLogic.IsNodeAllowedToCommunicate
logic.GetStaticNodeIps = proLogic.GetStaticNodeIps
logic.GetFwRulesOnIngressGateway = proLogic.GetFwRulesOnIngressGateway
}
func retrieveProLogo() string {

1930
pro/logic/acls.go Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,8 @@ package logic
import (
"encoding/json"
"fmt"
"github.com/google/uuid"
"github.com/gravitl/netmaker/database"
@@ -254,3 +256,48 @@ func MigrateUserRoleAndGroups(user models.User) {
}
logic.UpsertUser(user)
}
func MigrateToGws() {
nodes, err := logic.GetAllNodes()
if err != nil {
return
}
for _, node := range nodes {
if node.IsIngressGateway || node.IsRelay {
node.IsGw = true
node.IsIngressGateway = true
node.IsRelay = true
if node.Tags == nil {
node.Tags = make(map[models.TagID]struct{})
}
node.Tags[models.TagID(fmt.Sprintf("%s.%s", node.Network, models.GwTagName))] = struct{}{}
delete(node.Tags, models.TagID(fmt.Sprintf("%s.%s", node.Network, models.OldRemoteAccessTagName)))
logic.UpsertNode(&node)
}
}
acls := logic.ListAcls()
for _, acl := range acls {
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 = 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 = fmt.Sprintf("%s.%s", acl.NetworkID.String(), models.GwTagName)
acl.Dst[i] = dstI
upsert = true
}
}
if upsert {
logic.UpsertAcl(acl)
}
}
nets, _ := logic.GetNetworks()
for _, netI := range nets {
DeleteTag(models.TagID(fmt.Sprintf("%s.%s", netI.NetID, models.OldRemoteAccessTagName)), true)
}
}

View File

@@ -1,158 +1,10 @@
package logic
import (
"errors"
"fmt"
"net"
"github.com/google/uuid"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"golang.org/x/exp/slog"
)
const (
IPv4Network = "0.0.0.0/0"
IPv6Network = "::/0"
)
func ValidateInetGwReq(inetNode models.Node, req models.InetNodeReq, update bool) error {
inetHost, err := logic.GetHost(inetNode.HostID.String())
if err != nil {
return err
}
if inetHost.FirewallInUse == models.FIREWALL_NONE {
return errors.New("iptables or nftables needs to be installed")
}
if inetNode.EgressDetails.InternetGwID != "" {
return fmt.Errorf("node %s is using a internet gateway already", inetHost.Name)
}
if inetNode.IsRelayed {
return fmt.Errorf("node %s is being relayed", inetHost.Name)
}
for _, clientNodeID := range req.InetNodeClientIDs {
clientNode, err := logic.GetNodeByID(clientNodeID)
if err != nil {
return err
}
if clientNode.IsFailOver {
return errors.New("failover node cannot be set to use internet gateway")
}
clientHost, err := logic.GetHost(clientNode.HostID.String())
if err != nil {
return err
}
if clientHost.IsDefault {
return errors.New("default host cannot be set to use internet gateway")
}
if clientHost.OS != models.OS_Types.Linux && clientHost.OS != models.OS_Types.Windows {
return errors.New("can only attach linux or windows machine to a internet gateway")
}
if clientNode.EgressDetails.IsInternetGateway {
return fmt.Errorf("node %s acting as internet gateway cannot use another internet gateway", clientHost.Name)
}
if update {
if clientNode.EgressDetails.InternetGwID != "" && clientNode.EgressDetails.InternetGwID != inetNode.ID.String() {
return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name)
}
} else {
if clientNode.EgressDetails.InternetGwID != "" {
return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name)
}
}
if clientNode.FailedOverBy != uuid.Nil {
ResetFailedOverPeer(&clientNode)
}
if clientNode.IsRelayed && clientNode.RelayedBy != inetNode.ID.String() {
return fmt.Errorf("node %s is being relayed", clientHost.Name)
}
for _, nodeID := range clientHost.Nodes {
node, err := logic.GetNodeByID(nodeID)
if err != nil {
continue
}
if node.EgressDetails.InternetGwID != "" && node.EgressDetails.InternetGwID != inetNode.ID.String() {
return errors.New("nodes on same host cannot use different internet gateway")
}
}
}
return nil
}
// SetInternetGw - sets the node as internet gw based on flag bool
func SetInternetGw(node *models.Node, req models.InetNodeReq) {
node.EgressDetails.IsInternetGateway = true
node.EgressDetails.InetNodeReq = req
for _, clientNodeID := range req.InetNodeClientIDs {
clientNode, err := logic.GetNodeByID(clientNodeID)
if err != nil {
continue
}
clientNode.EgressDetails.InternetGwID = node.ID.String()
logic.UpsertNode(&clientNode)
}
}
func UnsetInternetGw(node *models.Node) {
nodes, err := logic.GetNetworkNodes(node.Network)
if err != nil {
slog.Error("failed to get network nodes", "network", node.Network, "error", err)
return
}
for _, clientNode := range nodes {
if node.ID.String() == clientNode.EgressDetails.InternetGwID {
clientNode.EgressDetails.InternetGwID = ""
logic.UpsertNode(&clientNode)
}
}
node.EgressDetails.IsInternetGateway = false
node.EgressDetails.InetNodeReq = models.InetNodeReq{}
}
func SetDefaultGwForRelayedUpdate(relayed, relay models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
if relay.EgressDetails.InternetGwID != "" {
relayedHost, err := logic.GetHost(relayed.HostID.String())
if err != nil {
return peerUpdate
}
peerUpdate.ChangeDefaultGw = true
peerUpdate.DefaultGwIp = relay.Address.IP
if peerUpdate.DefaultGwIp == nil || relayedHost.EndpointIP == nil {
peerUpdate.DefaultGwIp = relay.Address6.IP
}
}
return peerUpdate
}
func SetDefaultGw(node models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
if node.EgressDetails.InternetGwID != "" {
inetNode, err := logic.GetNodeByID(node.EgressDetails.InternetGwID)
if err != nil {
return peerUpdate
}
host, err := logic.GetHost(node.HostID.String())
if err != nil {
return peerUpdate
}
peerUpdate.ChangeDefaultGw = true
peerUpdate.DefaultGwIp = inetNode.Address.IP
if peerUpdate.DefaultGwIp == nil || host.EndpointIP == nil {
peerUpdate.DefaultGwIp = inetNode.Address6.IP
}
}
return peerUpdate
}
// GetNetworkIngresses - gets the gateways of a network
func GetNetworkIngresses(network string) ([]models.Node, error) {
var ingresses []models.Node
@@ -168,19 +20,206 @@ func GetNetworkIngresses(network string) ([]models.Node, error) {
return ingresses, nil
}
// GetAllowedIpForInetNodeClient - get inet cidr for node using a inet gw
func GetAllowedIpForInetNodeClient(node, peer *models.Node) []net.IPNet {
var allowedips = []net.IPNet{}
func GetTagMapWithNodes() (tagNodesMap map[models.TagID][]models.Node) {
tagNodesMap = make(map[models.TagID][]models.Node)
nodes, _ := logic.GetAllNodes()
for _, nodeI := range nodes {
if nodeI.Tags == nil {
continue
}
if nodeI.Mutex != nil {
nodeI.Mutex.Lock()
}
for nodeTagID := range nodeI.Tags {
tagNodesMap[nodeTagID] = append(tagNodesMap[nodeTagID], nodeI)
}
if nodeI.Mutex != nil {
nodeI.Mutex.Unlock()
}
if peer.Address.IP != nil {
_, ipnet, _ := net.ParseCIDR(IPv4Network)
allowedips = append(allowedips, *ipnet)
}
if peer.Address6.IP != nil {
_, ipnet, _ := net.ParseCIDR(IPv6Network)
allowedips = append(allowedips, *ipnet)
}
return allowedips
return
}
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
}
func AddTagMapWithStaticNodesWithUsers(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 {
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 {
tagNodesMap[tagID] = append(tagNodesMap[tagID], extclient.ConvertToStaticNode())
}
if extclient.Mutex != nil {
extclient.Mutex.Unlock()
}
}
return tagNodesMap
}
func GetNodeIDsWithTag(tagID models.TagID) (ids []string) {
tag, err := GetTag(tagID)
if err != nil {
return
}
nodes, _ := logic.GetNetworkNodes(tag.Network.String())
for _, nodeI := range nodes {
if nodeI.Tags == nil {
continue
}
if nodeI.Mutex != nil {
nodeI.Mutex.Lock()
}
if _, ok := nodeI.Tags[tagID]; ok {
ids = append(ids, nodeI.ID.String())
}
if nodeI.Mutex != nil {
nodeI.Mutex.Unlock()
}
}
return
}
func GetNodesWithTag(tagID models.TagID) map[string]models.Node {
nMap := make(map[string]models.Node)
tag, err := GetTag(tagID)
if err != nil {
return nMap
}
nodes, _ := logic.GetNetworkNodes(tag.Network.String())
for _, nodeI := range nodes {
if nodeI.Tags == nil {
continue
}
if nodeI.Mutex != nil {
nodeI.Mutex.Lock()
}
if _, ok := nodeI.Tags[tagID]; ok {
nMap[nodeI.ID.String()] = nodeI
}
if nodeI.Mutex != nil {
nodeI.Mutex.Unlock()
}
}
return AddStaticNodesWithTag(tag, nMap)
}
func AddStaticNodesWithTag(tag models.Tag, nMap map[string]models.Node) map[string]models.Node {
extclients, err := logic.GetNetworkExtClients(tag.Network.String())
if err != nil {
return nMap
}
for _, extclient := range extclients {
if extclient.RemoteAccessClientID != "" {
continue
}
if extclient.Mutex != nil {
extclient.Mutex.Lock()
}
if _, ok := extclient.Tags[tag.ID]; ok {
nMap[extclient.ClientID] = extclient.ConvertToStaticNode()
}
if extclient.Mutex != nil {
extclient.Mutex.Unlock()
}
}
return nMap
}
func GetStaticNodeWithTag(tagID models.TagID) map[string]models.Node {
nMap := make(map[string]models.Node)
tag, err := GetTag(tagID)
if err != nil {
return nMap
}
extclients, err := logic.GetNetworkExtClients(tag.Network.String())
if err != nil {
return nMap
}
for _, extclient := range extclients {
nMap[extclient.ClientID] = extclient.ConvertToStaticNode()
}
return nMap
}

View File

@@ -41,7 +41,7 @@ func GetNodeStatus(node *models.Node, defaultEnabledPolicy bool) {
return
}
if !defaultEnabledPolicy {
allowed, _ := logic.IsNodeAllowedToCommunicateV1(*node, ingNode, false)
allowed, _ := logic.IsNodeAllowedToCommunicate(*node, ingNode, false)
if !allowed {
node.Status = models.OnlineSt
return
@@ -161,7 +161,7 @@ func checkPeerStatus(node *models.Node, defaultAclPolicy bool) {
}
if !defaultAclPolicy {
allowed, _ := logic.IsNodeAllowedToCommunicateV1(*node, peer, false)
allowed, _ := logic.IsNodeAllowedToCommunicate(*node, peer, false)
if !allowed {
continue
}
@@ -199,7 +199,7 @@ func checkPeerConnectivity(node *models.Node, metrics *models.Metrics, defaultAc
}
if !defaultAclPolicy {
allowed, _ := logic.IsNodeAllowedToCommunicateV1(*node, peer, false)
allowed, _ := logic.IsNodeAllowedToCommunicate(*node, peer, false)
if !allowed {
continue
}

View File

@@ -10,6 +10,7 @@ import (
"time"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"golang.org/x/exp/slog"
)
@@ -62,7 +63,7 @@ func DeleteTag(tagID models.TagID, removeFromPolicy bool) error {
if err != nil {
return err
}
nodes, err := GetNetworkNodes(tag.Network.String())
nodes, err := logic.GetNetworkNodes(tag.Network.String())
if err != nil {
return err
}
@@ -70,18 +71,18 @@ func DeleteTag(tagID models.TagID, removeFromPolicy bool) error {
nodeI := nodeI
if _, ok := nodeI.Tags[tagID]; ok {
delete(nodeI.Tags, tagID)
UpsertNode(&nodeI)
logic.UpsertNode(&nodeI)
}
}
if removeFromPolicy {
// remove tag used on acl policy
go RemoveDeviceTagFromAclPolicies(tagID, tag.Network)
}
extclients, _ := GetNetworkExtClients(tag.Network.String())
extclients, _ := logic.GetNetworkExtClients(tag.Network.String())
for _, extclient := range extclients {
if _, ok := extclient.Tags[tagID]; ok {
delete(extclient.Tags, tagID)
SaveExtClient(&extclient)
logic.SaveExtClient(&extclient)
}
}
return database.DeleteRecord(database.TAG_TABLE_NAME, tagID.String())
@@ -99,7 +100,7 @@ func ListTagsWithNodes(netID models.NetworkID) ([]models.TagListResp, error) {
tagRespI := models.TagListResp{
Tag: tagI,
UsedByCnt: len(tagsNodeMap[tagI.ID]),
TaggedNodes: GetAllNodesAPI(tagsNodeMap[tagI.ID]),
TaggedNodes: logic.GetAllNodesAPI(tagsNodeMap[tagI.ID]),
}
resp = append(resp, tagRespI)
}
@@ -168,7 +169,7 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
if apiNode.StaticNode.RemoteAccessClientID != "" {
continue
}
extclient, err := GetExtClient(apiNode.StaticNode.ClientID, apiNode.StaticNode.Network)
extclient, err := logic.GetExtClient(apiNode.StaticNode.ClientID, apiNode.StaticNode.Network)
if err != nil {
continue
}
@@ -176,7 +177,7 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
nodeID = extclient.ClientID
node.StaticNode = extclient
} else {
node, err = GetNodeByID(apiNode.ID)
node, err = logic.GetNodeByID(apiNode.ID)
if err != nil {
continue
}
@@ -193,19 +194,19 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
if newID != "" {
if node.IsStatic {
node.StaticNode.Tags[newID] = struct{}{}
SaveExtClient(&node.StaticNode)
logic.SaveExtClient(&node.StaticNode)
} else {
node.Tags[newID] = struct{}{}
UpsertNode(&node)
logic.UpsertNode(&node)
}
} else {
if node.IsStatic {
node.StaticNode.Tags[req.ID] = struct{}{}
SaveExtClient(&node.StaticNode)
logic.SaveExtClient(&node.StaticNode)
} else {
node.Tags[req.ID] = struct{}{}
UpsertNode(&node)
logic.UpsertNode(&node)
}
}
} else {
@@ -214,10 +215,10 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
delete(node.StaticNode.Tags, req.ID)
if node.IsStatic {
node.StaticNode.Tags[newID] = struct{}{}
SaveExtClient(&node.StaticNode)
logic.SaveExtClient(&node.StaticNode)
} else {
node.Tags[newID] = struct{}{}
UpsertNode(&node)
logic.UpsertNode(&node)
}
}
delete(tagNodesMap, nodeID)
@@ -228,9 +229,9 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
delete(deletedTaggedNode.Tags, req.ID)
delete(deletedTaggedNode.StaticNode.Tags, req.ID)
if deletedTaggedNode.IsStatic {
SaveExtClient(&deletedTaggedNode.StaticNode)
logic.SaveExtClient(&deletedTaggedNode.StaticNode)
} else {
UpsertNode(&deletedTaggedNode)
logic.UpsertNode(&deletedTaggedNode)
}
}
go func(req models.UpdateTagReq) {
@@ -249,9 +250,9 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) {
nodeI.Tags[newID] = struct{}{}
nodeI.StaticNode.Tags[newID] = struct{}{}
if nodeI.IsStatic {
SaveExtClient(&nodeI.StaticNode)
logic.SaveExtClient(&nodeI.StaticNode)
} else {
UpsertNode(&nodeI)
logic.UpsertNode(&nodeI)
}
}
}

View File

@@ -4,9 +4,10 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/google/uuid"
"time"
"github.com/google/uuid"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
@@ -688,8 +689,8 @@ func GetUserRAGNodesV1(user models.User) (gws map[string]models.Node) {
}
}
tagNodesMap := logic.GetTagMapWithNodes()
accessPolices := logic.ListUserPolicies(user)
tagNodesMap := GetTagMapWithNodes()
accessPolices := ListUserPolicies(user)
for _, policyI := range accessPolices {
if !policyI.Enabled {
continue
@@ -722,9 +723,33 @@ func GetUserRAGNodes(user models.User) (gws map[string]models.Node) {
if err != nil {
return
}
for _, node := range nodes {
if ok, _ := logic.IsUserAllowedToCommunicate(user.UserName, node); ok {
if !node.IsGw {
continue
}
if user.PlatformRoleID == models.AdminRole || user.PlatformRoleID == models.SuperAdminRole {
gws[node.ID.String()] = node
} else {
// check if user has network role assigned
if roles, ok := user.NetworkRoles[models.NetworkID(node.Network)]; ok && len(roles) > 0 {
if ok, _ := IsUserAllowedToCommunicate(user.UserName, node); ok {
gws[node.ID.String()] = node
continue
}
}
for groupID := range user.UserGroups {
userGrp, err := logic.GetUserGroup(groupID)
if err == nil {
if roles, ok := userGrp.NetworkRoles[models.NetworkID(node.Network)]; ok && len(roles) > 0 {
if ok, _ := IsUserAllowedToCommunicate(user.UserName, node); ok {
gws[node.ID.String()] = node
break
}
}
}
}
}
}
return
@@ -1169,6 +1194,35 @@ func CreateDefaultUserPolicies(netID models.NetworkID) {
return
}
if !logic.IsAclExists(fmt.Sprintf("%s.%s", netID, "all-users")) {
defaultUserAcl := models.Acl{
ID: fmt.Sprintf("%s.%s", netID, "all-users"),
Default: true,
Name: "All Users",
MetaData: "This policy gives access to everything in the network for an user",
NetworkID: netID,
Proto: models.ALL,
ServiceType: models.Any,
Port: []string{},
RuleType: models.UserPolicy,
Src: []models.AclPolicyTag{
{
ID: models.UserAclID,
Value: "*",
},
},
Dst: []models.AclPolicyTag{{
ID: models.NodeTagID,
Value: "*",
}},
AllowedDirection: models.TrafficDirectionUni,
Enabled: true,
CreatedBy: "auto",
CreatedAt: time.Now().UTC(),
}
logic.InsertAcl(defaultUserAcl)
}
if !logic.IsAclExists(fmt.Sprintf("%s.%s-grp", netID, models.NetworkAdmin)) {
networkAdminGroupID := GetDefaultNetworkAdminGroupID(netID)
@@ -1268,3 +1322,22 @@ func AddGlobalNetRolesToAdmins(u *models.User) {
u.UserGroups[globalNetworksAdminGroupID] = struct{}{}
}
func GetUserGrpMap() map[models.UserGroupID]map[string]struct{} {
grpUsersMap := make(map[models.UserGroupID]map[string]struct{})
users, _ := logic.GetUsersDB()
for _, user := range users {
for gID := range user.UserGroups {
if grpUsers, ok := grpUsersMap[gID]; ok {
grpUsers[user.UserName] = struct{}{}
grpUsersMap[gID] = grpUsers
} else {
grpUsersMap[gID] = make(map[string]struct{})
grpUsersMap[gID][user.UserName] = struct{}{}
}
}
}
return grpUsersMap
}

View File

@@ -685,7 +685,7 @@ func GetMetricInterval() string {
// GetManageDNS - if manage DNS enabled or not
func GetManageDNS() bool {
enabled := false
enabled := true
if os.Getenv("MANAGE_DNS") != "" {
enabled = os.Getenv("MANAGE_DNS") == "true"
}