Selaa lähdekoodia

join via api - netclient changes

Signed-off-by: Matthew R. Kasun <[email protected]>
Matthew R. Kasun 3 vuotta sitten
vanhempi
commit
d04e96b77f
4 muutettua tiedostoa jossa 89 lisäystä ja 115 poistoa
  1. 1 0
      models/accessToken.go
  2. 17 0
      netclient/config/config.go
  3. 66 111
      netclient/functions/join.go
  4. 5 4
      netclient/wireguard/common.go

+ 1 - 0
models/accessToken.go

@@ -15,4 +15,5 @@ type ServerConfig struct {
 	GRPCConnString string `json:"grpcconn"`
 	GRPCSSL        string `json:"grpcssl"`
 	ServerName     string `json:"servername"`
+	API            string `json:"api"`
 }

+ 17 - 0
netclient/config/config.go

@@ -2,6 +2,8 @@ package config
 
 import (
 	//"github.com/davecgh/go-spew/spew"
+	"crypto/ed25519"
+	"crypto/x509"
 	"encoding/base64"
 	"encoding/json"
 	"errors"
@@ -13,6 +15,7 @@ import (
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/urfave/cli/v2"
+	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 	"gopkg.in/yaml.v3"
 )
 
@@ -34,6 +37,19 @@ type ServerConfig struct {
 	AccessKey   string `yaml:"accesskey"`
 	GRPCSSL     string `yaml:"grpcssl"`
 	ServerName  string `yaml:"servername"`
+	API         string `yaml:"api"`
+}
+
+type JoinRequest struct {
+	Config ClientConfig
+	Key    ed25519.PublicKey
+}
+
+type JoinResponse struct {
+	Config      ClientConfig
+	Peers       []wgtypes.PeerConfig
+	Certificate x509.Certificate
+	CA          x509.Certificate
 }
 
 // Write - writes the config of a client to disk
@@ -189,6 +205,7 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, string, error) {
 		cfg.Node.LocalRange = accesstoken.ClientConfig.LocalRange
 		cfg.Server.GRPCSSL = accesstoken.ServerConfig.GRPCSSL
 		cfg.Server.ServerName = accesstoken.ServerConfig.ServerName
+		cfg.Server.API = accesstoken.ServerConfig.API
 		if c.String("grpcserver") != "" {
 			cfg.Server.GRPCAddress = c.String("grpcserver")
 		}

+ 66 - 111
netclient/functions/join.go

@@ -1,15 +1,14 @@
 package functions
 
 import (
-	"context"
-	"crypto/rand"
+	"bytes"
+	"crypto/ed25519"
 	"encoding/json"
 	"errors"
 	"fmt"
 	"log"
-	"runtime"
+	"net/http"
 
-	nodepb "github.com/gravitl/netmaker/grpc"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/models"
@@ -18,15 +17,15 @@ import (
 	"github.com/gravitl/netmaker/netclient/daemon"
 	"github.com/gravitl/netmaker/netclient/local"
 	"github.com/gravitl/netmaker/netclient/ncutils"
-	"github.com/gravitl/netmaker/netclient/server"
 	"github.com/gravitl/netmaker/netclient/wireguard"
-	"golang.org/x/crypto/nacl/box"
+	"github.com/gravitl/netmaker/tls"
+	"github.com/kr/pretty"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
-	"google.golang.org/grpc"
 )
 
 // JoinNetwork - helps a client join a network
 func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
+	log.Println("starting join")
 	if cfg.Node.Network == "" {
 		return errors.New("no network provided")
 	}
@@ -44,31 +43,12 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 	if cfg.Node.Password == "" {
 		cfg.Node.Password = logic.GenKey()
 	}
-	var trafficPubKey, trafficPrivKey, errT = box.GenerateKey(rand.Reader) // generate traffic keys
-	if errT != nil {
-		return errT
-	}
 
 	// == handle keys ==
 	if err = auth.StoreSecret(cfg.Node.Password, cfg.Node.Network); err != nil {
 		return err
 	}
 
-	if err = auth.StoreTrafficKey(trafficPrivKey, cfg.Node.Network); err != nil {
-		return err
-	}
-
-	trafficPubKeyBytes, err := ncutils.ConvertKeyToBytes(trafficPubKey)
-	if err != nil {
-		return err
-	} else if trafficPubKeyBytes == nil {
-		return fmt.Errorf("traffic key is nil")
-	}
-
-	cfg.Node.TrafficKeys.Mine = trafficPubKeyBytes
-	cfg.Node.TrafficKeys.Server = nil
-	// == end handle keys ==
-
 	if cfg.Node.LocalAddress == "" {
 		intIP, err := getPrivateAddr()
 		if err == nil {
@@ -110,59 +90,32 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 		}
 	}
 
-	//	if ncutils.IsLinux() {
-	//		_, err := exec.LookPath("resolvectl")
-	//		if err != nil {
-	//			logger.Log("resolvectl not present", 2)
-	//			logger.Log("unable to configure DNS automatically, disabling automated DNS management", 2)
-	//			cfg.Node.DNSOn = "no"
-	//		}
-	//	}
 	if ncutils.IsFreeBSD() {
 		cfg.Node.UDPHolePunch = "no"
 	}
 	// make sure name is appropriate, if not, give blank name
 	cfg.Node.Name = formatName(cfg.Node)
-	// differentiate between client/server here
-	var node = models.Node{
-		Password:   cfg.Node.Password,
-		Address:    cfg.Node.Address,
-		Address6:   cfg.Node.Address6,
-		ID:         cfg.Node.ID,
-		MacAddress: cfg.Node.MacAddress,
-		AccessKey:  cfg.Server.AccessKey,
-		IsStatic:   cfg.Node.IsStatic,
-		//Roaming:             cfg.Node.Roaming,
-		Network:             cfg.Network,
-		ListenPort:          cfg.Node.ListenPort,
-		PostUp:              cfg.Node.PostUp,
-		PostDown:            cfg.Node.PostDown,
-		PersistentKeepalive: cfg.Node.PersistentKeepalive,
-		LocalAddress:        cfg.Node.LocalAddress,
-		Interface:           cfg.Node.Interface,
-		PublicKey:           cfg.Node.PublicKey,
-		DNSOn:               cfg.Node.DNSOn,
-		Name:                cfg.Node.Name,
-		Endpoint:            cfg.Node.Endpoint,
-		UDPHolePunch:        cfg.Node.UDPHolePunch,
-		TrafficKeys:         cfg.Node.TrafficKeys,
-		OS:                  runtime.GOOS,
-		Version:             ncutils.Version,
-	}
 
-	logger.Log(0, "joining "+cfg.Network+" at "+cfg.Server.GRPCAddress)
-	var wcclient nodepb.NodeServiceClient
+	seed := tls.NewKey()
+	key, err := seed.Ed25519PrivateKey()
+	if err != nil {
+		return err
+	}
 
-	conn, err := grpc.Dial(cfg.Server.GRPCAddress,
-		ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
+	request := config.JoinRequest{
+		Config: *cfg,
+		Key:    key.Public().(ed25519.PublicKey),
+	}
 
+	log.Println("calling api")
+	response, err := join(request, cfg.Server.API, cfg.Node.AccessKey)
 	if err != nil {
-		log.Fatalf("Unable to establish client connection to "+cfg.Server.GRPCAddress+": %v", err)
+		return fmt.Errorf("error joining network %w", err)
 	}
-	defer conn.Close()
-	wcclient = nodepb.NewNodeServiceClient(conn)
+	node := response.Config.Node
+	peers := response.Peers
 
-	// safety check. If returned node from server is local, but not currently configured as local, set to local addr
+	// safety check. If returned no:de from server is local, but not currently configured as local, set to local addr
 	if cfg.Node.IsLocal != "yes" && node.IsLocal == "yes" && node.LocalRange != "" {
 		node.LocalAddress, err = ncutils.GetLocalIP(node.LocalRange)
 		if err != nil {
@@ -186,35 +139,15 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 			return daemon.InstallDaemon(cfg)
 		}
 	}
-	data, err := json.Marshal(&node)
-	if err != nil {
-		return err
-	}
-	// Create node on server
-	res, err := wcclient.CreateNode(
-		context.TODO(),
-		&nodepb.Object{
-			Data: string(data),
-			Type: nodepb.NODE_TYPE,
-		},
-	)
-	if err != nil {
-		return err
-	}
-	logger.Log(1, "node created on remote server...updating configs")
 
 	// keep track of the old listenport value
 	oldListenPort := node.ListenPort
 
-	nodeData := res.Data
-	if err = json.Unmarshal([]byte(nodeData), &node); err != nil {
-		return err
-	}
-
 	cfg.Node = node
 
 	setListenPort(oldListenPort, cfg)
 
+	log.Println("join- modconfig")
 	err = config.ModConfig(&cfg.Node)
 	if err != nil {
 		return err
@@ -223,34 +156,25 @@ func JoinNetwork(cfg *config.ClientConfig, privateKey string) error {
 	if err = config.SaveBackup(node.Network); err != nil {
 		logger.Log(0, "failed to make backup, node will not auto restore if config is corrupted")
 	}
-
-	logger.Log(0, "retrieving peers")
-	peers, hasGateway, gateways, err := server.GetPeers(node.MacAddress, cfg.Network, cfg.Server.GRPCAddress, node.IsDualStack == "yes", node.IsIngressGateway == "yes", node.IsServer == "yes")
-	if err != nil && !ncutils.IsEmptyRecord(err) {
-		logger.Log(0, "failed to retrieve peers")
+	log.Println("init wireguard")
+	err = wireguard.InitWireguard(&node, privateKey, peers, false)
+	if err != nil {
 		return err
 	}
 
-	logger.Log(0, "starting wireguard")
-	err = wireguard.InitWireguard(&node, privateKey, peers, hasGateway, gateways, false)
-	if err != nil {
+	log.Println("save certs")
+	//save CA, certificate and key
+	if err := tls.SaveCert("/etc/netclient/"+cfg.Server.ServerName, "root.pem", &response.CA); err != nil {
+		return err
+	}
+	if err := tls.SaveCert("/etc/netclient/"+cfg.Server.ServerName, "client.pem", &response.Certificate); err != nil {
+		return err
+	}
+	if err := tls.SaveKey("/etc/netclient/"+cfg.Server.ServerName, "client.key", key); err != nil {
 		return err
 	}
-	//	if node.DNSOn == "yes" {
-	//		for _, server := range node.NetworkSettings.DefaultServerAddrs {
-	//			if server.IsLeader {
-	//				go func() {
-	//					if !local.SetDNSWithRetry(node, server.Address) {
-	//						cfg.Node.DNSOn = "no"
-	//						var currentCommsCfg = getCommsCfgByNode(&cfg.Node)
-	//						PublishNodeUpdate(&currentCommsCfg, &cfg)
-	//					}
-	//				}()
-	//				break
-	//			}
-	//		}
-	//	}
 
+	log.Println("start daemaon")
 	if cfg.Daemon != "off" {
 		err = daemon.InstallDaemon(cfg)
 	}
@@ -278,6 +202,7 @@ func formatName(node models.Node) string {
 		node.Name = ""
 	}
 	return node.Name
+
 }
 
 func setListenPort(oldListenPort int32, cfg *config.ClientConfig) {
@@ -299,3 +224,33 @@ func setListenPort(oldListenPort int32, cfg *config.ClientConfig) {
 		}
 	}
 }
+
+func join(node config.JoinRequest, url, authorization string) (*config.JoinResponse, error) {
+	var request *http.Request
+	var joinResponse config.JoinResponse
+	payload, err := json.Marshal(node)
+	if err != nil {
+		return nil, err
+	}
+	request, err = http.NewRequest(http.MethodPost, url, bytes.NewBuffer(payload))
+	if err != nil {
+		return nil, err
+	}
+	request.Header.Set("Content-Type", "application/json")
+	request.Header.Set("authorization", "Bearer "+authorization)
+	fmt.Println("sending api request")
+	pretty.Println(request)
+	client := http.Client{}
+	response, err := client.Do(request)
+	pretty.Println(response)
+	if err != nil {
+		return nil, err
+	}
+	if response.StatusCode != http.StatusOK {
+		return nil, fmt.Errorf("error join network %s", response.Status)
+	}
+	if err := json.NewDecoder(response.Body).Decode(&joinResponse); err != nil {
+		return nil, err
+	}
+	return &joinResponse, nil
+}

+ 5 - 4
netclient/wireguard/common.go

@@ -122,7 +122,7 @@ func SetPeers(iface string, node *models.Node, peers []wgtypes.PeerConfig) error
 }
 
 // Initializes a WireGuard interface
-func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string, syncconf bool) error {
+func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig, syncconf bool) error {
 
 	key, err := wgtypes.ParseKey(privkey)
 	if err != nil {
@@ -230,7 +230,8 @@ func SetWGConfig(network string, peerupdate bool) error {
 	servercfg := cfg.Server
 	nodecfg := cfg.Node
 
-	peers, hasGateway, gateways, err := server.GetPeers(nodecfg.MacAddress, nodecfg.Network, servercfg.GRPCAddress, nodecfg.IsDualStack == "yes", nodecfg.IsIngressGateway == "yes", nodecfg.IsServer == "yes")
+	peers, _, _, err := server.GetPeers(nodecfg.MacAddress, nodecfg.Network, servercfg.GRPCAddress, nodecfg.IsDualStack == "yes", nodecfg.IsIngressGateway == "yes", nodecfg.IsServer == "yes")
+
 	if err != nil {
 		return err
 	}
@@ -249,9 +250,9 @@ func SetWGConfig(network string, peerupdate bool) error {
 		}
 		err = SetPeers(iface, &nodecfg, peers)
 	} else if peerupdate {
-		err = InitWireguard(&nodecfg, privkey, peers, hasGateway, gateways, true)
+		err = InitWireguard(&nodecfg, privkey, peers, true)
 	} else {
-		err = InitWireguard(&nodecfg, privkey, peers, hasGateway, gateways, false)
+		err = InitWireguard(&nodecfg, privkey, peers, false)
 	}
 	if nodecfg.DNSOn == "yes" {
 		_ = local.UpdateDNS(nodecfg.Interface, nodecfg.Network, servercfg.CoreDNSAddr)