Browse Source

add remove server from networks with api. Add to default network by default.

afeiszli 4 years ago
parent
commit
f3f2140f23

+ 1 - 0
controllers/common.go

@@ -117,6 +117,7 @@ func ValidateNode(operation string, groupName string, node models.Node) error {
         return err
 }
 
+
 func UpdateNode(nodechange models.Node, node models.Node) (models.Node, error) {
     //Question: Is there a better way  of doing  this than a bunch of "if" statements? probably...
     //Eventually, lets have a better way to check if any of the fields are filled out...

+ 1 - 0
controllers/controller.go

@@ -29,6 +29,7 @@ func HandleRESTRequests(wg *sync.WaitGroup) {
     userHandlers(r)
     groupHandlers(r)
     fileHandlers(r)
+    serverHandlers(r)
 
 		port := config.Config.Server.ApiPort
 	        if os.Getenv("API_PORT") != "" {

+ 90 - 0
controllers/serverHttpController.go

@@ -0,0 +1,90 @@
+package controller
+
+import (
+    "github.com/gravitl/netmaker/models"
+    "github.com/gravitl/netmaker/serverctl"
+    "github.com/gravitl/netmaker/config"
+    "encoding/json"
+    "strings"
+    "net/http"
+    "github.com/gorilla/mux"
+)
+
+func serverHandlers(r *mux.Router) {
+    r.HandleFunc("/api/server/addnetwork/{network}", securityCheckServer(http.HandlerFunc(addNetwork))).Methods("POST")
+    r.HandleFunc("/api/server/removenetwork/{network}", securityCheckServer(http.HandlerFunc(removeNetwork))).Methods("DELETE")
+}
+
+//Security check is middleware for every function and just checks to make sure that its the master calling
+//Only admin should have access to all these group-level actions
+//or maybe some Users once implemented
+func securityCheckServer(next http.Handler) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var errorResponse = models.ErrorResponse{
+			Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
+		}
+
+		bearerToken := r.Header.Get("Authorization")
+
+		var hasBearer = true
+		var tokenSplit = strings.Split(bearerToken, " ")
+		var  authToken = ""
+
+		if len(tokenSplit) < 2 {
+			hasBearer = false
+		} else {
+			authToken = tokenSplit[1]
+		}
+		//all endpoints here require master so not as complicated
+		//still might not be a good  way of doing this
+		if !hasBearer || !authenticateMasterServer(authToken) {
+			errorResponse = models.ErrorResponse{
+				Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.",
+			}
+			returnErrorResponse(w, r, errorResponse)
+		} else {
+			next.ServeHTTP(w, r)
+		}
+	}
+}
+//Consider a more secure way of setting master key
+func authenticateMasterServer(tokenString string) bool {
+    if tokenString == config.Config.Server.MasterKey {
+        return true
+    }
+    return false
+}
+
+func removeNetwork(w http.ResponseWriter, r *http.Request) {
+        // Set header
+        w.Header().Set("Content-Type", "application/json")
+
+        // get params
+        var params = mux.Vars(r)
+
+        success, err := serverctl.RemoveNetwork(params["network"])
+
+        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"])
+}
+
+func addNetwork(w http.ResponseWriter, r *http.Request) {
+        // Set header
+        w.Header().Set("Content-Type", "application/json")
+
+        // get params
+        var params = mux.Vars(r)
+
+        success, err := serverctl.AddNetwork(params["network"])
+
+        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"])
+}

+ 52 - 0
functions/helpers.go

@@ -24,6 +24,58 @@ import (
 
 //Takes in an arbitrary field and value for field and checks to see if any other
 //node has that value for the same field within the group
+
+func CreateServerToken(network string) (string, error) {
+
+        var group models.Group
+        var accesskey models.AccessKey
+
+        group, err := GetParentGroup(network)
+        if err != nil {
+                return "", err
+        }
+
+                accesskey.Name = GenKeyName()
+                accesskey.Value = GenKey()
+                accesskey.Uses = 1
+        gconf, errG := GetGlobalConfig()
+        if errG != nil {
+                return "", errG
+        }
+        address := "localhost" + gconf.PortGRPC
+
+        accessstringdec := address + "." + network + "." + accesskey.Value
+        accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(accessstringdec))
+
+        group.AccessKeys = append(group.AccessKeys, accesskey)
+
+        collection := mongoconn.Client.Database("netmaker").Collection("groups")
+
+        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+
+        // Create filter
+        filter := bson.M{"nameid": network}
+
+        // Read update model from body request
+        fmt.Println("Adding key to " + group.NameID)
+
+        // prepare update model.
+        update := bson.D{
+                {"$set", bson.D{
+                        {"accesskeys", group.AccessKeys},
+                }},
+        }
+
+        errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&group)
+
+        defer cancel()
+
+        if errN != nil {
+                return "", errN
+        }
+        return accesskey.AccessString, nil
+}
+
 func IsFieldUnique(group string,  field string, value string) bool {
 
 	var node models.Node

+ 29 - 16
main.go

@@ -7,7 +7,7 @@ import (
     "log"
     "github.com/gravitl/netmaker/models"
     "github.com/gravitl/netmaker/controllers"
-    //"github.com/gravitl/netmaker/serverctl"
+    "github.com/gravitl/netmaker/serverctl"
     "github.com/gravitl/netmaker/functions"
     "github.com/gravitl/netmaker/mongoconn"
     "github.com/gravitl/netmaker/config"
@@ -34,18 +34,14 @@ var PortGRPC string
 func main() {
 	log.Println("Server starting...")
 	mongoconn.ConnectDatabase()
-
+	installserver := false
 	if config.Config.Server.CreateDefault {
-		err := createDefaultNetwork()
+		created, err := createDefaultNetwork()
 		if err != nil {
 			fmt.Printf("Error creating default network: %v", err)
-		} else {
-			/*
-			err = serverctl.NetworkAdd(config.Config.Server.DefaultNetName)
-			if err != nil {
-				fmt.Printf("Error adding to default network: %v", err)
-			}
-			*/
+		}
+		if created {
+			installserver = true
 		}
 	}
 
@@ -53,7 +49,7 @@ func main() {
 
 	if config.Config.Server.AgentBackend {
 		waitgroup.Add(1)
-		go runGRPC(&waitgroup)
+		go runGRPC(&waitgroup, installserver)
 	}
 
 	if config.Config.Server.RestBackend {
@@ -68,7 +64,7 @@ func main() {
 }
 
 
-func runGRPC(wg *sync.WaitGroup) {
+func runGRPC(wg *sync.WaitGroup, installserver bool) {
 
 
 	defer wg.Done()
@@ -134,6 +130,20 @@ func runGRPC(wg *sync.WaitGroup) {
         }()
         fmt.Println("Agent Server succesfully started on port " + grpcport + " (gRPC)")
 
+	if installserver {
+			fmt.Println("Adding server to default network")
+                        success, err := serverctl.AddNetwork(config.Config.Server.DefaultNetName)
+                        if err != nil || !success {
+                                fmt.Printf("Error adding to default network: %v", err)
+				fmt.Println("Unable to add server to network. Continuing.")
+			} else {
+                                fmt.Println("Server successfully added to default network.")
+			}
+	}
+        fmt.Println("Setup complete. You are ready to begin using netmaker.")
+
+
+
         // Right way to stop the server using a SHUTDOWN HOOK
         // Create a channel to receive OS signals
         c := make(chan os.Signal)
@@ -180,15 +190,15 @@ func setGlobalConfig(globalconf models.GlobalConfig) (error) {
 	return nil
 }
 
-func createDefaultNetwork() error {
-
+func createDefaultNetwork() (bool, error) {
 
+	iscreated := false
 	exists, err := functions.GroupExists(config.Config.Server.DefaultNetName)
 
 	if exists || err != nil {
 		fmt.Println("Default group already exists")
 		fmt.Println("Skipping default group create")
-		return err
+		return iscreated, err
 	} else {
 
 	var group models.Group
@@ -215,7 +225,10 @@ func createDefaultNetwork() error {
         defer cancel()
 
 	}
-	return err
+	if err == nil {
+		iscreated = true
+	}
+	return iscreated, err
 
 
 }

+ 4 - 1
netclient/functions/common.go

@@ -29,7 +29,7 @@ var (
         wcclient nodepb.NodeServiceClient
 )
 
-func Install(accesskey string, password string, server string, group string, noauto bool, accesstoken string) error {
+func Install(accesskey string, password string, server string, group string, noauto bool, accesstoken string,  inputname string) error {
 
 
 	tserver := ""
@@ -189,6 +189,9 @@ func Install(accesskey string, password string, server string, group string, noa
         if nodecfg.Name != "" {
                 name = nodecfg.Name
         }
+	if inputname != "" && inputname != "noname" {
+		name = inputname
+	}
        fmt.Println("     Name: " + name)
 
 

+ 2 - 1
netclient/main.go

@@ -36,6 +36,7 @@ func main() {
 	tpassword := flag.String("p", "changeme", "This node's password for accessing the server regularly")
 	taccesskey := flag.String("k", "badkey", "an access key generated by the server and used for one-time access (install only)")
 	taccesstoken := flag.String("t", "badtoken", "an token generated by the server and used for one-time access (install only)")
+	tname := flag.String("name", "noname", "give the node a name at runtime")
 	tserver := flag.String("s", "localhost:50051", "The location (including port) of the remote gRPC server.")
 	tnetwork := flag.String("n", "nonetwork", "The node group you are attempting to join.")
 	tnoauto := flag.Bool("na", false, "No auto mode. If true, netmclient will not be installed as a system service and you will have to retrieve updates manually via checkin command.")
@@ -100,7 +101,7 @@ func main() {
 			}
 
 			fmt.Println("Beginning agent installation.")
-			err := functions.Install(*taccesskey, *tpassword, *tserver, *tnetwork, *tnoauto, *taccesstoken)
+			err := functions.Install(*taccesskey, *tpassword, *tserver, *tnetwork, *tnoauto, *taccesstoken, *tname)
 			if err != nil {
 				fmt.Println("Error installing: ", err)
 				fmt.Println("Cleaning up (uninstall)")

+ 51 - 46
serverctl/serverctl.go

@@ -2,74 +2,79 @@ package serverctl
 
 import (
         "fmt"
-        "io/ioutil"
-        "log"
+  "github.com/gravitl/netmaker/functions"
+	"io"
+	"net/http"
         "os"
         "os/exec"
 )
 
 
-func fileExists(f string) bool {
-    info, err := os.Stat(f)
-    if os.IsNotExist(err) {
-        return false
-    }
-    notisdir := !info.IsDir()
-    return notisdir
-}
-
-
-func installScript() error {
-
-
-	installScript := `#!/bin/sh
-set -e
-
-[ -z "$SERVER_URL" ] && echo "Need to set SERVER_URL" && exit 1;
-[ -z "$NET_NAME" ] && echo "Need to set NET_NAME" && exit 1;
-[ -z "$KEY" ] && KEY=nokey;
-
+func DownloadNetclient() error {
 
+	// Get the data
+	resp, err := http.Get("https://github.com/gravitl/netmaker/releases/download/develop/netclient")
+	if err != nil {
+		return err
+	}
+	defer resp.Body.Close()
 
-wget -O netclient https://github.com/gravitl/netmaker/releases/download/develop/netclient
-chmod +x netclient
-sudo ./netclient -c install -s $SERVER_URL -g $NET_NAME -k $KEY
-rm -f netclient
-`
-
-        installbytes := []byte(installScript)
+	// Create the file
+	out, err := os.Create("/etc/netclient/netclient")
+	if err != nil {
+		return err
+	}
+	defer out.Close()
 
-	err := ioutil.WriteFile("/etc/netclient/netclient-install.sh", installbytes, 0755)
-        if err != nil {
-                log.Println(err)
-                return err
-        }
+	// Write the body to file
+	_, err = io.Copy(out, resp.Body)
 	return err
 }
+func RemoveNetwork(network string) (bool, error) {
+	_, err := os.Stat("/etc/netclient/netclient")
+        if err != nil {
+		return false, err
+	}
+        cmdoutput, err := exec.Command("/etc/netclient/netclient","-c","remove","-n",network).Output()
+        if err != nil {
+                fmt.Println(string(cmdoutput))
+                return false, err
+        }
+        fmt.Println("Server removed from network " + network)
+        return true, err
 
+}
 
-func NetworkAdd(network string) error {
+func AddNetwork(network string) (bool, error) {
 	_, err := os.Stat("/etc/netclient")
         if os.IsNotExist(err) {
                 os.Mkdir("/etc/netclient", 744)
         } else if err != nil {
                 fmt.Println("couldnt find or create /etc/netclient")
-                return err
+                return false, err
         }
-        if !fileExists("/etc/netclient/netclient-install.sh") {
-        err = installScript()
+	token, err := functions.CreateServerToken(network)
         if err != nil {
-                log.Println(err)
-                return err
+                return false, err
         }
+        _, err = os.Stat("/etc/netclient/netclient")
+	if os.IsNotExist(err) {
+		err = DownloadNetclient()
+		if err != nil {
+			return false, err
+		}
 	}
-
-	cmdoutput, err := exec.Command("/bin/sh", "/etc/netclient/netclient-install.sh").Output()
+        err = os.Chmod("/etc/netclient/netclient", 0755)
+        if err != nil {
+                return false, err
+        }
+	cmdoutput, err := exec.Command("/etc/netclient/netclient","-c","install","-t",token,"-name","netmaker").Output()
 	if err != nil {
-		fmt.Printf("Error installing netclient: %s", err)
-	}
-	fmt.Println(cmdoutput)
-	return err
+	        fmt.Println(string(cmdoutput))
+                return false, err
+        }
+	fmt.Println("Server added to network " + network)
+	return true, err
 }