Преглед изворни кода

Merge branch 'develop' into NET-1996

Vishal Dalwadi пре 4 месеци
родитељ
комит
f233f2d582

+ 4 - 0
auth/host_session.go

@@ -289,6 +289,10 @@ func CheckNetRegAndHostUpdate(networks []string, h *models.Host, relayNodeId uui
 				logic.CreateFailOver(*newNode)
 				// make host remote access gateway
 				logic.CreateIngressGateway(network, newNode.ID.String(), models.IngressRequest{})
+				logic.CreateRelay(models.RelayRequest{
+					NodeID: newNode.ID.String(),
+					NetID:  network,
+				})
 			}
 		}
 	}

+ 0 - 1
config/config.go

@@ -89,7 +89,6 @@ type ServerConfig struct {
 	DeployedByOperator         bool          `yaml:"deployed_by_operator"`
 	Environment                string        `yaml:"environment"`
 	JwtValidityDuration        time.Duration `yaml:"jwt_validity_duration" swaggertype:"primitive,integer" format:"int64"`
-	RacAutoDisable             bool          `yaml:"rac_auto_disable"`
 	RacRestrictToSingleNetwork bool          `yaml:"rac_restrict_to_single_network"`
 	CacheEnabled               string        `yaml:"caching_enabled"`
 	EndpointDetection          bool          `yaml:"endpoint_detection"`

+ 25 - 0
controllers/gateway.go

@@ -50,6 +50,14 @@ func createGateway(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 	}
+	if req.IsInternetGateway && len(req.InetNodeClientIDs) > 0 {
+		err = logic.ValidateInetGwReq(node, req.InetNodeReq, false)
+		if err != nil {
+			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
+			return
+		}
+	}
+
 	node, err = logic.CreateIngressGateway(netid, nodeid, req.IngressRequest)
 	if err != nil {
 		logger.Log(0, r.Header.Get("user"),
@@ -84,6 +92,22 @@ func createGateway(w http.ResponseWriter, r *http.Request) {
 
 		}
 	}
+	if len(req.InetNodeClientIDs) > 0 {
+		logic.SetInternetGw(&node, req.InetNodeReq)
+		if servercfg.IsPro {
+			if _, exists := logic.FailOverExists(node.Network); exists {
+				go func() {
+					logic.ResetFailedOverPeer(&node)
+					mq.PublishPeerUpdate(false)
+				}()
+			}
+		}
+		if node.IsGw && node.IngressDNS == "" {
+			node.IngressDNS = "1.1.1.1"
+		}
+		logic.UpsertNode(&node)
+	}
+
 	logger.Log(
 		1,
 		r.Header.Get("user"),
@@ -164,6 +188,7 @@ func deleteGateway(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 	}
+	logic.UnsetInternetGw(&node)
 	node.IsGw = false
 	logic.UpsertNode(&node)
 	logger.Log(1, r.Header.Get("user"), "deleted gw", nodeid, "on network", netid)

+ 4 - 0
controllers/hosts.go

@@ -522,6 +522,10 @@ func addHostToNetwork(w http.ResponseWriter, r *http.Request) {
 		logic.CreateFailOver(*newNode)
 		// make host remote access gateway
 		logic.CreateIngressGateway(network, newNode.ID.String(), models.IngressRequest{})
+		logic.CreateRelay(models.RelayRequest{
+			NodeID: newNode.ID.String(),
+			NetID:  network,
+		})
 	}
 	go func() {
 		mq.HostUpdate(&models.HostUpdate{

+ 5 - 16
pro/controllers/inet_gws.go → controllers/inet_gws.go

@@ -1,4 +1,4 @@
-package controllers
+package controller
 
 import (
 	"encoding/json"
@@ -10,20 +10,9 @@ import (
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/mq"
-	proLogic "github.com/gravitl/netmaker/pro/logic"
 	"github.com/gravitl/netmaker/servercfg"
 )
 
-// InetHandlers - handlers for internet gw
-func InetHandlers(r *mux.Router) {
-	r.HandleFunc("/api/nodes/{network}/{nodeid}/inet_gw", logic.SecurityCheck(true, http.HandlerFunc(createInternetGw))).
-		Methods(http.MethodPost)
-	r.HandleFunc("/api/nodes/{network}/{nodeid}/inet_gw", logic.SecurityCheck(true, http.HandlerFunc(updateInternetGw))).
-		Methods(http.MethodPut)
-	r.HandleFunc("/api/nodes/{network}/{nodeid}/inet_gw", logic.SecurityCheck(true, http.HandlerFunc(deleteInternetGw))).
-		Methods(http.MethodDelete)
-}
-
 // @Summary     Create an internet gateway
 // @Router      /api/nodes/{network}/{nodeid}/inet_gw [post]
 // @Tags        PRO
@@ -70,16 +59,16 @@ 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
 	}
 	logic.SetInternetGw(&node, request)
 	if servercfg.IsPro {
-		if _, exists := proLogic.FailOverExists(node.Network); exists {
+		if _, exists := logic.FailOverExists(node.Network); exists {
 			go func() {
-				proLogic.ResetFailedOverPeer(&node)
+				logic.ResetFailedOverPeer(&node)
 				mq.PublishPeerUpdate(false)
 			}()
 		}
@@ -140,7 +129,7 @@ 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

+ 6 - 0
controllers/legacy.go

@@ -11,6 +11,12 @@ import (
 func legacyHandlers(r *mux.Router) {
 	r.HandleFunc("/api/v1/legacy/nodes", logic.SecurityCheck(true, http.HandlerFunc(wipeLegacyNodes))).
 		Methods(http.MethodDelete)
+	r.HandleFunc("/api/nodes/{network}/{nodeid}/inet_gw", logic.SecurityCheck(true, http.HandlerFunc(createInternetGw))).
+		Methods(http.MethodPost)
+	r.HandleFunc("/api/nodes/{network}/{nodeid}/inet_gw", logic.SecurityCheck(true, http.HandlerFunc(updateInternetGw))).
+		Methods(http.MethodPut)
+	r.HandleFunc("/api/nodes/{network}/{nodeid}/inet_gw", logic.SecurityCheck(true, http.HandlerFunc(deleteInternetGw))).
+		Methods(http.MethodDelete)
 }
 
 // @Summary     Delete all legacy nodes from DB.

+ 19 - 7
controllers/node.go

@@ -626,6 +626,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 	}
+
 	if !servercfg.IsPro {
 		newData.AdditionalRagIps = []string{}
 	}
@@ -638,6 +639,13 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
 		)
 		return
 	}
+	if newNode.IsInternetGateway && len(newNode.InetNodeReq.InetNodeClientIDs) > 0 {
+		err = logic.ValidateInetGwReq(*newNode, newNode.InetNodeReq, newNode.IsInternetGateway && currentNode.IsInternetGateway)
+		if err != nil {
+			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
+			return
+		}
+	}
 	relayUpdate := logic.RelayUpdates(&currentNode, newNode)
 	if relayUpdate && newNode.IsRelay {
 		err = logic.ValidateRelay(models.RelayRequest{
@@ -657,7 +665,6 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 	}
-	ifaceDelta := logic.IfaceDelta(&currentNode, newNode)
 	aclUpdate := currentNode.DefaultACL != newNode.DefaultACL
 
 	err = logic.UpdateNode(&currentNode, newNode)
@@ -670,7 +677,17 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
 	if relayUpdate {
 		logic.UpdateRelayed(&currentNode, newNode)
 	}
-
+	if !currentNode.IsInternetGateway && newNode.IsInternetGateway {
+		logic.SetInternetGw(newNode, newNode.InetNodeReq)
+	}
+	if currentNode.IsInternetGateway && newNode.IsInternetGateway {
+		logic.UnsetInternetGw(newNode)
+		logic.SetInternetGw(newNode, newNode.InetNodeReq)
+	}
+	if !newNode.IsInternetGateway {
+		logic.UnsetInternetGw(newNode)
+	}
+	logic.UpsertNode(newNode)
 	logic.GetNodeStatus(newNode, false)
 
 	apiNode := newNode.ConvertToAPINode()
@@ -707,11 +724,6 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
 		if err := mq.NodeUpdate(newNode); err != nil {
 			slog.Error("error publishing node update to node", "node", newNode.ID, "error", err)
 		}
-		if aclUpdate || relayupdate || ifaceDelta {
-			if err := mq.PublishPeerUpdate(false); err != nil {
-				logger.Log(0, "error during node ACL update for node", newNode.ID.String())
-			}
-		}
 		mq.PublishPeerUpdate(false)
 		if servercfg.IsDNSMode() {
 			logic.SetDNS()

+ 1 - 1
controllers/user.go

@@ -397,7 +397,7 @@ func authenticateUser(response http.ResponseWriter, request *http.Request) {
 	response.Write(successJSONResponse)
 
 	go func() {
-		if servercfg.IsPro && logic.GetRacAutoDisable() {
+		if servercfg.IsPro {
 			// enable all associeated clients for the user
 			clients, err := logic.GetAllExtClients()
 			if err != nil {

+ 1 - 1
logic/acls.go

@@ -294,7 +294,7 @@ var MigrateToGws = func() {
 		return
 	}
 	for _, node := range nodes {
-		if node.IsIngressGateway || node.IsRelay {
+		if node.IsIngressGateway || node.IsRelay || node.IsInternetGateway {
 			node.IsGw = true
 			node.IsIngressGateway = true
 			node.IsRelay = true

+ 162 - 3
logic/gateway.go

@@ -3,14 +3,22 @@ package logic
 import (
 	"errors"
 	"fmt"
+	"net"
 	"slices"
 	"sort"
 	"time"
 
+	"github.com/google/uuid"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/servercfg"
+	"golang.org/x/exp/slog"
+)
+
+var (
+	IPv4Network = "0.0.0.0/0"
+	IPv6Network = "::/0"
 )
 
 // IsInternetGw - checks if node is acting as internet gw
@@ -267,9 +275,6 @@ func DeleteIngressGateway(nodeid string) (models.Node, []models.ExtClient, error
 	logger.Log(3, "deleting ingress gateway")
 	node.LastModified = time.Now().UTC()
 	node.IsIngressGateway = false
-	if !servercfg.IsPro {
-		node.IsInternetGateway = false
-	}
 	delete(node.Tags, models.TagID(fmt.Sprintf("%s.%s", node.Network, models.GwTagName)))
 	node.IngressGatewayRange = ""
 	node.Metadata = ""
@@ -316,3 +321,157 @@ func IsUserAllowedAccessToExtClient(username string, client models.ExtClient) bo
 	}
 	return true
 }
+
+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.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 := GetNodeByID(clientNodeID)
+		if err != nil {
+			return err
+		}
+		if clientNode.IsFailOver {
+			return errors.New("failover node cannot be set to use internet gateway")
+		}
+		clientHost, err := 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.IsInternetGateway {
+			return fmt.Errorf("node %s acting as internet gateway cannot use another internet gateway", clientHost.Name)
+		}
+		if update {
+			if clientNode.InternetGwID != "" && clientNode.InternetGwID != inetNode.ID.String() {
+				return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name)
+			}
+		} else {
+			if clientNode.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
+			}
+			if node.InternetGwID != "" && node.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.IsInternetGateway = true
+	node.InetNodeReq = req
+	for _, clientNodeID := range req.InetNodeClientIDs {
+		clientNode, err := GetNodeByID(clientNodeID)
+		if err != nil {
+			continue
+		}
+		clientNode.InternetGwID = node.ID.String()
+		UpsertNode(&clientNode)
+	}
+
+}
+
+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
+	}
+	for _, clientNode := range nodes {
+		if node.ID.String() == clientNode.InternetGwID {
+			clientNode.InternetGwID = ""
+			UpsertNode(&clientNode)
+		}
+
+	}
+	node.IsInternetGateway = false
+	node.InetNodeReq = models.InetNodeReq{}
+
+}
+
+func SetDefaultGwForRelayedUpdate(relayed, relay models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
+	if relay.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
+		}
+
+	}
+	return peerUpdate
+}
+
+func SetDefaultGw(node models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
+	if node.InternetGwID != "" {
+
+		inetNode, err := GetNodeByID(node.InternetGwID)
+		if err != nil {
+			return peerUpdate
+		}
+		host, err := 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
+}
+
+// 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)
+	}
+
+	if peer.Address6.IP != nil {
+		_, ipnet, _ := net.ParseCIDR(IPv6Network)
+		allowedips = append(allowedips, *ipnet)
+	}
+
+	return allowedips
+}

+ 7 - 9
logic/jwts.go

@@ -61,11 +61,10 @@ func CreateJWT(uuid string, macAddress string, network string) (response string,
 // CreateUserJWT - creates a user jwt token
 func CreateUserAccessJwtToken(username string, role models.UserRoleID, d time.Time, tokenID string) (response string, err error) {
 	claims := &models.UserClaims{
-		UserName:       username,
-		Role:           role,
-		TokenType:      models.AccessTokenType,
-		Api:            servercfg.GetAPIHost(),
-		RacAutoDisable: GetRacAutoDisable() && (role != models.SuperAdminRole && role != models.AdminRole),
+		UserName:  username,
+		Role:      role,
+		TokenType: models.AccessTokenType,
+		Api:       servercfg.GetAPIHost(),
 		RegisteredClaims: jwt.RegisteredClaims{
 			Issuer:    "Netmaker",
 			Subject:   fmt.Sprintf("user|%s", username),
@@ -88,10 +87,9 @@ func CreateUserJWT(username string, role models.UserRoleID) (response string, er
 	settings := GetServerSettings()
 	expirationTime := time.Now().Add(time.Duration(settings.JwtValidityDuration) * time.Minute)
 	claims := &models.UserClaims{
-		UserName:       username,
-		Role:           role,
-		TokenType:      models.UserIDTokenType,
-		RacAutoDisable: settings.RacAutoDisable && (role != models.SuperAdminRole && role != models.AdminRole),
+		UserName:  username,
+		Role:      role,
+		TokenType: models.UserIDTokenType,
 		RegisteredClaims: jwt.RegisteredClaims{
 			Issuer:    "Netmaker",
 			Subject:   fmt.Sprintf("user|%s", username),

+ 4 - 0
logic/networks.go

@@ -215,6 +215,10 @@ func DeleteNetwork(network string, force bool, done chan struct{}) error {
 				if err != nil {
 					continue
 				}
+				if node.IsGw {
+					// delete ext clients belonging to gateway
+					DeleteGatewayExtClients(node.ID.String(), node.Network)
+				}
 				DissasociateNodeFromHost(&node, host)
 			}
 		}

+ 0 - 19
logic/peers.go

@@ -42,25 +42,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.IsInternetGateway = false
-	}
-	// SetInternetGw
-	SetInternetGw = func(node *models.Node, req models.InetNodeReq) {
-		node.IsInternetGateway = true
-	}
-	// GetAllowedIpForInetNodeClient
-	GetAllowedIpForInetNodeClient = func(node, peer *models.Node) []net.IPNet {
-		return []net.IPNet{}
-	}
 )
 
 // GetHostPeerInfo - fetches required peer info per network

+ 0 - 7
logic/settings.go

@@ -62,7 +62,6 @@ func GetServerSettingsFromEnv() (s models.ServerSettings) {
 		Telemetry:                  servercfg.Telemetry(),
 		BasicAuth:                  servercfg.IsBasicAuthEnabled(),
 		JwtValidityDuration:        servercfg.GetJwtValidityDurationFromEnv() / 60,
-		RacAutoDisable:             servercfg.GetRacAutoDisable(),
 		RacRestrictToSingleNetwork: servercfg.GetRacRestrictToSingleNetwork(),
 		EndpointDetection:          servercfg.IsEndpointDetectionEnabled(),
 		AllowedEmailDomains:        servercfg.GetAllowedEmailDomains(),
@@ -140,7 +139,6 @@ func GetServerConfig() config.ServerConfig {
 		cfg.IsPro = "yes"
 	}
 	cfg.JwtValidityDuration = time.Duration(settings.JwtValidityDuration) * time.Minute
-	cfg.RacAutoDisable = settings.RacAutoDisable
 	cfg.RacRestrictToSingleNetwork = settings.RacRestrictToSingleNetwork
 	cfg.MetricInterval = settings.MetricInterval
 	cfg.ManageDNS = settings.ManageDNS
@@ -206,11 +204,6 @@ func GetJwtValidityDuration() time.Duration {
 	return GetServerConfig().JwtValidityDuration
 }
 
-// GetRacAutoDisable - returns whether the feature to autodisable RAC is enabled
-func GetRacAutoDisable() bool {
-	return GetServerSettings().RacAutoDisable
-}
-
 // GetRacRestrictToSingleNetwork - returns whether the feature to allow simultaneous network connections via RAC is enabled
 func GetRacRestrictToSingleNetwork() bool {
 	return GetServerSettings().RacRestrictToSingleNetwork

+ 13 - 0
logic/util.go

@@ -224,6 +224,19 @@ func CompareMaps[K comparable, V any](a, b map[K]V) bool {
 	return true
 }
 
+func UniqueStrings(input []string) []string {
+	seen := make(map[string]struct{})
+	var result []string
+
+	for _, val := range input {
+		if _, ok := seen[val]; !ok {
+			seen[val] = struct{}{}
+			result = append(result, val)
+		}
+	}
+
+	return result
+}
 func GetClientIP(r *http.Request) string {
 	// Trust X-Forwarded-For first
 	if xff := r.Header.Get("X-Forwarded-For"); xff != "" {

+ 44 - 0
migrate/migrate.go

@@ -37,6 +37,50 @@ func Run() {
 	updateAcls()
 	logic.MigrateToGws()
 	migrateToEgressV1()
+	resync()
+}
+
+// removes if any stale configurations from previous run.
+func resync() {
+
+	nodes, _ := logic.GetAllNodes()
+	for _, node := range nodes {
+		if !node.IsGw {
+			if len(node.RelayedNodes) > 0 {
+				logic.DeleteRelay(node.Network, node.ID.String())
+			}
+			if node.IsIngressGateway {
+				logic.DeleteIngressGateway(node.ID.String())
+			}
+			if len(node.InetNodeReq.InetNodeClientIDs) > 0 || node.IsInternetGateway {
+				logic.UnsetInternetGw(&node)
+				logic.UpsertNode(&node)
+			}
+		}
+		if node.IsRelayed {
+			if node.RelayedBy == "" {
+				node.IsRelayed = false
+				node.InternetGwID = ""
+				logic.UpsertNode(&node)
+			}
+			if node.RelayedBy != "" {
+				// check if node exists
+				_, err := logic.GetNodeByID(node.RelayedBy)
+				if err != nil {
+					node.RelayedBy = ""
+					node.InternetGwID = ""
+					logic.UpsertNode(&node)
+				}
+			}
+		}
+		if node.InternetGwID != "" {
+			_, err := logic.GetNodeByID(node.InternetGwID)
+			if err != nil {
+				node.InternetGwID = ""
+				logic.UpsertNode(&node)
+			}
+		}
+	}
 }
 
 func assignSuperAdmin() {

+ 1 - 0
models/gateway.go

@@ -3,6 +3,7 @@ package models
 type CreateGwReq struct {
 	IngressRequest
 	RelayRequest
+	InetNodeReq
 }
 
 type DeleteGw struct {

+ 0 - 1
models/settings.go

@@ -26,7 +26,6 @@ type ServerSettings struct {
 	BasicAuth                      bool     `json:"basic_auth"`
 	JwtValidityDuration            int      `json:"jwt_validity_duration"`
 	MFAEnforced                    bool     `json:"mfa_enforced"`
-	RacAutoDisable                 bool     `json:"rac_auto_disable"`
 	RacRestrictToSingleNetwork     bool     `json:"rac_restrict_to_single_network"`
 	EndpointDetection              bool     `json:"endpoint_detection"`
 	AllowedEmailDomains            string   `json:"allowed_email_domains"`

+ 1 - 9
pro/initialize.go

@@ -32,7 +32,6 @@ func InitPro() {
 		proControllers.MetricHandlers,
 		proControllers.UserHandlers,
 		proControllers.FailOverHandlers,
-		proControllers.InetHandlers,
 		proControllers.RacHandlers,
 		proControllers.EventHandlers,
 		proControllers.TagHandlers,
@@ -82,9 +81,7 @@ func InitPro() {
 			addTrialLicenseHook()
 		}
 
-		if logic.GetRacAutoDisable() {
-			AddRacHooks()
-		}
+		AddUnauthorisedUserNodeHooks()
 
 		var authProvider = auth.InitializeAuthProvider()
 		if authProvider != "" {
@@ -113,11 +110,6 @@ func InitPro() {
 	logic.UpdateMetrics = proLogic.UpdateMetrics
 	logic.DeleteMetrics = proLogic.DeleteMetrics
 	logic.GetTrialEndDate = getTrialEndDate
-	logic.SetDefaultGw = proLogic.SetDefaultGw
-	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

+ 2 - 2
pro/logic/acls.go

@@ -1468,12 +1468,12 @@ func GetAclRuleForInetGw(targetnode models.Node) (rules map[string]models.AclRul
 		}
 		if targetnode.NetworkRange.IP != nil {
 			aclRule.IPList = append(aclRule.IPList, targetnode.NetworkRange)
-			_, allIpv4, _ := net.ParseCIDR(IPv4Network)
+			_, allIpv4, _ := net.ParseCIDR(logic.IPv4Network)
 			aclRule.Dst = append(aclRule.Dst, *allIpv4)
 		}
 		if targetnode.NetworkRange6.IP != nil {
 			aclRule.IP6List = append(aclRule.IP6List, targetnode.NetworkRange6)
-			_, allIpv6, _ := net.ParseCIDR(IPv6Network)
+			_, allIpv6, _ := net.ParseCIDR(logic.IPv6Network)
 			aclRule.Dst6 = append(aclRule.Dst6, *allIpv6)
 		}
 		rules[aclRule.ID] = aclRule

+ 14 - 1
pro/logic/migrate.go

@@ -263,7 +263,7 @@ func MigrateToGws() {
 		return
 	}
 	for _, node := range nodes {
-		if node.IsIngressGateway || node.IsRelay {
+		if node.IsIngressGateway || node.IsRelay || node.IsInternetGateway {
 			node.IsGw = true
 			node.IsIngressGateway = true
 			node.IsRelay = true
@@ -274,6 +274,19 @@ func MigrateToGws() {
 			delete(node.Tags, models.TagID(fmt.Sprintf("%s.%s", node.Network, models.OldRemoteAccessTagName)))
 			logic.UpsertNode(&node)
 		}
+		if node.IsInternetGateway && len(node.InetNodeReq.InetNodeClientIDs) > 0 {
+			node.RelayedNodes = append(node.RelayedNodes, node.InetNodeReq.InetNodeClientIDs...)
+			node.RelayedNodes = logic.UniqueStrings(node.RelayedNodes)
+			for _, nodeID := range node.InetNodeReq.InetNodeClientIDs {
+				relayedNode, err := logic.GetNodeByID(nodeID)
+				if err == nil {
+					relayedNode.IsRelayed = true
+					relayedNode.RelayedBy = node.ID.String()
+					logic.UpsertNode(&relayedNode)
+				}
+			}
+			logic.UpsertNode(&node)
+		}
 	}
 	acls := logic.ListAcls()
 	for _, acl := range acls {

+ 0 - 165
pro/logic/nodes.go

@@ -1,19 +1,8 @@
 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"
-)
-
-var (
-	IPv4Network = "0.0.0.0/0"
-	IPv6Network = "::/0"
 )
 
 // GetNetworkIngresses - gets the gateways of a network
@@ -234,157 +223,3 @@ func GetStaticNodeWithTag(tagID models.TagID) map[string]models.Node {
 	}
 	return nMap
 }
-
-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.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.IsInternetGateway {
-			return fmt.Errorf("node %s acting as internet gateway cannot use another internet gateway", clientHost.Name)
-		}
-		if update {
-			if clientNode.InternetGwID != "" && clientNode.InternetGwID != inetNode.ID.String() {
-				return fmt.Errorf("node %s is already using a internet gateway", clientHost.Name)
-			}
-		} else {
-			if clientNode.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.InternetGwID != "" && node.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.IsInternetGateway = true
-	node.InetNodeReq = req
-	for _, clientNodeID := range req.InetNodeClientIDs {
-		clientNode, err := logic.GetNodeByID(clientNodeID)
-		if err != nil {
-			continue
-		}
-		clientNode.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.InternetGwID {
-			clientNode.InternetGwID = ""
-			logic.UpsertNode(&clientNode)
-		}
-
-	}
-	node.IsInternetGateway = false
-	node.InetNodeReq = models.InetNodeReq{}
-
-}
-
-func SetDefaultGwForRelayedUpdate(relayed, relay models.Node, peerUpdate models.HostPeerUpdate) models.HostPeerUpdate {
-	if relay.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.InternetGwID != "" {
-
-		inetNode, err := logic.GetNodeByID(node.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
-}
-
-// 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)
-	}
-
-	if peer.Address6.IP != nil {
-		_, ipnet, _ := net.ParseCIDR(IPv6Network)
-		allowedips = append(allowedips, *ipnet)
-	}
-
-	return allowedips
-}

+ 12 - 12
pro/remote_access_client.go

@@ -13,20 +13,20 @@ import (
 	"golang.org/x/exp/slog"
 )
 
-const racAutoDisableCheckInterval = 3 * time.Minute
+const unauthorisedUserNodeCheckInterval = 3 * time.Minute
 
-// AddRacHooks - adds hooks for Remote Access Client
-func AddRacHooks() {
-	slog.Debug("adding RAC autodisable hook")
+// AddUnauthorisedUserNodeHooks - adds hook to prevent access from unauthorised (expired) user nodes
+func AddUnauthorisedUserNodeHooks() {
+	slog.Debug("adding unauthorisedUserNode hook")
 	logic.HookManagerCh <- models.HookDetails{
-		Hook:     racAutoDisableHook,
-		Interval: racAutoDisableCheckInterval,
+		Hook:     unauthorisedUserNodeHook,
+		Interval: unauthorisedUserNodeCheckInterval,
 	}
 }
 
-// racAutoDisableHook - checks if RAC is enabled and if it is, checks if it should be disabled
-func racAutoDisableHook() error {
-	slog.Debug("running RAC autodisable hook")
+// unauthorisedUserNodeHook - checks if a user node should be disabled, using the user's last login time
+func unauthorisedUserNodeHook() error {
+	slog.Debug("running unauthorisedUserNode hook")
 
 	users, err := logic.GetUsers()
 	if err != nil {
@@ -55,16 +55,16 @@ func racAutoDisableHook() error {
 			}
 			if (client.OwnerID == user.UserName) &&
 				client.Enabled {
-				slog.Info(fmt.Sprintf("disabling ext client %s for user %s due to RAC autodisabling", client.ClientID, client.OwnerID))
+				slog.Info(fmt.Sprintf("disabling user node %s for user %s: auth token expired", client.ClientID, client.OwnerID))
 				if err := disableExtClient(&client); err != nil {
-					slog.Error("error disabling ext client in RAC autodisable hook", "error", err)
+					slog.Error("error disabling user node", "error", err)
 					continue // dont return but try for other clients
 				}
 			}
 		}
 	}
 
-	slog.Debug("finished running RAC autodisable hook")
+	slog.Debug("finished running unauthorisedUserNode hook")
 	return nil
 }
 

+ 0 - 2
scripts/netmaker.default.env

@@ -71,8 +71,6 @@ AZURE_TENANT=
 OIDC_ISSUER=
 # Duration of JWT token validity in seconds
 JWT_VALIDITY_DURATION=43200
-# Auto disable a user's connecteds clients bassed on JWT token expiration
-RAC_AUTO_DISABLE=false
 # Allow a user to connect to multiple networks simultaneously
 RAC_RESTRICT_TO_SINGLE_NETWORK=false
 # if turned on data will be cached on to improve performance significantly (IMPORTANT: If HA set to `false` )

+ 1 - 1
scripts/nm-quick.sh

@@ -257,7 +257,7 @@ save_config() { (
 		"INSTALL_TYPE" "NODE_ID" "DNS_MODE" "NETCLIENT_AUTO_UPDATE" "API_PORT" "MANAGE_DNS" "DEFAULT_DOMAIN"
 		"CORS_ALLOWED_ORIGIN" "DISPLAY_KEYS" "DATABASE" "SERVER_BROKER_ENDPOINT" "VERBOSITY"
 		"DEBUG_MODE"  "REST_BACKEND" "DISABLE_REMOTE_IP_CHECK" "TELEMETRY" "ALLOWED_EMAIL_DOMAINS" "AUTH_PROVIDER" "CLIENT_ID" "CLIENT_SECRET"
-		"FRONTEND_URL" "AZURE_TENANT" "OIDC_ISSUER" "EXPORTER_API_PORT" "JWT_VALIDITY_DURATION" "RAC_AUTO_DISABLE" "RAC_RESTRICT_TO_SINGLE_NETWORK" "CACHING_ENABLED" "ENDPOINT_DETECTION"
+		"FRONTEND_URL" "AZURE_TENANT" "OIDC_ISSUER" "EXPORTER_API_PORT" "JWT_VALIDITY_DURATION" "RAC_RESTRICT_TO_SINGLE_NETWORK" "CACHING_ENABLED" "ENDPOINT_DETECTION"
 		"SMTP_HOST" "SMTP_PORT" "EMAIL_SENDER_ADDR" "EMAIL_SENDER_USER" "EMAIL_SENDER_PASSWORD")
 	for name in "${toCopy[@]}"; do
 		save_config_item $name "${!name}"

+ 1 - 1
scripts/nm-upgrade.sh

@@ -179,7 +179,7 @@ save_config() { (
 		"CORS_ALLOWED_ORIGIN" "DISPLAY_KEYS" "DATABASE" "SERVER_BROKER_ENDPOINT" "STUN_PORT" "VERBOSITY"
 		"TURN_PORT" "USE_TURN" "DEBUG_MODE" "TURN_API_PORT" "REST_BACKEND"
 		"DISABLE_REMOTE_IP_CHECK" "TELEMETRY" "AUTH_PROVIDER" "CLIENT_ID" "CLIENT_SECRET"
-		"FRONTEND_URL" "AZURE_TENANT" "OIDC_ISSUER" "EXPORTER_API_PORT" "JWT_VALIDITY_DURATION" "RAC_AUTO_DISABLE" "RAC_RESTRICT_TO_SINGLE_NETWORK")
+		"FRONTEND_URL" "AZURE_TENANT" "OIDC_ISSUER" "EXPORTER_API_PORT" "JWT_VALIDITY_DURATION" "RAC_RESTRICT_TO_SINGLE_NETWORK")
 	for name in "${toCopy[@]}"; do
 		save_config_item $name "${!name}"
 	done

+ 0 - 6
servercfg/serverconf.go

@@ -91,7 +91,6 @@ func GetServerConfig() config.ServerConfig {
 		cfg.IsPro = "yes"
 	}
 	cfg.JwtValidityDuration = GetJwtValidityDuration()
-	cfg.RacAutoDisable = GetRacAutoDisable()
 	cfg.RacRestrictToSingleNetwork = GetRacRestrictToSingleNetwork()
 	cfg.MetricInterval = GetMetricInterval()
 	cfg.ManageDNS = GetManageDNS()
@@ -126,11 +125,6 @@ func GetJwtValidityDurationFromEnv() int {
 	return defaultDuration
 }
 
-// GetRacAutoDisable - returns whether the feature to autodisable RAC is enabled
-func GetRacAutoDisable() bool {
-	return os.Getenv("RAC_AUTO_DISABLE") == "true"
-}
-
 // GetRacRestrictToSingleNetwork - returns whether the feature to allow simultaneous network connections via RAC is enabled
 func GetRacRestrictToSingleNetwork() bool {
 	return os.Getenv("RAC_RESTRICT_TO_SINGLE_NETWORK") == "true"