diff --git a/netclient/functions/common.go b/netclient/functions/common.go index f546cc4b..e188c678 100644 --- a/netclient/functions/common.go +++ b/netclient/functions/common.go @@ -1,11 +1,13 @@ package functions import ( + "bytes" "encoding/json" "errors" "fmt" "log" "net" + "net/http" "os" "strings" @@ -329,3 +331,56 @@ func WipeLocal(network string) error { func GetNetmakerPath() string { return LINUX_APP_DATA_PATH } + +//API function to interact with netmaker api endpoints. response from endpoint is returned +func API(data any, method, url, authorization string) (*http.Response, error) { + var request *http.Request + var err error + if data != "" { + payload, err := json.Marshal(data) + if err != nil { + return nil, fmt.Errorf("error encoding data %w", err) + } + request, err = http.NewRequest(method, url, bytes.NewBuffer(payload)) + if err != nil { + return nil, fmt.Errorf("error creating http request %w", err) + } + request.Header.Set("Content-Type", "application/json") + } else { + request, err = http.NewRequest(method, url, nil) + if err != nil { + return nil, fmt.Errorf("error creating http request %w", err) + } + } + if authorization != "" { + request.Header.Set("authorization", "Bearer "+authorization) + } + client := http.Client{} + return client.Do(request) +} + +// Authenticate authenticates with api to permit subsequent interactions with the api +func Authenticate(cfg *config.ClientConfig) (string, error) { + + pass, err := os.ReadFile(ncutils.GetNetclientPathSpecific() + "/secret-" + cfg.Network) + if err != nil { + return "", fmt.Errorf("could not read secrets file %w", err) + } + data := models.AuthParams{ + MacAddress: cfg.Node.MacAddress, + ID: cfg.Node.ID, + Password: string(pass), + } + url := "https://" + cfg.Server.API + "/api/nodes/adm/" + cfg.Network + "/authenticate" + response, err := API(data, http.MethodPost, url, "") + if err != nil { + return "", err + } + resp := models.SuccessResponse{} + if err := json.NewDecoder(response.Body).Decode(&resp); err != nil { + return "", err + } + tokenData := (resp.Response.(map[string]interface{})) + token := tokenData["AuthToken"] + return token.(string), nil +} diff --git a/netclient/functions/pull.go b/netclient/functions/pull.go index f66f4a84..25a93640 100644 --- a/netclient/functions/pull.go +++ b/netclient/functions/pull.go @@ -1,22 +1,20 @@ package functions import ( - "context" "encoding/json" "errors" + "fmt" + "io/ioutil" + "net/http" "os" "runtime" - nodepb "github.com/gravitl/netmaker/grpc" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/models" - "github.com/gravitl/netmaker/netclient/auth" "github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/local" "github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/netclient/wireguard" - "google.golang.org/grpc" - "google.golang.org/grpc/metadata" //homedir "github.com/mitchellh/go-homedir" ) @@ -26,54 +24,31 @@ func Pull(network string, manual bool) (*models.Node, error) { if err != nil { return nil, err } - node := cfg.Node - //servercfg := cfg.Server - if cfg.Node.IPForwarding == "yes" && !ncutils.IsWindows() { if err = local.SetIPForwarding(); err != nil { return nil, err } } - var resNode models.Node // just need to fill this with either server calls or client calls - - var header metadata.MD - var wcclient nodepb.NodeServiceClient - var ctx context.Context - - if cfg.Node.IsServer != "yes" { - conn, err := grpc.Dial(cfg.Server.GRPCAddress, - ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL)) + token, err := Authenticate(cfg) + if err != nil { + return nil, err + } + url := "https://" + cfg.Server.API + "/api/nodes/" + cfg.Network + "/" + cfg.Node.ID + response, err := API("", http.MethodGet, url, token) + if err != nil { + return nil, err + } + if response.StatusCode != http.StatusOK { + bytes, err := ioutil.ReadAll(response.Body) if err != nil { - logger.Log(1, "Cant dial GRPC server: ", err.Error()) - return nil, err - } - defer conn.Close() - wcclient = nodepb.NewNodeServiceClient(conn) - - ctx, err = auth.SetJWT(wcclient, network) - if err != nil { - logger.Log(1, "Failed to authenticate: ", err.Error()) - return nil, err - } - data, err := json.Marshal(&node) - if err != nil { - logger.Log(1, "Failed to parse node config: ", err.Error()) - return nil, err - } - - req := &nodepb.Object{ - Data: string(data), - Type: nodepb.NODE_TYPE, - } - - readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header)) - if err != nil { - return nil, err - } - - if err = json.Unmarshal([]byte(readres.Data), &resNode); err != nil { - return nil, err + fmt.Println(err) } + return nil, (fmt.Errorf("%s %w", string(bytes), err)) + } + defer response.Body.Close() + resNode := models.Node{} + if err := json.NewDecoder(response.Body).Decode(&resNode); err != nil { + return nil, fmt.Errorf("error decoding node %w", err) } // ensure that the OS never changes resNode.OS = runtime.GOOS @@ -90,25 +65,6 @@ func Pull(network string, manual bool) (*models.Node, error) { if err = wireguard.SetWGConfig(network, false); err != nil { return nil, err } - nodeData, err := json.Marshal(&resNode) - if err != nil { - return &resNode, err - } - - if resNode.IsServer != "yes" { - if wcclient == nil || ctx == nil { - return &cfg.Node, errors.New("issue initializing gRPC client") - } - req := &nodepb.Object{ - Data: string(nodeData), - Type: nodepb.NODE_TYPE, - Metadata: "", - } - _, err = wcclient.UpdateNode(ctx, req, grpc.Header(&header)) - if err != nil { - return &resNode, err - } - } } else { if err = wireguard.SetWGConfig(network, true); err != nil { if errors.Is(err, os.ErrNotExist) && !ncutils.IsFreeBSD() {