Browse Source

Merge pull request #236 from gravitl/hotfix-0.7.1-docs-and-quickstart-version

v0.7.2
Alex 4 years ago
parent
commit
1fee2c36e0

+ 3 - 0
.gitignore

@@ -1,4 +1,7 @@
 netmaker
 netclient/netclient
 netclient/files/netclient
+netclient/netclient-amd64
+netclient/netclient-arm
+netclient/netclient-arm64
 config/dnsconfig/

+ 1 - 0
compose/docker-compose.quickstart.yml

@@ -54,6 +54,7 @@ services:
       - "8082:80"
     environment:
       BACKEND_URL: "https://api.NETMAKER_BASE_DOMAIN"
+    restart: always
   coredns:
     depends_on:
       - netmaker 

+ 5 - 1
config/config.go

@@ -42,7 +42,6 @@ type ServerConfig struct {
 	GRPCHost             string `yaml:"grpchost"`
 	GRPCPort             string `yaml:"grpcport"`
 	GRPCSecure           string `yaml:"grpcsecure"`
-	DefaultNodeLimit     int32  `yaml:"defaultnodelimit"`
 	MasterKey            string `yaml:"masterkey"`
 	AllowedOrigin        string `yaml:"allowedorigin"`
 	RestBackend          string `yaml:"restbackend"`
@@ -52,6 +51,11 @@ type ServerConfig struct {
 	DisableRemoteIPCheck string `yaml:"disableremoteipcheck"`
 	DisableDefaultNet    string `yaml:"disabledefaultnet"`
 	GRPCSSL              string `yaml:"grpcssl"`
+	Version              string `yaml:"version"`
+	SQLConn              string `yaml:"sqlconn"`
+	Platform              string `yaml:"platform"`
+	Database             string `yaml:database`
+	DefaultNodeLimit     int32  `yaml:"defaultnodelimit"`
 	Verbosity            int32  `yaml:"verbosity"`
 }
 

+ 3 - 1
config/environments/dev.yaml

@@ -9,4 +9,6 @@ server:
   agentbackend: "" # defaults to "on" or AGENT_BACKEND (if set)
   clientmode: "" # defaults to "on" or CLIENT_MODE (if set)
   dnsmode: "" # defaults to "on" or DNS_MODE (if set)
-  disableremoteipcheck: "" # defaults to "false" or DISABLE_REMOTE_IP_CHECK (if set)
+  sqlconn: "" # defaults to "http://" or SQL_CONN (if set)
+  disableremoteipcheck: "" # defaults to "false" or DISABLE_REMOTE_IP_CHECK (if set)
+  version: "" # version of server

+ 2 - 2
controllers/dnsHttpController.go

@@ -58,7 +58,7 @@ func getAllDNS(w http.ResponseWriter, r *http.Request) {
 func GetAllDNS() ([]models.DNSEntry, error) {
 	var dns []models.DNSEntry
 	networks, err := models.GetNetworks()
-	if err != nil {
+	if err != nil && !database.IsEmptyRecord(err) {
 		return []models.DNSEntry{}, err
 	}
 	for _, net := range networks {
@@ -139,7 +139,7 @@ func SetDNS() error {
 	hostfile := txeh.Hosts{}
 	var corefilestring string
 	networks, err := models.GetNetworks()
-	if err != nil {
+	if err != nil && !database.IsEmptyRecord(err){
 		return err
 	}
 

+ 9 - 22
controllers/networkHttpController.go

@@ -133,7 +133,7 @@ func getNetworks(w http.ResponseWriter, r *http.Request) {
 	err := errors.New("Networks Error")
 	if networksSlice[0] == ALL_NETWORK_ACCESS {
 		allnetworks, err = models.GetNetworks()
-		if err != nil {
+		if err != nil && !database.IsEmptyRecord(err){
 			returnErrorResponse(w, r, formatError(err, "internal"))
 			return
 		}
@@ -150,21 +150,6 @@ func getNetworks(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(allnetworks)
 }
 
-func RemoveComms(networks []models.Network) []models.Network {
-	var index int = 100000001
-	for ind, net := range networks {
-		if net.NetID == "comms" {
-			index = ind
-		}
-	}
-	if index == 100000001 {
-		return networks
-	}
-	returnable := make([]models.Network, 0)
-	returnable = append(returnable, networks[:index]...)
-	return append(returnable, networks[index+1:]...)
-}
-
 func ValidateNetworkUpdate(network models.Network) error {
 	v := validator.New()
 
@@ -379,13 +364,15 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
 		returnErrorResponse(w, r, formatError(err, "badrequest"))
 		return
 	}
-	success, err := serverctl.AddNetwork(network.NetID)
-	if err != nil || !success {
-		if err == nil {
-			err = errors.New("Failed to add server to network " + network.DisplayName)
+	if servercfg.IsClientMode() {
+		success, err := serverctl.AddNetwork(network.NetID)
+		if err != nil || !success {
+			if err == nil {
+				err = errors.New("Failed to add server to network " + network.DisplayName)
+			}
+			returnErrorResponse(w, r, formatError(err, "internal"))
+			return
 		}
-		returnErrorResponse(w, r, formatError(err, "internal"))
-		return
 	}
 	functions.PrintUserLog(r.Header.Get("user"), "created network "+network.NetID, 1)
 	w.WriteHeader(http.StatusOK)

+ 61 - 70
controllers/serverHttpController.go

@@ -1,20 +1,21 @@
 package controller
 
 import (
-    "github.com/gravitl/netmaker/models"
-    "github.com/gravitl/netmaker/functions"
-    "github.com/gravitl/netmaker/serverctl"
-    "github.com/gravitl/netmaker/servercfg"
-    "encoding/json"
-    "strings"
-    "net/http"
-    "github.com/gorilla/mux"
+	"encoding/json"
+	"net/http"
+	"strings"
+
+	"github.com/gorilla/mux"
+	"github.com/gravitl/netmaker/functions"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/servercfg"
+	"github.com/gravitl/netmaker/serverctl"
 )
 
 func serverHandlers(r *mux.Router) {
-    r.HandleFunc("/api/server/addnetwork/{network}", securityCheckServer(true, http.HandlerFunc(addNetwork))).Methods("POST")
-    r.HandleFunc("/api/server/getconfig", securityCheckServer(false, http.HandlerFunc(getConfig))).Methods("GET")
-    r.HandleFunc("/api/server/removenetwork/{network}", securityCheckServer(true, http.HandlerFunc(removeNetwork))).Methods("DELETE")
+	r.HandleFunc("/api/server/addnetwork/{network}", securityCheckServer(true, http.HandlerFunc(addNetwork))).Methods("POST")
+	r.HandleFunc("/api/server/getconfig", securityCheckServer(false, http.HandlerFunc(getConfig))).Methods("GET")
+	r.HandleFunc("/api/server/removenetwork/{network}", securityCheckServer(true, http.HandlerFunc(removeNetwork))).Methods("DELETE")
 }
 
 //Security check is middleware for every function and just checks to make sure that its the master calling
@@ -29,93 +30,83 @@ func securityCheckServer(adminonly bool, next http.Handler) http.HandlerFunc {
 		bearerToken := r.Header.Get("Authorization")
 
 		var tokenSplit = strings.Split(bearerToken, " ")
-		var  authToken = ""
+		var authToken = ""
 		if len(tokenSplit) < 2 {
-                      errorResponse = models.ErrorResponse{
-                                Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
-                      }
-                      returnErrorResponse(w, r, errorResponse)
-			return 
-	        } else {
+			errorResponse = models.ErrorResponse{
+				Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
+			}
+			returnErrorResponse(w, r, errorResponse)
+			return
+		} else {
 			authToken = tokenSplit[1]
 		}
 		//all endpoints here require master so not as complicated
 		//still might not be a good  way of doing this
-                user, _, isadmin, err := functions.VerifyUserToken(authToken)
-                errorResponse = models.ErrorResponse{
-                        Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
-                }
-                if !adminonly && (err != nil || user == "") {
-                        returnErrorResponse(w, r, errorResponse)
-                }
-		if !isadmin && !authenticateMasterServer(authToken) {
-                        returnErrorResponse(w, r, errorResponse)
-                }
+		user, _, isadmin, err := functions.VerifyUserToken(authToken)
+		errorResponse = models.ErrorResponse{
+			Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
+		}
+		if !adminonly && (err != nil || user == "") {
+			returnErrorResponse(w, r, errorResponse)
+			return
+		} 
+		if adminonly && !isadmin && !authenticateMasterServer(authToken) {
+			returnErrorResponse(w, r, errorResponse)
+			return
+		}
 		next.ServeHTTP(w, r)
 	}
 }
+
 //Consider a more secure way of setting master key
 func authenticateMasterServer(tokenString string) bool {
-    if tokenString == servercfg.GetMasterKey() {
-        return true
-    }
-    return false
+	if tokenString == servercfg.GetMasterKey() {
+		return true
+	}
+	return false
 }
 
 func removeNetwork(w http.ResponseWriter, r *http.Request) {
-        // Set header
-        w.Header().Set("Content-Type", "application/json")
+	// Set header
+	w.Header().Set("Content-Type", "application/json")
 
-        // get params
-        var params = mux.Vars(r)
+	// get params
+	var params = mux.Vars(r)
 
-        success, err := serverctl.RemoveNetwork(params["network"])
+	success, err := serverctl.RemoveNetwork(params["network"])
 
-        if err != nil || !success {
-                json.NewEncoder(w).Encode("Could not remove server from network " + params["network"])
-                return
-        }
+	if err != nil || !success {
+		json.NewEncoder(w).Encode("Could not remove server from network " + params["network"])
+		return
+	}
 
-        json.NewEncoder(w).Encode("Server removed from network " + params["network"])
+	json.NewEncoder(w).Encode("Server removed from network " + params["network"])
 }
 
 func getConfig(w http.ResponseWriter, r *http.Request) {
 	// Set header
-        w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Content-Type", "application/json")
 
-        // get params
+	// get params
 
-        scfg := servercfg.GetServerConfig()
-        w.WriteHeader(http.StatusOK)
-        json.NewEncoder(w).Encode(scfg)
+	scfg := servercfg.GetServerConfig()
+	json.NewEncoder(w).Encode(scfg)
+	//w.WriteHeader(http.StatusOK)
 }
 
-/*
-func getMongoConfig(w http.ResponseWriter, r *http.Request) {
-        // Set header
-        w.Header().Set("Content-Type", "application/json")
-
-        // get params
-
-        mcfg := servercfg.GetMongoConfig()
-        w.WriteHeader(http.StatusOK)
-        json.NewEncoder(w).Encode(mcfg)
-}
-*/
-
 func addNetwork(w http.ResponseWriter, r *http.Request) {
-        // Set header
-        w.Header().Set("Content-Type", "application/json")
+	// Set header
+	w.Header().Set("Content-Type", "application/json")
 
-        // get params
-        var params = mux.Vars(r)
+	// get params
+	var params = mux.Vars(r)
 
-        success, err := serverctl.AddNetwork(params["network"])
+	success, err := serverctl.AddNetwork(params["network"])
 
-        if err != nil || !success {
-                json.NewEncoder(w).Encode("Could not add server to network " + params["network"])
-                return
-        }
+	if err != nil || !success {
+		json.NewEncoder(w).Encode("Could not add server to network " + params["network"])
+		return
+	}
 
-        json.NewEncoder(w).Encode("Server added to network " + params["network"])
+	json.NewEncoder(w).Encode("Server added to network " + params["network"])
 }

+ 35 - 48
database/database.go

@@ -3,8 +3,7 @@ package database
 import (
 	"encoding/json"
 	"errors"
-
-	"github.com/rqlite/gorqlite"
+	"github.com/gravitl/netmaker/servercfg"
 )
 
 const NETWORKS_TABLE_NAME = "networks"
@@ -21,18 +20,32 @@ const DATABASE_FILENAME = "netmaker.db"
 const NO_RECORD = "no result found"
 const NO_RECORDS = "could not find any records"
 
-var Database gorqlite.Connection
+// == Constants ==
+const INIT_DB = "init"
+const CREATE_TABLE = "createtable"
+const INSERT = "insert"
+const INSERT_PEER = "insertpeer"
+const DELETE = "delete"
+const DELETE_ALL = "deleteall"
+const FETCH_ALL = "fetchall"
+const CLOSE_DB = "closedb"
+
+func getCurrentDB() map[string]interface{} {
+	switch servercfg.GetDB() {
+	case "rqlite":
+		return RQLITE_FUNCTIONS
+	case "sqlite":
+		return SQLITE_FUNCTIONS
+	default:
+		return RQLITE_FUNCTIONS
+	}
+}
 
 func InitializeDatabase() error {
 
-	conn, err := gorqlite.Open("http://")
-	if err != nil {
+	if err := getCurrentDB()[INIT_DB].(func() error)(); err != nil {
 		return err
 	}
-
-	// sqliteDatabase, _ := sql.Open("sqlite3", "./database/"+dbFilename)
-	Database = conn
-	Database.SetConsistencyLevel("strong")
 	createTables()
 	return nil
 }
@@ -49,52 +62,36 @@ func createTables() {
 }
 
 func createTable(tableName string) error {
-	_, err := Database.WriteOne("CREATE TABLE IF NOT EXISTS " + tableName + " (key TEXT NOT NULL UNIQUE PRIMARY KEY, value TEXT)")
-	if err != nil {
-		return err
-	}
-	return nil
+	return getCurrentDB()[CREATE_TABLE].(func(string) error)(tableName)
 }
 
-func isJSONString(value string) bool {
+func IsJSONString(value string) bool {
 	var jsonInt interface{}
 	return json.Unmarshal([]byte(value), &jsonInt) == nil
 }
 
 func Insert(key string, value string, tableName string) error {
-	if key != "" && value != "" && isJSONString(value) {
-		_, err := Database.WriteOne("INSERT OR REPLACE INTO " + tableName + " (key, value) VALUES ('" + key + "', '" + value + "')")
-		if err != nil {
-			return err
-		}
-		return nil
+	if key != "" && value != "" && IsJSONString(value) {
+		return getCurrentDB()[INSERT].(func(string, string, string) error)(key, value, tableName)
 	} else {
 		return errors.New("invalid insert " + key + " : " + value)
 	}
 }
 
 func InsertPeer(key string, value string) error {
-	if key != "" && value != "" && isJSONString(value) {
-		_, err := Database.WriteOne("INSERT OR REPLACE INTO " + PEERS_TABLE_NAME + " (key, value) VALUES ('" + key + "', '" + value + "')")
-		if err != nil {
-			return err
-		}
-		return nil
+	if key != "" && value != "" && IsJSONString(value) {
+		return getCurrentDB()[INSERT_PEER].(func(string, string) error)(key, value)
 	} else {
 		return errors.New("invalid peer insert " + key + " : " + value)
 	}
 }
 
 func DeleteRecord(tableName string, key string) error {
-	_, err := Database.WriteOne("DELETE FROM " + tableName + " WHERE key = \"" + key + "\"")
-	if err != nil {
-		return err
-	}
-	return nil
+	return getCurrentDB()[DELETE].(func(string, string) error)(tableName, key)
 }
 
 func DeleteAllRecords(tableName string) error {
-	_, err := Database.WriteOne("DELETE TABLE " + tableName)
+	err := getCurrentDB()[DELETE_ALL].(func(string) error)(tableName)
 	if err != nil {
 		return err
 	}
@@ -117,19 +114,9 @@ func FetchRecord(tableName string, key string) (string, error) {
 }
 
 func FetchRecords(tableName string) (map[string]string, error) {
-	row, err := Database.QueryOne("SELECT * FROM " + tableName + " ORDER BY key")
-	if err != nil {
-		return nil, err
-	}
-	records := make(map[string]string)
-	for row.Next() { // Iterate and fetch the records from result cursor
-		var key string
-		var value string
-		row.Scan(&key, &value)
-		records[key] = value
-	}
-	if len(records) == 0 {
-		return nil, errors.New(NO_RECORDS)
-	}
-	return records, nil
+	return getCurrentDB()[FETCH_ALL].(func(string) (map[string]string, error))(tableName)
+}
+
+func CloseDB() {
+	getCurrentDB()[CLOSE_DB].(func())()
 }

+ 117 - 0
database/rqlite.go

@@ -0,0 +1,117 @@
+package database
+
+import (
+	"errors"
+
+	"github.com/gravitl/netmaker/servercfg"
+	"github.com/rqlite/gorqlite"
+)
+
+var RQliteDatabase gorqlite.Connection
+
+var RQLITE_FUNCTIONS = map[string]interface{}{
+	INIT_DB:      initRqliteDatabase,
+	CREATE_TABLE: rqliteCreateTable,
+	INSERT:       rqliteInsert,
+	INSERT_PEER:  rqliteInsertPeer,
+	DELETE:       rqliteDeleteRecord,
+	DELETE_ALL:   rqliteDeleteAllRecords,
+	FETCH_ALL:    rqliteFetchRecords,
+	CLOSE_DB:     rqliteCloseDB,
+}
+
+func initRqliteDatabase() error {
+
+	conn, err := gorqlite.Open(servercfg.GetSQLConn())
+	if err != nil {
+		return err
+	}
+	RQliteDatabase = conn
+	RQliteDatabase.SetConsistencyLevel("strong")
+	return nil
+}
+
+func rqliteCreateTable(tableName string) error {
+	_, err := RQliteDatabase.WriteOne("CREATE TABLE IF NOT EXISTS " + tableName + " (key TEXT NOT NULL UNIQUE PRIMARY KEY, value TEXT)")
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func rqliteInsert(key string, value string, tableName string) error {
+	if key != "" && value != "" && IsJSONString(value) {
+		_, err := RQliteDatabase.WriteOne("INSERT OR REPLACE INTO " + tableName + " (key, value) VALUES ('" + key + "', '" + value + "')")
+		if err != nil {
+			return err
+		}
+		return nil
+	} else {
+		return errors.New("invalid insert " + key + " : " + value)
+	}
+}
+
+func rqliteInsertPeer(key string, value string) error {
+	if key != "" && value != "" && IsJSONString(value) {
+		_, err := RQliteDatabase.WriteOne("INSERT OR REPLACE INTO " + PEERS_TABLE_NAME + " (key, value) VALUES ('" + key + "', '" + value + "')")
+		if err != nil {
+			return err
+		}
+		return nil
+	} else {
+		return errors.New("invalid peer insert " + key + " : " + value)
+	}
+}
+
+func rqliteDeleteRecord(tableName string, key string) error {
+	_, err := RQliteDatabase.WriteOne("DELETE FROM " + tableName + " WHERE key = \"" + key + "\"")
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func rqliteDeleteAllRecords(tableName string) error {
+	_, err := RQliteDatabase.WriteOne("DELETE TABLE " + tableName)
+	if err != nil {
+		return err
+	}
+	err = rqliteCreateTable(tableName)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func rqliteFetchRecord(tableName string, key string) (string, error) {
+	results, err := FetchRecords(tableName)
+	if err != nil {
+		return "", err
+	}
+	if results[key] == "" {
+		return "", errors.New(NO_RECORD)
+	}
+	return results[key], nil
+}
+
+func rqliteFetchRecords(tableName string) (map[string]string, error) {
+	row, err := RQliteDatabase.QueryOne("SELECT * FROM " + tableName + " ORDER BY key")
+	if err != nil {
+		return nil, err
+	}
+	records := make(map[string]string)
+	for row.Next() { // Iterate and fetch the records from result cursor
+		var key string
+		var value string
+		row.Scan(&key, &value)
+		records[key] = value
+	}
+	if len(records) == 0 {
+		return nil, errors.New(NO_RECORDS)
+	}
+	return records, nil
+}
+
+func rqliteCloseDB() {
+	RQliteDatabase.Close()
+}

+ 132 - 0
database/sqlite.go

@@ -0,0 +1,132 @@
+package database
+
+import (
+	"database/sql"
+	"errors"
+	"os"
+	"path/filepath"
+
+	_ "github.com/mattn/go-sqlite3"
+)
+
+// == sqlite ==
+const dbFilename = "netmaker.db"
+
+var SqliteDB *sql.DB
+
+var SQLITE_FUNCTIONS = map[string]interface{}{
+	INIT_DB:      initSqliteDB,
+	CREATE_TABLE: sqliteCreateTable,
+	INSERT:       sqliteInsert,
+	INSERT_PEER:  sqliteInsertPeer,
+	DELETE:       sqliteDeleteRecord,
+	DELETE_ALL:   sqliteDeleteAllRecords,
+	FETCH_ALL:    sqliteFetchRecords,
+	CLOSE_DB:     sqliteCloseDB,
+}
+
+func initSqliteDB() error {
+	// == create db file if not present ==
+	if _, err := os.Stat("data"); os.IsNotExist(err) {
+		os.Mkdir("data", 0644)
+	}
+	dbFilePath := filepath.Join("data", dbFilename)
+	if _, err := os.Stat(dbFilePath); os.IsNotExist(err) {
+		os.Create(dbFilePath)
+	}
+	// == "connect" the database ==
+	var dbOpenErr error
+	SqliteDB, dbOpenErr = sql.Open("sqlite3", dbFilePath)
+	if dbOpenErr != nil {
+		return dbOpenErr
+	}
+	return nil
+}
+
+func sqliteCreateTable(tableName string) error {
+	statement, err := SqliteDB.Prepare("CREATE TABLE IF NOT EXISTS " + tableName + " (key TEXT NOT NULL UNIQUE PRIMARY KEY, value TEXT)")
+	if err != nil {
+		return err
+	}
+	_, err = statement.Exec()
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func sqliteInsert(key string, value string, tableName string) error {
+	if key != "" && value != "" && IsJSONString(value) {
+		insertSQL := "INSERT OR REPLACE INTO " + tableName + " (key, value) VALUES (?, ?)"
+		statement, err := SqliteDB.Prepare(insertSQL)
+		if err != nil {
+			return err
+		}
+		_, err = statement.Exec(key, value)
+		if err != nil {
+			return err
+		}
+		return nil
+	} else {
+		return errors.New("invalid insert " + key + " : " + value)
+	}
+}
+
+func sqliteInsertPeer(key string, value string) error {
+	if key != "" && value != "" && IsJSONString(value) {
+		err := sqliteInsert(key, value, PEERS_TABLE_NAME)
+		if err != nil {
+			return err
+		}
+		return nil
+	} else {
+		return errors.New("invalid peer insert " + key + " : " + value)
+	}
+}
+
+func sqliteDeleteRecord(tableName string, key string) error {
+	deleteSQL := "DELETE FROM " + tableName + " WHERE key = \"" + key + "\""
+	statement, err := SqliteDB.Prepare(deleteSQL)
+	if err != nil {
+		return err
+	}
+	if _, err = statement.Exec(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func sqliteDeleteAllRecords(tableName string) error {
+	deleteSQL := "DELETE FROM " + tableName
+	statement, err := SqliteDB.Prepare(deleteSQL)
+	if err != nil {
+		return err
+	}
+	if _, err = statement.Exec(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func sqliteFetchRecords(tableName string) (map[string]string, error) {
+	row, err := SqliteDB.Query("SELECT * FROM " + tableName + " ORDER BY key")
+	if err != nil {
+		return nil, err
+	}
+	records := make(map[string]string)
+	defer row.Close()
+	for row.Next() { // Iterate and fetch the records from result cursor
+		var key string
+		var value string
+		row.Scan(&key, &value)
+		records[key] = value
+	}
+	if len(records) == 0 {
+		return nil, errors.New(NO_RECORDS)
+	}
+	return records, nil
+}
+
+func sqliteCloseDB() {
+	SqliteDB.Close()
+}

+ 1 - 1
docs/quick-start.rst

@@ -103,7 +103,7 @@ Make sure firewall settings are appropriate for Netmaker. You need ports 53 and
 
 .. code-block::
 
-  sudo ufw allow proto tcp from any to any port 443 && sudo ufw allow dns
+  sudo ufw allow proto tcp from any to any port 443 && sudo ufw allow 53/udp
 
 **Based on your cloud provider, you may also need to set inbound security rules for your server. This will be dependent on your cloud provider. Be sure to check before moving on:**
   - allow 443/tcp from all

+ 1 - 1
docs/server-installation.rst

@@ -175,7 +175,7 @@ This template is equivalent but omits CoreDNS.
 Linux Install without Docker
 =============================
 
-Most systems support Docker, but some, such as LXC, do not. In such environments, there are many options for installing Netmaker. Netmaker is available as a binary file, and there is a zip file of the Netmaker UI static HTML on GitHub. Beyond the UI and Server, you need to install MongoDB and CoreDNS (optional). 
+Most systems support Docker, but some do not. In such environments, there are many options for installing Netmaker. Netmaker is available as a binary file, and there is a zip file of the Netmaker UI static HTML on GitHub. Beyond the UI and Server, you need to install MongoDB and CoreDNS (optional). 
 
 To start, we recommend following the Nginx instructions in the :doc:`Quick Install <./quick-start>` guide to enable SSL for your environment.
 

+ 8 - 1
docs/troubleshoot.rst

@@ -62,7 +62,7 @@ UI
 **Can I have multiple nodes with the same name?**
   Yes, nodes can share names without issue. It may just be harder on you to know which is which.
 
-Agent
+Netclient
 -------
 **How do I connect a node to my Netmaker network with Netclient?**
   First get your access token (not just access key), then run ``sudo netclient join -t <access token>``.
@@ -83,6 +83,13 @@ Agent
 **I am done with the agent on my machine, can I uninstall it?**
   Yes, on the node simply run ``sudo /etc/netclient/netclient uninstall``. 
 
+**I am running SELinux and when I reboot my node I get a permission denied in my netclient logs and it doesn't connect anymore, why?**
+  If you're running SELinux, it will interfere with systemd's ability to restart the client properly. Therefore, please run the following:
+  .. code-block::
+  
+    sudo semanage fcontext -a -t bin_t '/etc/netclient/netclient' 
+    sudo chcon -Rv -u system_u -t bin_t '/etc/netclient/netclient' 
+    sudo restorecon -R -v /etc/netclient/netclient
 
 CoreDNS
 --------

+ 19 - 7
functions/helpers.go

@@ -92,11 +92,25 @@ func CreateServerToken(netID string) (string, error) {
 	}
 
 	var accessToken models.AccessToken
-	servervals := models.ServerConfig{
-		APIConnString:  "127.0.0.1:" + servercfg.GetAPIPort(),
-		GRPCConnString: "127.0.0.1:" + servercfg.GetGRPCPort(),
-		GRPCSSL:        "off",
+	servervals := models.ServerConfig{}
+	if servercfg.GetPlatform() == "Kubernetes" {
+		log.Println("server on kubernetes")
+		servervals = models.ServerConfig{
+			APIConnString:  servercfg.GetPodIP() + ":" + servercfg.GetAPIPort(),
+			GRPCConnString: servercfg.GetPodIP() + ":" + servercfg.GetGRPCPort(),
+			GRPCSSL:        "off",
+		}
+	} else {
+		log.Println("server on linux")
+		servervals = models.ServerConfig{
+			APIConnString:  "127.0.0.1:" + servercfg.GetAPIPort(),
+			GRPCConnString: "127.0.0.1:" + servercfg.GetGRPCPort(),
+			GRPCSSL:        "off",
+		}
 	}
+	log.Println("APIConnString:",servervals.APIConnString)
+	log.Println("GRPCConnString:",servervals.GRPCConnString)
+	log.Println("GRPCSSL:",servervals.GRPCSSL)
 	accessToken.ServerConfig = servervals
 	accessToken.ClientConfig.Network = netID
 	accessToken.ClientConfig.Key = GenKey()
@@ -104,14 +118,12 @@ func CreateServerToken(netID string) (string, error) {
 	accesskey.Name = GenKeyName()
 	accesskey.Value = accessToken.ClientConfig.Key
 	accesskey.Uses = 1
-
 	tokenjson, err := json.Marshal(accessToken)
 	if err != nil {
 		return accesskey.AccessString, err
 	}
-
 	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(tokenjson))
-
+	log.Println("accessstring:",accesskey.AccessString)
 	network.AccessKeys = append(network.AccessKeys, accesskey)
 	if data, err := json.Marshal(network); err != nil {
 		return "", err

+ 15 - 1
functions/local.go

@@ -20,11 +20,25 @@ func SetDNSDir() error {
         }
         _, err = os.Stat(dir + "/config/dnsconfig")
         if os.IsNotExist(err) {
-                os.Mkdir(dir+"/config/dnsconfig", 744)
+                os.Mkdir(dir+"/config/dnsconfig", 0744)
         } else if err != nil {
                 PrintUserLog("","couldnt find or create /config/dnsconfig",0)
                 return err
         }
+		_, err = os.Stat(dir + "/config/dnsconfig/Corefile")
+        if os.IsNotExist(err) {
+			err = SetCorefile("example.com")
+			if err != nil {
+				PrintUserLog("",err.Error(),0)
+			}
+		}
+		_, err = os.Stat(dir + "/config/dnsconfig/netmaker.hosts")
+        if os.IsNotExist(err) {
+			_, err = os.Create(dir + "/config/dnsconfig/netmaker.hosts")
+			if err != nil {
+				PrintUserLog("",err.Error(),0)
+			}
+		}		
 	return nil
 }
 

+ 3 - 3
kube/netclient-daemonset.yaml

@@ -17,13 +17,13 @@ spec:
       hostNetwork: true
       containers:
       - name: netclient
-        image: gravitl/netclient:v0.7
+        image: gravitl/netclient:v0.7.2
         command: ['bash', '-c', "netclient checkin -n $NETWORK; sleep $SLEEP"]
         env:
         - name: ACCESS_TOKEN
           value: "XXXX"
         - name: NETWORK
-          value: "default"
+          value: "YYYY"
         - name: SLEEP
           value: 30
         volumeMounts:
@@ -35,7 +35,7 @@ spec:
           privileged: true
       initContainers:
       - name: netclient-join
-        image: gravitl/netclient:v0.7
+        image: gravitl/netclient:v0.7.2
         command: ['bash', '-c', "netclient join -t $ACCESS_TOKEN --daemon off"]
         env:
         - name: ACCESS_TOKEN

+ 361 - 0
kube/netmaker-template-udp.yaml

@@ -0,0 +1,361 @@
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: rqlite-pvc
+spec:
+  accessModes:
+    - ReadWriteOnce
+  resources:
+    requests:
+      storage: 1Gi
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: netmaker-backend
+  labels:
+    app: netmaker-backend
+spec:
+  nodeSelector:
+    netmaker-server: true
+  selector:
+    matchLabels:
+      app: netmaker-backend
+  replicas: 1
+  strategy:
+    type: Recreate
+  template:
+    metadata:
+      labels:
+        app: netmaker-backend
+    spec:
+      containers:
+      - name: netmaker-backend
+        image: gravitl/netmaker:0.7.2
+        imagePullPolicy: Always
+        ports:
+        - containerPort: 8081
+        volumeMounts:
+        - name: nm-pvc
+          mountPath: /root/config/dnsconfig
+        - mountPath: /etc/netclient
+          name: etc-netclient
+        - mountPath: /usr/bin/wg
+          name: wg
+        - mountPath: /var/run/dbus/system_bus_socket
+          name: systemd-bus-socket
+        - mountPath: /sys/fs/cgroup
+          name: cgroup
+        - mountPath: /run/systemd/system
+          name: run-systemd
+        - mountPath: /etc/systemd/system
+          name: etc-systemd
+        securityContext:
+          privileged: true
+        env:
+        - name: SERVER_API_CONN_STRING
+          value: "api.NETMAKER_BASE_DOMAIN:443"
+        - name: SERVER_GRPC_CONN_STRING
+          value: "grpc.NETMAKER_BASE_DOMAIN:443"
+        - name: COREDNS_ADDR
+          value: "10.152.183.53"
+        - name: POD_IP
+          valueFrom:
+            fieldRef:
+              fieldPath: status.podIP
+        - name: GRPC_SSL
+          value: "on"
+        - name: SERVER_HTTP_HOST
+          value: "api.NETMAKER_BASE_DOMAIN:443"
+        - name: SERVER_GRPC_HOST
+          value: "grpc.NETMAKER_BASE_DOMAIN:443"
+        - name: API_PORT
+          value: "8081"
+        - name: GRPC_PORT
+          value: "443"
+        - name: CLIENT_MODE
+          value: "off"
+        - name: MASTER_KEY
+          value: "Unkn0wn!"
+        - name: PLATFORM
+          value: "Kubernetes"
+        - name: CORS_ALLOWED_ORIGIN
+          value: "*"
+      - name: rqlite
+        image: rqlite/rqlite
+        ports:
+        - containerPort: 4001
+        - containerPort: 4002
+        volumeMounts:
+        - name: rqlitevol
+          mountPath: /rqlite/file/data
+      volumes:
+      - name: rqlitevol
+        persistentVolumeClaim:
+          claimName: rqlite-pvc
+      - name: nm-pvc
+        persistentVolumeClaim:
+          claimName: nm-pvc
+      - hostPath:
+          path: /etc/netclient
+          type: DirectoryOrCreate
+        name: etc-netclient
+      - hostPath:
+          path: /usr/bin/wg
+          type: File
+        name: wg
+      - hostPath:
+          path: /usr/bin/resolvectl
+          type: File
+        name: resolvectl
+      - hostPath:
+          path: /var/run/dbus/system_bus_socket
+          type: ""
+        name: systemd-bus-socket
+      - hostPath:
+          path: /etc/systemd/system
+          type: ""
+        name: etc-systemd
+      - hostPath:
+          path: /run/systemd/system
+          type: ""
+        name: run-systemd
+      - hostPath:
+          path: /sys/fs/cgroup
+          type: ""
+        name: cgroup
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: nm-pvc
+spec:
+  accessModes:
+    - ReadWriteMany
+  resources:
+    requests:
+      storage: 128Mi
+---
+apiVersion: v1
+kind: Service
+metadata:
+  labels:
+    app: netmaker-backend
+  name: netmaker-api
+spec:
+  ports:
+  - port: 8081
+    protocol: TCP
+    targetPort: 8081
+  selector:
+    app: netmaker-backend
+  sessionAffinity: None
+  type: ClusterIP
+---
+apiVersion: v1
+kind: Service
+metadata:
+  labels:
+    app: netmaker-backend
+  name: netmaker-grpc
+spec:
+  ports:
+  - port: 443
+    protocol: TCP
+    targetPort: 443
+  selector:
+    app: netmaker-backend
+  sessionAffinity: None
+  type: ClusterIP
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: netmaker-dns
+  labels:
+    app: netmaker-dns
+spec:
+  selector:
+    matchLabels:
+      app: netmaker-dns
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: netmaker-dns
+    spec:
+      containers:
+      - args:
+        - -conf
+        - /root/dnsconfig/Corefile
+        image: coredns/coredns
+        imagePullPolicy: Always
+        name: netmaker-dns
+        ports:
+        - containerPort: 53
+          name: dns
+          protocol: UDP
+        - containerPort: 53
+          name: dns-tcp
+          protocol: TCP
+        volumeMounts:
+        - mountPath: /root/dnsconfig
+          name: nm-pvc
+          readOnly: true
+        securityContext:
+          allowPrivilegeEscalation: false
+          capabilities:
+            add:
+            - NET_BIND_SERVICE
+            drop:
+            - all
+      dnsPolicy: "None"
+      dnsConfig:
+        nameservers:
+          - 127.0.0.1
+      volumes:
+      - name: nm-pvc
+        persistentVolumeClaim:
+          claimName: nm-pvc
+---
+apiVersion: v1
+kind: Service
+metadata:
+  labels:
+    app: netmaker-dns
+  name: netmaker-dns
+spec:
+  ports:
+  - port: 53
+    protocol: UDP
+    targetPort: 53
+    name: udp
+  - port: 53
+    protocol: TCP
+    targetPort: 53
+    name: tcp
+  selector:
+    app: netmaker-dns
+  sessionAffinity: None
+  type: ClusterIP
+  clusterIP: 10.152.183.53
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: netmaker-ui
+  labels:
+    app: netmaker-ui
+spec:
+  selector:
+    matchLabels:
+      app: netmaker-ui
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: netmaker-ui
+    spec:
+      containers:
+      - name: netmaker-ui
+        image: gravitl/netmaker-ui:v0.7
+        ports:
+        - containerPort: 80
+        env:
+        - name: BACKEND_URL
+          value: "https://api.NETMAKER_BASE_DOMAIN"
+---
+apiVersion: v1
+kind: Service
+metadata:
+  labels:
+    app: netmaker-ui
+  name: netmaker-ui
+spec:
+  ports:
+  - port: 80
+    protocol: TCP
+    targetPort: 80
+  selector:
+    app: netmaker-ui
+  sessionAffinity: None
+  type: ClusterIP
+---
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: nm-api-ingress-nginx
+  annotations:
+    nginx.ingress.kubernetes.io/rewrite-target: /
+    cert-manager.io/cluster-issuer: "letsencrypt-prod"
+    nginx.ingress.kubernetes.io/ssl-redirect: 'true'
+spec:
+  ingressClassName: nginx
+  tls:
+  - hosts:
+    - api.NETMAKER_BASE_DOMAIN
+    secretName: nm-api-tls
+  rules:
+  - host: api.NETMAKER_BASE_DOMAIN
+    http:
+      paths:
+      - path: /
+        pathType: Prefix
+        backend:
+          service:
+            name: netmaker-api
+            port:
+              number: 8081
+---
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: nm-grpc-ingress-nginx
+  annotations:
+    cert-manager.io/cluster-issuer: "letsencrypt-prod"
+    nginx.ingress.kubernetes.io/ssl-redirect: 'true'
+    nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
+spec:
+  ingressClassName: nginx
+  tls:
+  - hosts:
+    - grpc.NETMAKER_BASE_DOMAIN
+    secretName: nm-grpc-tls
+  rules:
+  - host: grpc.NETMAKER_BASE_DOMAIN
+    http:
+      paths:
+      - path: /
+        pathType: Prefix
+        backend:
+          service:
+            name: netmaker-grpc
+            port:
+              number: 443
+---
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: nm-ui-ingress-nginx
+  annotations:
+    nginx.ingress.kubernetes.io/rewrite-target: /
+    cert-manager.io/cluster-issuer: "letsencrypt-prod"
+    nginx.ingress.kubernetes.io/ssl-redirect: 'true'
+spec:
+  ingressClassName: nginx
+  tls:
+  - hosts:
+    - dashboard.NETMAKER_BASE_DOMAIN
+    secretName: nm-ui-tls
+  rules:
+  - host: dashboard.NETMAKER_BASE_DOMAIN
+    http:
+      paths:
+      - path: /
+        pathType: Prefix
+        backend:
+          service:
+            name: netmaker-ui
+            port:
+              number: 80

+ 28 - 70
kube/netmaker-template.yaml

@@ -1,62 +1,14 @@
-apiVersion: v1
-kind: Service
-metadata:
-  name: mongo
-  labels:
-    name: mongo
-spec:
-  ports:
-    - port: 27017
-      targetPort: 27017
-  clusterIP: None
-  selector:
-    role: mongo
----
-apiVersion: apps/v1
-kind: StatefulSet
-metadata:
-  name: mongo
-spec:
-  serviceName: "mongo"
-  replicas: 1
-  selector:
-    matchLabels:
-      role: mongo
-  template:
-    metadata:
-      labels:
-        app: mongo
-        role: mongo
-    spec:
-      containers:
-      - name: mongo
-        image: mongo
-        env:
-          - name: MONGO_INITDB_ROOT_USERNAME
-            value: mongoadmin
-          - name: MONGO_INITDB_ROOT_PASSWORD
-            value: mongopass
-        securityContext:
-          privileged: true
-        volumeMounts:
-        - name: mongovol
-          mountPath: /data/db
-      volumes:
-      - name: mongovol
-        persistentVolumeClaim:
-          claimName: mongodb-pvc
 ---
 apiVersion: v1
 kind: PersistentVolumeClaim
 metadata:
-  name: mongodb-pvc
+  name: rqlite-pvc
 spec:
   accessModes:
     - ReadWriteOnce
   resources:
     requests:
-      storage: 7Gi
-  storageClassName: microk8s-hostpath
+      storage: 1Gi
 ---
 apiVersion: apps/v1
 kind: Deployment
@@ -69,6 +21,8 @@ spec:
     matchLabels:
       app: netmaker-backend
   replicas: 1
+  strategy:
+    type: Recreate
   template:
     metadata:
       labels:
@@ -77,11 +31,11 @@ spec:
       containers:
       - name: netmaker-backend
         image: gravitl/netmaker:v0.7
+        imagePullPolicy: Always
         ports:
         - containerPort: 8081
-        volumeMounts:
-        - name: nm-pvc
-          mountPath: /root/config/dnsconfig
+        securityContext:
+          privileged: true
         env:
         - name: SERVER_API_CONN_STRING
           value: "api.NETMAKER_BASE_DOMAIN:443"
@@ -89,6 +43,10 @@ spec:
           value: "grpc.NETMAKER_BASE_DOMAIN:443"
         - name: COREDNS_ADDR
           value: "10.152.183.53"
+        - name: POD_IP
+          valueFrom:
+            fieldRef:
+              fieldPath: status.podIP
         - name: GRPC_SSL
           value: "on"
         - name: SERVER_HTTP_HOST
@@ -98,26 +56,27 @@ spec:
         - name: API_PORT
           value: "8081"
         - name: GRPC_PORT
-          value: "443"
+          value: "80"
         - name: CLIENT_MODE
           value: "off"
         - name: MASTER_KEY
           value: "Unkn0wn!"
-        - name: SERVER_GRPC_WIREGUARD
-          value: "off"
-        - name: MASTER_KEY
-          value: "secretkey"
+        - name: PLATFORM
+          value: "Kubernetes"
         - name: CORS_ALLOWED_ORIGIN
           value: "*"
-        - name: MONGO_ADMIN
-          value: "mongoadmin"
-        - name: MONGO_PASS
-          value: "mongopass"
-        - name: MONGO_HOST
-          value: "mongo-0.mongo"
-        - name: MONGO_OPTS
-          value: "/?authSource=admin"
+      - name: rqlite
+        image: rqlite/rqlite
+        ports:
+        - containerPort: 4001
+        - containerPort: 4002
+        volumeMounts:
+        - name: rqlitevol
+          mountPath: /rqlite/file/data
       volumes:
+      - name: rqlitevol
+        persistentVolumeClaim:
+          claimName: rqlite-pvc
       - name: nm-pvc
         persistentVolumeClaim:
           claimName: nm-pvc
@@ -132,7 +91,6 @@ spec:
   resources:
     requests:
       storage: 128Mi
-  storageClassName: microk8s-hostpath
 ---
 apiVersion: v1
 kind: Service
@@ -288,7 +246,7 @@ metadata:
     cert-manager.io/cluster-issuer: "letsencrypt-prod"
     nginx.ingress.kubernetes.io/ssl-redirect: 'true'
 spec:
-  ingressClassName: public
+  ingressClassName: nginx
   tls:
   - hosts:
     - api.NETMAKER_BASE_DOMAIN
@@ -314,7 +272,7 @@ metadata:
     nginx.ingress.kubernetes.io/ssl-redirect: 'true'
     nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
 spec:
-  ingressClassName: public
+  ingressClassName: nginx
   tls:
   - hosts:
     - grpc.NETMAKER_BASE_DOMAIN
@@ -340,7 +298,7 @@ metadata:
     cert-manager.io/cluster-issuer: "letsencrypt-prod"
     nginx.ingress.kubernetes.io/ssl-redirect: 'true'
 spec:
-  ingressClassName: public
+  ingressClassName: nginx
   tls:
   - hosts:
     - dashboard.NETMAKER_BASE_DOMAIN

+ 30 - 0
kube/ubuntu.yaml

@@ -0,0 +1,30 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: ubuntu
+  labels:
+    app: ubuntu
+spec:
+  # Uncomment and specify a specific node you want to debug
+  # nodeName: <insert-node-name-here>
+  containers:
+  - image: ubuntu
+    command:
+      - "sleep"
+      - "3600"
+    imagePullPolicy: IfNotPresent
+    name: ubuntu
+    securityContext:
+      privileged: true
+    volumeMounts:
+    - name: rootfolder
+      mountPath: /
+  restartPolicy: Never
+  hostIPC: true
+  hostNetwork: true
+  hostPID: true
+  volumes:
+  - hostPath:
+      path: /
+      type: ""
+    name: rootfolder

+ 2 - 2
main.go

@@ -26,7 +26,7 @@ import (
 func main() {
 	fmt.Println(models.RetrieveLogo()) // print the logo
 	initialize()                       // initial db and grpc server
-	defer database.Database.Close()
+	defer database.CloseDB()
 	startControllers() // start the grpc or rest endpoints
 }
 
@@ -41,7 +41,7 @@ func initialize() { // Client Mode Prereq Check
 
 	if err != nil {
 		log.Println("Error running 'id -u' for prereq check. Please investigate or disable client mode.")
-		log.Fatal(err)
+		log.Fatal(output, err)
 	}
 	uid, err := strconv.Atoi(string(output[:len(output)-1]))
 	if err != nil {

+ 6 - 2
models/network.go

@@ -7,7 +7,7 @@ import (
 	"reflect"
 	"strings"
 	"time"
-
+	"github.com/gravitl/netmaker/servercfg"
 	"github.com/go-playground/validator/v10"
 	"github.com/gravitl/netmaker/database"
 )
@@ -215,7 +215,11 @@ func (network *Network) SetNetworkLastModified() {
 
 func (network *Network) SetDefaults() {
 	if network.DefaultUDPHolePunch == "" {
-		network.DefaultUDPHolePunch = "yes"
+		if servercfg.IsClientMode() {
+			network.DefaultUDPHolePunch = "yes"
+		} else {
+			network.DefaultUDPHolePunch = "no"
+		}
 	}
 	if network.IsLocal == "" {
 		network.IsLocal = "no"

BIN
netclient/functions/.logging.go.swp


+ 4 - 9
netclient/functions/common.go

@@ -10,7 +10,6 @@ import (
 	"log"
 	"net"
 	"net/http"
-	"os"
 	"os/exec"
 	"strings"
 
@@ -314,17 +313,13 @@ func RemoveLocalInstance(cfg *config.ClientConfig, networkName string) error {
 
 func DeleteInterface(ifacename string, postdown string) error {
 	ipExec, err := exec.LookPath("ip")
-
-	cmdIPLinkDel := &exec.Cmd{
-		Path:   ipExec,
-		Args:   []string{ipExec, "link", "del", ifacename},
-		Stdout: os.Stdout,
-		Stderr: os.Stdout,
-	}
-	err = cmdIPLinkDel.Run()
 	if err != nil {
 		log.Println(err)
 	}
+	out, err := local.RunCmd(ipExec + " link del " + ifacename)
+	if err != nil {
+		log.Println(out, err)
+	}
 	if postdown != "" {
 		runcmds := strings.Split(postdown, "; ")
 		err = local.RunCmds(runcmds)

+ 9 - 6
netclient/functions/join.go

@@ -136,12 +136,7 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
 			cfg.Node.MacAddress = macs[0]
 		}
 	}
-	if cfg.Node.ListenPort == 0 {
-		cfg.Node.ListenPort, err = GetFreePort(51821)
-		if err != nil {
-			fmt.Printf("Error retrieving port: %v", err)
-		}
-	}
+
 	var wcclient nodepb.NodeServiceClient
 	var requestOpts grpc.DialOption
 	requestOpts = grpc.WithInsecure()
@@ -174,6 +169,7 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
 		SaveConfig:          cfg.Node.SaveConfig,
 		UDPHolePunch:        cfg.Node.UDPHolePunch,
 	}
+
 	if err = config.ModConfig(postnode); err != nil {
 		return err
 	}
@@ -200,6 +196,13 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
 		return err
 	}
 
+	if node.ListenPort == 0 {
+		node.ListenPort, err = GetFreePort(51821)
+		if err != nil {
+			fmt.Printf("Error retrieving port: %v", err)
+		}
+	}
+
 	if node.DNSOn == "yes" {
 		cfg.Node.DNSOn = "yes"
 	}

+ 8 - 9
netclient/local/local.go

@@ -274,22 +274,21 @@ func WipeLocal(network string) error {
 	if FileExists(home + "/nettoken-" + network) {
 		_ = os.Remove(home + "/nettoken-" + network)
 	}
+	if FileExists(home + "/secret-" + network) {
+		_ = os.Remove(home + "/secret-" + network)
+	}
 	if FileExists(home + "/wgkey-" + network) {
 		_ = os.Remove(home + "/wgkey-" + network)
 	}
 
 	ipExec, err := exec.LookPath("ip")
-
+	if err != nil {
+		return err
+	}
 	if ifacename != "" {
-		cmdIPLinkDel := &exec.Cmd{
-			Path:   ipExec,
-			Args:   []string{ipExec, "link", "del", ifacename},
-			Stdout: os.Stdout,
-			Stderr: os.Stdout,
-		}
-		err = cmdIPLinkDel.Run()
+		out, err := RunCmd(ipExec + " link del " + ifacename)
 		if err != nil {
-			log.Println(err)
+			log.Println(out, err)
 		}
 		if nodecfg.PostDown != "" {
 			runcmds := strings.Split(nodecfg.PostDown, "; ")

+ 1 - 1
netclient/main.go

@@ -316,7 +316,7 @@ func main() {
 	out, err := local.RunCmd("id -u")
 
 	if err != nil {
-		log.Fatal(err)
+		log.Fatal(out, err)
 	}
 	id, err := strconv.Atoi(string(out[:len(out)-1]))
 

BIN
netclient/netclient-amd64


BIN
netclient/netclient-arm


BIN
netclient/netclient-arm64


+ 23 - 31
netclient/wireguard/kernel.go

@@ -65,16 +65,17 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 	}
 
 	_, delErr := local.RunCmd("ip link delete dev " + ifacename)
-	_, addLinkErr := local.RunCmd(ipExec + " link add dev " + ifacename + " type wireguard")
-	_, addErr := local.RunCmd(ipExec + " address add dev " + ifacename + " " + node.Address + "/24")
+	addLinkOut, addLinkErr := local.RunCmd(ipExec + " link add dev " + ifacename + " type wireguard")
+	addOut, addErr := local.RunCmd(ipExec + " address add dev " + ifacename + " " + node.Address + "/24")
 	if delErr != nil {
-		// pass
+		// not displaying error
+		// log.Println(delOut, delErr)
 	}
 	if addLinkErr != nil {
-		log.Println(addLinkErr)
+		log.Println(addLinkOut, addLinkErr)
 	}
 	if addErr != nil {
-		log.Println(addErr)
+		log.Println(addOut, addErr)
 	}
 	var nodeport int
 	nodeport = int(node.ListenPort)
@@ -122,21 +123,11 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 		_ = local.UpdateDNS(ifacename, network, nameserver)
 	}
 	//=========End DNS Setup=======\\
-
-	cmdIPLinkUp := &exec.Cmd{
-		Path:   ipExec,
-		Args:   []string{ipExec, "link", "set", "up", "dev", ifacename},
-		Stdout: os.Stdout,
-		Stderr: os.Stdout,
+	if ipLinkDownOut, err := local.RunCmd(ipExec + " link set down dev " + ifacename); err != nil {
+		log.Println(ipLinkDownOut, err)
+		return err
 	}
 
-	cmdIPLinkDown := &exec.Cmd{
-		Path:   ipExec,
-		Args:   []string{ipExec, "link", "set", "down", "dev", ifacename},
-		Stdout: os.Stdout,
-		Stderr: os.Stdout,
-	}
-	err = cmdIPLinkDown.Run()
 	if nodecfg.PostDown != "" {
 		runcmds := strings.Split(nodecfg.PostDown, "; ")
 		err = local.RunCmds(runcmds)
@@ -145,8 +136,8 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 		}
 	}
 
-	err = cmdIPLinkUp.Run()
-	if err != nil {
+	if ipLinkUpOut, err := local.RunCmd(ipExec + " link set up dev " + ifacename); err != nil {
+		log.Println(ipLinkUpOut, err)
 		return err
 	}
 
@@ -162,16 +153,16 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig
 			out, err := local.RunCmd(ipExec + " -4 route add " + gateway + " dev " + ifacename)
 			fmt.Println(string(out))
 			if err != nil {
-				fmt.Println("Error encountered adding gateway: " + err.Error())
+				fmt.Println("error encountered adding gateway: " + err.Error())
 			}
 		}
 	}
 	if node.Address6 != "" && node.IsDualStack == "yes" {
-		fmt.Println("Adding address: " + node.Address6)
+		fmt.Println("adding address: " + node.Address6)
 		out, err := local.RunCmd(ipExec + " address add dev " + ifacename + " " + node.Address6 + "/64")
 		if err != nil {
 			fmt.Println(out)
-			fmt.Println("Error encountered adding ipv6: " + err.Error())
+			fmt.Println("error encountered adding ipv6: " + err.Error())
 		}
 	}
 
@@ -268,9 +259,9 @@ func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error {
 		for _, currentPeer := range devicePeers {
 			if currentPeer.AllowedIPs[0].String() == peer.AllowedIPs[0].String() &&
 				currentPeer.PublicKey.String() != peer.PublicKey.String() {
-				_, err := local.RunCmd("wg set " + iface + " peer " + currentPeer.PublicKey.String() + " remove")
+				output, err := local.RunCmd("wg set " + iface + " peer " + currentPeer.PublicKey.String() + " remove")
 				if err != nil {
-					log.Println("error removing peer", peer.Endpoint.String())
+					log.Println(output, "error removing peer", peer.Endpoint.String())
 				}
 			}
 		}
@@ -285,18 +276,19 @@ func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error {
 		if keepAliveString == "0" {
 			keepAliveString = "5"
 		}
+		var output string
 		if peer.Endpoint != nil {
-			_, err = local.RunCmd("wg set " + iface + " peer " + peer.PublicKey.String() +
+			output, err = local.RunCmd("wg set " + iface + " peer " + peer.PublicKey.String() +
 				" endpoint " + udpendpoint +
 				" persistent-keepalive " + keepAliveString +
 				" allowed-ips " + allowedips)
 		} else {
-			_, err = local.RunCmd("wg set " + iface + " peer " + peer.PublicKey.String() +
+			output, err = local.RunCmd("wg set " + iface + " peer " + peer.PublicKey.String() +
 				" persistent-keepalive " + keepAliveString +
 				" allowed-ips " + allowedips)
 		}
 		if err != nil {
-			log.Println("error setting peer", peer.PublicKey.String(), err)
+			log.Println(output, "error setting peer", peer.PublicKey.String(), err)
 		}
 	}
 
@@ -308,15 +300,15 @@ func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) error {
 			}
 		}
 		if shouldDelete {
-			_, err := local.RunCmd("wg set " + iface + " peer " + currentPeer.PublicKey.String() + " remove")
+			output, err := local.RunCmd("wg set " + iface + " peer " + currentPeer.PublicKey.String() + " remove")
 			if err != nil {
-				log.Println("error removing peer", currentPeer.PublicKey.String())
+				log.Println(output, "error removing peer", currentPeer.PublicKey.String())
 			} else {
 				log.Println("removed peer " + currentPeer.PublicKey.String())
 			}
 		}
 	}
-	
+
 	return nil
 }
 

+ 1 - 1
scripts/netclient-install.sh

@@ -8,7 +8,7 @@ fi
 
 [ -z "$KEY" ] && KEY=nokey;
 
-wget -O netclient https://github.com/gravitl/netmaker/releases/download/v0.7/netclient
+wget -O netclient https://github.com/gravitl/netmaker/releases/download/v0.7.2/netclient
 chmod +x netclient
 sudo ./netclient join -t $KEY
 rm -f netclient

+ 54 - 7
servercfg/serverconf.go

@@ -58,6 +58,9 @@ func GetServerConfig() config.ServerConfig {
 	if DisableDefaultNet() {
 		cfg.DisableRemoteIPCheck = "on"
 	}
+	cfg.Database = GetDB()
+	cfg.Platform = GetPlatform()
+	cfg.Version = GetVersion()
 	return cfg
 }
 func GetAPIConnString() string {
@@ -69,6 +72,22 @@ func GetAPIConnString() string {
 	}
 	return conn
 }
+func GetVersion() string {
+	version := "0.7.2"
+	if config.Config.Server.Version != "" {
+		version = config.Config.Server.Version
+	}
+	return version
+}
+func GetDB() string {
+	database := "rqlite"
+	if os.Getenv("DATABASE") == "sqlite" {
+		database = os.Getenv("DATABASE")
+	} else if config.Config.Server.Database == "sqlite" {
+		database = config.Config.Server.Database
+	}
+	return database
+}
 func GetAPIHost() string {
 	serverhost := "127.0.0.1"
 	remoteip, _ := GetPublicIP()
@@ -85,6 +104,14 @@ func GetAPIHost() string {
 	}
 	return serverhost
 }
+func GetPodIP() string {
+	podip := "127.0.0.1"
+	if os.Getenv("POD_IP") != "" {
+		podip = os.Getenv("POD_IP")
+	}
+	return podip
+}
+
 func GetAPIPort() string {
 	apiport := "8081"
 	if os.Getenv("API_PORT") != "" {
@@ -117,13 +144,13 @@ func GetGRPCConnString() string {
 }
 
 func GetCoreDNSAddr() string {
-        addr, _ := GetPublicIP()
-        if os.Getenv("COREDNS_ADDR") != ""  {
-                addr = os.Getenv("COREDNS_ADDR")
-        } else if config.Config.Server.CoreDNSAddr != "" {
-                addr = config.Config.Server.GRPCConnString
-        }
-        return addr
+	addr, _ := GetPublicIP()
+	if os.Getenv("COREDNS_ADDR") != "" {
+		addr = os.Getenv("COREDNS_ADDR")
+	} else if config.Config.Server.CoreDNSAddr != "" {
+		addr = config.Config.Server.GRPCConnString
+	}
+	return addr
 }
 
 func GetGRPCHost() string {
@@ -299,3 +326,23 @@ func GetVerbose() int32 {
 	}
 	return int32(level)
 }
+
+func GetPlatform() string {
+	platform := "linux"
+	if os.Getenv("PLATFORM") != "" {
+		platform = os.Getenv("PLATFORM")
+	} else if config.Config.Server.Platform != ""  {
+		platform = config.Config.Server.SQLConn
+	}
+	return platform
+}
+
+func GetSQLConn() string {
+	sqlconn := "http://"
+	if os.Getenv("SQL_CONN") != "" {
+		sqlconn = os.Getenv("SQL_CONN")
+	} else if config.Config.Server.SQLConn != "" {
+		sqlconn = config.Config.Server.SQLConn
+	}
+	return sqlconn
+}