Browse Source

Merge branch 'develop' into start-hooks-after-controllers

Gabriel de Souza Seibel 1 year ago
parent
commit
097467118f

+ 5 - 1
cli/cmd/host/update.go

@@ -5,9 +5,10 @@ import (
 	"log"
 	"log"
 	"os"
 	"os"
 
 
+	"github.com/spf13/cobra"
+
 	"github.com/gravitl/netmaker/cli/functions"
 	"github.com/gravitl/netmaker/cli/functions"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
-	"github.com/spf13/cobra"
 )
 )
 
 
 var (
 var (
@@ -18,6 +19,7 @@ var (
 	mtu             int
 	mtu             int
 	isStatic        bool
 	isStatic        bool
 	isDefault       bool
 	isDefault       bool
+	keepAlive       int
 )
 )
 
 
 var hostUpdateCmd = &cobra.Command{
 var hostUpdateCmd = &cobra.Command{
@@ -43,6 +45,7 @@ var hostUpdateCmd = &cobra.Command{
 			apiHost.MTU = mtu
 			apiHost.MTU = mtu
 			apiHost.IsStatic = isStatic
 			apiHost.IsStatic = isStatic
 			apiHost.IsDefault = isDefault
 			apiHost.IsDefault = isDefault
+			apiHost.PersistentKeepalive = keepAlive
 		}
 		}
 		functions.PrettyPrint(functions.UpdateHost(args[0], apiHost))
 		functions.PrettyPrint(functions.UpdateHost(args[0], apiHost))
 	},
 	},
@@ -54,6 +57,7 @@ func init() {
 	hostUpdateCmd.Flags().StringVar(&name, "name", "", "Host name")
 	hostUpdateCmd.Flags().StringVar(&name, "name", "", "Host name")
 	hostUpdateCmd.Flags().IntVar(&listenPort, "listen_port", 0, "Listen port of the host")
 	hostUpdateCmd.Flags().IntVar(&listenPort, "listen_port", 0, "Listen port of the host")
 	hostUpdateCmd.Flags().IntVar(&mtu, "mtu", 0, "Host MTU size")
 	hostUpdateCmd.Flags().IntVar(&mtu, "mtu", 0, "Host MTU size")
+	hostUpdateCmd.Flags().IntVar(&keepAlive, "keep_alive", 0, "Interval (seconds) in which packets are sent to keep connections open with peers")
 	hostUpdateCmd.Flags().BoolVar(&isStatic, "static", false, "Make Host Static ?")
 	hostUpdateCmd.Flags().BoolVar(&isStatic, "static", false, "Make Host Static ?")
 	hostUpdateCmd.Flags().BoolVar(&isDefault, "default", false, "Make Host Default ?")
 	hostUpdateCmd.Flags().BoolVar(&isDefault, "default", false, "Make Host Default ?")
 	rootCmd.AddCommand(hostUpdateCmd)
 	rootCmd.AddCommand(hostUpdateCmd)

+ 0 - 1
cli/cmd/node/flags.go

@@ -11,7 +11,6 @@ var (
 	name                   string
 	name                   string
 	postUp                 string
 	postUp                 string
 	postDown               string
 	postDown               string
-	keepAlive              int
 	relayedNodes           string
 	relayedNodes           string
 	egressGatewayRanges    string
 	egressGatewayRanges    string
 	expirationDateTime     int
 	expirationDateTime     int

+ 0 - 2
cli/cmd/node/update.go

@@ -34,7 +34,6 @@ var nodeUpdateCmd = &cobra.Command{
 			node.Address = address
 			node.Address = address
 			node.Address6 = address6
 			node.Address6 = address6
 			node.LocalAddress = localAddress
 			node.LocalAddress = localAddress
-			node.PersistentKeepalive = int32(keepAlive)
 			if relayedNodes != "" {
 			if relayedNodes != "" {
 				node.RelayedNodes = strings.Split(relayedNodes, ",")
 				node.RelayedNodes = strings.Split(relayedNodes, ",")
 			}
 			}
@@ -61,7 +60,6 @@ func init() {
 	nodeUpdateCmd.Flags().StringVar(&name, "name", "", "Node name")
 	nodeUpdateCmd.Flags().StringVar(&name, "name", "", "Node name")
 	nodeUpdateCmd.Flags().StringVar(&postUp, "post_up", "", "Commands to run after node is up `;` separated")
 	nodeUpdateCmd.Flags().StringVar(&postUp, "post_up", "", "Commands to run after node is up `;` separated")
 	nodeUpdateCmd.Flags().StringVar(&postDown, "post_down", "", "Commands to run after node is down `;` separated")
 	nodeUpdateCmd.Flags().StringVar(&postDown, "post_down", "", "Commands to run after node is down `;` separated")
-	nodeUpdateCmd.Flags().IntVar(&keepAlive, "keep_alive", 0, "Interval in which packets are sent to keep connections open with peers")
 	nodeUpdateCmd.Flags().StringVar(&relayedNodes, "relayed_nodes", "", "relayed nodes if node acts as a relay")
 	nodeUpdateCmd.Flags().StringVar(&relayedNodes, "relayed_nodes", "", "relayed nodes if node acts as a relay")
 	nodeUpdateCmd.Flags().StringVar(&egressGatewayRanges, "egress_addrs", "", "Addresses for egressing traffic if node acts as an egress")
 	nodeUpdateCmd.Flags().StringVar(&egressGatewayRanges, "egress_addrs", "", "Addresses for egressing traffic if node acts as an egress")
 	nodeUpdateCmd.Flags().IntVar(&expirationDateTime, "expiry", 0, "UNIX timestamp after which node will lose access to the network")
 	nodeUpdateCmd.Flags().IntVar(&expirationDateTime, "expiry", 0, "UNIX timestamp after which node will lose access to the network")

+ 0 - 1
compose/docker-compose.yml

@@ -53,7 +53,6 @@ services:
       - "host.docker.internal:host-gateway"
       - "host.docker.internal:host-gateway"
     volumes:
     volumes:
       - ./Caddyfile:/etc/caddy/Caddyfile
       - ./Caddyfile:/etc/caddy/Caddyfile
-      - ./certs:/root/certs
       - caddy_data:/data
       - caddy_data:/data
       - caddy_conf:/config
       - caddy_conf:/config
     ports:
     ports:

+ 46 - 14
controllers/enrollmentkeys.go

@@ -7,6 +7,7 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/gorilla/mux"
 	"github.com/gorilla/mux"
+
 	"github.com/gravitl/netmaker/auth"
 	"github.com/gravitl/netmaker/auth"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
@@ -17,10 +18,14 @@ import (
 )
 )
 
 
 func enrollmentKeyHandlers(r *mux.Router) {
 func enrollmentKeyHandlers(r *mux.Router) {
-	r.HandleFunc("/api/v1/enrollment-keys", logic.SecurityCheck(true, http.HandlerFunc(createEnrollmentKey))).Methods(http.MethodPost)
-	r.HandleFunc("/api/v1/enrollment-keys", logic.SecurityCheck(true, http.HandlerFunc(getEnrollmentKeys))).Methods(http.MethodGet)
-	r.HandleFunc("/api/v1/enrollment-keys/{keyID}", logic.SecurityCheck(true, http.HandlerFunc(deleteEnrollmentKey))).Methods(http.MethodDelete)
-	r.HandleFunc("/api/v1/host/register/{token}", http.HandlerFunc(handleHostRegister)).Methods(http.MethodPost)
+	r.HandleFunc("/api/v1/enrollment-keys", logic.SecurityCheck(true, http.HandlerFunc(createEnrollmentKey))).
+		Methods(http.MethodPost)
+	r.HandleFunc("/api/v1/enrollment-keys", logic.SecurityCheck(true, http.HandlerFunc(getEnrollmentKeys))).
+		Methods(http.MethodGet)
+	r.HandleFunc("/api/v1/enrollment-keys/{keyID}", logic.SecurityCheck(true, http.HandlerFunc(deleteEnrollmentKey))).
+		Methods(http.MethodDelete)
+	r.HandleFunc("/api/v1/host/register/{token}", http.HandlerFunc(handleHostRegister)).
+		Methods(http.MethodPost)
 }
 }
 
 
 // swagger:route GET /api/v1/enrollment-keys enrollmentKeys getEnrollmentKeys
 // swagger:route GET /api/v1/enrollment-keys enrollmentKeys getEnrollmentKeys
@@ -70,7 +75,7 @@ func getEnrollmentKeys(w http.ResponseWriter, r *http.Request) {
 //			Responses:
 //			Responses:
 //				200: okResponse
 //				200: okResponse
 func deleteEnrollmentKey(w http.ResponseWriter, r *http.Request) {
 func deleteEnrollmentKey(w http.ResponseWriter, r *http.Request) {
-	var params = mux.Vars(r)
+	params := mux.Vars(r)
 	keyID := params["keyID"]
 	keyID := params["keyID"]
 	err := logic.DeleteEnrollmentKey(keyID)
 	err := logic.DeleteEnrollmentKey(keyID)
 	if err != nil {
 	if err != nil {
@@ -94,7 +99,6 @@ func deleteEnrollmentKey(w http.ResponseWriter, r *http.Request) {
 //			Responses:
 //			Responses:
 //				200: EnrollmentKey
 //				200: EnrollmentKey
 func createEnrollmentKey(w http.ResponseWriter, r *http.Request) {
 func createEnrollmentKey(w http.ResponseWriter, r *http.Request) {
-
 	var enrollmentKeyBody models.APIEnrollmentKey
 	var enrollmentKeyBody models.APIEnrollmentKey
 
 
 	err := json.NewDecoder(r.Body).Decode(&enrollmentKeyBody)
 	err := json.NewDecoder(r.Body).Decode(&enrollmentKeyBody)
@@ -109,7 +113,13 @@ func createEnrollmentKey(w http.ResponseWriter, r *http.Request) {
 		newTime = time.Unix(enrollmentKeyBody.Expiration, 0)
 		newTime = time.Unix(enrollmentKeyBody.Expiration, 0)
 	}
 	}
 
 
-	newEnrollmentKey, err := logic.CreateEnrollmentKey(enrollmentKeyBody.UsesRemaining, newTime, enrollmentKeyBody.Networks, enrollmentKeyBody.Tags, enrollmentKeyBody.Unlimited)
+	newEnrollmentKey, err := logic.CreateEnrollmentKey(
+		enrollmentKeyBody.UsesRemaining,
+		newTime,
+		enrollmentKeyBody.Networks,
+		enrollmentKeyBody.Tags,
+		enrollmentKeyBody.Unlimited,
+	)
 	if err != nil {
 	if err != nil {
 		logger.Log(0, r.Header.Get("user"), "failed to create enrollment key:", err.Error())
 		logger.Log(0, r.Header.Get("user"), "failed to create enrollment key:", err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
@@ -138,7 +148,7 @@ func createEnrollmentKey(w http.ResponseWriter, r *http.Request) {
 //			Responses:
 //			Responses:
 //				200: RegisterResponse
 //				200: RegisterResponse
 func handleHostRegister(w http.ResponseWriter, r *http.Request) {
 func handleHostRegister(w http.ResponseWriter, r *http.Request) {
-	var params = mux.Vars(r)
+	params := mux.Vars(r)
 	token := params["token"]
 	token := params["token"]
 	logger.Log(0, "received registration attempt with token", token)
 	logger.Log(0, "received registration attempt with token", token)
 	// check if token exists
 	// check if token exists
@@ -156,7 +166,6 @@ func handleHostRegister(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 		return
 	}
 	}
-	hostExists := false
 	// re-register host with turn just in case.
 	// re-register host with turn just in case.
 	if servercfg.IsUsingTurn() {
 	if servercfg.IsUsingTurn() {
 		err = logic.RegisterHostWithTurn(newHost.ID.String(), newHost.HostPass)
 		err = logic.RegisterHostWithTurn(newHost.ID.String(), newHost.HostPass)
@@ -165,9 +174,20 @@ func handleHostRegister(w http.ResponseWriter, r *http.Request) {
 		}
 		}
 	}
 	}
 	// check if host already exists
 	// check if host already exists
+	hostExists := false
 	if hostExists = logic.HostExists(&newHost); hostExists && len(enrollmentKey.Networks) == 0 {
 	if hostExists = logic.HostExists(&newHost); hostExists && len(enrollmentKey.Networks) == 0 {
-		logger.Log(0, "host", newHost.ID.String(), newHost.Name, "attempted to re-register with no networks")
-		logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("host already exists"), "badrequest"))
+		logger.Log(
+			0,
+			"host",
+			newHost.ID.String(),
+			newHost.Name,
+			"attempted to re-register with no networks",
+		)
+		logic.ReturnErrorResponse(
+			w,
+			r,
+			logic.FormatError(fmt.Errorf("host already exists"), "badrequest"),
+		)
 		return
 		return
 	}
 	}
 	// version check
 	// version check
@@ -190,11 +210,16 @@ func handleHostRegister(w http.ResponseWriter, r *http.Request) {
 	// use the token
 	// use the token
 	if ok := logic.TryToUseEnrollmentKey(enrollmentKey); !ok {
 	if ok := logic.TryToUseEnrollmentKey(enrollmentKey); !ok {
 		logger.Log(0, "host", newHost.ID.String(), newHost.Name, "failed registration")
 		logger.Log(0, "host", newHost.ID.String(), newHost.Name, "failed registration")
-		logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("invalid enrollment key"), "badrequest"))
+		logic.ReturnErrorResponse(
+			w,
+			r,
+			logic.FormatError(fmt.Errorf("invalid enrollment key"), "badrequest"),
+		)
 		return
 		return
 	}
 	}
 	hostPass := newHost.HostPass
 	hostPass := newHost.HostPass
 	if !hostExists {
 	if !hostExists {
+		newHost.PersistentKeepalive = models.DefaultPersistentKeepAlive
 		// register host
 		// register host
 		logic.CheckHostPorts(&newHost)
 		logic.CheckHostPorts(&newHost)
 		// create EMQX credentials and ACLs for host
 		// create EMQX credentials and ACLs for host
@@ -209,14 +234,21 @@ func handleHostRegister(w http.ResponseWriter, r *http.Request) {
 			}
 			}
 		}
 		}
 		if err = logic.CreateHost(&newHost); err != nil {
 		if err = logic.CreateHost(&newHost); err != nil {
-			logger.Log(0, "host", newHost.ID.String(), newHost.Name, "failed registration -", err.Error())
+			logger.Log(
+				0,
+				"host",
+				newHost.ID.String(),
+				newHost.Name,
+				"failed registration -",
+				err.Error(),
+			)
 			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 			return
 			return
 		}
 		}
 	} else {
 	} else {
 		// need to revise the list of networks from key
 		// need to revise the list of networks from key
 		// based on the ones host currently has
 		// based on the ones host currently has
-		var networksToAdd = []string{}
+		networksToAdd := []string{}
 		currentNets := logic.GetHostNetworks(newHost.ID.String())
 		currentNets := logic.GetHostNetworks(newHost.ID.String())
 		for _, newNet := range enrollmentKey.Networks {
 		for _, newNet := range enrollmentKey.Networks {
 			if !logic.StringSliceContains(currentNets, newNet) {
 			if !logic.StringSliceContains(currentNets, newNet) {

+ 2 - 2
controllers/hosts.go

@@ -100,13 +100,13 @@ func pull(w http.ResponseWriter, r *http.Request) {
 	}
 	}
 	allNodes, err := logic.GetAllNodes()
 	allNodes, err := logic.GetAllNodes()
 	if err != nil {
 	if err != nil {
-		logger.Log(0, "could not pull peers for host", hostID)
+		logger.Log(0, "failed to get nodes: ", hostID)
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 		return
 	}
 	}
 	hPU, err := logic.GetPeerUpdateForHost("", host, allNodes, nil, nil)
 	hPU, err := logic.GetPeerUpdateForHost("", host, allNodes, nil, nil)
 	if err != nil {
 	if err != nil {
-		logger.Log(0, "could not pull peers for host", hostID)
+		logger.Log(0, "could not pull peers for host", hostID, err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 		return
 	}
 	}

+ 8 - 1
controllers/migrate.go

@@ -140,6 +140,9 @@ func convertLegacyHostNode(legacy models.LegacyNode) (models.Host, models.Node)
 	host.AutoUpdate = servercfg.AutoUpdateEnabled()
 	host.AutoUpdate = servercfg.AutoUpdateEnabled()
 	host.Interface = "netmaker"
 	host.Interface = "netmaker"
 	host.ListenPort = int(legacy.ListenPort)
 	host.ListenPort = int(legacy.ListenPort)
+	if host.ListenPort == 0 {
+		host.ListenPort = 51821
+	}
 	host.MTU = int(legacy.MTU)
 	host.MTU = int(legacy.MTU)
 	host.PublicKey, _ = wgtypes.ParseKey(legacy.PublicKey)
 	host.PublicKey, _ = wgtypes.ParseKey(legacy.PublicKey)
 	host.MacAddress = net.HardwareAddr(legacy.MacAddress)
 	host.MacAddress = net.HardwareAddr(legacy.MacAddress)
@@ -151,6 +154,11 @@ func convertLegacyHostNode(legacy models.LegacyNode) (models.Host, models.Node)
 	host.IsDocker = models.ParseBool(legacy.IsDocker)
 	host.IsDocker = models.ParseBool(legacy.IsDocker)
 	host.IsK8S = models.ParseBool(legacy.IsK8S)
 	host.IsK8S = models.ParseBool(legacy.IsK8S)
 	host.IsStatic = models.ParseBool(legacy.IsStatic)
 	host.IsStatic = models.ParseBool(legacy.IsStatic)
+	host.PersistentKeepalive = time.Duration(legacy.PersistentKeepalive)
+	if host.PersistentKeepalive == 0 {
+		host.PersistentKeepalive = models.DefaultPersistentKeepAlive
+	}
+
 	node := convertLegacyNode(legacy, host.ID)
 	node := convertLegacyNode(legacy, host.ID)
 	return host, node
 	return host, node
 }
 }
@@ -202,7 +210,6 @@ func convertLegacyNode(legacy models.LegacyNode, hostID uuid.UUID) models.Node {
 	node.IsRelay = false
 	node.IsRelay = false
 	node.RelayedNodes = []string{}
 	node.RelayedNodes = []string{}
 	node.DNSOn = models.ParseBool(legacy.DNSOn)
 	node.DNSOn = models.ParseBool(legacy.DNSOn)
-	node.PersistentKeepalive = time.Duration(int64(time.Second) * int64(legacy.PersistentKeepalive))
 	node.LastModified = time.Now()
 	node.LastModified = time.Now()
 	node.ExpirationDateTime = time.Unix(legacy.ExpirationDateTime, 0)
 	node.ExpirationDateTime = time.Unix(legacy.ExpirationDateTime, 0)
 	node.EgressGatewayNatEnabled = models.ParseBool(legacy.EgressGatewayNatEnabled)
 	node.EgressGatewayNatEnabled = models.ParseBool(legacy.EgressGatewayNatEnabled)

+ 37 - 20
controllers/server.go

@@ -6,6 +6,7 @@ import (
 	"strings"
 	"strings"
 
 
 	"github.com/gorilla/mux"
 	"github.com/gorilla/mux"
+
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
@@ -15,24 +16,32 @@ import (
 
 
 func serverHandlers(r *mux.Router) {
 func serverHandlers(r *mux.Router) {
 	// r.HandleFunc("/api/server/addnetwork/{network}", securityCheckServer(true, http.HandlerFunc(addNetwork))).Methods(http.MethodPost)
 	// r.HandleFunc("/api/server/addnetwork/{network}", securityCheckServer(true, http.HandlerFunc(addNetwork))).Methods(http.MethodPost)
-	r.HandleFunc("/api/server/health", http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
-		resp.WriteHeader(http.StatusOK)
-		resp.Write([]byte("Server is up and running!!"))
-	}))
-	r.HandleFunc("/api/server/getconfig", allowUsers(http.HandlerFunc(getConfig))).Methods(http.MethodGet)
-	r.HandleFunc("/api/server/getserverinfo", Authorize(true, false, "node", http.HandlerFunc(getServerInfo))).Methods(http.MethodGet)
+	r.HandleFunc(
+		"/api/server/health",
+		http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
+			resp.WriteHeader(http.StatusOK)
+			resp.Write([]byte("Server is up and running!!"))
+		}),
+	)
+	r.HandleFunc("/api/server/getconfig", allowUsers(http.HandlerFunc(getConfig))).
+		Methods(http.MethodGet)
+	r.HandleFunc("/api/server/getserverinfo", Authorize(true, false, "node", http.HandlerFunc(getServerInfo))).
+		Methods(http.MethodGet)
 	r.HandleFunc("/api/server/status", http.HandlerFunc(getStatus)).Methods(http.MethodGet)
 	r.HandleFunc("/api/server/status", http.HandlerFunc(getStatus)).Methods(http.MethodGet)
-	r.HandleFunc("/api/server/usage", Authorize(true, false, "user", http.HandlerFunc(getUsage))).Methods(http.MethodGet)
+	r.HandleFunc("/api/server/usage", Authorize(true, false, "user", http.HandlerFunc(getUsage))).
+		Methods(http.MethodGet)
 }
 }
 
 
-func getUsage(w http.ResponseWriter, r *http.Request) {
+func getUsage(w http.ResponseWriter, _ *http.Request) {
 	type usage struct {
 	type usage struct {
-		Hosts     int `json:"hosts"`
-		Clients   int `json:"clients"`
-		Networks  int `json:"networks"`
-		Users     int `json:"users"`
-		Ingresses int `json:"ingresses"`
-		Egresses  int `json:"egresses"`
+		Hosts            int `json:"hosts"`
+		Clients          int `json:"clients"`
+		Networks         int `json:"networks"`
+		Users            int `json:"users"`
+		Ingresses        int `json:"ingresses"`
+		Egresses         int `json:"egresses"`
+		Relays           int `json:"relays"`
+		InternetGateways int `json:"internet_gateways"`
 	}
 	}
 	var serverUsage usage
 	var serverUsage usage
 	hosts, err := logic.GetAllHosts()
 	hosts, err := logic.GetAllHosts()
@@ -51,6 +60,7 @@ func getUsage(w http.ResponseWriter, r *http.Request) {
 	if err == nil {
 	if err == nil {
 		serverUsage.Networks = len(networks)
 		serverUsage.Networks = len(networks)
 	}
 	}
+	// TODO this part bellow can be optimized to get nodes just once
 	ingresses, err := logic.GetAllIngresses()
 	ingresses, err := logic.GetAllIngresses()
 	if err == nil {
 	if err == nil {
 		serverUsage.Ingresses = len(ingresses)
 		serverUsage.Ingresses = len(ingresses)
@@ -59,12 +69,19 @@ func getUsage(w http.ResponseWriter, r *http.Request) {
 	if err == nil {
 	if err == nil {
 		serverUsage.Egresses = len(egresses)
 		serverUsage.Egresses = len(egresses)
 	}
 	}
+	relays, err := logic.GetRelays()
+	if err == nil {
+		serverUsage.Relays = len(relays)
+	}
+	gateways, err := logic.GetInternetGateways()
+	if err == nil {
+		serverUsage.InternetGateways = len(gateways)
+	}
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")
 	json.NewEncoder(w).Encode(models.SuccessResponse{
 	json.NewEncoder(w).Encode(models.SuccessResponse{
 		Code:     http.StatusOK,
 		Code:     http.StatusOK,
 		Response: serverUsage,
 		Response: serverUsage,
 	})
 	})
-
 }
 }
 
 
 // swagger:route GET /api/server/status server getStatus
 // swagger:route GET /api/server/status server getStatus
@@ -105,12 +122,12 @@ func getStatus(w http.ResponseWriter, r *http.Request) {
 // allowUsers - allow all authenticated (valid) users - only used by getConfig, may be able to remove during refactor
 // allowUsers - allow all authenticated (valid) users - only used by getConfig, may be able to remove during refactor
 func allowUsers(next http.Handler) http.HandlerFunc {
 func allowUsers(next http.Handler) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 	return func(w http.ResponseWriter, r *http.Request) {
-		var errorResponse = models.ErrorResponse{
+		errorResponse := models.ErrorResponse{
 			Code: http.StatusUnauthorized, Message: logic.Unauthorized_Msg,
 			Code: http.StatusUnauthorized, Message: logic.Unauthorized_Msg,
 		}
 		}
 		bearerToken := r.Header.Get("Authorization")
 		bearerToken := r.Header.Get("Authorization")
-		var tokenSplit = strings.Split(bearerToken, " ")
-		var authToken = ""
+		tokenSplit := strings.Split(bearerToken, " ")
+		authToken := ""
 		if len(tokenSplit) < 2 {
 		if len(tokenSplit) < 2 {
 			logic.ReturnErrorResponse(w, r, errorResponse)
 			logic.ReturnErrorResponse(w, r, errorResponse)
 			return
 			return
@@ -144,7 +161,7 @@ func getServerInfo(w http.ResponseWriter, r *http.Request) {
 	// get params
 	// get params
 
 
 	json.NewEncoder(w).Encode(servercfg.GetServerInfo())
 	json.NewEncoder(w).Encode(servercfg.GetServerInfo())
-	//w.WriteHeader(http.StatusOK)
+	// w.WriteHeader(http.StatusOK)
 }
 }
 
 
 // swagger:route GET /api/server/getconfig server getConfig
 // swagger:route GET /api/server/getconfig server getConfig
@@ -170,5 +187,5 @@ func getConfig(w http.ResponseWriter, r *http.Request) {
 		scfg.IsPro = "yes"
 		scfg.IsPro = "yes"
 	}
 	}
 	json.NewEncoder(w).Encode(scfg)
 	json.NewEncoder(w).Encode(scfg)
-	//w.WriteHeader(http.StatusOK)
+	// w.WriteHeader(http.StatusOK)
 }
 }

+ 0 - 5
docker/Caddyfile

@@ -1,6 +1,5 @@
 # Dashboard
 # Dashboard
 https://dashboard.{$NM_DOMAIN} {
 https://dashboard.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	# Apply basic security headers
 	# Apply basic security headers
 	header {
 	header {
 		# Enable cross origin access to *.{$NM_DOMAIN}
 		# Enable cross origin access to *.{$NM_DOMAIN}
@@ -22,24 +21,20 @@ https://dashboard.{$NM_DOMAIN} {
 
 
 # API
 # API
 https://api.{$NM_DOMAIN} {
 https://api.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy http://netmaker:8081
 	reverse_proxy http://netmaker:8081
 }
 }
 
 
 # TURN
 # TURN
 https://turn.{$NM_DOMAIN} {
 https://turn.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy host.docker.internal:3479
 	reverse_proxy host.docker.internal:3479
 }
 }
 
 
 # TURN API
 # TURN API
 https://turnapi.{$NM_DOMAIN} {
 https://turnapi.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy http://host.docker.internal:8089
 	reverse_proxy http://host.docker.internal:8089
 }
 }
 
 
 # MQ
 # MQ
 wss://broker.{$NM_DOMAIN} {
 wss://broker.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy ws://mq:8883 # For EMQX websockets use `reverse_proxy ws://mq:8083`
 	reverse_proxy ws://mq:8883 # For EMQX websockets use `reverse_proxy ws://mq:8083`
 }
 }

+ 0 - 8
docker/Caddyfile-pro

@@ -1,6 +1,5 @@
 # Dashboard
 # Dashboard
 https://dashboard.{$NM_DOMAIN} {
 https://dashboard.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	# Apply basic security headers
 	# Apply basic security headers
 	header {
 	header {
 		# Enable cross origin access to *.{$NM_DOMAIN}
 		# Enable cross origin access to *.{$NM_DOMAIN}
@@ -22,42 +21,35 @@ https://dashboard.{$NM_DOMAIN} {
 
 
 # Netmaker Exporter
 # Netmaker Exporter
 https://netmaker-exporter.{$NM_DOMAIN} {
 https://netmaker-exporter.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy http://netmaker-exporter:8085
 	reverse_proxy http://netmaker-exporter:8085
 }
 }
 
 
 # Prometheus
 # Prometheus
 https://prometheus.{$NM_DOMAIN} {
 https://prometheus.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy http://prometheus:9090
 	reverse_proxy http://prometheus:9090
 }
 }
 
 
 # Grafana
 # Grafana
 https://grafana.{$NM_DOMAIN} {
 https://grafana.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy http://grafana:3000
 	reverse_proxy http://grafana:3000
 }
 }
 
 
 # API
 # API
 https://api.{$NM_DOMAIN} {
 https://api.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy http://netmaker:8081
 	reverse_proxy http://netmaker:8081
 }
 }
 
 
 # TURN
 # TURN
 https://turn.{$NM_DOMAIN} {
 https://turn.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy host.docker.internal:3479
 	reverse_proxy host.docker.internal:3479
 }
 }
 
 
 # TURN API
 # TURN API
 https://turnapi.{$NM_DOMAIN} {
 https://turnapi.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy http://host.docker.internal:8089
 	reverse_proxy http://host.docker.internal:8089
 }
 }
 
 
 # MQ
 # MQ
 wss://broker.{$NM_DOMAIN} {
 wss://broker.{$NM_DOMAIN} {
-	tls /root/certs/fullchain.pem /root/certs/privkey.pem
 	reverse_proxy ws://mq:8883
 	reverse_proxy ws://mq:8883
 }
 }

+ 1 - 0
logic/auth.go

@@ -112,6 +112,7 @@ func CreateSuperAdmin(u *models.User) error {
 		return errors.New("superadmin user already exists")
 		return errors.New("superadmin user already exists")
 	}
 	}
 	u.IsSuperAdmin = true
 	u.IsSuperAdmin = true
+	u.IsAdmin = false
 	return CreateUser(u)
 	return CreateUser(u)
 }
 }
 
 

+ 22 - 2
logic/gateway.go

@@ -11,7 +11,27 @@ import (
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
 )
 )
 
 
-// GetAllIngresses - gets all the hosts that are ingresses
+// GetInternetGateways - gets all the nodes that are internet gateways
+func GetInternetGateways() ([]models.Node, error) {
+	nodes, err := GetAllNodes()
+	if err != nil {
+		return nil, err
+	}
+	igs := make([]models.Node, 0)
+	for _, node := range nodes {
+		if !node.IsEgressGateway {
+			continue
+		}
+		for _, ran := range node.EgressGatewayRanges {
+			if ran == "0.0.0.0/0" {
+				igs = append(igs, node)
+			}
+		}
+	}
+	return igs, nil
+}
+
+// GetAllIngresses - gets all the nodes that are ingresses
 func GetAllIngresses() ([]models.Node, error) {
 func GetAllIngresses() ([]models.Node, error) {
 	nodes, err := GetAllNodes()
 	nodes, err := GetAllNodes()
 	if err != nil {
 	if err != nil {
@@ -26,7 +46,7 @@ func GetAllIngresses() ([]models.Node, error) {
 	return ingresses, nil
 	return ingresses, nil
 }
 }
 
 
-// GetAllEgresses - gets all the hosts that are egresses
+// GetAllEgresses - gets all the nodes that are egresses
 func GetAllEgresses() ([]models.Node, error) {
 func GetAllEgresses() ([]models.Node, error) {
 	nodes, err := GetAllNodes()
 	nodes, err := GetAllNodes()
 	if err != nil {
 	if err != nil {

+ 9 - 7
logic/hosts.go

@@ -13,11 +13,12 @@ import (
 
 
 	"github.com/devilcove/httpclient"
 	"github.com/devilcove/httpclient"
 	"github.com/google/uuid"
 	"github.com/google/uuid"
+	"golang.org/x/crypto/bcrypt"
+
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
-	"golang.org/x/crypto/bcrypt"
 )
 )
 
 
 var (
 var (
@@ -66,6 +67,7 @@ func deleteHostFromCache(hostID string) {
 	delete(hostsCacheMap, hostID)
 	delete(hostsCacheMap, hostID)
 	hostCacheMutex.Unlock()
 	hostCacheMutex.Unlock()
 }
 }
+
 func loadHostsIntoCache(hMap map[string]models.Host) {
 func loadHostsIntoCache(hMap map[string]models.Host) {
 	hostCacheMutex.Lock()
 	hostCacheMutex.Lock()
 	hostsCacheMap = hMap
 	hostsCacheMap = hMap
@@ -79,7 +81,6 @@ const (
 
 
 // GetAllHosts - returns all hosts in flat list or error
 // GetAllHosts - returns all hosts in flat list or error
 func GetAllHosts() ([]models.Host, error) {
 func GetAllHosts() ([]models.Host, error) {
-
 	currHosts := getHostsFromCache()
 	currHosts := getHostsFromCache()
 	if len(currHosts) != 0 {
 	if len(currHosts) != 0 {
 		return currHosts, nil
 		return currHosts, nil
@@ -139,7 +140,6 @@ func GetHostsMap() (map[string]models.Host, error) {
 
 
 // GetHost - gets a host from db given id
 // GetHost - gets a host from db given id
 func GetHost(hostid string) (*models.Host, error) {
 func GetHost(hostid string) (*models.Host, error) {
-
 	if host, ok := getHostFromCache(hostid); ok {
 	if host, ok := getHostFromCache(hostid); ok {
 		return &host, nil
 		return &host, nil
 	}
 	}
@@ -217,11 +217,13 @@ func UpdateHost(newHost, currentHost *models.Host) {
 		newHost.ListenPort = currentHost.ListenPort
 		newHost.ListenPort = currentHost.ListenPort
 	}
 	}
 
 
+	if newHost.PersistentKeepalive == 0 {
+		newHost.PersistentKeepalive = currentHost.PersistentKeepalive
+	}
 }
 }
 
 
 // UpdateHostFromClient - used for updating host on server with update recieved from client
 // UpdateHostFromClient - used for updating host on server with update recieved from client
 func UpdateHostFromClient(newHost, currHost *models.Host) (sendPeerUpdate bool) {
 func UpdateHostFromClient(newHost, currHost *models.Host) (sendPeerUpdate bool) {
-
 	if newHost.PublicKey != currHost.PublicKey {
 	if newHost.PublicKey != currHost.PublicKey {
 		currHost.PublicKey = newHost.PublicKey
 		currHost.PublicKey = newHost.PublicKey
 		sendPeerUpdate = true
 		sendPeerUpdate = true
@@ -230,7 +232,8 @@ func UpdateHostFromClient(newHost, currHost *models.Host) (sendPeerUpdate bool)
 		currHost.ListenPort = newHost.ListenPort
 		currHost.ListenPort = newHost.ListenPort
 		sendPeerUpdate = true
 		sendPeerUpdate = true
 	}
 	}
-	if newHost.WgPublicListenPort != 0 && currHost.WgPublicListenPort != newHost.WgPublicListenPort {
+	if newHost.WgPublicListenPort != 0 &&
+		currHost.WgPublicListenPort != newHost.WgPublicListenPort {
 		currHost.WgPublicListenPort = newHost.WgPublicListenPort
 		currHost.WgPublicListenPort = newHost.WgPublicListenPort
 		sendPeerUpdate = true
 		sendPeerUpdate = true
 	}
 	}
@@ -488,7 +491,7 @@ func CheckHostPorts(h *models.Host) {
 	}
 	}
 	for _, host := range hosts {
 	for _, host := range hosts {
 		if host.ID.String() == h.ID.String() {
 		if host.ID.String() == h.ID.String() {
-			//skip self
+			// skip self
 			continue
 			continue
 		}
 		}
 		if !host.EndpointIP.Equal(h.EndpointIP) {
 		if !host.EndpointIP.Equal(h.EndpointIP) {
@@ -503,7 +506,6 @@ func CheckHostPorts(h *models.Host) {
 			h.ListenPort = minPort
 			h.ListenPort = minPort
 		}
 		}
 	}
 	}
-
 }
 }
 
 
 // HostExists - checks if given host already exists
 // HostExists - checks if given host already exists

+ 0 - 3
logic/nodes.go

@@ -350,9 +350,6 @@ func SetNodeDefaults(node *models.Node) {
 		node.DefaultACL = parentNetwork.DefaultACL
 		node.DefaultACL = parentNetwork.DefaultACL
 	}
 	}
 
 
-	if node.PersistentKeepalive == 0 {
-		node.PersistentKeepalive = time.Second * time.Duration(parentNetwork.DefaultKeepalive)
-	}
 	node.SetLastModified()
 	node.SetLastModified()
 	node.SetLastCheckIn()
 	node.SetLastCheckIn()
 	node.SetDefaultConnected()
 	node.SetDefaultConnected()

+ 6 - 6
logic/peers.go

@@ -64,7 +64,7 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
 				}
 				}
 				relayPeer := wgtypes.PeerConfig{
 				relayPeer := wgtypes.PeerConfig{
 					PublicKey:                   relayHost.PublicKey,
 					PublicKey:                   relayHost.PublicKey,
-					PersistentKeepaliveInterval: &relayNode.PersistentKeepalive,
+					PersistentKeepaliveInterval: &relayHost.PersistentKeepalive,
 					ReplaceAllowedIPs:           true,
 					ReplaceAllowedIPs:           true,
 					AllowedIPs:                  GetAllowedIPs(&node, &relayNode, nil),
 					AllowedIPs:                  GetAllowedIPs(&node, &relayNode, nil),
 				}
 				}
@@ -111,18 +111,18 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
 			peer := peer
 			peer := peer
 			if peer.ID.String() == node.ID.String() {
 			if peer.ID.String() == node.ID.String() {
 				logger.Log(2, "peer update, skipping self")
 				logger.Log(2, "peer update, skipping self")
-				//skip yourself
+				// skip yourself
 				continue
 				continue
 			}
 			}
 
 
 			peerHost, err := GetHost(peer.HostID.String())
 			peerHost, err := GetHost(peer.HostID.String())
 			if err != nil {
 			if err != nil {
 				logger.Log(1, "no peer host", peer.HostID.String(), err.Error())
 				logger.Log(1, "no peer host", peer.HostID.String(), err.Error())
-				return models.HostPeerUpdate{}, err
+				continue
 			}
 			}
 			peerConfig := wgtypes.PeerConfig{
 			peerConfig := wgtypes.PeerConfig{
 				PublicKey:                   peerHost.PublicKey,
 				PublicKey:                   peerHost.PublicKey,
-				PersistentKeepaliveInterval: &peer.PersistentKeepalive,
+				PersistentKeepaliveInterval: &peerHost.PersistentKeepalive,
 				ReplaceAllowedIPs:           true,
 				ReplaceAllowedIPs:           true,
 			}
 			}
 			if peer.IsEgressGateway {
 			if peer.IsEgressGateway {
@@ -390,7 +390,7 @@ func GetEgressIPs(peer *models.Node) []net.IPNet {
 		logger.Log(0, "error retrieving host for peer", peer.ID.String(), err.Error())
 		logger.Log(0, "error retrieving host for peer", peer.ID.String(), err.Error())
 	}
 	}
 
 
-	//check for internet gateway
+	// check for internet gateway
 	internetGateway := false
 	internetGateway := false
 	if slices.Contains(peer.EgressGatewayRanges, "0.0.0.0/0") || slices.Contains(peer.EgressGatewayRanges, "::/0") {
 	if slices.Contains(peer.EgressGatewayRanges, "0.0.0.0/0") || slices.Contains(peer.EgressGatewayRanges, "::/0") {
 		internetGateway = true
 		internetGateway = true
@@ -439,7 +439,7 @@ func getNodeAllowedIPs(peer, node *models.Node) []net.IPNet {
 	}
 	}
 	// handle egress gateway peers
 	// handle egress gateway peers
 	if peer.IsEgressGateway {
 	if peer.IsEgressGateway {
-		//hasGateway = true
+		// hasGateway = true
 		egressIPs := GetEgressIPs(peer)
 		egressIPs := GetEgressIPs(peer)
 		allowedips = append(allowedips, egressIPs...)
 		allowedips = append(allowedips, egressIPs...)
 	}
 	}

+ 4 - 0
logic/relay.go

@@ -5,6 +5,10 @@ import (
 	"net"
 	"net"
 )
 )
 
 
+var GetRelays = func() ([]models.Node, error) {
+	return []models.Node{}, nil
+}
+
 var RelayedAllowedIPs = func(peer, node *models.Node) []net.IPNet {
 var RelayedAllowedIPs = func(peer, node *models.Node) []net.IPNet {
 	return []net.IPNet{}
 	return []net.IPNet{}
 }
 }

+ 0 - 1
logic/wireguard.go

@@ -12,7 +12,6 @@ func IfaceDelta(currentNode *models.Node, newNode *models.Node) bool {
 		newNode.IsEgressGateway != currentNode.IsEgressGateway ||
 		newNode.IsEgressGateway != currentNode.IsEgressGateway ||
 		newNode.IsIngressGateway != currentNode.IsIngressGateway ||
 		newNode.IsIngressGateway != currentNode.IsIngressGateway ||
 		newNode.IsRelay != currentNode.IsRelay ||
 		newNode.IsRelay != currentNode.IsRelay ||
-		newNode.PersistentKeepalive != currentNode.PersistentKeepalive ||
 		newNode.DNSOn != currentNode.DNSOn ||
 		newNode.DNSOn != currentNode.DNSOn ||
 		newNode.Connected != currentNode.Connected {
 		newNode.Connected != currentNode.Connected {
 		return true
 		return true

+ 31 - 3
migrate/migrate.go

@@ -3,17 +3,19 @@ package migrate
 import (
 import (
 	"encoding/json"
 	"encoding/json"
 
 
+	"golang.org/x/exp/slog"
+
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
-	"golang.org/x/exp/slog"
 )
 )
 
 
 // Run - runs all migrations
 // Run - runs all migrations
 func Run() {
 func Run() {
 	updateEnrollmentKeys()
 	updateEnrollmentKeys()
 	assignSuperAdmin()
 	assignSuperAdmin()
+	updateHosts()
 }
 }
 
 
 func assignSuperAdmin() {
 func assignSuperAdmin() {
@@ -37,7 +39,13 @@ func assignSuperAdmin() {
 			user.IsAdmin = false
 			user.IsAdmin = false
 			err = logic.UpsertUser(*user)
 			err = logic.UpsertUser(*user)
 			if err != nil {
 			if err != nil {
-				slog.Error("error updating user to superadmin", "user", user.UserName, "error", err.Error())
+				slog.Error(
+					"error updating user to superadmin",
+					"user",
+					user.UserName,
+					"error",
+					err.Error(),
+				)
 				continue
 				continue
 			} else {
 			} else {
 				createdSuperAdmin = true
 				createdSuperAdmin = true
@@ -49,7 +57,6 @@ func assignSuperAdmin() {
 	if !createdSuperAdmin {
 	if !createdSuperAdmin {
 		slog.Error("failed to create superadmin!!")
 		slog.Error("failed to create superadmin!!")
 	}
 	}
-
 }
 }
 
 
 func updateEnrollmentKeys() {
 func updateEnrollmentKeys() {
@@ -87,3 +94,24 @@ func updateEnrollmentKeys() {
 
 
 	}
 	}
 }
 }
+
+func updateHosts() {
+	rows, err := database.FetchRecords(database.HOSTS_TABLE_NAME)
+	if err != nil {
+		logger.Log(0, "failed to fetch database records for hosts")
+	}
+	for _, row := range rows {
+		var host models.Host
+		if err := json.Unmarshal([]byte(row), &host); err != nil {
+			logger.Log(0, "failed to unmarshal database row to host", "row", row)
+			continue
+		}
+		if host.PersistentKeepalive == 0 {
+			host.PersistentKeepalive = models.DefaultPersistentKeepAlive
+			if err := logic.UpsertHost(&host); err != nil {
+				logger.Log(0, "failed to upsert host", host.ID.String())
+				continue
+			}
+		}
+	}
+}

+ 27 - 24
models/api_host.go

@@ -3,33 +3,35 @@ package models
 import (
 import (
 	"net"
 	"net"
 	"strings"
 	"strings"
+	"time"
 )
 )
 
 
 // ApiHost - the host struct for API usage
 // ApiHost - the host struct for API usage
 type ApiHost struct {
 type ApiHost struct {
-	ID                 string   `json:"id"`
-	Verbosity          int      `json:"verbosity"`
-	FirewallInUse      string   `json:"firewallinuse"`
-	Version            string   `json:"version"`
-	Name               string   `json:"name"`
-	OS                 string   `json:"os"`
-	Debug              bool     `json:"debug"`
-	IsStatic           bool     `json:"isstatic"`
-	ListenPort         int      `json:"listenport"`
-	WgPublicListenPort int      `json:"wg_public_listen_port" yaml:"wg_public_listen_port"`
-	MTU                int      `json:"mtu" yaml:"mtu"`
-	Interfaces         []Iface  `json:"interfaces" yaml:"interfaces"`
-	DefaultInterface   string   `json:"defaultinterface" yaml:"defautlinterface"`
-	EndpointIP         string   `json:"endpointip" yaml:"endpointip"`
-	PublicKey          string   `json:"publickey"`
-	MacAddress         string   `json:"macaddress"`
-	Nodes              []string `json:"nodes"`
-	IsDefault          bool     `json:"isdefault" yaml:"isdefault"`
-	IsRelayed          bool     `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"`
-	RelayedBy          string   `json:"relayed_by" bson:"relayed_by" yaml:"relayed_by"`
-	IsRelay            bool     `json:"isrelay" bson:"isrelay" yaml:"isrelay"`
-	RelayedHosts       []string `json:"relay_hosts" bson:"relay_hosts" yaml:"relay_hosts"`
-	NatType            string   `json:"nat_type" yaml:"nat_type"`
+	ID                  string   `json:"id"`
+	Verbosity           int      `json:"verbosity"`
+	FirewallInUse       string   `json:"firewallinuse"`
+	Version             string   `json:"version"`
+	Name                string   `json:"name"`
+	OS                  string   `json:"os"`
+	Debug               bool     `json:"debug"`
+	IsStatic            bool     `json:"isstatic"`
+	ListenPort          int      `json:"listenport"`
+	WgPublicListenPort  int      `json:"wg_public_listen_port" yaml:"wg_public_listen_port"`
+	MTU                 int      `json:"mtu"                   yaml:"mtu"`
+	Interfaces          []Iface  `json:"interfaces"            yaml:"interfaces"`
+	DefaultInterface    string   `json:"defaultinterface"      yaml:"defautlinterface"`
+	EndpointIP          string   `json:"endpointip"            yaml:"endpointip"`
+	PublicKey           string   `json:"publickey"`
+	MacAddress          string   `json:"macaddress"`
+	Nodes               []string `json:"nodes"`
+	IsDefault           bool     `json:"isdefault"             yaml:"isdefault"`
+	IsRelayed           bool     `json:"isrelayed"             yaml:"isrelayed"             bson:"isrelayed"`
+	RelayedBy           string   `json:"relayed_by"            yaml:"relayed_by"            bson:"relayed_by"`
+	IsRelay             bool     `json:"isrelay"               yaml:"isrelay"               bson:"isrelay"`
+	RelayedHosts        []string `json:"relay_hosts"           yaml:"relay_hosts"           bson:"relay_hosts"`
+	NatType             string   `json:"nat_type"              yaml:"nat_type"`
+	PersistentKeepalive int      `json:"persistentkeepalive"   yaml:"persistentkeepalive"`
 }
 }
 
 
 // Host.ConvertNMHostToAPI - converts a Netmaker host to an API editable host
 // Host.ConvertNMHostToAPI - converts a Netmaker host to an API editable host
@@ -57,6 +59,7 @@ func (h *Host) ConvertNMHostToAPI() *ApiHost {
 	a.Version = h.Version
 	a.Version = h.Version
 	a.IsDefault = h.IsDefault
 	a.IsDefault = h.IsDefault
 	a.NatType = h.NatType
 	a.NatType = h.NatType
+	a.PersistentKeepalive = int(h.PersistentKeepalive.Seconds())
 	return &a
 	return &a
 }
 }
 
 
@@ -94,6 +97,6 @@ func (a *ApiHost) ConvertAPIHostToNMHost(currentHost *Host) *Host {
 	h.IsDefault = a.IsDefault
 	h.IsDefault = a.IsDefault
 	h.NatType = currentHost.NatType
 	h.NatType = currentHost.NatType
 	h.TurnEndpoint = currentHost.TurnEndpoint
 	h.TurnEndpoint = currentHost.TurnEndpoint
-
+	h.PersistentKeepalive = time.Duration(a.PersistentKeepalive) * time.Second
 	return &h
 	return &h
 }
 }

+ 0 - 3
models/api_node.go

@@ -15,7 +15,6 @@ type ApiNode struct {
 	Address6                string   `json:"address6" validate:"omitempty,ipv6"`
 	Address6                string   `json:"address6" validate:"omitempty,ipv6"`
 	LocalAddress            string   `json:"localaddress" validate:"omitempty,ipv4"`
 	LocalAddress            string   `json:"localaddress" validate:"omitempty,ipv4"`
 	AllowedIPs              []string `json:"allowedips"`
 	AllowedIPs              []string `json:"allowedips"`
-	PersistentKeepalive     int32    `json:"persistentkeepalive"`
 	LastModified            int64    `json:"lastmodified"`
 	LastModified            int64    `json:"lastmodified"`
 	ExpirationDateTime      int64    `json:"expdatetime"`
 	ExpirationDateTime      int64    `json:"expdatetime"`
 	LastCheckIn             int64    `json:"lastcheckin"`
 	LastCheckIn             int64    `json:"lastcheckin"`
@@ -68,7 +67,6 @@ func (a *ApiNode) ConvertToServerNode(currentNode *Node) *Node {
 	convertedNode.IngressDNS = a.IngressDns
 	convertedNode.IngressDNS = a.IngressDns
 	convertedNode.EgressGatewayRequest = currentNode.EgressGatewayRequest
 	convertedNode.EgressGatewayRequest = currentNode.EgressGatewayRequest
 	convertedNode.EgressGatewayNatEnabled = currentNode.EgressGatewayNatEnabled
 	convertedNode.EgressGatewayNatEnabled = currentNode.EgressGatewayNatEnabled
-	convertedNode.PersistentKeepalive = time.Second * time.Duration(a.PersistentKeepalive)
 	convertedNode.RelayedNodes = a.RelayedNodes
 	convertedNode.RelayedNodes = a.RelayedNodes
 	convertedNode.DefaultACL = a.DefaultACL
 	convertedNode.DefaultACL = a.DefaultACL
 	convertedNode.OwnerID = currentNode.OwnerID
 	convertedNode.OwnerID = currentNode.OwnerID
@@ -127,7 +125,6 @@ func (nm *Node) ConvertToAPINode() *ApiNode {
 	if isEmptyAddr(apiNode.LocalAddress) {
 	if isEmptyAddr(apiNode.LocalAddress) {
 		apiNode.LocalAddress = ""
 		apiNode.LocalAddress = ""
 	}
 	}
-	apiNode.PersistentKeepalive = int32(nm.PersistentKeepalive.Seconds())
 	apiNode.LastModified = nm.LastModified.Unix()
 	apiNode.LastModified = nm.LastModified.Unix()
 	apiNode.LastCheckIn = nm.LastCheckIn.Unix()
 	apiNode.LastCheckIn = nm.LastCheckIn.Unix()
 	apiNode.LastPeerUpdate = nm.LastPeerUpdate.Unix()
 	apiNode.LastPeerUpdate = nm.LastPeerUpdate.Unix()

+ 34 - 29
models/host.go

@@ -3,6 +3,7 @@ package models
 import (
 import (
 	"net"
 	"net"
 	"net/netip"
 	"net/netip"
+	"time"
 
 
 	"github.com/google/uuid"
 	"github.com/google/uuid"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
@@ -33,38 +34,42 @@ var NAT_Types = struct {
 }
 }
 
 
 // WIREGUARD_INTERFACE name of wireguard interface
 // WIREGUARD_INTERFACE name of wireguard interface
-const WIREGUARD_INTERFACE = "netmaker"
+const (
+	WIREGUARD_INTERFACE        = "netmaker"
+	DefaultPersistentKeepAlive = 20 * time.Second
+)
 
 
 // Host - represents a host on the network
 // Host - represents a host on the network
 type Host struct {
 type Host struct {
-	ID                 uuid.UUID        `json:"id" yaml:"id"`
-	Verbosity          int              `json:"verbosity" yaml:"verbosity"`
-	FirewallInUse      string           `json:"firewallinuse" yaml:"firewallinuse"`
-	Version            string           `json:"version" yaml:"version"`
-	IPForwarding       bool             `json:"ipforwarding" yaml:"ipforwarding"`
-	DaemonInstalled    bool             `json:"daemoninstalled" yaml:"daemoninstalled"`
-	AutoUpdate         bool             `json:"autoupdate" yaml:"autoupdate"`
-	HostPass           string           `json:"hostpass" yaml:"hostpass"`
-	Name               string           `json:"name" yaml:"name"`
-	OS                 string           `json:"os" yaml:"os"`
-	Interface          string           `json:"interface" yaml:"interface"`
-	Debug              bool             `json:"debug" yaml:"debug"`
-	ListenPort         int              `json:"listenport" yaml:"listenport"`
-	WgPublicListenPort int              `json:"wg_public_listen_port" yaml:"wg_public_listen_port"`
-	MTU                int              `json:"mtu" yaml:"mtu"`
-	PublicKey          wgtypes.Key      `json:"publickey" yaml:"publickey"`
-	MacAddress         net.HardwareAddr `json:"macaddress" yaml:"macaddress"`
-	TrafficKeyPublic   []byte           `json:"traffickeypublic" yaml:"traffickeypublic"`
-	Nodes              []string         `json:"nodes" yaml:"nodes"`
-	Interfaces         []Iface          `json:"interfaces" yaml:"interfaces"`
-	DefaultInterface   string           `json:"defaultinterface" yaml:"defaultinterface"`
-	EndpointIP         net.IP           `json:"endpointip" yaml:"endpointip"`
-	IsDocker           bool             `json:"isdocker" yaml:"isdocker"`
-	IsK8S              bool             `json:"isk8s" yaml:"isk8s"`
-	IsStatic           bool             `json:"isstatic" yaml:"isstatic"`
-	IsDefault          bool             `json:"isdefault" yaml:"isdefault"`
-	NatType            string           `json:"nat_type,omitempty" yaml:"nat_type,omitempty"`
-	TurnEndpoint       *netip.AddrPort  `json:"turn_endpoint,omitempty" yaml:"turn_endpoint,omitempty"`
+	ID                  uuid.UUID        `json:"id"                      yaml:"id"`
+	Verbosity           int              `json:"verbosity"               yaml:"verbosity"`
+	FirewallInUse       string           `json:"firewallinuse"           yaml:"firewallinuse"`
+	Version             string           `json:"version"                 yaml:"version"`
+	IPForwarding        bool             `json:"ipforwarding"            yaml:"ipforwarding"`
+	DaemonInstalled     bool             `json:"daemoninstalled"         yaml:"daemoninstalled"`
+	AutoUpdate          bool             `json:"autoupdate"              yaml:"autoupdate"`
+	HostPass            string           `json:"hostpass"                yaml:"hostpass"`
+	Name                string           `json:"name"                    yaml:"name"`
+	OS                  string           `json:"os"                      yaml:"os"`
+	Interface           string           `json:"interface"               yaml:"interface"`
+	Debug               bool             `json:"debug"                   yaml:"debug"`
+	ListenPort          int              `json:"listenport"              yaml:"listenport"`
+	WgPublicListenPort  int              `json:"wg_public_listen_port"   yaml:"wg_public_listen_port"`
+	MTU                 int              `json:"mtu"                     yaml:"mtu"`
+	PublicKey           wgtypes.Key      `json:"publickey"               yaml:"publickey"`
+	MacAddress          net.HardwareAddr `json:"macaddress"              yaml:"macaddress"`
+	TrafficKeyPublic    []byte           `json:"traffickeypublic"        yaml:"traffickeypublic"`
+	Nodes               []string         `json:"nodes"                   yaml:"nodes"`
+	Interfaces          []Iface          `json:"interfaces"              yaml:"interfaces"`
+	DefaultInterface    string           `json:"defaultinterface"        yaml:"defaultinterface"`
+	EndpointIP          net.IP           `json:"endpointip"              yaml:"endpointip"`
+	IsDocker            bool             `json:"isdocker"                yaml:"isdocker"`
+	IsK8S               bool             `json:"isk8s"                   yaml:"isk8s"`
+	IsStatic            bool             `json:"isstatic"                yaml:"isstatic"`
+	IsDefault           bool             `json:"isdefault"               yaml:"isdefault"`
+	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"     yaml:"persistentkeepalive"`
 }
 }
 
 
 // FormatBool converts a boolean to a [yes|no] string
 // FormatBool converts a boolean to a [yes|no] string

+ 21 - 25
models/node.go

@@ -54,28 +54,27 @@ type Iface struct {
 
 
 // CommonNode - represents a commonn node data elements shared by netmaker and netclient
 // CommonNode - represents a commonn node data elements shared by netmaker and netclient
 type CommonNode struct {
 type CommonNode struct {
-	ID                  uuid.UUID     `json:"id" yaml:"id"`
-	HostID              uuid.UUID     `json:"hostid" yaml:"hostid"`
-	Network             string        `json:"network" yaml:"network"`
-	NetworkRange        net.IPNet     `json:"networkrange" yaml:"networkrange"`
-	NetworkRange6       net.IPNet     `json:"networkrange6" yaml:"networkrange6"`
-	InternetGateway     *net.UDPAddr  `json:"internetgateway" yaml:"internetgateway"`
-	Server              string        `json:"server" yaml:"server"`
-	Connected           bool          `json:"connected" yaml:"connected"`
-	Address             net.IPNet     `json:"address" yaml:"address"`
-	Address6            net.IPNet     `json:"address6" yaml:"address6"`
-	Action              string        `json:"action" yaml:"action"`
-	LocalAddress        net.IPNet     `json:"localaddress" yaml:"localaddress"`
-	IsEgressGateway     bool          `json:"isegressgateway" yaml:"isegressgateway"`
-	EgressGatewayRanges []string      `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"`
-	IsIngressGateway    bool          `json:"isingressgateway" yaml:"isingressgateway"`
-	IsRelayed           bool          `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"`
-	RelayedBy           string        `json:"relayedby" bson:"relayedby" yaml:"relayedby"`
-	IsRelay             bool          `json:"isrelay" bson:"isrelay" yaml:"isrelay"`
-	RelayedNodes        []string      `json:"relaynodes" yaml:"relayedNodes"`
-	IngressDNS          string        `json:"ingressdns" yaml:"ingressdns"`
-	DNSOn               bool          `json:"dnson" yaml:"dnson"`
-	PersistentKeepalive time.Duration `json:"persistentkeepalive" yaml:"persistentkeepalive"`
+	ID                  uuid.UUID    `json:"id" yaml:"id"`
+	HostID              uuid.UUID    `json:"hostid" yaml:"hostid"`
+	Network             string       `json:"network" yaml:"network"`
+	NetworkRange        net.IPNet    `json:"networkrange" yaml:"networkrange"`
+	NetworkRange6       net.IPNet    `json:"networkrange6" yaml:"networkrange6"`
+	InternetGateway     *net.UDPAddr `json:"internetgateway" yaml:"internetgateway"`
+	Server              string       `json:"server" yaml:"server"`
+	Connected           bool         `json:"connected" yaml:"connected"`
+	Address             net.IPNet    `json:"address" yaml:"address"`
+	Address6            net.IPNet    `json:"address6" yaml:"address6"`
+	Action              string       `json:"action" yaml:"action"`
+	LocalAddress        net.IPNet    `json:"localaddress" yaml:"localaddress"`
+	IsEgressGateway     bool         `json:"isegressgateway" yaml:"isegressgateway"`
+	EgressGatewayRanges []string     `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"`
+	IsIngressGateway    bool         `json:"isingressgateway" yaml:"isingressgateway"`
+	IsRelayed           bool         `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"`
+	RelayedBy           string       `json:"relayedby" bson:"relayedby" yaml:"relayedby"`
+	IsRelay             bool         `json:"isrelay" bson:"isrelay" yaml:"isrelay"`
+	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
 // Node - a model of a network node
@@ -369,9 +368,6 @@ func (newNode *Node) Fill(currentNode *Node, isPro bool) { // TODO add new field
 	if newNode.Address6.String() == "" {
 	if newNode.Address6.String() == "" {
 		newNode.Address6 = currentNode.Address6
 		newNode.Address6 = currentNode.Address6
 	}
 	}
-	if newNode.PersistentKeepalive < 0 {
-		newNode.PersistentKeepalive = currentNode.PersistentKeepalive
-	}
 	if newNode.LastModified != currentNode.LastModified {
 	if newNode.LastModified != currentNode.LastModified {
 		newNode.LastModified = currentNode.LastModified
 		newNode.LastModified = currentNode.LastModified
 	}
 	}

+ 1 - 0
pro/initialize.go

@@ -55,6 +55,7 @@ func InitPro() {
 	logic.GetMetrics = proLogic.GetMetrics
 	logic.GetMetrics = proLogic.GetMetrics
 	logic.UpdateMetrics = proLogic.UpdateMetrics
 	logic.UpdateMetrics = proLogic.UpdateMetrics
 	logic.DeleteMetrics = proLogic.DeleteMetrics
 	logic.DeleteMetrics = proLogic.DeleteMetrics
+	logic.GetRelays = proLogic.GetRelays
 	logic.GetAllowedIpsForRelayed = proLogic.GetAllowedIpsForRelayed
 	logic.GetAllowedIpsForRelayed = proLogic.GetAllowedIpsForRelayed
 	logic.RelayedAllowedIPs = proLogic.RelayedAllowedIPs
 	logic.RelayedAllowedIPs = proLogic.RelayedAllowedIPs
 	logic.UpdateRelayed = proLogic.UpdateRelayed
 	logic.UpdateRelayed = proLogic.UpdateRelayed

+ 16 - 8
pro/license.go

@@ -9,17 +9,18 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
-	"golang.org/x/exp/slog"
 	"io"
 	"io"
 	"net/http"
 	"net/http"
 	"time"
 	"time"
 
 
+	"golang.org/x/crypto/nacl/box"
+	"golang.org/x/exp/slog"
+
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
-	"golang.org/x/crypto/nacl/box"
 )
 )
 
 
 const (
 const (
@@ -28,7 +29,7 @@ const (
 
 
 type apiServerConf struct {
 type apiServerConf struct {
 	PrivateKey []byte `json:"private_key" binding:"required"`
 	PrivateKey []byte `json:"private_key" binding:"required"`
-	PublicKey  []byte `json:"public_key" binding:"required"`
+	PublicKey  []byte `json:"public_key"  binding:"required"`
 }
 }
 
 
 // AddLicenseHooks - adds the validation and cache clear hooks
 // AddLicenseHooks - adds the validation and cache clear hooks
@@ -112,7 +113,11 @@ func ValidateLicense() (err error) {
 		return err
 		return err
 	}
 	}
 
 
-	respData, err := ncutils.BoxDecrypt(base64decode(licenseResponse.EncryptedLicense), apiPublicKey, tempPrivKey)
+	respData, err := ncutils.BoxDecrypt(
+		base64decode(licenseResponse.EncryptedLicense),
+		apiPublicKey,
+		tempPrivKey,
+	)
 	if err != nil {
 	if err != nil {
 		err = fmt.Errorf("failed to decrypt license: %w", err)
 		err = fmt.Errorf("failed to decrypt license: %w", err)
 		return err
 		return err
@@ -132,7 +137,7 @@ func ValidateLicense() (err error) {
 // as well as secure communication with API
 // as well as secure communication with API
 // if none present, it generates a new pair
 // if none present, it generates a new pair
 func FetchApiServerKeys() (pub *[32]byte, priv *[32]byte, err error) {
 func FetchApiServerKeys() (pub *[32]byte, priv *[32]byte, err error) {
-	var returnData = apiServerConf{}
+	returnData := apiServerConf{}
 	currentData, err := database.FetchRecord(database.SERVERCONF_TABLE_NAME, db_license_key)
 	currentData, err := database.FetchRecord(database.SERVERCONF_TABLE_NAME, db_license_key)
 	if err != nil && !database.IsEmptyRecord(err) {
 	if err != nil && !database.IsEmptyRecord(err) {
 		return nil, nil, err
 		return nil, nil, err
@@ -181,7 +186,6 @@ func getLicensePublicKey(licensePubKeyEncoded string) (*[32]byte, error) {
 }
 }
 
 
 func validateLicenseKey(encryptedData []byte, publicKey *[32]byte) ([]byte, error) {
 func validateLicenseKey(encryptedData []byte, publicKey *[32]byte) ([]byte, error) {
-
 	publicKeyBytes, err := ncutils.ConvertKeyToBytes(publicKey)
 	publicKeyBytes, err := ncutils.ConvertKeyToBytes(publicKey)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
@@ -198,7 +202,11 @@ func validateLicenseKey(encryptedData []byte, publicKey *[32]byte) ([]byte, erro
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	req, err := http.NewRequest(http.MethodPost, getAccountsHost()+"/api/v1/license/validate", bytes.NewReader(requestBody))
+	req, err := http.NewRequest(
+		http.MethodPost,
+		getAccountsHost()+"/api/v1/license/validate",
+		bytes.NewReader(requestBody),
+	)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -241,7 +249,7 @@ func getAccountsHost() string {
 }
 }
 
 
 func cacheResponse(response []byte) error {
 func cacheResponse(response []byte) error {
-	var lrc = licenseResponseCache{
+	lrc := licenseResponseCache{
 		Body: response,
 		Body: response,
 	}
 	}
 
 

+ 18 - 3
pro/logic/relays.go

@@ -14,6 +14,21 @@ import (
 	"golang.org/x/exp/slog"
 	"golang.org/x/exp/slog"
 )
 )
 
 
+// GetRelays - gets all the nodes that are relays
+func GetRelays() ([]models.Node, error) {
+	nodes, err := logic.GetAllNodes()
+	if err != nil {
+		return nil, err
+	}
+	relays := make([]models.Node, 0)
+	for _, node := range nodes {
+		if node.IsRelay {
+			relays = append(relays, node)
+		}
+	}
+	return relays, nil
+}
+
 // CreateRelay - creates a relay
 // CreateRelay - creates a relay
 func CreateRelay(relay models.RelayRequest) ([]models.Node, models.Node, error) {
 func CreateRelay(relay models.RelayRequest) ([]models.Node, models.Node, error) {
 	var returnnodes []models.Node
 	var returnnodes []models.Node
@@ -69,7 +84,7 @@ func SetRelayedNodes(setRelayed bool, relay string, relayed []string) []models.N
 	return returnnodes
 	return returnnodes
 }
 }
 
 
-//func GetRelayedNodes(relayNode *models.Node) (models.Node, error) {
+// func GetRelayedNodes(relayNode *models.Node) (models.Node, error) {
 //	var returnnodes []models.Node
 //	var returnnodes []models.Node
 //	networkNodes, err := GetNetworkNodes(relayNode.Network)
 //	networkNodes, err := GetNetworkNodes(relayNode.Network)
 //	if err != nil {
 //	if err != nil {
@@ -83,12 +98,12 @@ func SetRelayedNodes(setRelayed bool, relay string, relayed []string) []models.N
 //		}
 //		}
 //	}
 //	}
 //	return returnnodes, nil
 //	return returnnodes, nil
-//}
+// }
 
 
 // ValidateRelay - checks if relay is valid
 // ValidateRelay - checks if relay is valid
 func ValidateRelay(relay models.RelayRequest) error {
 func ValidateRelay(relay models.RelayRequest) error {
 	var err error
 	var err error
-	//isIp := functions.IsIpCIDR(gateway.RangeString)
+	// isIp := functions.IsIpCIDR(gateway.RangeString)
 	empty := len(relay.RelayedNodes) == 0
 	empty := len(relay.RelayedNodes) == 0
 	if empty {
 	if empty {
 		return errors.New("IP Ranges Cannot Be Empty")
 		return errors.New("IP Ranges Cannot Be Empty")

+ 11 - 7
pro/types.go

@@ -54,13 +54,15 @@ type LicenseSecret struct {
 
 
 // Usage - struct for license usage
 // Usage - struct for license usage
 type Usage struct {
 type Usage struct {
-	Servers   int `json:"servers"`
-	Users     int `json:"users"`
-	Hosts     int `json:"hosts"`
-	Clients   int `json:"clients"`
-	Networks  int `json:"networks"`
-	Ingresses int `json:"ingresses"`
-	Egresses  int `json:"egresses"`
+	Servers          int `json:"servers"`
+	Users            int `json:"users"`
+	Hosts            int `json:"hosts"`
+	Clients          int `json:"clients"`
+	Networks         int `json:"networks"`
+	Ingresses        int `json:"ingresses"`
+	Egresses         int `json:"egresses"`
+	Relays           int `json:"relays"`
+	InternetGateways int `json:"internet_gateways"`
 }
 }
 
 
 // Usage.SetDefaults - sets the default values for usage
 // Usage.SetDefaults - sets the default values for usage
@@ -72,6 +74,8 @@ func (l *Usage) SetDefaults() {
 	l.Networks = 0
 	l.Networks = 0
 	l.Ingresses = 0
 	l.Ingresses = 0
 	l.Egresses = 0
 	l.Egresses = 0
+	l.Relays = 0
+	l.InternetGateways = 0
 }
 }
 
 
 // ValidateLicenseRequest - used for request to validate license endpoint
 // ValidateLicenseRequest - used for request to validate license endpoint

+ 9 - 2
pro/util.go

@@ -16,9 +16,7 @@ func base64encode(input []byte) string {
 
 
 // base64decode - base64 decode helper function
 // base64decode - base64 decode helper function
 func base64decode(input string) []byte {
 func base64decode(input string) []byte {
-
 	bytes, err := base64.StdEncoding.DecodeString(input)
 	bytes, err := base64.StdEncoding.DecodeString(input)
-
 	if err != nil {
 	if err != nil {
 		return nil
 		return nil
 	}
 	}
@@ -44,6 +42,7 @@ func getCurrentServerUsage() (limits Usage) {
 	if err == nil {
 	if err == nil {
 		limits.Networks = len(networks)
 		limits.Networks = len(networks)
 	}
 	}
+	// TODO this part bellow can be optimized to get nodes just once
 	ingresses, err := logic.GetAllIngresses()
 	ingresses, err := logic.GetAllIngresses()
 	if err == nil {
 	if err == nil {
 		limits.Ingresses = len(ingresses)
 		limits.Ingresses = len(ingresses)
@@ -52,5 +51,13 @@ func getCurrentServerUsage() (limits Usage) {
 	if err == nil {
 	if err == nil {
 		limits.Egresses = len(egresses)
 		limits.Egresses = len(egresses)
 	}
 	}
+	relays, err := logic.GetRelays()
+	if err == nil {
+		limits.Relays = len(relays)
+	}
+	gateways, err := logic.GetInternetGateways()
+	if err == nil {
+		limits.InternetGateways = len(gateways)
+	}
 	return
 	return
 }
 }

+ 0 - 113
scripts/nm-certs.sh

@@ -1,113 +0,0 @@
-#!/bin/bash
-
-CONFIG_FILE=netmaker.env
-SCRIPT_DIR=$(dirname "$(realpath "$0")")
-
-# get and check the config
-if [ ! -f "$SCRIPT_DIR/$CONFIG_FILE" ]; then
-	echo "Config file missing"
-	exit 1
-fi
-source "$SCRIPT_DIR/$CONFIG_FILE"
-if [ -z "$NM_DOMAIN" ] || [ -z "$NM_EMAIL" ]; then
-	echo "Config not valid"
-	exit 1
-fi
-
-# TODO make sure this doesnt break, parse `certbot certificates` if yes
-CERT_DIR="$SCRIPT_DIR/letsencrypt/live/api.$NM_DOMAIN"
-
-echo "Setting up SSL certificates..."
-
-# preserve the env state
-RESTART_CADDY=false
-if [ -n "$(docker ps | grep caddy)" ]; then
-	echo "Caddy is running, stopping for now..."
-	RESTART_CADDY=true
-	docker-compose -f /root/docker-compose.yml stop caddy
-fi
-
-if [ "$INSTALL_TYPE" = "ce" ]; then
-	CERTBOT_PARAMS=$(cat <<EOF
-	certonly --standalone \
-		--non-interactive --agree-tos \
-		-m $NM_EMAIL \
-		-d api.$NM_DOMAIN \
-		-d broker.$NM_DOMAIN \
-		-d dashboard.$NM_DOMAIN \
-		-d turn.$NM_DOMAIN \
-		-d turnapi.$NM_DOMAIN
-EOF
-)
-elif [ "$INSTALL_TYPE" = "pro" ]; then
-	CERTBOT_PARAMS=$(cat <<EOF
-	certonly --standalone \
-		--non-interactive --expand --agree-tos \
-		-m $NM_EMAIL \
-		-d api.$NM_DOMAIN \
-		-d broker.$NM_DOMAIN \
-		-d dashboard.$NM_DOMAIN \
-		-d turn.$NM_DOMAIN \
-		-d turnapi.$NM_DOMAIN \
-		-d netmaker-exporter.$NM_DOMAIN \
-		-d grafana.$NM_DOMAIN \
-		-d prometheus.$NM_DOMAIN
-EOF
-)
-fi
-
-# generate an entrypoint for zerossl-certbot
-cat <<EOF >"$SCRIPT_DIR/certbot-entry.sh"
-#!/bin/sh
-# deps
-apk update
-apk add bash curl
-# zerossl
-wget -qO zerossl-bot.sh "https://github.com/zerossl/zerossl-bot/raw/master/zerossl-bot.sh"
-chmod +x zerossl-bot.sh
-# request the certs
-./zerossl-bot.sh "$CERTBOT_PARAMS"
-EOF
-
-chmod +x "$SCRIPT_DIR/certbot-entry.sh"
-
-# request certs
-sudo docker run -it --rm --name certbot \
-	-p 80:80 -p 443:443 \
-	-v "$SCRIPT_DIR/certbot-entry.sh:/opt/certbot/certbot-entry.sh" \
-	-v "$SCRIPT_DIR/letsencrypt:/etc/letsencrypt" \
-	--entrypoint "/opt/certbot/certbot-entry.sh" \
-	certbot/certbot
-
-# clean up
-rm "$SCRIPT_DIR/certbot-entry.sh"
-
-# check if successful
-if [ ! -f "$CERT_DIR"/fullchain.pem ]; then
-	# fallback to letsencrypt-certbot
-	sudo docker run -it --rm --name certbot \
-		-p 80:80 -p 443:443 \
-		-v "$SCRIPT_DIR/letsencrypt:/etc/letsencrypt" \
-		certbot/certbot $CERTBOT_PARAMS
-	if [ ! -f "$CERT_DIR"/fullchain.pem ]; then
-		echo "Missing file: $CERT_DIR/fullchain.pem"
-		echo "SSL certificates failed"
-		exit 1
-	fi
-fi
-
-# copy for mounting
-mkdir -p certs
-cp -L "$CERT_DIR/fullchain.pem" "$SCRIPT_DIR/certs/fullchain.pem"
-cp -L "$CERT_DIR/privkey.pem" "$SCRIPT_DIR/certs/privkey.pem"
-
-echo "SSL certificates ready"
-
-# preserve the env state
-if [ "$RESTART_CADDY" = true ]; then
-	echo "Starting Caddy..."
-	docker-compose -f /root/docker-compose.yml start caddy
-fi
-
-# install crontab
-ln -sfn "$SCRIPT_DIR"/nm-certs.sh /etc/cron.monthly/nm-certs.sh

+ 0 - 5
scripts/nm-quick.sh

@@ -759,7 +759,6 @@ install_netmaker() {
 		wget -qO "$SCRIPT_DIR"/Caddyfile "$CADDY_URL"
 		wget -qO "$SCRIPT_DIR"/Caddyfile "$CADDY_URL"
 		wget -qO "$SCRIPT_DIR"/netmaker.default.env "$BASE_URL/scripts/netmaker.default.env"
 		wget -qO "$SCRIPT_DIR"/netmaker.default.env "$BASE_URL/scripts/netmaker.default.env"
 		wget -qO "$SCRIPT_DIR"/mosquitto.conf "$BASE_URL/docker/mosquitto.conf"
 		wget -qO "$SCRIPT_DIR"/mosquitto.conf "$BASE_URL/docker/mosquitto.conf"
-		wget -qO "$SCRIPT_DIR"/nm-certs.sh "$BASE_URL/scripts/nm-certs.sh"
 		wget -qO "$SCRIPT_DIR"/wait.sh "$BASE_URL/docker/wait.sh"
 		wget -qO "$SCRIPT_DIR"/wait.sh "$BASE_URL/docker/wait.sh"
 	fi
 	fi
 
 
@@ -770,10 +769,6 @@ install_netmaker() {
 	ln -fs "$SCRIPT_DIR/netmaker.env" "$SCRIPT_DIR/.env"
 	ln -fs "$SCRIPT_DIR/netmaker.env" "$SCRIPT_DIR/.env"
 	save_config
 	save_config
 
 
-	# Fetch / update certs using certbot
-	chmod +x "$SCRIPT_DIR"/nm-certs.sh
-	"$SCRIPT_DIR"/nm-certs.sh
-
 	echo "Starting containers..."
 	echo "Starting containers..."
 
 
 	# increase the timeouts
 	# increase the timeouts