Browse Source

Merge branch 'develop' into bugfix_v0.22.0_bump-gorqlite-to-a8a425b1a6aa

Seongbin Hong 1 year ago
parent
commit
ea235a5d3f

+ 1 - 0
.github/ISSUE_TEMPLATE/bug-report.yml

@@ -31,6 +31,7 @@ body:
       label: Version
       label: Version
       description: What version are you running?
       description: What version are you running?
       options:
       options:
+        - v0.22.1
         - v0.22.0
         - v0.22.0
         - v0.21.2
         - v0.21.2
         - v0.21.1
         - v0.21.1

+ 6 - 6
README.md

@@ -16,7 +16,7 @@
 
 
 <p align="center">
 <p align="center">
   <a href="https://github.com/gravitl/netmaker/releases">
   <a href="https://github.com/gravitl/netmaker/releases">
-    <img src="https://img.shields.io/badge/Version-0.22.0-informational?style=flat-square" />
+    <img src="https://img.shields.io/badge/Version-0.22.1-informational?style=flat-square" />
   </a>
   </a>
   <a href="https://hub.docker.com/r/gravitl/netmaker/tags">
   <a href="https://hub.docker.com/r/gravitl/netmaker/tags">
     <img src="https://img.shields.io/docker/pulls/gravitl/netmaker?label=downloads" />
     <img src="https://img.shields.io/docker/pulls/gravitl/netmaker?label=downloads" />
@@ -47,13 +47,13 @@
 | :heavy_check_mark: Mesh VPNs              | :heavy_check_mark: Private DNS          | :heavy_check_mark: Mac                  |
 | :heavy_check_mark: Mesh VPNs              | :heavy_check_mark: Private DNS          | :heavy_check_mark: Mac                  |
 | :heavy_check_mark: Site-to-Site           | :heavy_check_mark: Access Control Lists | :heavy_check_mark: Windows              |
 | :heavy_check_mark: Site-to-Site           | :heavy_check_mark: Access Control Lists | :heavy_check_mark: Windows              |
 
 
-# Try Online  
+# Try Netmaker SaaS  
 
 
-If you're just looking to use Netmaker, you can create an account for free at [netmaker.io](https://account.netmaker.io).  
+If you're looking for a managed service, you can get started with just few clicks, visit [netmaker.io](https://account.netmaker.io) to create your netmaker server.  
 
 
 # Self-Hosted Quick Start  
 # Self-Hosted Quick Start  
 
 
-These are the instructions for deploying a Netmaker server on your own cloud VM as quickly as possible. For more detailed instructions, visit the [Install Docs](https://netmaker.readthedocs.io/en/master/install.html).  
+These are the instructions for deploying a Netmaker server on your own cloud VM as quickly as possible. For more detailed instructions, visit the [Install Docs](https://docs.netmaker.io/install.html).  
 
 
 1. Get a cloud VM with Ubuntu 22.04 and a public IP.
 1. Get a cloud VM with Ubuntu 22.04 and a public IP.
 2. Open ports 443, 80, 3479, 8089 and 51821-51830/udp on the VM firewall and in cloud security settings.
 2. Open ports 443, 80, 3479, 8089 and 51821-51830/udp on the VM firewall and in cloud security settings.
@@ -62,13 +62,13 @@ These are the instructions for deploying a Netmaker server on your own cloud VM
 
 
 `sudo wget -qO /root/nm-quick.sh https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/nm-quick.sh && sudo chmod +x /root/nm-quick.sh && sudo /root/nm-quick.sh`  
 `sudo wget -qO /root/nm-quick.sh https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/nm-quick.sh && sudo chmod +x /root/nm-quick.sh && sudo /root/nm-quick.sh`  
 
 
-This script gives you the option to deploy the Community or Enterprise version of Netmaker. It also gives you the option to use your own domain (recommended) or an auto-generated domain. 
+This script by default installs PRO version with 14-day trial, check out these instructions for post trial period https://docs.netmaker.io/install.html#after-trial-period-ends. It also gives you the option to use your own domain (recommended) or an auto-generated domain. 
 
 
 <p float="left" align="middle">
 <p float="left" align="middle">
 <img src="https://raw.githubusercontent.com/gravitl/netmaker-docs/master/images/netmaker-github/readme.gif" />
 <img src="https://raw.githubusercontent.com/gravitl/netmaker-docs/master/images/netmaker-github/readme.gif" />
 </p>
 </p>
 
 
-After installing Netmaker, check out the [Walkthrough](https://itnext.io/getting-started-with-netmaker-a-wireguard-virtual-networking-platform-3d563fbd87f0) and [Getting Started](https://netmaker.readthedocs.io/en/master/getting-started.html) guides to learn more about configuring networks. Or, check out some of our other [Tutorials](https://www.netmaker.io/blog) for different use cases, including Kubernetes.
+After installing Netmaker, check out the [Walkthrough](https://itnext.io/getting-started-with-netmaker-a-wireguard-virtual-networking-platform-3d563fbd87f0) and [Getting Started](https://docs.netmaker.io/getting-started.html) guides to learn more about configuring networks. Or, check out some of our other [Tutorials](https://www.netmaker.io/blog) for different use cases, including Kubernetes.
 
 
 # Get Support
 # Get Support
 
 

+ 18 - 0
auth/host_session.go

@@ -86,6 +86,24 @@ func SessionHandler(conn *websocket.Conn) {
 			return
 			return
 		}
 		}
 		req.Pass = req.Host.ID.String()
 		req.Pass = req.Host.ID.String()
+		user, err := logic.GetUser(req.User)
+		if err != nil {
+			logger.Log(0, "failed to get user", req.User, "from database")
+			err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
+			if err != nil {
+				logger.Log(0, "error during message writing:", err.Error())
+			}
+			return
+		}
+		if !user.IsAdmin && !user.IsSuperAdmin {
+			logger.Log(0, "user", req.User, "is neither an admin or superadmin. denying registeration")
+			conn.WriteMessage(messageType, []byte("cannot register with a non-admin or non-superadmin"))
+			err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
+			if err != nil {
+				logger.Log(0, "error during message writing:", err.Error())
+			}
+			return
+		}
 
 
 		if err = netcache.Set(stateStr, req); err != nil { // give the user's host access in the DB
 		if err = netcache.Set(stateStr, req); err != nil { // give the user's host access in the DB
 			logger.Log(0, "machine failed to complete join on network,", registerMessage.Network, "-", err.Error())
 			logger.Log(0, "machine failed to complete join on network,", registerMessage.Network, "-", err.Error())

+ 1 - 1
compose/docker-compose.netclient.yml

@@ -3,7 +3,7 @@ version: "3.4"
 services:
 services:
   netclient:
   netclient:
     container_name: netclient
     container_name: netclient
-    image: 'gravitl/netclient:v0.22.0'
+    image: 'gravitl/netclient:v0.22.1'
     hostname: netmaker-1
     hostname: netmaker-1
     network_mode: host
     network_mode: host
     restart: on-failure
     restart: on-failure

+ 1 - 1
controllers/docs.go

@@ -10,7 +10,7 @@
 //
 //
 //	Schemes: https
 //	Schemes: https
 //	BasePath: /
 //	BasePath: /
-//	Version: 0.22.0
+//	Version: 0.22.1
 //	Host: api.demo.netmaker.io
 //	Host: api.demo.netmaker.io
 //
 //
 //	Consumes:
 //	Consumes:

+ 1 - 1
controllers/hosts.go

@@ -254,7 +254,7 @@ func hostUpdateFallback(w http.ResponseWriter, r *http.Request) {
 			return
 			return
 		}
 		}
 	case models.UpdateMetrics:
 	case models.UpdateMetrics:
-		// mq.UpdateMetricsFallBack(hostUpdate.Node.ID.String(), hostUpdate.NewMetrics)
+		mq.UpdateMetricsFallBack(hostUpdate.Node.ID.String(), hostUpdate.NewMetrics)
 	}
 	}
 	logic.ReturnSuccessResponse(w, r, "updated host data")
 	logic.ReturnSuccessResponse(w, r, "updated host data")
 
 

+ 24 - 9
controllers/server.go

@@ -5,6 +5,7 @@ import (
 	"net/http"
 	"net/http"
 	"strings"
 	"strings"
 	"syscall"
 	"syscall"
+	"time"
 
 
 	"github.com/gorilla/mux"
 	"github.com/gorilla/mux"
 	"golang.org/x/exp/slog"
 	"golang.org/x/exp/slog"
@@ -109,22 +110,36 @@ func getUsage(w http.ResponseWriter, _ *http.Request) {
 //				200: serverConfigResponse
 //				200: serverConfigResponse
 func getStatus(w http.ResponseWriter, r *http.Request) {
 func getStatus(w http.ResponseWriter, r *http.Request) {
 	type status struct {
 	type status struct {
-		DB           bool   `json:"db_connected"`
-		Broker       bool   `json:"broker_connected"`
-		LicenseError string `json:"license_error"`
-		IsPro        bool   `json:"is_pro"`
+		DB               bool      `json:"db_connected"`
+		Broker           bool      `json:"broker_connected"`
+		LicenseError     string    `json:"license_error"`
+		IsPro            bool      `json:"is_pro"`
+		TrialEndDate     time.Time `json:"trial_end_date"`
+		IsOnTrialLicense bool      `json:"is_on_trial_license"`
 	}
 	}
 
 
 	licenseErr := ""
 	licenseErr := ""
 	if servercfg.ErrLicenseValidation != nil {
 	if servercfg.ErrLicenseValidation != nil {
 		licenseErr = servercfg.ErrLicenseValidation.Error()
 		licenseErr = servercfg.ErrLicenseValidation.Error()
 	}
 	}
-
+	var trialEndDate time.Time
+	var err error
+	isOnTrial := false
+	if servercfg.IsPro && (servercfg.GetLicenseKey() == "" || servercfg.GetNetmakerTenantID() == "") {
+		trialEndDate, err = logic.GetTrialEndDate()
+		if err != nil {
+			slog.Error("failed to get trial end date", "error", err)
+		} else {
+			isOnTrial = true
+		}
+	}
 	currentServerStatus := status{
 	currentServerStatus := status{
-		DB:           database.IsConnected(),
-		Broker:       mq.IsConnected(),
-		LicenseError: licenseErr,
-		IsPro:        servercfg.IsPro,
+		DB:               database.IsConnected(),
+		Broker:           mq.IsConnected(),
+		LicenseError:     licenseErr,
+		IsPro:            servercfg.IsPro,
+		TrialEndDate:     trialEndDate,
+		IsOnTrialLicense: isOnTrial,
 	}
 	}
 
 
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")

+ 22 - 22
database/database.go

@@ -124,29 +124,29 @@ func InitializeDatabase() error {
 }
 }
 
 
 func createTables() {
 func createTables() {
-	createTable(NETWORKS_TABLE_NAME)
-	createTable(NODES_TABLE_NAME)
-	createTable(CERTS_TABLE_NAME)
-	createTable(DELETED_NODES_TABLE_NAME)
-	createTable(USERS_TABLE_NAME)
-	createTable(DNS_TABLE_NAME)
-	createTable(EXT_CLIENT_TABLE_NAME)
-	createTable(PEERS_TABLE_NAME)
-	createTable(SERVERCONF_TABLE_NAME)
-	createTable(SERVER_UUID_TABLE_NAME)
-	createTable(GENERATED_TABLE_NAME)
-	createTable(NODE_ACLS_TABLE_NAME)
-	createTable(SSO_STATE_CACHE)
-	createTable(METRICS_TABLE_NAME)
-	createTable(NETWORK_USER_TABLE_NAME)
-	createTable(USER_GROUPS_TABLE_NAME)
-	createTable(CACHE_TABLE_NAME)
-	createTable(HOSTS_TABLE_NAME)
-	createTable(ENROLLMENT_KEYS_TABLE_NAME)
-	createTable(HOST_ACTIONS_TABLE_NAME)
+	CreateTable(NETWORKS_TABLE_NAME)
+	CreateTable(NODES_TABLE_NAME)
+	CreateTable(CERTS_TABLE_NAME)
+	CreateTable(DELETED_NODES_TABLE_NAME)
+	CreateTable(USERS_TABLE_NAME)
+	CreateTable(DNS_TABLE_NAME)
+	CreateTable(EXT_CLIENT_TABLE_NAME)
+	CreateTable(PEERS_TABLE_NAME)
+	CreateTable(SERVERCONF_TABLE_NAME)
+	CreateTable(SERVER_UUID_TABLE_NAME)
+	CreateTable(GENERATED_TABLE_NAME)
+	CreateTable(NODE_ACLS_TABLE_NAME)
+	CreateTable(SSO_STATE_CACHE)
+	CreateTable(METRICS_TABLE_NAME)
+	CreateTable(NETWORK_USER_TABLE_NAME)
+	CreateTable(USER_GROUPS_TABLE_NAME)
+	CreateTable(CACHE_TABLE_NAME)
+	CreateTable(HOSTS_TABLE_NAME)
+	CreateTable(ENROLLMENT_KEYS_TABLE_NAME)
+	CreateTable(HOST_ACTIONS_TABLE_NAME)
 }
 }
 
 
-func createTable(tableName string) error {
+func CreateTable(tableName string) error {
 	return getCurrentDB()[CREATE_TABLE].(func(string) error)(tableName)
 	return getCurrentDB()[CREATE_TABLE].(func(string) error)(tableName)
 }
 }
 
 
@@ -194,7 +194,7 @@ func DeleteAllRecords(tableName string) error {
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	err = createTable(tableName)
+	err = CreateTable(tableName)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 6 - 6
go.mod

@@ -4,7 +4,7 @@ go 1.19
 
 
 require (
 require (
 	github.com/eclipse/paho.mqtt.golang v1.4.3
 	github.com/eclipse/paho.mqtt.golang v1.4.3
-	github.com/go-playground/validator/v10 v10.16.0
+	github.com/go-playground/validator/v10 v10.17.0
 	github.com/golang-jwt/jwt/v4 v4.5.0
 	github.com/golang-jwt/jwt/v4 v4.5.0
 	github.com/google/uuid v1.5.0
 	github.com/google/uuid v1.5.0
 	github.com/gorilla/handlers v1.5.2
 	github.com/gorilla/handlers v1.5.2
@@ -15,10 +15,10 @@ require (
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
 	github.com/stretchr/testify v1.8.4
 	github.com/stretchr/testify v1.8.4
 	github.com/txn2/txeh v1.5.5
 	github.com/txn2/txeh v1.5.5
-	golang.org/x/crypto v0.17.0
-	golang.org/x/net v0.19.0 // indirect
-	golang.org/x/oauth2 v0.15.0
-	golang.org/x/sys v0.15.0 // indirect
+	golang.org/x/crypto v0.18.0
+	golang.org/x/net v0.20.0 // indirect
+	golang.org/x/oauth2 v0.16.0
+	golang.org/x/sys v0.16.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20221104135756-97bc4ad4a1cb
 	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20221104135756-97bc4ad4a1cb
 	google.golang.org/protobuf v1.31.0 // indirect
 	google.golang.org/protobuf v1.31.0 // indirect
@@ -27,7 +27,7 @@ require (
 
 
 require (
 require (
 	filippo.io/edwards25519 v1.1.0
 	filippo.io/edwards25519 v1.1.0
-	github.com/c-robinson/iplib v1.0.7
+	github.com/c-robinson/iplib v1.0.8
 	github.com/posthog/posthog-go v0.0.0-20211028072449-93c17c49e2b0
 	github.com/posthog/posthog-go v0.0.0-20211028072449-93c17c49e2b0
 )
 )
 
 

+ 12 - 12
go.sum

@@ -5,8 +5,8 @@ cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2Aawl
 filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
 filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
 filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
 filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/c-robinson/iplib v1.0.7 h1:Dh9AINAlkc+NsNzZuFiVs+pi3AjN+0B7mu01KHdJKHU=
-github.com/c-robinson/iplib v1.0.7/go.mod h1:i3LuuFL1hRT5gFpBRnEydzw8R6yhGkF4szNDIbF8pgo=
+github.com/c-robinson/iplib v1.0.8 h1:exDRViDyL9UBLcfmlxxkY5odWX5092nPsQIykHXhIn4=
+github.com/c-robinson/iplib v1.0.8/go.mod h1:i3LuuFL1hRT5gFpBRnEydzw8R6yhGkF4szNDIbF8pgo=
 github.com/coreos/go-oidc/v3 v3.9.0 h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo=
 github.com/coreos/go-oidc/v3 v3.9.0 h1:0J/ogVOd4y8P0f0xUh8l9t07xRP/d8tccvjHl2dcsSo=
 github.com/coreos/go-oidc/v3 v3.9.0/go.mod h1:rTKz2PYwftcrtoCzV5g5kvfJoWcm0Mk8AF8y1iAQro4=
 github.com/coreos/go-oidc/v3 v3.9.0/go.mod h1:rTKz2PYwftcrtoCzV5g5kvfJoWcm0Mk8AF8y1iAQro4=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@@ -27,8 +27,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
 github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
-github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE=
-github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
+github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74=
+github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
 github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
@@ -104,8 +104,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
-golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
+golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -113,10 +113,10 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
-golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
-golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
-golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
+golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
+golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
+golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
 golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
@@ -127,8 +127,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

+ 1 - 1
k8s/client/netclient-daemonset.yaml

@@ -16,7 +16,7 @@ spec:
       hostNetwork: true
       hostNetwork: true
       containers:
       containers:
       - name: netclient
       - name: netclient
-        image: gravitl/netclient:v0.22.0
+        image: gravitl/netclient:v0.22.1
         env:
         env:
         - name: TOKEN
         - name: TOKEN
           value: "TOKEN_VALUE"
           value: "TOKEN_VALUE"

+ 1 - 1
k8s/client/netclient.yaml

@@ -28,7 +28,7 @@ spec:
       #           - "<node label value>"
       #           - "<node label value>"
       containers:
       containers:
       - name: netclient
       - name: netclient
-        image: gravitl/netclient:v0.22.0
+        image: gravitl/netclient:v0.22.1
         env:
         env:
         - name: TOKEN
         - name: TOKEN
           value: "TOKEN_VALUE"
           value: "TOKEN_VALUE"

+ 1 - 1
k8s/server/netmaker-ui.yaml

@@ -15,7 +15,7 @@ spec:
     spec:
     spec:
       containers:
       containers:
       - name: netmaker-ui
       - name: netmaker-ui
-        image: gravitl/netmaker-ui:v0.22.0
+        image: gravitl/netmaker-ui:v0.22.1
         ports:
         ports:
         - containerPort: 443
         - containerPort: 443
         env:
         env:

+ 14 - 33
logic/peers.go

@@ -24,6 +24,10 @@ var (
 	ResetFailedOverPeer = func(failedOverNode *models.Node) error {
 	ResetFailedOverPeer = func(failedOverNode *models.Node) error {
 		return nil
 		return nil
 	}
 	}
+	// GetFailOverPeerIps - gets failover peerips
+	GetFailOverPeerIps = func(peer, node *models.Node) []net.IPNet {
+		return []net.IPNet{}
+	}
 )
 )
 
 
 // GetPeerUpdateForHost - gets the consolidated peer update for the host from all networks
 // GetPeerUpdateForHost - gets the consolidated peer update for the host from all networks
@@ -144,16 +148,18 @@ func GetPeerUpdateForHost(network string, host *models.Host, allNodes []models.N
 				hostPeerUpdate.EgressRoutes = append(hostPeerUpdate.EgressRoutes, getExtpeersExtraRoutes(peer.Network)...)
 				hostPeerUpdate.EgressRoutes = append(hostPeerUpdate.EgressRoutes, getExtpeersExtraRoutes(peer.Network)...)
 			}
 			}
 			_, isFailOverPeer := node.FailOverPeers[peer.ID.String()]
 			_, isFailOverPeer := node.FailOverPeers[peer.ID.String()]
-			if (node.IsRelayed && node.RelayedBy != peer.ID.String()) ||
-				(peer.IsRelayed && peer.RelayedBy != node.ID.String()) || isFailOverPeer {
-				// if node is relayed and peer is not the relay, set remove to true
-				if _, ok := peerIndexMap[peerHost.PublicKey.String()]; ok {
+			if servercfg.IsPro {
+				if (node.IsRelayed && node.RelayedBy != peer.ID.String()) ||
+					(peer.IsRelayed && peer.RelayedBy != node.ID.String()) || isFailOverPeer {
+					// if node is relayed and peer is not the relay, set remove to true
+					if _, ok := peerIndexMap[peerHost.PublicKey.String()]; ok {
+						continue
+					}
+					peerConfig.Remove = true
+					hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, peerConfig)
+					peerIndexMap[peerHost.PublicKey.String()] = len(hostPeerUpdate.Peers) - 1
 					continue
 					continue
 				}
 				}
-				peerConfig.Remove = true
-				hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, peerConfig)
-				peerIndexMap[peerHost.PublicKey.String()] = len(hostPeerUpdate.Peers) - 1
-				continue
 			}
 			}
 
 
 			uselocal := false
 			uselocal := false
@@ -362,31 +368,6 @@ func GetAllowedIPs(node, peer *models.Node, metrics *models.Metrics) []net.IPNet
 	return allowedips
 	return allowedips
 }
 }
 
 
-func GetFailOverPeerIps(peer, node *models.Node) []net.IPNet {
-	allowedips := []net.IPNet{}
-	for failOverpeerID := range node.FailOverPeers {
-		failOverpeer, err := GetNodeByID(failOverpeerID)
-		if err == nil && failOverpeer.FailedOverBy == peer.ID {
-			if failOverpeer.Address.IP != nil {
-				allowed := net.IPNet{
-					IP:   failOverpeer.Address.IP,
-					Mask: net.CIDRMask(32, 32),
-				}
-				allowedips = append(allowedips, allowed)
-			}
-			if failOverpeer.Address6.IP != nil {
-				allowed := net.IPNet{
-					IP:   failOverpeer.Address6.IP,
-					Mask: net.CIDRMask(128, 128),
-				}
-				allowedips = append(allowedips, allowed)
-			}
-
-		}
-	}
-	return allowedips
-}
-
 func GetEgressIPs(peer *models.Node) []net.IPNet {
 func GetEgressIPs(peer *models.Node) []net.IPNet {
 
 
 	peerHost, err := GetHost(peer.HostID.String())
 	peerHost, err := GetHost(peer.HostID.String())

+ 6 - 34
logic/serverconf.go

@@ -2,6 +2,8 @@ package logic
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
+	"time"
+
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
 )
 )
@@ -19,46 +21,16 @@ var (
 	EgressesLimit = 1000000000
 	EgressesLimit = 1000000000
 	// FreeTier - specifies if free tier
 	// FreeTier - specifies if free tier
 	FreeTier = false
 	FreeTier = false
+
+	GetTrialEndDate = func() (time.Time, error) {
+		return time.Time{}, nil
+	}
 )
 )
 
 
 type serverData struct {
 type serverData struct {
 	PrivateKey string `json:"privatekey,omitempty" bson:"privatekey,omitempty"`
 	PrivateKey string `json:"privatekey,omitempty" bson:"privatekey,omitempty"`
 }
 }
 
 
-// StorePrivKey - stores server client WireGuard privatekey if needed
-func StorePrivKey(serverID string, privateKey string) error {
-	var newData = serverData{}
-	var err error
-	var data []byte
-	newData.PrivateKey = privateKey
-	data, err = json.Marshal(&newData)
-	if err != nil {
-		return err
-	}
-	return database.Insert(serverID, string(data), database.SERVERCONF_TABLE_NAME)
-}
-
-// FetchPrivKey - fetches private key
-func FetchPrivKey(serverID string) (string, error) {
-	var dbData string
-	var err error
-	var fetchedData = serverData{}
-	dbData, err = database.FetchRecord(database.SERVERCONF_TABLE_NAME, serverID)
-	if err != nil {
-		return "", err
-	}
-	err = json.Unmarshal([]byte(dbData), &fetchedData)
-	if err != nil {
-		return "", err
-	}
-	return fetchedData.PrivateKey, nil
-}
-
-// RemovePrivKey - removes a private key
-func RemovePrivKey(serverID string) error {
-	return database.DeleteRecord(database.SERVERCONF_TABLE_NAME, serverID)
-}
-
 // FetchJWTSecret - fetches jwt secret from db
 // FetchJWTSecret - fetches jwt secret from db
 func FetchJWTSecret() (string, error) {
 func FetchJWTSecret() (string, error) {
 	var dbData string
 	var dbData string

+ 6 - 6
logic/telemetry.go

@@ -32,12 +32,12 @@ func sendTelemetry() error {
 		return nil
 		return nil
 	}
 	}
 
 
-	var telRecord, err = fetchTelemetryRecord()
+	var telRecord, err = FetchTelemetryRecord()
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 	// get telemetry data
 	// get telemetry data
-	d, err := fetchTelemetryData()
+	d, err := FetchTelemetryData()
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -71,8 +71,8 @@ func sendTelemetry() error {
 	})
 	})
 }
 }
 
 
-// fetchTelemetry - fetches telemetry data: count of various object types in DB
-func fetchTelemetryData() (telemetryData, error) {
+// FetchTelemetryData - fetches telemetry data: count of various object types in DB
+func FetchTelemetryData() (telemetryData, error) {
 	var data telemetryData
 	var data telemetryData
 
 
 	data.IsPro = servercfg.IsPro
 	data.IsPro = servercfg.IsPro
@@ -138,8 +138,8 @@ func getClientCount(nodes []models.Node) clientCount {
 	return count
 	return count
 }
 }
 
 
-// fetchTelemetryRecord - get the existing UUID and Timestamp from the DB
-func fetchTelemetryRecord() (models.Telemetry, error) {
+// FetchTelemetryRecord - get the existing UUID and Timestamp from the DB
+func FetchTelemetryRecord() (models.Telemetry, error) {
 	var rawData string
 	var rawData string
 	var telObj models.Telemetry
 	var telObj models.Telemetry
 	var err error
 	var err error

+ 4 - 3
logic/timer.go

@@ -3,11 +3,12 @@ package logic
 import (
 import (
 	"context"
 	"context"
 	"fmt"
 	"fmt"
-	"github.com/gravitl/netmaker/logger"
-	"golang.org/x/exp/slog"
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
+	"github.com/gravitl/netmaker/logger"
+	"golang.org/x/exp/slog"
+
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 )
 )
 
 
@@ -24,7 +25,7 @@ var HookManagerCh = make(chan models.HookDetails, 3)
 // TimerCheckpoint - Checks if 24 hours has passed since telemetry was last sent. If so, sends telemetry data to posthog
 // TimerCheckpoint - Checks if 24 hours has passed since telemetry was last sent. If so, sends telemetry data to posthog
 func TimerCheckpoint() error {
 func TimerCheckpoint() error {
 	// get the telemetry record in the DB, which contains a timestamp
 	// get the telemetry record in the DB, which contains a timestamp
-	telRecord, err := fetchTelemetryRecord()
+	telRecord, err := FetchTelemetryRecord()
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 2 - 2
logic/traffic.go

@@ -2,7 +2,7 @@ package logic
 
 
 // RetrievePrivateTrafficKey - retrieves private key of server
 // RetrievePrivateTrafficKey - retrieves private key of server
 func RetrievePrivateTrafficKey() ([]byte, error) {
 func RetrievePrivateTrafficKey() ([]byte, error) {
-	var telRecord, err = fetchTelemetryRecord()
+	var telRecord, err = FetchTelemetryRecord()
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -12,7 +12,7 @@ func RetrievePrivateTrafficKey() ([]byte, error) {
 
 
 // RetrievePublicTrafficKey - retrieves public key of server
 // RetrievePublicTrafficKey - retrieves public key of server
 func RetrievePublicTrafficKey() ([]byte, error) {
 func RetrievePublicTrafficKey() ([]byte, error) {
-	var telRecord, err = fetchTelemetryRecord()
+	var telRecord, err = FetchTelemetryRecord()
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 1 - 1
main.go

@@ -28,7 +28,7 @@ import (
 	"golang.org/x/exp/slog"
 	"golang.org/x/exp/slog"
 )
 )
 
 
-var version = "v0.22.0"
+var version = "v0.22.1"
 
 
 // Start DB Connection and start API Request Handler
 // Start DB Connection and start API Request Handler
 func main() {
 func main() {

+ 47 - 8
pro/initialize.go

@@ -4,7 +4,10 @@
 package pro
 package pro
 
 
 import (
 import (
+	"time"
+
 	controller "github.com/gravitl/netmaker/controllers"
 	controller "github.com/gravitl/netmaker/controllers"
+	"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"
 	"github.com/gravitl/netmaker/mq"
 	"github.com/gravitl/netmaker/mq"
@@ -31,21 +34,56 @@ func InitPro() {
 	)
 	)
 	logic.EnterpriseCheckFuncs = append(logic.EnterpriseCheckFuncs, func() {
 	logic.EnterpriseCheckFuncs = append(logic.EnterpriseCheckFuncs, func() {
 		// == License Handling ==
 		// == License Handling ==
-		ClearLicenseCache()
-		if err := ValidateLicense(); err != nil {
-			slog.Error(err.Error())
-			return
+		enableLicenseHook := false
+		licenseKeyValue := servercfg.GetLicenseKey()
+		netmakerTenantID := servercfg.GetNetmakerTenantID()
+		if licenseKeyValue != "" && netmakerTenantID != "" {
+			enableLicenseHook = true
+		}
+		if !enableLicenseHook {
+			err := initTrial()
+			if err != nil {
+				logger.Log(0, "failed to init trial", err.Error())
+				enableLicenseHook = true
+			}
+			trialEndDate, err := getTrialEndDate()
+			if err != nil {
+				slog.Error("failed to get trial end date", "error", err)
+				enableLicenseHook = true
+			} else {
+				// check if trial ended
+				if time.Now().After(trialEndDate) {
+					// trial ended already
+					enableLicenseHook = true
+				}
+			}
+
 		}
 		}
-		slog.Info("proceeding with Paid Tier license")
-		logic.SetFreeTierForTelemetry(false)
-		// == End License Handling ==
-		AddLicenseHooks()
+
+		if enableLicenseHook {
+			logger.Log(0, "starting license checker")
+			ClearLicenseCache()
+			if err := ValidateLicense(); err != nil {
+				slog.Error(err.Error())
+				return
+			}
+			logger.Log(0, "proceeding with Paid Tier license")
+			logic.SetFreeTierForTelemetry(false)
+			// == End License Handling ==
+			AddLicenseHooks()
+		} else {
+			logger.Log(0, "starting trial license hook")
+			addTrialLicenseHook()
+		}
+
 		if servercfg.GetServerConfig().RacAutoDisable {
 		if servercfg.GetServerConfig().RacAutoDisable {
 			AddRacHooks()
 			AddRacHooks()
 		}
 		}
+
 	})
 	})
 	logic.ResetFailOver = proLogic.ResetFailOver
 	logic.ResetFailOver = proLogic.ResetFailOver
 	logic.ResetFailedOverPeer = proLogic.ResetFailedOverPeer
 	logic.ResetFailedOverPeer = proLogic.ResetFailedOverPeer
+	logic.GetFailOverPeerIps = proLogic.GetFailOverPeerIps
 	logic.DenyClientNodeAccess = proLogic.DenyClientNode
 	logic.DenyClientNodeAccess = proLogic.DenyClientNode
 	logic.IsClientNodeAllowed = proLogic.IsClientNodeAllowed
 	logic.IsClientNodeAllowed = proLogic.IsClientNodeAllowed
 	logic.AllowClientNodeAccess = proLogic.RemoveDeniedNodeFromClient
 	logic.AllowClientNodeAccess = proLogic.RemoveDeniedNodeFromClient
@@ -63,6 +101,7 @@ func InitPro() {
 	logic.RelayUpdates = proLogic.RelayUpdates
 	logic.RelayUpdates = proLogic.RelayUpdates
 	logic.IsInternetGw = proLogic.IsInternetGw
 	logic.IsInternetGw = proLogic.IsInternetGw
 	logic.SetInternetGw = proLogic.SetInternetGw
 	logic.SetInternetGw = proLogic.SetInternetGw
+	logic.GetTrialEndDate = getTrialEndDate
 	mq.UpdateMetrics = proLogic.MQUpdateMetrics
 	mq.UpdateMetrics = proLogic.MQUpdateMetrics
 	mq.UpdateMetricsFallBack = proLogic.MQUpdateMetricsFallBack
 	mq.UpdateMetricsFallBack = proLogic.MQUpdateMetricsFallBack
 }
 }

+ 27 - 0
pro/logic/failover.go

@@ -2,6 +2,7 @@ package logic
 
 
 import (
 import (
 	"errors"
 	"errors"
+	"net"
 
 
 	"github.com/google/uuid"
 	"github.com/google/uuid"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
@@ -96,3 +97,29 @@ func ResetFailOver(failOverNode *models.Node) error {
 	}
 	}
 	return nil
 	return nil
 }
 }
+
+// GetFailOverPeerIps - adds the failedOvered peerIps by the peer
+func GetFailOverPeerIps(peer, node *models.Node) []net.IPNet {
+	allowedips := []net.IPNet{}
+	for failOverpeerID := range node.FailOverPeers {
+		failOverpeer, err := logic.GetNodeByID(failOverpeerID)
+		if err == nil && failOverpeer.FailedOverBy == peer.ID {
+			if failOverpeer.Address.IP != nil {
+				allowed := net.IPNet{
+					IP:   failOverpeer.Address.IP,
+					Mask: net.CIDRMask(32, 32),
+				}
+				allowedips = append(allowedips, allowed)
+			}
+			if failOverpeer.Address6.IP != nil {
+				allowed := net.IPNet{
+					IP:   failOverpeer.Address6.IP,
+					Mask: net.CIDRMask(128, 128),
+				}
+				allowedips = append(allowedips, allowed)
+			}
+
+		}
+	}
+	return allowedips
+}

+ 3 - 0
pro/remote_access_client.go

@@ -1,3 +1,6 @@
+//go:build ee
+// +build ee
+
 package pro
 package pro
 
 
 import (
 import (

+ 164 - 0
pro/trial.go

@@ -0,0 +1,164 @@
+//go:build ee
+// +build ee
+
+package pro
+
+import (
+	"crypto/rand"
+	"encoding/json"
+	"errors"
+	"time"
+
+	"github.com/gravitl/netmaker/database"
+	"github.com/gravitl/netmaker/logger"
+	"github.com/gravitl/netmaker/logic"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/netclient/ncutils"
+	"github.com/gravitl/netmaker/servercfg"
+	"golang.org/x/crypto/nacl/box"
+)
+
+type TrialInfo struct {
+	PrivKey []byte `json:"priv_key"`
+	PubKey  []byte `json:"pub_key"`
+	Secret  []byte `json:"secret"`
+}
+
+func addTrialLicenseHook() {
+	logic.HookManagerCh <- models.HookDetails{
+		Hook:     TrialLicenseHook,
+		Interval: time.Hour,
+	}
+}
+
+type TrialDates struct {
+	TrialStartedAt time.Time `json:"trial_started_at"`
+	TrialEndsAt    time.Time `json:"trial_ends_at"`
+}
+
+const trial_table_name = "trial"
+
+const trial_data_key = "trialdata"
+
+// stores trial end date
+func initTrial() error {
+	telData, err := logic.FetchTelemetryData()
+	if err != nil {
+		return err
+	}
+	if telData.Hosts > 0 || telData.Networks > 0 || telData.Users > 0 {
+		return nil // database is already populated, so skip creating trial
+	}
+	database.CreateTable(trial_table_name)
+	records, err := database.FetchRecords(trial_table_name)
+	if err != nil && !database.IsEmptyRecord(err) {
+		return err
+	}
+	if len(records) > 0 {
+		return nil
+	}
+	// setup encryption keys
+	trafficPubKey, trafficPrivKey, err := box.GenerateKey(rand.Reader) // generate traffic keys
+	if err != nil {
+		return err
+	}
+	tPriv, err := ncutils.ConvertKeyToBytes(trafficPrivKey)
+	if err != nil {
+		return err
+	}
+
+	tPub, err := ncutils.ConvertKeyToBytes(trafficPubKey)
+	if err != nil {
+		return err
+	}
+	trialDates := TrialDates{
+		TrialStartedAt: time.Now(),
+		TrialEndsAt:    time.Now().Add(time.Hour * 24 * 14),
+	}
+	t := TrialInfo{
+		PrivKey: tPriv,
+		PubKey:  tPub,
+	}
+	tel, err := logic.FetchTelemetryRecord()
+	if err != nil {
+		return err
+	}
+
+	trialDatesData, err := json.Marshal(trialDates)
+	if err != nil {
+		return err
+	}
+	telePubKey, err := ncutils.ConvertBytesToKey(tel.TrafficKeyPub)
+	if err != nil {
+		return err
+	}
+	trialDatesSecret, err := ncutils.BoxEncrypt(trialDatesData, telePubKey, trafficPrivKey)
+	if err != nil {
+		return err
+	}
+	t.Secret = trialDatesSecret
+	trialData, err := json.Marshal(t)
+	if err != nil {
+		return err
+	}
+	err = database.Insert(trial_data_key, string(trialData), trial_table_name)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// TrialLicenseHook - hook func to check if pro trial has ended
+func TrialLicenseHook() error {
+	endDate, err := getTrialEndDate()
+	if err != nil {
+		logger.FatalLog0("failed to trial end date", err.Error())
+	}
+	if time.Now().After(endDate) {
+		logger.Log(0, "***IMPORTANT: Your Trial Has Ended, to continue using pro version, please visit https://app.netmaker.io/ and create on-prem tenant to obtain a license***\nIf you wish to downgrade to community version, please run this command `/root/nm-quick.sh -d`")
+		err = errors.New("your trial has ended")
+		servercfg.ErrLicenseValidation = err
+		return err
+	}
+	return nil
+}
+
+// get trial date
+func getTrialEndDate() (time.Time, error) {
+	record, err := database.FetchRecord(trial_table_name, trial_data_key)
+	if err != nil {
+		return time.Time{}, err
+	}
+	var trialInfo TrialInfo
+	err = json.Unmarshal([]byte(record), &trialInfo)
+	if err != nil {
+		return time.Time{}, err
+	}
+	tel, err := logic.FetchTelemetryRecord()
+	if err != nil {
+		return time.Time{}, err
+	}
+	telePrivKey, err := ncutils.ConvertBytesToKey(tel.TrafficKeyPriv)
+	if err != nil {
+		return time.Time{}, err
+	}
+	trialPubKey, err := ncutils.ConvertBytesToKey(trialInfo.PubKey)
+	if err != nil {
+		return time.Time{}, err
+	}
+	// decrypt secret
+	secretDecrypt, err := ncutils.BoxDecrypt(trialInfo.Secret, trialPubKey, telePrivKey)
+	if err != nil {
+		return time.Time{}, err
+	}
+	trialDates := TrialDates{}
+	err = json.Unmarshal(secretDecrypt, &trialDates)
+	if err != nil {
+		return time.Time{}, err
+	}
+	if trialDates.TrialEndsAt.IsZero() {
+		return time.Time{}, errors.New("invalid date")
+	}
+	return trialDates.TrialEndsAt, nil
+
+}

+ 0 - 1
pro/types.go

@@ -1,4 +1,3 @@
-// go:build ee
 //go:build ee
 //go:build ee
 // +build ee
 // +build ee
 
 

+ 1 - 1
release.md

@@ -1,5 +1,5 @@
 
 
-# Netmaker v0.22.0
+# Netmaker v0.22.1
 
 
 ## Whats New
 ## Whats New
 - Revamped Internet Gateways
 - Revamped Internet Gateways

+ 206 - 264
scripts/nm-quick.sh

@@ -11,64 +11,25 @@ if [ $(id -u) -ne 0 ]; then
 	echo "This script must be run as root"
 	echo "This script must be run as root"
 	exit 1
 	exit 1
 fi
 fi
-
+# increase the timeouts
+export DOCKER_CLIENT_TIMEOUT=120
+export COMPOSE_HTTP_TIMEOUT=120
 unset INSTALL_TYPE
 unset INSTALL_TYPE
-unset BUILD_TYPE
 unset BUILD_TAG
 unset BUILD_TAG
 unset IMAGE_TAG
 unset IMAGE_TAG
-unset AUTO_BUILD
 unset NETMAKER_BASE_DOMAIN
 unset NETMAKER_BASE_DOMAIN
-
+unset UPGRADE_FLAG
 # usage - displays usage instructions
 # usage - displays usage instructions
 usage() {
 usage() {
 	echo "nm-quick.sh v$NM_QUICK_VERSION"
 	echo "nm-quick.sh v$NM_QUICK_VERSION"
-	echo "usage: ./nm-quick.sh [-e] [-b buildtype] [-t tag] [-a auto] [-d domain]"
-	echo "  -e      if specified, will install netmaker pro"
-	echo "  -b      type of build; options:"
-	echo "          \"version\" - will install a specific version of Netmaker using remote git and dockerhub"
-	echo "          \"local\": - will install by cloning repo and building images from git"
-	echo "          \"branch\": - will install a specific branch using remote git and dockerhub"
-	echo "  -t      tag of build; if buildtype=version, tag=version. If builtype=branch or builtype=local, tag=branch"
-	echo "  -a      auto-build; skip prompts and use defaults, if none provided"
-	echo "  -d      domain; if specified, will use this domain instead of auto-generating one"
-	echo "examples:"
-	echo "          nm-quick.sh -e -b version -t $LATEST"
-	echo "          nm-quick.sh -e -b local -t feature_v0.17.2_newfeature"
-	echo "          nm-quick.sh -e -b branch -t develop"
-	echo "          nm-quick.sh -e -b version -t $LATEST -a -d example.com"
+	echo "usage: ./nm-quick.sh [-c]"
+	echo " -c  if specified, will install netmaker community version"
+	echo " -u  if specified, will upgrade netmaker to pro version"
+	echo " -d if specified, will downgrade netmaker to community version"
 	exit 1
 	exit 1
 }
 }
 
 
-while getopts evab:d:t: flag; do
-	case "${flag}" in
-	e)
-		INSTALL_TYPE="pro"
-		UPGRADE_FLAG="yes"
-		;;
-	v)
-		usage
-		exit 0
-		;;
-	a)
-		AUTO_BUILD="on"
-		;;
-	b)
-		BUILD_TYPE=${OPTARG}
-		if [[ ! "$BUILD_TYPE" =~ ^(version|local|branch)$ ]]; then
-			echo "error: $BUILD_TYPE is invalid"
-			echo "valid options: version, local, branch"
-			usage
-			exit 1
-		fi
-		;;
-	t)
-		BUILD_TAG=${OPTARG}
-		;;
-	d)
-		NETMAKER_BASE_DOMAIN=${OPTARG}
-		;;
-	esac
-done
+
 
 
 # print_logo - prints the netmaker logo
 # print_logo - prints the netmaker logo
 print_logo() {
 print_logo() {
@@ -93,32 +54,12 @@ EOF
 # set_buildinfo - sets the information based on script input for how the installation should be run
 # set_buildinfo - sets the information based on script input for how the installation should be run
 set_buildinfo() {
 set_buildinfo() {
 
 
-	if [ -z "$BUILD_TYPE" ]; then
-		BUILD_TYPE="version"
-		BUILD_TAG=$LATEST
-	fi
-
-	if [ -z "$BUILD_TAG" ] && [ "$BUILD_TYPE" = "version" ]; then
-		BUILD_TAG=$LATEST
-	fi
-
-	if [ -z "$BUILD_TAG" ] && [ ! -z "$BUILD_TYPE" ]; then
-		echo "error: must specify build tag when build type \"$BUILD_TYPE\" is specified"
-		usage
-		exit 1
-	fi
 
 
+	
+	BUILD_TAG=$LATEST
 	IMAGE_TAG=$(sed 's/\//-/g' <<<"$BUILD_TAG")
 	IMAGE_TAG=$(sed 's/\//-/g' <<<"$BUILD_TAG")
 
 
-	if [ "$1" = "ce" ]; then
-		INSTALL_TYPE="ce"
-	elif [ "$1" = "pro" ]; then
-		INSTALL_TYPE="pro"
-	fi
-
-	if [ "$AUTO_BUILD" = "on" ] && [ -z "$INSTALL_TYPE" ]; then
-		INSTALL_TYPE="ce"
-	elif [ -z "$INSTALL_TYPE" ]; then
+	if [ -z "$INSTALL_TYPE" ]; then
 		echo "-----------------------------------------------------"
 		echo "-----------------------------------------------------"
 		echo "Would you like to install Netmaker Community Edition (CE), or Netmaker Enterprise Edition (pro)?"
 		echo "Would you like to install Netmaker Community Edition (CE), or Netmaker Enterprise Edition (pro)?"
 		echo "pro will require you to create an account at https://app.netmaker.io"
 		echo "pro will require you to create an account at https://app.netmaker.io"
@@ -141,7 +82,6 @@ set_buildinfo() {
 	fi
 	fi
 	echo "-----------Build Options-----------------------------"
 	echo "-----------Build Options-----------------------------"
 	echo "   Pro or CE: $INSTALL_TYPE"
 	echo "   Pro or CE: $INSTALL_TYPE"
-	echo "  Build Type: $BUILD_TYPE"
 	echo "   Build Tag: $BUILD_TAG"
 	echo "   Build Tag: $BUILD_TAG"
 	echo "   Image Tag: $IMAGE_TAG"
 	echo "   Image Tag: $IMAGE_TAG"
 	echo "   Installer: v$NM_QUICK_VERSION"
 	echo "   Installer: v$NM_QUICK_VERSION"
@@ -173,7 +113,9 @@ install_yq() {
 setup_netclient() {
 setup_netclient() {
 
 
 	set +e
 	set +e
-	netclient uninstall
+	if [ -x "$(command -v netclient)" ]; then
+		netclient uninstall
+	fi
 	set -e
 	set -e
 
 
 	wget -qO netclient https://github.com/gravitl/netclient/releases/download/$LATEST/netclient-linux-$ARCH
 	wget -qO netclient https://github.com/gravitl/netclient/releases/download/$LATEST/netclient-linux-$ARCH
@@ -257,9 +199,6 @@ wait_seconds() { (
 
 
 # confirm - get user input to confirm that they want to perform the next step
 # confirm - get user input to confirm that they want to perform the next step
 confirm() { (
 confirm() { (
-	if [ "$AUTO_BUILD" = "on" ]; then
-		return 0
-	fi
 	while true; do
 	while true; do
 		read -p 'Does everything look right? [y/n]: ' yn
 		read -p 'Does everything look right? [y/n]: ' yn
 		case $yn in
 		case $yn in
@@ -277,28 +216,26 @@ confirm() { (
 	done
 	done
 ) }
 ) }
 
 
+
 save_config() { (
 save_config() { (
 	echo "Saving the config to $CONFIG_PATH"
 	echo "Saving the config to $CONFIG_PATH"
 	touch "$CONFIG_PATH"
 	touch "$CONFIG_PATH"
-	save_config_item NM_EMAIL "$EMAIL"
-	save_config_item NM_DOMAIN "$NETMAKER_BASE_DOMAIN"
-	save_config_item UI_IMAGE_TAG "$IMAGE_TAG"
-	if [ "$BUILD_TYPE" = "local" ]; then
-		save_config_item UI_IMAGE_TAG "$LATEST"
-	else
-		save_config_item UI_IMAGE_TAG "$IMAGE_TAG"
+	if [ -n "$EMAIL" ]; then 
+		save_config_item NM_EMAIL "$EMAIL"
+	fi
+	if [ -n "$NETMAKER_BASE_DOMAIN" ]; then
+		save_config_item NM_DOMAIN "$NETMAKER_BASE_DOMAIN"
 	fi
 	fi
+	save_config_item UI_IMAGE_TAG "$IMAGE_TAG"
 	# version-specific entries
 	# version-specific entries
 	if [ "$INSTALL_TYPE" = "pro" ]; then
 	if [ "$INSTALL_TYPE" = "pro" ]; then
 		save_config_item NETMAKER_TENANT_ID "$TENANT_ID"
 		save_config_item NETMAKER_TENANT_ID "$TENANT_ID"
 		save_config_item LICENSE_KEY "$LICENSE_KEY"
 		save_config_item LICENSE_KEY "$LICENSE_KEY"
-		save_config_item METRICS_EXPORTER "on"
-		save_config_item PROMETHEUS "on"
-		if [ "$BUILD_TYPE" = "version" ]; then
-			save_config_item SERVER_IMAGE_TAG "$IMAGE_TAG-ee"
-		else
-			save_config_item SERVER_IMAGE_TAG "$IMAGE_TAG"
+		if [ "$UPGRADE_FLAG" = "yes" ];then
+			save_config_item METRICS_EXPORTER "on"
+			save_config_item PROMETHEUS "on"
 		fi
 		fi
+		save_config_item SERVER_IMAGE_TAG "$IMAGE_TAG-ee"
 	else
 	else
 		save_config_item METRICS_EXPORTER "off"
 		save_config_item METRICS_EXPORTER "off"
 		save_config_item PROMETHEUS "off"
 		save_config_item PROMETHEUS "off"
@@ -309,7 +246,7 @@ save_config() { (
 		"INSTALL_TYPE" "NODE_ID" "DNS_MODE" "NETCLIENT_AUTO_UPDATE" "API_PORT"
 		"INSTALL_TYPE" "NODE_ID" "DNS_MODE" "NETCLIENT_AUTO_UPDATE" "API_PORT"
 		"CORS_ALLOWED_ORIGIN" "DISPLAY_KEYS" "DATABASE" "SERVER_BROKER_ENDPOINT" "VERBOSITY"
 		"CORS_ALLOWED_ORIGIN" "DISPLAY_KEYS" "DATABASE" "SERVER_BROKER_ENDPOINT" "VERBOSITY"
 		"DEBUG_MODE"  "REST_BACKEND" "DISABLE_REMOTE_IP_CHECK" "TELEMETRY" "AUTH_PROVIDER" "CLIENT_ID" "CLIENT_SECRET"
 		"DEBUG_MODE"  "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")
+		"FRONTEND_URL" "AZURE_TENANT" "OIDC_ISSUER" "EXPORTER_API_PORT" "JWT_VALIDITY_DURATION" "RAC_AUTO_DISABLE" "CACHING_ENABLED")
 	for name in "${toCopy[@]}"; do
 	for name in "${toCopy[@]}"; do
 		save_config_item $name "${!name}"
 		save_config_item $name "${!name}"
 	done
 	done
@@ -345,38 +282,7 @@ save_config_item() { (
 	fi
 	fi
 ); }
 ); }
 
 
-# local_install_setup - builds artifacts based on specified branch locally to use in install
-local_install_setup() { (
-	if test -z "$NM_SKIP_CLONE"; then
-		rm -rf netmaker-tmp
-		mkdir netmaker-tmp
-		cd netmaker-tmp
-		git clone --single-branch --depth=1 --branch=$BUILD_TAG https://www.github.com/gravitl/netmaker
-	else
-		cd netmaker-tmp
-		echo "Skipping git clone on NM_SKIP_CLONE"
-	fi
-	cd netmaker
-	if test -z "$NM_SKIP_BUILD"; then
-		docker build --no-cache --build-arg version=$IMAGE_TAG -t gravitl/netmaker:$IMAGE_TAG .
-	else
-		echo "Skipping build on NM_SKIP_BUILD"
-	fi
-	cp compose/docker-compose.yml "$SCRIPT_DIR/docker-compose.yml"
-	if [ "$INSTALL_TYPE" = "pro" ]; then
-		cp compose/docker-compose.ee.yml "$SCRIPT_DIR/docker-compose.override.yml"
-		cp docker/Caddyfile-pro "$SCRIPT_DIR/Caddyfile"
-	else
-		cp docker/Caddyfile "$SCRIPT_DIR/Caddyfile"
-	fi
-	cp scripts/netmaker.default.env "$SCRIPT_DIR/netmaker.default.env"
-	cp docker/mosquitto.conf "$SCRIPT_DIR/mosquitto.conf"
-	cp docker/wait.sh "$SCRIPT_DIR/wait.sh"
-	cd ../../
-	if test -z "$NM_SKIP_CLONE"; then
-		rm -rf netmaker-tmp
-	fi
-); }
+
 
 
 # install_dependencies - install necessary packages to run netmaker
 # install_dependencies - install necessary packages to run netmaker
 install_dependencies() {
 install_dependencies() {
@@ -520,27 +426,23 @@ set_install_vars() {
 	echo "For this reason, we STRONGLY RECOMMEND using your own domain. Using the auto-generated domain may lead to a failed installation due to rate limiting."
 	echo "For this reason, we STRONGLY RECOMMEND using your own domain. Using the auto-generated domain may lead to a failed installation due to rate limiting."
 	echo "-----------------------------------------------------"
 	echo "-----------------------------------------------------"
 
 
-	if [ "$AUTO_BUILD" = "on" ]; then
-		DOMAIN_TYPE="auto"
-	else
-		select domain_option in "Auto Generated ($NETMAKER_BASE_DOMAIN)" "Custom Domain (e.x: netmaker.example.com)"; do
-			case $REPLY in
-			1)
-				echo "using $NETMAKER_BASE_DOMAIN for base domain"
-				DOMAIN_TYPE="auto"
-				break
-				;;
-			2)
-				read -p "Enter Custom Domain (make sure  *.domain points to $SERVER_HOST first): " domain
-				NETMAKER_BASE_DOMAIN=$domain
-				echo "using $NETMAKER_BASE_DOMAIN"
-				DOMAIN_TYPE="custom"
-				break
-				;;
-			*) echo "invalid option $REPLY" ;;
-			esac
-		done
-	fi
+	select domain_option in "Auto Generated ($NETMAKER_BASE_DOMAIN)" "Custom Domain (e.x: netmaker.example.com)"; do
+		case $REPLY in
+		1)
+			echo "using $NETMAKER_BASE_DOMAIN for base domain"
+			DOMAIN_TYPE="auto"
+			break
+			;;
+		2)
+			read -p "Enter Custom Domain (make sure  *.domain points to $SERVER_HOST first): " domain
+			NETMAKER_BASE_DOMAIN=$domain
+			echo "using $NETMAKER_BASE_DOMAIN"
+			DOMAIN_TYPE="custom"
+			break
+			;;
+		*) echo "invalid option $REPLY" ;;
+		esac
+	done
 
 
 	wait_seconds 2
 	wait_seconds 2
 
 
@@ -550,7 +452,7 @@ set_install_vars() {
 	echo "                api.$NETMAKER_BASE_DOMAIN"
 	echo "                api.$NETMAKER_BASE_DOMAIN"
 	echo "             broker.$NETMAKER_BASE_DOMAIN"
 	echo "             broker.$NETMAKER_BASE_DOMAIN"
 
 
-	if [ "$INSTALL_TYPE" = "pro" ]; then
+	if [ "$UPGRADE_FLAG" = "yes" ]; then
 		echo "         prometheus.$NETMAKER_BASE_DOMAIN"
 		echo "         prometheus.$NETMAKER_BASE_DOMAIN"
 		echo "  netmaker-exporter.$NETMAKER_BASE_DOMAIN"
 		echo "  netmaker-exporter.$NETMAKER_BASE_DOMAIN"
 		echo "            grafana.$NETMAKER_BASE_DOMAIN"
 		echo "            grafana.$NETMAKER_BASE_DOMAIN"
@@ -565,33 +467,13 @@ set_install_vars() {
 
 
 	wait_seconds 1
 	wait_seconds 1
 
 
-	if [ "$INSTALL_TYPE" = "pro" ]; then
-
-		echo "-----------------------------------------------------"
-		echo "Provide Details for pro installation:"
-		echo "    1. Log into https://app.netmaker.io"
-		echo "    2. follow instructions to get a license at: https://docs.netmaker.io/ee/ee-setup.html"
-		echo "    3. Retrieve License and Tenant ID"
-		echo "    4. note email address"
-		echo "-----------------------------------------------------"
-		unset LICENSE_KEY
-		while [ -z "$LICENSE_KEY" ]; do
-			read -p "License Key: " LICENSE_KEY
-		done
-		unset TENANT_ID
-		while [ -z ${TENANT_ID} ]; do
-			read -p "Tenant ID: " TENANT_ID
-		done
-	fi
 
 
 	unset GET_EMAIL
 	unset GET_EMAIL
 	unset RAND_EMAIL
 	unset RAND_EMAIL
 	RAND_EMAIL="$(echo $RANDOM | md5sum | head -c 16)@email.com"
 	RAND_EMAIL="$(echo $RANDOM | md5sum | head -c 16)@email.com"
 	# suggest the prev email or a random one
 	# suggest the prev email or a random one
 	EMAIL_SUGGESTED=${NM_EMAIL:-$RAND_EMAIL}
 	EMAIL_SUGGESTED=${NM_EMAIL:-$RAND_EMAIL}
-	if [ -z $AUTO_BUILD ]; then
-		read -p "Email Address for Domain Registration (click 'enter' to use $EMAIL_SUGGESTED): " GET_EMAIL
-	fi
+	read -p "Email Address for Domain Registration (click 'enter' to use $EMAIL_SUGGESTED): " GET_EMAIL
 	if [ -z "$GET_EMAIL" ]; then
 	if [ -z "$GET_EMAIL" ]; then
 		EMAIL="$EMAIL_SUGGESTED"
 		EMAIL="$EMAIL_SUGGESTED"
 		if [ "$EMAIL" = "$NM_EMAIL" ]; then
 		if [ "$EMAIL" = "$NM_EMAIL" ]; then
@@ -609,9 +491,8 @@ set_install_vars() {
 	unset GET_MQ_PASSWORD
 	unset GET_MQ_PASSWORD
 	unset CONFIRM_MQ_PASSWORD
 	unset CONFIRM_MQ_PASSWORD
 	echo "Enter Credentials For MQ..."
 	echo "Enter Credentials For MQ..."
-	if [ -z $AUTO_BUILD ]; then
-		read -p "MQ Username (click 'enter' to use 'netmaker'): " GET_MQ_USERNAME
-	fi
+	
+	read -p "MQ Username (click 'enter' to use 'netmaker'): " GET_MQ_USERNAME
 	if [ -z "$GET_MQ_USERNAME" ]; then
 	if [ -z "$GET_MQ_USERNAME" ]; then
 		echo "using default username for mq"
 		echo "using default username for mq"
 		MQ_USERNAME="netmaker"
 		MQ_USERNAME="netmaker"
@@ -626,33 +507,33 @@ set_install_vars() {
 		)
 		)
 	fi
 	fi
 
 
-	if [ -z $AUTO_BUILD ]; then
-		select domain_option in "Auto Generated / Config Password" "Input Your Own Password"; do
-			case $REPLY in
-			1)
-				echo "using random password for mq"
-				break
-				;;
-			2)
-				while true; do
-					echo "Enter your Password For MQ: "
-					read -s GET_MQ_PASSWORD
-					echo "Enter your password again to confirm: "
-					read -s CONFIRM_MQ_PASSWORD
-					if [ ${GET_MQ_PASSWORD} != ${CONFIRM_MQ_PASSWORD} ]; then
-						echo "wrong password entered, try again..."
-						continue
-					fi
-					MQ_PASSWORD="$GET_MQ_PASSWORD"
-					echo "MQ Password Saved Successfully!!"
-					break
-				done
+
+	select domain_option in "Auto Generated / Config Password" "Input Your Own Password"; do
+		case $REPLY in
+		1)
+			echo "using random password for mq"
+			break
+			;;
+		2)
+			while true; do
+				echo "Enter your Password For MQ: "
+				read -s GET_MQ_PASSWORD
+				echo "Enter your password again to confirm: "
+				read -s CONFIRM_MQ_PASSWORD
+				if [ ${GET_MQ_PASSWORD} != ${CONFIRM_MQ_PASSWORD} ]; then
+					echo "wrong password entered, try again..."
+					continue
+				fi
+				MQ_PASSWORD="$GET_MQ_PASSWORD"
+				echo "MQ Password Saved Successfully!!"
 				break
 				break
-				;;
-			*) echo "invalid option $REPLY" ;;
-			esac
-		done
-	fi
+			done
+			break
+			;;
+		*) echo "invalid option $REPLY" ;;
+		esac
+	done
+	
 
 
 	wait_seconds 2
 	wait_seconds 2
 
 
@@ -662,18 +543,10 @@ set_install_vars() {
 	echo "        domain: $NETMAKER_BASE_DOMAIN"
 	echo "        domain: $NETMAKER_BASE_DOMAIN"
 	echo "         email: $EMAIL"
 	echo "         email: $EMAIL"
 	echo "     public ip: $SERVER_HOST"
 	echo "     public ip: $SERVER_HOST"
-	if [ "$INSTALL_TYPE" = "pro" ]; then
-		echo "       license: $LICENSE_KEY"
-		echo "    account id: $TENANT_ID"
-	fi
 	echo "-----------------------------------------------------------------"
 	echo "-----------------------------------------------------------------"
 	echo "Confirm Settings for Installation"
 	echo "Confirm Settings for Installation"
 	echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
 	echo "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
 
 
-	if [ ! "$BUILD_TYPE" = "local" ]; then
-		IMAGE_TAG="$LATEST"
-	fi
-
 	confirm
 	confirm
 }
 }
 
 
@@ -688,26 +561,24 @@ install_netmaker() {
 
 
 	echo "Pulling config files..."
 	echo "Pulling config files..."
 
 
-	if [ "$BUILD_TYPE" = "local" ]; then
-		local_install_setup
-	else
-		local BASE_URL="https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG"
-
-		local COMPOSE_URL="$BASE_URL/compose/docker-compose.yml"
-		local CADDY_URL="$BASE_URL/docker/Caddyfile"
-		if [ "$INSTALL_TYPE" = "pro" ]; then
-			local COMPOSE_OVERRIDE_URL="$BASE_URL/compose/docker-compose.pro.yml"
-			local CADDY_URL="$BASE_URL/docker/Caddyfile-pro"
-		fi
-		wget -qO "$SCRIPT_DIR"/docker-compose.yml $COMPOSE_URL
-		if test -n "$COMPOSE_OVERRIDE_URL"; then
-			wget -qO "$SCRIPT_DIR"/docker-compose.override.yml $COMPOSE_OVERRIDE_URL
-		fi
-		wget -qO "$SCRIPT_DIR"/Caddyfile "$CADDY_URL"
-		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"/wait.sh "$BASE_URL/docker/wait.sh"
+	
+	local BASE_URL="https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG"
+	local COMPOSE_URL="$BASE_URL/compose/docker-compose.yml"
+	local CADDY_URL="$BASE_URL/docker/Caddyfile"
+	if [ "$INSTALL_TYPE" = "pro" ]; then
+		local COMPOSE_OVERRIDE_URL="$BASE_URL/compose/docker-compose.pro.yml"
+		local CADDY_URL="$BASE_URL/docker/Caddyfile-pro"
+	fi
+	wget -qO "$SCRIPT_DIR"/docker-compose.yml $COMPOSE_URL
+	if [ "$UPGRADE_FLAG" = "yes" ]; then
+		wget -qO "$SCRIPT_DIR"/docker-compose.override.yml $COMPOSE_OVERRIDE_URL
+	elif [ -a "$SCRIPT_DIR"/docker-compose.override.yml ]; then
+		rm -f "$SCRIPT_DIR"/docker-compose.override.yml
 	fi
 	fi
+	wget -qO "$SCRIPT_DIR"/Caddyfile "$CADDY_URL"
+	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"/wait.sh "$BASE_URL/docker/wait.sh"
 
 
 	chmod +x "$SCRIPT_DIR"/wait.sh
 	chmod +x "$SCRIPT_DIR"/wait.sh
 	mkdir -p /etc/netmaker
 	mkdir -p /etc/netmaker
@@ -718,9 +589,7 @@ install_netmaker() {
 
 
 	echo "Starting containers..."
 	echo "Starting containers..."
 
 
-	# increase the timeouts
-	export DOCKER_CLIENT_TIMEOUT=120
-	export COMPOSE_HTTP_TIMEOUT=120
+	
 
 
 	# start docker and rebuild containers / networks
 	# start docker and rebuild containers / networks
 	cd "${SCRIPT_DIR}"
 	cd "${SCRIPT_DIR}"
@@ -800,6 +669,9 @@ print_success() {
 
 
 cleanup() {
 cleanup() {
 	# remove the existing netclient's instance from the existing network
 	# remove the existing netclient's instance from the existing network
+	if ! command -v netclient >/dev/null 2>&1; then
+		return
+	fi
 	if command -v nmctl >/dev/null 2>&1; then
 	if command -v nmctl >/dev/null 2>&1; then
 		local node_id=$(netclient list | jq '.[0].node_id' 2>/dev/null)
 		local node_id=$(netclient list | jq '.[0].node_id' 2>/dev/null)
 		# trim doublequotes
 		# trim doublequotes
@@ -810,7 +682,11 @@ cleanup() {
 		fi
 		fi
 	fi
 	fi
 
 
-	echo "Stopping all containers..."
+	stop_services
+}
+
+stop_services(){
+	echo "Stopping all containers, this will take a while please wait..."
 	local containers=("mq" "netmaker-ui" "coredns" "turn" "caddy" "netmaker" "netmaker-exporter" "prometheus" "grafana")
 	local containers=("mq" "netmaker-ui" "coredns" "turn" "caddy" "netmaker" "netmaker-exporter" "prometheus" "grafana")
 	for name in "${containers[@]}"; do
 	for name in "${containers[@]}"; do
 		local running=$(docker ps | grep -w "$name")
 		local running=$(docker ps | grep -w "$name")
@@ -824,61 +700,127 @@ cleanup() {
 	done
 	done
 }
 }
 
 
-# 1. print netmaker logo
-print_logo
+upgrade() {
+	print_logo
+	unset IMAGE_TAG
+	unset BUILD_TAG
+	IMAGE_TAG=$UI_IMAGE_TAG
+	BUILD_TAG=$UI_IMAGE_TAG
+	echo "-----------------------------------------------------"
+	echo "Provide Details for pro installation:"
+	echo "    1. Log into https://app.netmaker.io"
+	echo "    2. follow instructions to get a license at: https://docs.netmaker.io/pro/pro-setup.html"
+	echo "    3. Retrieve License and Tenant ID"
+	echo "-----------------------------------------------------"
+	unset LICENSE_KEY
+	while [ -z "$LICENSE_KEY" ]; do
+		read -p "License Key: " LICENSE_KEY
+	done
+	unset TENANT_ID
+	while [ -z ${TENANT_ID} ]; do
+		read -p "Tenant ID: " TENANT_ID
+	done
+	save_config
+	# start docker and rebuild containers / networks
+	stop_services
+	install_netmaker
+}
 
 
-# read the config
-if [ -f "$CONFIG_PATH" ]; then
-	echo "Using config: $CONFIG_PATH"
-	source "$CONFIG_PATH"
-	if [ "$UPGRADE_FLAG" = "yes" ]; then
-		INSTALL_TYPE="pro"
+downgrade () {
+	print_logo
+	unset IMAGE_TAG
+	unset BUILD_TAG
+	IMAGE_TAG=$UI_IMAGE_TAG
+	BUILD_TAG=$UI_IMAGE_TAG
+	save_config
+	if [ -a "$SCRIPT_DIR"/docker-compose.override.yml ]; then
+		rm -f "$SCRIPT_DIR"/docker-compose.override.yml
 	fi
 	fi
-fi
+	# start docker and rebuild containers / networks
+	stop_services
+	install_netmaker
+}
+
+
+main (){
 
 
-# 2. setup the build instructions
-set_buildinfo
+	# read the config
+	if [ -f "$CONFIG_PATH" ]; then
+		echo "Using config: $CONFIG_PATH"
+		source "$CONFIG_PATH"
+	fi
+
+	INSTALL_TYPE="pro"
+	while getopts :cudv flag; do
+	case "${flag}" in
+	c)
+		INSTALL_TYPE="ce"
+		;;
+	u)
+		echo "upgrading to pro version..."
+		INSTALL_TYPE="pro"
+		UPGRADE_FLAG="yes"
+		upgrade
+		exit 0
+		;;
+	d) 
+		echo "downgrading to community version..."
+		INSTALL_TYPE="ce"
+		downgrade
+		exit 0
+		;;
+	v)
+		usage
+		exit 0
+		;;
+	esac
+done
 
 
-set +e
+	# 1. print netmaker logo
+	print_logo
 
 
-# 3. install necessary packages
-install_dependencies
+	# 2. setup the build instructions
+	set_buildinfo
+	set +e
+	# 3. install necessary packages
+	install_dependencies
 
 
-# 4. install yq if necessary
-install_yq
+	# 4. install yq if necessary
+	install_yq
 
 
-set -e
+	set -e
 
 
-# 6. get user input for variables
-set_install_vars
+	# 6. get user input for variables
+	set_install_vars
 
 
-set +e
-cleanup
-set -e
+	set +e
+	cleanup
+	set -e
 
 
-# 7. get and set config files, startup docker-compose
-install_netmaker
+	# 7. get and set config files, startup docker-compose
+	install_netmaker
 
 
-set +e
+	set +e
 
 
-# 8. make sure Caddy certs are working
-test_connection
+	# 8. make sure Caddy certs are working
+	test_connection
 
 
-# 9. install the netmaker CLI
-setup_nmctl
+	# 9. install the netmaker CLI
+	setup_nmctl
 
 
-# 10. create a default mesh network for netmaker
-setup_mesh
+	# 10. create a default mesh network for netmaker
+	setup_mesh
 
 
-set -e
+	set -e
 
 
-# 11. add netclient to docker-compose and start it up
-setup_netclient
+	# 11. add netclient to docker-compose and start it up
+	setup_netclient
 
 
-# 12. make the netclient a default host and ingress gw
-configure_netclient
+	# 12. make the netclient a default host and ingress gw
+	configure_netclient
 
 
-# 13. print success message
-print_success
+	# 13. print success message
+	print_success
+}
 
 
-# cp -f /etc/skel/.bashrc /root/.bashrc
+main "${@}"

+ 1 - 1
swagger.yml

@@ -1149,7 +1149,7 @@ info:
 
 
         API calls must be authenticated via a header of the format -H “Authorization: Bearer <YOUR_SECRET_KEY>” There are two methods to obtain YOUR_SECRET_KEY: 1. Using the masterkey. By default, this value is “secret key,” but you should change this on your instance and keep it secure. This value can be set via env var at startup or in a config file (config/environments/< env >.yaml). See the [Netmaker](https://docs.netmaker.org/index.html) documentation for more details. 2. Using a JWT received for a node. This can be retrieved by calling the /api/nodes/<network>/authenticate endpoint, as documented below.
         API calls must be authenticated via a header of the format -H “Authorization: Bearer <YOUR_SECRET_KEY>” There are two methods to obtain YOUR_SECRET_KEY: 1. Using the masterkey. By default, this value is “secret key,” but you should change this on your instance and keep it secure. This value can be set via env var at startup or in a config file (config/environments/< env >.yaml). See the [Netmaker](https://docs.netmaker.org/index.html) documentation for more details. 2. Using a JWT received for a node. This can be retrieved by calling the /api/nodes/<network>/authenticate endpoint, as documented below.
     title: Netmaker
     title: Netmaker
-    version: 0.22.0
+    version: 0.22.1
 paths:
 paths:
     /api/dns:
     /api/dns:
         get:
         get: