Browse Source

Merge branch 'develop' into bugfix_v0.2_portconflicts

Alex 4 years ago
parent
commit
8d434bd43c

+ 33 - 0
.github/workflows/publish-docker-latest.yml

@@ -0,0 +1,33 @@
+name: Publish Docker
+
+on: 
+  push:
+        branches: 
+        - 'master'
+jobs:
+  docker:
+    runs-on: ubuntu-latest
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v2
+      -
+        name: Set up QEMU
+        uses: docker/setup-qemu-action@v1
+      -
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v1
+      -
+        name: Login to DockerHub
+        uses: docker/login-action@v1 
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+      -
+        name: Build and push
+        uses: docker/build-push-action@v2
+        with:
+          context: .
+          platforms: linux/amd64, linux/arm64
+          push: true
+          tags: gravitl/netmaker:latest      

+ 35 - 0
.github/workflows/publish-docker.yml

@@ -0,0 +1,35 @@
+name: Publish Docker
+
+on: 
+  push:
+        branches: 
+        - 'arm-docker'
+        - 'develop'
+        - 
+jobs:
+  docker:
+    runs-on: ubuntu-latest
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v2
+      -
+        name: Set up QEMU
+        uses: docker/setup-qemu-action@v1
+      -
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v1
+      -
+        name: Login to DockerHub
+        uses: docker/login-action@v1 
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+      -
+        name: Build and push
+        uses: docker/build-push-action@v2
+        with:
+          context: .
+          platforms: linux/amd64, linux/arm64
+          push: true
+          tags: gravitl/netmaker:dev      

+ 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") != "" {

+ 1 - 1
controllers/groupHttpController.go

@@ -551,7 +551,7 @@ func createAccessKey(w http.ResponseWriter, r *http.Request) {
                 mongoconn.GetError(errN, w)
                 return
         }
-	w.Write([]byte(accesskey.Value))
+	w.Write([]byte(accesskey.AccessString))
 }
 
 //pretty simple get

+ 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 - 8
main.go

@@ -7,6 +7,7 @@ import (
     "log"
     "github.com/gravitl/netmaker/models"
     "github.com/gravitl/netmaker/controllers"
+    "github.com/gravitl/netmaker/serverctl"
     "github.com/gravitl/netmaker/functions"
     "github.com/gravitl/netmaker/mongoconn"
     "github.com/gravitl/netmaker/config"
@@ -33,19 +34,22 @@ 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)
 		}
+		if created {
+			installserver = true
+		}
 	}
 
 	var waitgroup sync.WaitGroup
 
 	if config.Config.Server.AgentBackend {
 		waitgroup.Add(1)
-		go runGRPC(&waitgroup)
+		go runGRPC(&waitgroup, installserver)
 	}
 
 	if config.Config.Server.RestBackend {
@@ -60,7 +64,7 @@ func main() {
 }
 
 
-func runGRPC(wg *sync.WaitGroup) {
+func runGRPC(wg *sync.WaitGroup, installserver bool) {
 
 
 	defer wg.Done()
@@ -126,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)
@@ -172,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
@@ -207,7 +225,10 @@ func createDefaultNetwork() error {
         defer cancel()
 
 	}
-	return err
+	if err == nil {
+		iscreated = true
+	}
+	return iscreated, err
 
 
 }

+ 4 - 3
netclient/functions/common.go

@@ -73,9 +73,7 @@ func GetFreePort(rangestart int32) (int32, error){
         return portno, err
 }
 
-
-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 := ""
 	tnetwork := ""
@@ -234,6 +232,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.")
@@ -107,7 +108,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)")

+ 80 - 0
serverctl/serverctl.go

@@ -0,0 +1,80 @@
+package serverctl
+
+import (
+        "fmt"
+  "github.com/gravitl/netmaker/functions"
+	"io"
+	"net/http"
+        "os"
+        "os/exec"
+)
+
+
+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()
+
+	// Create the file
+	out, err := os.Create("/etc/netclient/netclient")
+	if err != nil {
+		return err
+	}
+	defer out.Close()
+
+	// 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 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 false, err
+        }
+	token, err := functions.CreateServerToken(network)
+        if err != nil {
+                return false, err
+        }
+        _, err = os.Stat("/etc/netclient/netclient")
+	if os.IsNotExist(err) {
+		err = DownloadNetclient()
+		if err != nil {
+			return false, err
+		}
+	}
+        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.Println(string(cmdoutput))
+                return false, err
+        }
+	fmt.Println("Server added to network " + network)
+	return true, err
+}
+
+