Browse Source

added access token for ease of configuration

afeiszli 4 years ago
parent
commit
779dc6d499

+ 16 - 2
controllers/groupHttpController.go

@@ -3,6 +3,7 @@ package controller
 import (
     "gopkg.in/go-playground/validator.v9"
     "github.com/gravitl/netmaker/models"
+    "encoding/base64"
     "github.com/gravitl/netmaker/functions"
     "github.com/gravitl/netmaker/mongoconn"
     "time"
@@ -454,6 +455,18 @@ func createAccessKey(w http.ResponseWriter, r *http.Request) {
         if accesskey.Uses == 0 {
                 accesskey.Uses = 1
         }
+	gconf, errG := functions.GetGlobalConfig()
+        if errG != nil {
+                mongoconn.GetError(errG, w)
+                return
+        }
+
+
+	network := params["groupname"]
+	address := gconf.ServerGRPC + gconf.PortGRPC
+
+	accessstringdec := address + "." + network + "." + accesskey.Value
+	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(accessstringdec))
 
 
 	group.AccessKeys = append(group.AccessKeys, accesskey)
@@ -495,8 +508,8 @@ func getAccessKeys(w http.ResponseWriter, r *http.Request) {
         var params = mux.Vars(r)
 
         var group models.Group
-        var keys []models.DisplayKey
-
+        //var keys []models.DisplayKey
+	var keys []models.AccessKey
         collection := mongoconn.Client.Database("netmaker").Collection("groups")
 
         ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
@@ -522,6 +535,7 @@ func getAccessKeys(w http.ResponseWriter, r *http.Request) {
         json.NewEncoder(w).Encode(keys)
 }
 
+
 //delete key. Has to do a little funky logic since it's not a collection item
 func deleteAccessKey(w http.ResponseWriter, r *http.Request) {
 

+ 25 - 0
functions/helpers.go

@@ -377,6 +377,31 @@ func UniqueAddress(groupName string) (string, error){
 	return "W1R3: NO UNIQUE ADDRESSES AVAILABLE", err1
 }
 
+//pretty simple get
+func GetGlobalConfig() ( models.GlobalConfig, error) {
+
+        filter := bson.M{}
+
+        var globalconf models.GlobalConfig
+
+        collection := mongoconn.Client.Database("netmaker").Collection("config")
+
+        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+
+        err := collection.FindOne(ctx, filter).Decode(&globalconf)
+
+        defer cancel()
+
+        if err != nil {
+                fmt.Println(err)
+                fmt.Println("Could not get global config")
+                return globalconf, err
+        }
+	return globalconf, err
+}
+
+
+
 //generate an access key value
 func GenKey() string {
 

+ 85 - 0
main.go

@@ -5,10 +5,17 @@ package main
 
 import (
     "log"
+    "github.com/gravitl/netmaker/models"
     "github.com/gravitl/netmaker/controllers"
+    "github.com/gravitl/netmaker/functions"
     "github.com/gravitl/netmaker/mongoconn"
     "github.com/gravitl/netmaker/config"
+    "go.mongodb.org/mongo-driver/bson"
     "fmt"
+    "time"
+    "net/http"
+    "errors"
+    "io/ioutil"
     "os"
     "net"
     "context"
@@ -18,6 +25,10 @@ import (
     nodepb "github.com/gravitl/netmaker/grpc"
     "google.golang.org/grpc"
 )
+
+var ServerGRPC string
+var PortGRPC string
+
 //Start MongoDB Connection and start API Request Handler
 func main() {
 	log.Println("Server starting...")
@@ -59,6 +70,27 @@ func runGRPC(wg *sync.WaitGroup) {
         if os.Getenv("GRPC_PORT") != "" {
 		grpcport = ":" + os.Getenv("GRPC_PORT")
         }
+	PortGRPC = grpcport
+	if os.Getenv("BACKEND_URL") == ""  {
+		if config.Config.Server.Host == "" {
+			ServerGRPC, _ = getPublicIP()
+		} else {
+			ServerGRPC = config.Config.Server.Host
+		}
+	} else {
+		ServerGRPC = os.Getenv("BACKEND_URL")
+	}
+	fmt.Println("GRPC Server set to: " + ServerGRPC)
+	fmt.Println("GRPC Port set to: " + PortGRPC)
+	var gconf models.GlobalConfig
+	gconf.ServerGRPC = ServerGRPC
+	gconf.PortGRPC = PortGRPC
+	gconf.Name = "netmaker"
+	err := setGlobalConfig(gconf)
+
+	if err != nil {
+	      log.Fatalf("Unable to set global config: %v", err)
+	}
 
 
 	listener, err := net.Listen("tcp", grpcport)
@@ -108,6 +140,59 @@ func runGRPC(wg *sync.WaitGroup) {
         mongoconn.Client.Disconnect(context.TODO())
         fmt.Println("MongoDB connection closed.")
 }
+func setGlobalConfig(globalconf models.GlobalConfig) (error) {
+
+        collection := mongoconn.Client.Database("netmaker").Collection("config")
+        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+
+	_, err := functions.GetGlobalConfig()
+	if err != nil {
+		_, err := collection.InsertOne(ctx, globalconf)
+		defer cancel()
+		if err != nil {
+			return err
+		}
+	} else {
+		filter := bson.M{"name": "netmaker"}
+		update := bson.D{
+			{"$set", bson.D{
+				{"servergrpc", globalconf.ServerGRPC},
+				{"portgrpc", globalconf.PortGRPC},
+			}},
+		}
+		err = collection.FindOneAndUpdate(ctx, filter, update).Decode(&globalconf)
+	}
+	return nil
+}
+
+
+func getPublicIP() (string, error) {
+
+        iplist := []string{"https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
+        endpoint := ""
+        var err error
+            for _, ipserver := range iplist {
+                resp, err := http.Get(ipserver)
+                if err != nil {
+                        continue
+                }
+                defer resp.Body.Close()
+                if resp.StatusCode == http.StatusOK {
+                        bodyBytes, err := ioutil.ReadAll(resp.Body)
+                        if err != nil {
+                                continue
+                        }
+                        endpoint = string(bodyBytes)
+                        break
+                }
+
+        }
+        if err == nil && endpoint == "" {
+                err =  errors.New("Public Address Not Found.")
+        }
+        return endpoint, err
+}
+
 
 func authServerUnaryInterceptor() grpc.ServerOption {
 	return grpc.UnaryInterceptor(controller.AuthServerUnaryInterceptor)

+ 8 - 0
models/structs.go

@@ -64,6 +64,7 @@ type SuccessResponse struct {
 type AccessKey struct {
     Name string `json:"name" bson:"name"`
     Value string `json:"value" bson:"value"`
+    AccessString string `json:"accessstring" bson:"accessstring"`
     Uses int `json:"uses" bson:"uses"`
 }
 
@@ -72,6 +73,13 @@ type DisplayKey struct {
     Uses int `json:"uses" bson:"uses"`
 }
 
+type GlobalConfig struct {
+    Name string `json:"name" bson:"name"`
+    PortGRPC string `json:"portgrpc" bson:"portgrpc"`
+    ServerGRPC string `json:"servergrpc" bson:"servergrpc"`
+}
+
+
 type CheckInResponse struct{
     Success bool `json:"success" bson:"success"`
     NeedPeerUpdate bool `json:"needpeerupdate" bson:"needpeerupdate"`

BIN
netclient/functions/.common.go.swp


+ 37 - 4
netclient/functions/common.go

@@ -19,6 +19,7 @@ import (
         nodepb "github.com/gravitl/netmaker/grpc"
 	"golang.zx2c4.com/wireguard/wgctrl"
         "google.golang.org/grpc"
+	"encoding/base64"
 	"google.golang.org/grpc/metadata"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 	//homedir "github.com/mitchellh/go-homedir"
@@ -28,8 +29,31 @@ var (
         wcclient nodepb.NodeServiceClient
 )
 
-func Install(accesskey string, password string, server string, group string, noauto bool) error {
+func Install(accesskey string, password string, server string, group string, noauto bool, accesstoken string) error {
 
+
+	tserver := ""
+	tnetwork := ""
+	tkey := ""
+
+	if accesstoken != "" && accesstoken != "badtoken" {
+		btoken, err := base64.StdEncoding.DecodeString(accesstoken)
+		if err  != nil {
+			log.Fatalf("Something went wrong decoding your token: %v", err)
+		}
+		token := string(btoken)
+		tokenvals := strings.Split(token, ".")
+		tserver = tokenvals[0]
+		tnetwork = tokenvals[1]
+		tkey = tokenvals[2]
+		server = tserver
+		group = tnetwork
+		accesskey = tkey
+		fmt.Println("Decoded values from token:")
+		fmt.Println("    Server: " + tserver)
+		fmt.Println("    Network: " + tnetwork)
+		fmt.Println("    Key: " + tkey)
+	}
         wgclient, err := wgctrl.New()
 
         if err != nil {
@@ -46,21 +70,27 @@ func Install(accesskey string, password string, server string, group string, noa
 	fmt.Println("SERVER SETTINGS:")
 
 	if server == "" {
-		if servercfg.Address == "" {
+		if servercfg.Address == "" && tserver == "" {
 			log.Fatal("no server provided")
 		} else {
                         server = servercfg.Address
 		}
 	}
+	if tserver != "" {
+		server = tserver
+	}
        fmt.Println("     Server: " + server)
 
 	if accesskey == "" {
-		if servercfg.AccessKey == "" {
+		if servercfg.AccessKey == "" && tkey == "" {
 			fmt.Println("no access key provided.Proceeding anyway.")
 		} else {
 			accesskey = servercfg.AccessKey
 		}
 	}
+	if tkey != "" {
+		accesskey = tkey
+	}
        fmt.Println("     AccessKey: " + accesskey)
        err = config.WriteServer(server, accesskey, group)
         if err != nil {
@@ -81,13 +111,16 @@ func Install(accesskey string, password string, server string, group string, noa
        fmt.Println("     Password: " + password)
 
         if group == "badgroup" {
-                if nodecfg.Group == "" {
+                if nodecfg.Group == "" && tnetwork == "" {
                         //create error here                
                         log.Fatal("no group provided")
                 } else {
 			group = nodecfg.Group
 		}
         }
+	if tnetwork != "" {
+		group =  tnetwork
+	}
        fmt.Println("     Group: " + group)
 
 	var macaddress string

+ 3 - 2
netclient/main.go

@@ -35,6 +35,7 @@ var (
 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)")
 	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.")
@@ -76,7 +77,7 @@ func main() {
 			log.Fatal("Exiting")
                 case "install":
 
-                        if *tnetwork == "nonetwork"  || *tnetwork == ""{
+                        if *taccesstoken == "badtoken" && (*tnetwork == "nonetwork"  || *tnetwork == "") {
                                 fmt.Println("Required, '-n'. No network provided. Exiting.")
                                 os.Exit(1)
                         }
@@ -99,7 +100,7 @@ func main() {
 			}
 
 			fmt.Println("Beginning agent installation.")
-			err := functions.Install(*taccesskey, *tpassword, *tserver, *tnetwork, *tnoauto)
+			err := functions.Install(*taccesskey, *tpassword, *tserver, *tnetwork, *tnoauto, *taccesstoken)
 			if err != nil {
 				fmt.Println("Error installing: ", err)
 				fmt.Println("Cleaning up (uninstall)")