mirror of
				https://github.com/gravitl/netmaker.git
				synced 2025-10-31 20:22:44 +08:00 
			
		
		
		
	removed references to AccessKey model
This commit is contained in:
		| @@ -106,12 +106,12 @@ func HandleNodeSSOCallback(w http.ResponseWriter, r *http.Request) { | ||||
| 	var answer string | ||||
| 	// The registation logic is starting here: | ||||
| 	// we request access key with 1 use for the required network | ||||
| 	accessToken, err := requestAccessKey(reqKeyIf.Network, 1, userClaims.getUserName()) | ||||
| 	if err != nil { | ||||
| 		answer = fmt.Sprintf("Error from the netmaker controller %s", err.Error()) | ||||
| 	} else { | ||||
| 		answer = fmt.Sprintf("AccessToken: %s", accessToken) | ||||
| 	} | ||||
| 	// accessToken, err := requestAccessKey(reqKeyIf.Network, 1, userClaims.getUserName()) | ||||
| 	// if err != nil { | ||||
| 	// 	answer = fmt.Sprintf("Error from the netmaker controller %s", err.Error()) | ||||
| 	// } else { | ||||
| 	// 	answer = fmt.Sprintf("AccessToken: %s", accessToken) | ||||
| 	// } | ||||
| 	logger.Log(0, "Updating the token for the client request ... ") | ||||
| 	// Give the user the access token via Pass in the DB | ||||
| 	reqKeyIf.Pass = answer | ||||
| @@ -184,44 +184,44 @@ func RegisterNodeSSO(w http.ResponseWriter, r *http.Request) { | ||||
|  | ||||
| // == private == | ||||
| // API to create an access key for a given network with a given name | ||||
| func requestAccessKey(network string, uses int, name string) (accessKey string, err error) { | ||||
| // func requestAccessKey(network string, uses int, name string) (accessKey string, err error) { | ||||
|  | ||||
| 	var sAccessKey models.AccessKey | ||||
| 	var sNetwork models.Network | ||||
| // 	var sAccessKey models.AccessKey | ||||
| // 	var sNetwork models.Network | ||||
|  | ||||
| 	sNetwork, err = logic.GetParentNetwork(network) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, "err calling GetParentNetwork API=%s", err.Error()) | ||||
| 		return "", fmt.Errorf("internal controller error %s", err.Error()) | ||||
| 	} | ||||
| 	// If a key already exists, we recreate it. | ||||
| 	// @TODO Is that a preferred handling ? We could also trying to re-use. | ||||
| 	// can happen if user started log in but did not finish | ||||
| 	for _, currentkey := range sNetwork.AccessKeys { | ||||
| 		if currentkey.Name == name { | ||||
| 			logger.Log(0, "erasing existing AccessKey for: ", name) | ||||
| 			err = logic.DeleteKey(currentkey.Name, network) | ||||
| 			if err != nil { | ||||
| 				logger.Log(0, "err calling CreateAccessKey API ", err.Error()) | ||||
| 				return "", fmt.Errorf("key already exists. Contact admin to resolve") | ||||
| 			} | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	// Only one usage is needed - for the next time new access key will be required | ||||
| 	// it will be created next time after another IdP approval | ||||
| 	sAccessKey.Uses = 1 | ||||
| 	sAccessKey.Name = name | ||||
| // 	sNetwork, err = logic.GetParentNetwork(network) | ||||
| // 	if err != nil { | ||||
| // 		logger.Log(0, "err calling GetParentNetwork API=%s", err.Error()) | ||||
| // 		return "", fmt.Errorf("internal controller error %s", err.Error()) | ||||
| // 	} | ||||
| // 	// If a key already exists, we recreate it. | ||||
| // 	// @TODO Is that a preferred handling ? We could also trying to re-use. | ||||
| // 	// can happen if user started log in but did not finish | ||||
| // 	for _, currentkey := range sNetwork.AccessKeys { | ||||
| // 		if currentkey.Name == name { | ||||
| // 			logger.Log(0, "erasing existing AccessKey for: ", name) | ||||
| // 			err = logic.DeleteKey(currentkey.Name, network) | ||||
| // 			if err != nil { | ||||
| // 				logger.Log(0, "err calling CreateAccessKey API ", err.Error()) | ||||
| // 				return "", fmt.Errorf("key already exists. Contact admin to resolve") | ||||
| // 			} | ||||
| // 			break | ||||
| // 		} | ||||
| // 	} | ||||
| // 	// Only one usage is needed - for the next time new access key will be required | ||||
| // 	// it will be created next time after another IdP approval | ||||
| // 	sAccessKey.Uses = 1 | ||||
| // 	sAccessKey.Name = name | ||||
|  | ||||
| 	accessToken, err := logic.CreateAccessKey(sAccessKey, sNetwork) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, "err calling CreateAccessKey API ", err.Error()) | ||||
| 		return "", fmt.Errorf("error from the netmaker controller %s", err.Error()) | ||||
| 	} else { | ||||
| 		logger.Log(1, "created access key", sAccessKey.Name, "on", network) | ||||
| 	} | ||||
| 	return accessToken.AccessString, nil | ||||
| } | ||||
| // 	accessToken, err := logic.CreateAccessKey(sAccessKey, sNetwork) | ||||
| // 	if err != nil { | ||||
| // 		logger.Log(0, "err calling CreateAccessKey API ", err.Error()) | ||||
| // 		return "", fmt.Errorf("error from the netmaker controller %s", err.Error()) | ||||
| // 	} else { | ||||
| // 		logger.Log(1, "created access key", sAccessKey.Name, "on", network) | ||||
| // 	} | ||||
| // 	return accessToken.AccessString, nil | ||||
| // } | ||||
|  | ||||
| func isUserIsAllowed(username, network string, shouldAddUser bool) (*models.User, error) { | ||||
|  | ||||
|   | ||||
| @@ -85,7 +85,7 @@ func SessionHandler(conn *websocket.Conn) { | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 		user, err := isUserIsAllowed(loginMessage.User, loginMessage.Network, false) | ||||
| 		_, err = isUserIsAllowed(loginMessage.User, loginMessage.Network, false) | ||||
| 		if err != nil { | ||||
| 			err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) | ||||
| 			if err != nil { | ||||
| @@ -93,12 +93,7 @@ func SessionHandler(conn *websocket.Conn) { | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 		accessToken, err := requestAccessKey(loginMessage.Network, 1, user.UserName) | ||||
| 		if err != nil { | ||||
| 			req.Pass = fmt.Sprintf("Error from the netmaker controller %s", err.Error()) | ||||
| 		} else { | ||||
| 			req.Pass = fmt.Sprintf("AccessToken: %s", accessToken) | ||||
| 		} | ||||
|  | ||||
| 		// Give the user the access token via Pass in the DB | ||||
| 		if err = netcache.Set(stateStr, req); err != nil { | ||||
| 			logger.Log(0, "machine failed to complete join on network,", loginMessage.Network, "-", err.Error()) | ||||
|   | ||||
| @@ -1,35 +0,0 @@ | ||||
| package keys | ||||
|  | ||||
| import ( | ||||
| 	"log" | ||||
| 	"strconv" | ||||
|  | ||||
| 	"github.com/gravitl/netmaker/cli/functions" | ||||
| 	"github.com/gravitl/netmaker/models" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
|  | ||||
| var keyName string | ||||
|  | ||||
| var keysCreateCmd = &cobra.Command{ | ||||
| 	Use:   "create [NETWORK NAME] [NUM USES]", | ||||
| 	Args:  cobra.ExactArgs(2), | ||||
| 	Short: "Create an access key", | ||||
| 	Long:  `Create an access key`, | ||||
| 	Run: func(cmd *cobra.Command, args []string) { | ||||
| 		keyUses, err := strconv.ParseInt(args[1], 10, 64) | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err) | ||||
| 		} | ||||
| 		key := &models.AccessKey{Uses: int(keyUses)} | ||||
| 		if keyName != "" { | ||||
| 			key.Name = keyName | ||||
| 		} | ||||
| 		functions.PrettyPrint(functions.CreateKey(args[0], key)) | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	keysCreateCmd.Flags().StringVar(&keyName, "name", "", "Name of the key") | ||||
| 	rootCmd.AddCommand(keysCreateCmd) | ||||
| } | ||||
| @@ -1,23 +0,0 @@ | ||||
| package keys | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/gravitl/netmaker/cli/functions" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
|  | ||||
| var keysDeleteCmd = &cobra.Command{ | ||||
| 	Use:   "delete [NETWORK NAME] [KEY NAME]", | ||||
| 	Args:  cobra.ExactArgs(2), | ||||
| 	Short: "Delete a key", | ||||
| 	Long:  `Delete a key`, | ||||
| 	Run: func(cmd *cobra.Command, args []string) { | ||||
| 		functions.DeleteKey(args[0], args[1]) | ||||
| 		fmt.Println("Success") | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	rootCmd.AddCommand(keysDeleteCmd) | ||||
| } | ||||
| @@ -1,20 +0,0 @@ | ||||
| package keys | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gravitl/netmaker/cli/functions" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
|  | ||||
| var keysListCmd = &cobra.Command{ | ||||
| 	Use:   "list [NETWORK NAME]", | ||||
| 	Args:  cobra.ExactArgs(1), | ||||
| 	Short: "List all keys associated with a network", | ||||
| 	Long:  `List all keys associated with a network`, | ||||
| 	Run: func(cmd *cobra.Command, args []string) { | ||||
| 		functions.PrettyPrint(functions.GetKeys(args[0])) | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	rootCmd.AddCommand(keysListCmd) | ||||
| } | ||||
| @@ -1,28 +0,0 @@ | ||||
| package keys | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
|  | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
|  | ||||
| // rootCmd represents the base command when called without any subcommands | ||||
| var rootCmd = &cobra.Command{ | ||||
| 	Use:   "keys", | ||||
| 	Short: "Manage access keys associated with a network", | ||||
| 	Long:  `Manage access keys associated with a network`, | ||||
| } | ||||
|  | ||||
| // GetRoot returns the root subcommand | ||||
| func GetRoot() *cobra.Command { | ||||
| 	return rootCmd | ||||
| } | ||||
|  | ||||
| // Execute adds all child commands to the root command and sets flags appropriately. | ||||
| // This is called by main.main(). It only needs to happen once to the rootCmd. | ||||
| func Execute() { | ||||
| 	err := rootCmd.Execute() | ||||
| 	if err != nil { | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| } | ||||
| @@ -10,7 +10,6 @@ import ( | ||||
| 	"github.com/gravitl/netmaker/cli/cmd/enrollment_key" | ||||
| 	"github.com/gravitl/netmaker/cli/cmd/ext_client" | ||||
| 	"github.com/gravitl/netmaker/cli/cmd/host" | ||||
| 	"github.com/gravitl/netmaker/cli/cmd/keys" | ||||
| 	"github.com/gravitl/netmaker/cli/cmd/metrics" | ||||
| 	"github.com/gravitl/netmaker/cli/cmd/network" | ||||
| 	"github.com/gravitl/netmaker/cli/cmd/network_user" | ||||
| @@ -47,7 +46,6 @@ func init() { | ||||
| 	// Bind subcommands here | ||||
| 	rootCmd.AddCommand(network.GetRoot()) | ||||
| 	rootCmd.AddCommand(context.GetRoot()) | ||||
| 	rootCmd.AddCommand(keys.GetRoot()) | ||||
| 	rootCmd.AddCommand(acl.GetRoot()) | ||||
| 	rootCmd.AddCommand(node.GetRoot()) | ||||
| 	rootCmd.AddCommand(dns.GetRoot()) | ||||
|   | ||||
| @@ -1,23 +0,0 @@ | ||||
| package functions | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
|  | ||||
| 	"github.com/gravitl/netmaker/models" | ||||
| ) | ||||
|  | ||||
| // GetKeys - fetch all access keys of a network | ||||
| func GetKeys(networkName string) *[]models.AccessKey { | ||||
| 	return request[[]models.AccessKey](http.MethodGet, fmt.Sprintf("/api/networks/%s/keys", networkName), nil) | ||||
| } | ||||
|  | ||||
| // CreateKey - create an access key | ||||
| func CreateKey(networkName string, key *models.AccessKey) *models.AccessKey { | ||||
| 	return request[models.AccessKey](http.MethodPost, fmt.Sprintf("/api/networks/%s/keys", networkName), key) | ||||
| } | ||||
|  | ||||
| // DeleteKey - delete an access key | ||||
| func DeleteKey(networkName, keyName string) { | ||||
| 	request[string](http.MethodDelete, fmt.Sprintf("/api/networks/%s/keys/%s", networkName, keyName), nil) | ||||
| } | ||||
| @@ -203,27 +203,6 @@ type networkBodyResponse struct { | ||||
| 	Network models.Network `json:"network"` | ||||
| } | ||||
|  | ||||
| // swagger:parameters createAccessKey | ||||
| type accessKeyBodyParam struct { | ||||
| 	// Access Key | ||||
| 	// in: body | ||||
| 	AccessKey models.AccessKey `json:"access_key"` | ||||
| } | ||||
|  | ||||
| // swagger:response accessKeyBodyResponse | ||||
| type accessKeyBodyResponse struct { | ||||
| 	// Access Key | ||||
| 	// in: body | ||||
| 	AccessKey models.AccessKey `json:"access_key"` | ||||
| } | ||||
|  | ||||
| // swagger:response accessKeySliceBodyResponse | ||||
| type accessKeySliceBodyResponse struct { | ||||
| 	// Access Keys | ||||
| 	// in: body | ||||
| 	AccessKey []models.AccessKey `json:"access_key"` | ||||
| } | ||||
|  | ||||
| // swagger:parameters updateNetworkACL getNetworkACL | ||||
| type aclContainerBodyParam struct { | ||||
| 	// ACL Container | ||||
| @@ -373,9 +352,6 @@ func useUnused() bool { | ||||
| 	_ = networkPathParam{} | ||||
| 	_ = networkAccessKeyNamePathParam{} | ||||
| 	_ = networkBodyResponse{} | ||||
| 	_ = accessKeyBodyParam{} | ||||
| 	_ = accessKeyBodyResponse{} | ||||
| 	_ = accessKeySliceBodyResponse{} | ||||
| 	_ = aclContainerBodyParam{} | ||||
| 	_ = aclContainerResponse{} | ||||
| 	_ = nodeSliceResponse{} | ||||
|   | ||||
| @@ -1,17 +1,7 @@ | ||||
| package controller | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/gorilla/mux" | ||||
| 	"github.com/gravitl/netmaker/database" | ||||
| 	"github.com/gravitl/netmaker/logger" | ||||
| 	"github.com/gravitl/netmaker/logic" | ||||
| 	"github.com/gravitl/netmaker/models" | ||||
| 	"golang.org/x/crypto/bcrypt" | ||||
| ) | ||||
|  | ||||
| // swagger:route PUT /api/nodes/{network}/{nodeid}/migrate nodes migrateNode | ||||
| @@ -26,78 +16,79 @@ import ( | ||||
| //			Responses: | ||||
| //				200: nodeJoinResponse | ||||
| func migrate(w http.ResponseWriter, r *http.Request) { | ||||
| 	// TODO adapt with enrollment-keys or re-think how this works | ||||
| 	// we decode our body request params | ||||
| 	data := models.MigrationData{} | ||||
| 	err := json.NewDecoder(r.Body).Decode(&data) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, r.Header.Get("user"), "error decoding request body: ", err.Error()) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 		return | ||||
| 	} | ||||
| 	params := mux.Vars(r) | ||||
| 	//check authorization | ||||
| 	record, err := database.FetchRecord(database.NODES_TABLE_NAME, data.LegacyNodeID) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, "no record for legacy node", data.LegacyNodeID, err.Error()) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 		return | ||||
| 	} | ||||
| 	var legacyNode models.LegacyNode | ||||
| 	if err = json.Unmarshal([]byte(record), &legacyNode); err != nil { | ||||
| 		logger.Log(0, "error decoding legacy node", err.Error()) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 		return | ||||
| 	} | ||||
| 	if err := bcrypt.CompareHashAndPassword([]byte(legacyNode.Password), []byte(data.Password)); err != nil { | ||||
| 		logger.Log(0, "error decoding legacy password", err.Error()) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "unauthorized")) | ||||
| 		return | ||||
| 	} | ||||
| 	network, err := logic.GetNetwork(params["network"]) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, "error retrieving network:  ", err.Error()) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 		return | ||||
| 	} | ||||
| 	key, err := logic.CreateAccessKey(models.AccessKey{}, network) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, "error creating key:  ", err.Error()) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 		return | ||||
| 	} | ||||
| 	data.JoinData.Key = key.Value | ||||
| 	payload, err := json.Marshal(data.JoinData) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, "error encoding data:  ", err.Error()) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 		return | ||||
| 	} | ||||
| 	r.Body = io.NopCloser(strings.NewReader(string(payload))) | ||||
| 	r.ContentLength = int64(len(string(payload))) | ||||
| 	logger.Log(3, "deleteing legacy node", data.LegacyNodeID, legacyNode.ID, legacyNode.Name) | ||||
| 	if err := database.DeleteRecord(database.NODES_TABLE_NAME, data.LegacyNodeID); err != nil { | ||||
| 		logger.Log(0, "error deleting legacy node", legacyNode.Name, err.Error()) | ||||
| 	} | ||||
| 	createNode(w, r) | ||||
| 	//newly created node has same node id as legacy node allowing using legacyNode.ID in gateway creation | ||||
| 	logger.Log(3, "re-creating legacy gateways") | ||||
| 	if legacyNode.IsIngressGateway == "yes" { | ||||
| 		if _, err := logic.CreateIngressGateway(legacyNode.Network, legacyNode.ID, false); err != nil { | ||||
| 			logger.Log(0, "error creating ingress gateway during migration", err.Error()) | ||||
| 		} | ||||
| 	} | ||||
| 	if legacyNode.IsEgressGateway == "yes" { | ||||
| 		if _, err := logic.CreateEgressGateway(legacyNode.EgressGatewayRequest); err != nil { | ||||
| 			logger.Log(0, "error creating egress gateway during migration", err.Error()) | ||||
| 		} | ||||
| 	} | ||||
| 	if legacyNode.IsRelay == "yes" { | ||||
| 		if _, _, err := logic.CreateRelay(models.RelayRequest{ | ||||
| 			NodeID:     legacyNode.ID, | ||||
| 			NetID:      legacyNode.Network, | ||||
| 			RelayAddrs: legacyNode.RelayAddrs, | ||||
| 		}); err != nil { | ||||
| 			logger.Log(0, "error creating relay during migration", err.Error()) | ||||
| 		} | ||||
| 	} | ||||
| 	// data := models.MigrationData{} | ||||
| 	// err := json.NewDecoder(r.Body).Decode(&data) | ||||
| 	// if err != nil { | ||||
| 	// 	logger.Log(0, r.Header.Get("user"), "error decoding request body: ", err.Error()) | ||||
| 	// 	logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 	// 	return | ||||
| 	// } | ||||
| 	// params := mux.Vars(r) | ||||
| 	// //check authorization | ||||
| 	// record, err := database.FetchRecord(database.NODES_TABLE_NAME, data.LegacyNodeID) | ||||
| 	// if err != nil { | ||||
| 	// 	logger.Log(0, "no record for legacy node", data.LegacyNodeID, err.Error()) | ||||
| 	// 	logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 	// 	return | ||||
| 	// } | ||||
| 	// var legacyNode models.LegacyNode | ||||
| 	// if err = json.Unmarshal([]byte(record), &legacyNode); err != nil { | ||||
| 	// 	logger.Log(0, "error decoding legacy node", err.Error()) | ||||
| 	// 	logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 	// 	return | ||||
| 	// } | ||||
| 	// if err := bcrypt.CompareHashAndPassword([]byte(legacyNode.Password), []byte(data.Password)); err != nil { | ||||
| 	// 	logger.Log(0, "error decoding legacy password", err.Error()) | ||||
| 	// 	logic.ReturnErrorResponse(w, r, logic.FormatError(err, "unauthorized")) | ||||
| 	// 	return | ||||
| 	// } | ||||
| 	// network, err := logic.GetNetwork(params["network"]) | ||||
| 	// if err != nil { | ||||
| 	// 	logger.Log(0, "error retrieving network:  ", err.Error()) | ||||
| 	// 	logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 	// 	return | ||||
| 	// } | ||||
| 	// key, err := logic.CreateAccessKey(models.AccessKey{}, network) | ||||
| 	// if err != nil { | ||||
| 	// 	logger.Log(0, "error creating key:  ", err.Error()) | ||||
| 	// 	logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 	// 	return | ||||
| 	// } | ||||
| 	// data.JoinData.Key = key.Value | ||||
| 	// payload, err := json.Marshal(data.JoinData) | ||||
| 	// if err != nil { | ||||
| 	// 	logger.Log(0, "error encoding data:  ", err.Error()) | ||||
| 	// 	logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 	// 	return | ||||
| 	// } | ||||
| 	// r.Body = io.NopCloser(strings.NewReader(string(payload))) | ||||
| 	// r.ContentLength = int64(len(string(payload))) | ||||
| 	// logger.Log(3, "deleteing legacy node", data.LegacyNodeID, legacyNode.ID, legacyNode.Name) | ||||
| 	// if err := database.DeleteRecord(database.NODES_TABLE_NAME, data.LegacyNodeID); err != nil { | ||||
| 	// 	logger.Log(0, "error deleting legacy node", legacyNode.Name, err.Error()) | ||||
| 	// } | ||||
| 	// // createNode(w, r) should not have been tied to another handler func | ||||
| 	// //newly created node has same node id as legacy node allowing using legacyNode.ID in gateway creation | ||||
| 	// logger.Log(3, "re-creating legacy gateways") | ||||
| 	// if legacyNode.IsIngressGateway == "yes" { | ||||
| 	// 	if _, err := logic.CreateIngressGateway(legacyNode.Network, legacyNode.ID, false); err != nil { | ||||
| 	// 		logger.Log(0, "error creating ingress gateway during migration", err.Error()) | ||||
| 	// 	} | ||||
| 	// } | ||||
| 	// if legacyNode.IsEgressGateway == "yes" { | ||||
| 	// 	if _, err := logic.CreateEgressGateway(legacyNode.EgressGatewayRequest); err != nil { | ||||
| 	// 		logger.Log(0, "error creating egress gateway during migration", err.Error()) | ||||
| 	// 	} | ||||
| 	// } | ||||
| 	// if legacyNode.IsRelay == "yes" { | ||||
| 	// 	if _, _, err := logic.CreateRelay(models.RelayRequest{ | ||||
| 	// 		NodeID:     legacyNode.ID, | ||||
| 	// 		NetID:      legacyNode.Network, | ||||
| 	// 		RelayAddrs: legacyNode.RelayAddrs, | ||||
| 	// 	}); err != nil { | ||||
| 	// 		logger.Log(0, "error creating relay during migration", err.Error()) | ||||
| 	// 	} | ||||
| 	// } | ||||
| } | ||||
|   | ||||
| @@ -25,9 +25,6 @@ func networkHandlers(r *mux.Router) { | ||||
| 	r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(false, http.HandlerFunc(updateNetwork))).Methods(http.MethodPut) | ||||
| 	r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(true, http.HandlerFunc(deleteNetwork))).Methods(http.MethodDelete) | ||||
| 	r.HandleFunc("/api/networks/{networkname}/keyupdate", logic.SecurityCheck(true, http.HandlerFunc(keyUpdate))).Methods(http.MethodPost) | ||||
| 	r.HandleFunc("/api/networks/{networkname}/keys", logic.SecurityCheck(false, http.HandlerFunc(createAccessKey))).Methods(http.MethodPost) | ||||
| 	r.HandleFunc("/api/networks/{networkname}/keys", logic.SecurityCheck(false, http.HandlerFunc(getAccessKeys))).Methods(http.MethodGet) | ||||
| 	r.HandleFunc("/api/networks/{networkname}/keys/{name}", logic.SecurityCheck(false, http.HandlerFunc(deleteAccessKey))).Methods(http.MethodDelete) | ||||
| 	// ACLs | ||||
| 	r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(updateNetworkACL))).Methods(http.MethodPut) | ||||
| 	r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(getNetworkACL))).Methods(http.MethodGet) | ||||
| @@ -72,12 +69,6 @@ func getNetworks(w http.ResponseWriter, r *http.Request) { | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if !servercfg.IsDisplayKeys() { | ||||
| 		for i, net := range allnetworks { | ||||
| 			net.AccessKeys = logic.RemoveKeySensitiveInfo(net.AccessKeys) | ||||
| 			allnetworks[i] = net | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	logger.Log(2, r.Header.Get("user"), "fetched networks.") | ||||
| 	w.WriteHeader(http.StatusOK) | ||||
| @@ -107,9 +98,7 @@ func getNetwork(w http.ResponseWriter, r *http.Request) { | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 		return | ||||
| 	} | ||||
| 	if !servercfg.IsDisplayKeys() { | ||||
| 		network.AccessKeys = logic.RemoveKeySensitiveInfo(network.AccessKeys) | ||||
| 	} | ||||
|  | ||||
| 	logger.Log(2, r.Header.Get("user"), "fetched network", netname) | ||||
| 	w.WriteHeader(http.StatusOK) | ||||
| 	json.NewEncoder(w).Encode(network) | ||||
| @@ -426,117 +415,3 @@ func createNetwork(w http.ResponseWriter, r *http.Request) { | ||||
| 	w.WriteHeader(http.StatusOK) | ||||
| 	json.NewEncoder(w).Encode(network) | ||||
| } | ||||
|  | ||||
| // swagger:route POST /api/networks/{networkname}/keys networks createAccessKey | ||||
| // | ||||
| // Create a network access key. | ||||
| // | ||||
| //			Schemes: https | ||||
| // | ||||
| //			Security: | ||||
| //	  		oauth | ||||
| // | ||||
| //			Responses: | ||||
| //				200: accessKeyBodyResponse | ||||
| // | ||||
| // BEGIN KEY MANAGEMENT SECTION | ||||
| func createAccessKey(w http.ResponseWriter, r *http.Request) { | ||||
| 	w.Header().Set("Content-Type", "application/json") | ||||
| 	var params = mux.Vars(r) | ||||
| 	var accesskey models.AccessKey | ||||
| 	// start here | ||||
| 	netname := params["networkname"] | ||||
| 	network, err := logic.GetParentNetwork(netname) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, r.Header.Get("user"), "failed to get network info: ", | ||||
| 			err.Error()) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 		return | ||||
| 	} | ||||
| 	err = json.NewDecoder(r.Body).Decode(&accesskey) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, r.Header.Get("user"), "error decoding request body: ", | ||||
| 			err.Error()) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 		return | ||||
| 	} | ||||
| 	key, err := logic.CreateAccessKey(accesskey, network) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, r.Header.Get("user"), "failed to create access key: ", | ||||
| 			err.Error()) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// do not allow access key creations view API with user names | ||||
| 	if _, err = logic.GetUser(key.Name); err == nil { | ||||
| 		logger.Log(0, "access key creation with invalid name attempted by", r.Header.Get("user")) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("cannot create access key with user name"), "badrequest")) | ||||
| 		logic.DeleteKey(key.Name, network.NetID) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	logger.Log(1, r.Header.Get("user"), "created access key", accesskey.Name, "on", netname) | ||||
| 	w.WriteHeader(http.StatusOK) | ||||
| 	json.NewEncoder(w).Encode(key) | ||||
| } | ||||
|  | ||||
| // swagger:route GET /api/networks/{networkname}/keys networks getAccessKeys | ||||
| // | ||||
| // Get network access keys for a network. | ||||
| // | ||||
| //			Schemes: https | ||||
| // | ||||
| //			Security: | ||||
| //	  		oauth | ||||
| // | ||||
| //			Responses: | ||||
| //				200: accessKeySliceBodyResponse | ||||
| func getAccessKeys(w http.ResponseWriter, r *http.Request) { | ||||
| 	w.Header().Set("Content-Type", "application/json") | ||||
| 	var params = mux.Vars(r) | ||||
| 	network := params["networkname"] | ||||
| 	keys, err := logic.GetKeys(network) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, r.Header.Get("user"), fmt.Sprintf("failed to get keys for network [%s]: %v", | ||||
| 			network, err)) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 		return | ||||
| 	} | ||||
| 	if !servercfg.IsDisplayKeys() { | ||||
| 		keys = logic.RemoveKeySensitiveInfo(keys) | ||||
| 	} | ||||
| 	logger.Log(2, r.Header.Get("user"), "fetched access keys on network", network) | ||||
| 	w.WriteHeader(http.StatusOK) | ||||
| 	json.NewEncoder(w).Encode(keys) | ||||
| } | ||||
|  | ||||
| // swagger:route DELETE /api/networks/{networkname}/keys/{name} networks deleteAccessKey | ||||
| // | ||||
| // Delete a network access key. | ||||
| // | ||||
| //			Schemes: https | ||||
| // | ||||
| //			Security: | ||||
| //	  		oauth | ||||
| // | ||||
| //			Responses: | ||||
| //				200: | ||||
| //				*: stringJSONResponse | ||||
| // | ||||
| // delete key. Has to do a little funky logic since it's not a collection item | ||||
| func deleteAccessKey(w http.ResponseWriter, r *http.Request) { | ||||
| 	w.Header().Set("Content-Type", "application/json") | ||||
| 	var params = mux.Vars(r) | ||||
| 	keyname := params["name"] | ||||
| 	netname := params["networkname"] | ||||
| 	err := logic.DeleteKey(keyname, netname) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, r.Header.Get("user"), fmt.Sprintf("failed to delete key [%s] for network [%s]: %v", | ||||
| 			keyname, netname, err)) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 		return | ||||
| 	} | ||||
| 	logger.Log(1, r.Header.Get("user"), "deleted access key", keyname, "on network,", netname) | ||||
| 	w.WriteHeader(http.StatusOK) | ||||
| } | ||||
|   | ||||
| @@ -84,118 +84,6 @@ func TestDeleteNetwork(t *testing.T) { | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestCreateKey(t *testing.T) { | ||||
| 	createNet() | ||||
| 	keys, _ := logic.GetKeys("skynet") | ||||
| 	for _, key := range keys { | ||||
| 		logic.DeleteKey(key.Name, "skynet") | ||||
| 	} | ||||
| 	var accesskey models.AccessKey | ||||
| 	var network models.Network | ||||
| 	network.NetID = "skynet" | ||||
| 	t.Run("NameTooLong", func(t *testing.T) { | ||||
| 		network, err := logic.GetNetwork("skynet") | ||||
| 		assert.Nil(t, err) | ||||
| 		accesskey.Name = "ThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfailThisisareallylongkeynamethatwillfail" | ||||
| 		_, err = logic.CreateAccessKey(accesskey, network) | ||||
| 		assert.NotNil(t, err) | ||||
| 		assert.Contains(t, err.Error(), "Field validation for 'Name' failed on the 'max' tag") | ||||
| 	}) | ||||
| 	t.Run("BlankName", func(t *testing.T) { | ||||
| 		network, err := logic.GetNetwork("skynet") | ||||
| 		assert.Nil(t, err) | ||||
| 		accesskey.Name = "" | ||||
| 		key, err := logic.CreateAccessKey(accesskey, network) | ||||
| 		assert.Nil(t, err) | ||||
| 		assert.NotEqual(t, "", key.Name) | ||||
| 	}) | ||||
| 	t.Run("InvalidValue", func(t *testing.T) { | ||||
| 		network, err := logic.GetNetwork("skynet") | ||||
| 		assert.Nil(t, err) | ||||
| 		accesskey.Value = "bad-value" | ||||
| 		_, err = logic.CreateAccessKey(accesskey, network) | ||||
| 		assert.NotNil(t, err) | ||||
| 		assert.Contains(t, err.Error(), "Field validation for 'Value' failed on the 'alphanum' tag") | ||||
| 	}) | ||||
| 	t.Run("BlankValue", func(t *testing.T) { | ||||
| 		network, err := logic.GetNetwork("skynet") | ||||
| 		assert.Nil(t, err) | ||||
| 		accesskey.Name = "mykey" | ||||
| 		accesskey.Value = "" | ||||
| 		key, err := logic.CreateAccessKey(accesskey, network) | ||||
| 		assert.Nil(t, err) | ||||
| 		assert.NotEqual(t, "", key.Value) | ||||
| 		assert.Equal(t, accesskey.Name, key.Name) | ||||
| 	}) | ||||
| 	t.Run("ValueTooLong", func(t *testing.T) { | ||||
| 		network, err := logic.GetNetwork("skynet") | ||||
| 		assert.Nil(t, err) | ||||
| 		accesskey.Name = "keyname" | ||||
| 		accesskey.Value = "AccessKeyValuethatistoolong" | ||||
| 		_, err = logic.CreateAccessKey(accesskey, network) | ||||
| 		assert.NotNil(t, err) | ||||
| 		assert.Contains(t, err.Error(), "Field validation for 'Value' failed on the 'max' tag") | ||||
| 	}) | ||||
| 	t.Run("BlankUses", func(t *testing.T) { | ||||
| 		network, err := logic.GetNetwork("skynet") | ||||
| 		assert.Nil(t, err) | ||||
| 		accesskey.Uses = 0 | ||||
| 		accesskey.Value = "" | ||||
| 		key, err := logic.CreateAccessKey(accesskey, network) | ||||
| 		assert.Nil(t, err) | ||||
| 		assert.Equal(t, 1, key.Uses) | ||||
| 	}) | ||||
| 	t.Run("DuplicateKey", func(t *testing.T) { | ||||
| 		network, err := logic.GetNetwork("skynet") | ||||
| 		assert.Nil(t, err) | ||||
| 		accesskey.Name = "mykey" | ||||
| 		_, err = logic.CreateAccessKey(accesskey, network) | ||||
| 		assert.NotNil(t, err) | ||||
| 		assert.EqualError(t, err, "duplicate AccessKey Name") | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestGetKeys(t *testing.T) { | ||||
| 	deleteAllNetworks() | ||||
| 	createNet() | ||||
| 	network, err := logic.GetNetwork("skynet") | ||||
| 	assert.Nil(t, err) | ||||
| 	var key models.AccessKey | ||||
| 	key.Name = "mykey" | ||||
| 	_, err = logic.CreateAccessKey(key, network) | ||||
| 	assert.Nil(t, err) | ||||
| 	t.Run("KeyExists", func(t *testing.T) { | ||||
| 		keys, err := logic.GetKeys(network.NetID) | ||||
| 		assert.Nil(t, err) | ||||
| 		assert.NotEqual(t, models.AccessKey{}, keys) | ||||
| 	}) | ||||
| 	t.Run("NonExistantKey", func(t *testing.T) { | ||||
| 		err := logic.DeleteKey("mykey", "skynet") | ||||
| 		assert.Nil(t, err) | ||||
| 		keys, err := logic.GetKeys(network.NetID) | ||||
| 		assert.Nil(t, err) | ||||
| 		assert.Equal(t, []models.AccessKey(nil), keys) | ||||
| 	}) | ||||
| } | ||||
| func TestDeleteKey(t *testing.T) { | ||||
| 	createNet() | ||||
| 	network, err := logic.GetNetwork("skynet") | ||||
| 	assert.Nil(t, err) | ||||
| 	var key models.AccessKey | ||||
| 	key.Name = "mykey" | ||||
| 	_, err = logic.CreateAccessKey(key, network) | ||||
| 	assert.Nil(t, err) | ||||
| 	t.Run("ExistingKey", func(t *testing.T) { | ||||
| 		err := logic.DeleteKey("mykey", "skynet") | ||||
| 		assert.Nil(t, err) | ||||
| 	}) | ||||
| 	t.Run("NonExistantKey", func(t *testing.T) { | ||||
| 		err := logic.DeleteKey("mykey", "skynet") | ||||
| 		assert.NotNil(t, err) | ||||
| 		assert.Equal(t, "key mykey does not exist", err.Error()) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestSecurityCheck(t *testing.T) { | ||||
| 	//these seem to work but not sure it the tests are really testing the functionality | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,6 @@ package controller | ||||
| import ( | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
| @@ -35,7 +34,6 @@ func nodeHandlers(r *mux.Router) { | ||||
| 	r.HandleFunc("/api/nodes/{network}/{nodeid}/createingress", logic.SecurityCheck(false, http.HandlerFunc(createIngressGateway))).Methods(http.MethodPost) | ||||
| 	r.HandleFunc("/api/nodes/{network}/{nodeid}/deleteingress", logic.SecurityCheck(false, http.HandlerFunc(deleteIngressGateway))).Methods(http.MethodDelete) | ||||
| 	r.HandleFunc("/api/nodes/{network}/{nodeid}", authorize(true, true, "node", http.HandlerFunc(updateNode))).Methods(http.MethodPost) | ||||
| 	r.HandleFunc("/api/nodes/{network}", nodeauth(checkFreeTierLimits(node_l, http.HandlerFunc(createNode)))).Methods(http.MethodPost) | ||||
| 	r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods(http.MethodPost) | ||||
| } | ||||
|  | ||||
| @@ -147,52 +145,6 @@ func authenticate(response http.ResponseWriter, request *http.Request) { | ||||
| 	response.Write(successJSONResponse) | ||||
| } | ||||
|  | ||||
| // auth middleware for api calls from nodes where node is has not yet joined the server (register, join) | ||||
| func nodeauth(next http.Handler) http.HandlerFunc { | ||||
| 	return func(w http.ResponseWriter, r *http.Request) { | ||||
| 		bearerToken := r.Header.Get("Authorization") | ||||
| 		var tokenSplit = strings.Split(bearerToken, " ") | ||||
| 		var token = "" | ||||
| 		if len(tokenSplit) < 2 { | ||||
| 			errorResponse := models.ErrorResponse{ | ||||
| 				Code: http.StatusUnauthorized, Message: "W1R3: You are unauthorized to access this endpoint.", | ||||
| 			} | ||||
| 			logic.ReturnErrorResponse(w, r, errorResponse) | ||||
| 			return | ||||
| 		} else { | ||||
| 			token = tokenSplit[1] | ||||
| 		} | ||||
| 		found := false | ||||
| 		networks, err := logic.GetNetworks() | ||||
| 		if err != nil { | ||||
| 			logger.Log(0, "no networks", err.Error()) | ||||
| 			errorResponse := models.ErrorResponse{ | ||||
| 				Code: http.StatusNotFound, Message: "no networks", | ||||
| 			} | ||||
| 			logic.ReturnErrorResponse(w, r, errorResponse) | ||||
| 			return | ||||
| 		} | ||||
| 		for _, network := range networks { | ||||
| 			for _, key := range network.AccessKeys { | ||||
| 				if key.Value == token { | ||||
| 					found = true | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		if !found { | ||||
| 			logger.Log(0, "valid access key not found") | ||||
| 			errorResponse := models.ErrorResponse{ | ||||
| 				Code: http.StatusUnauthorized, Message: "You are unauthorized to access this endpoint.", | ||||
| 			} | ||||
| 			logic.ReturnErrorResponse(w, r, errorResponse) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		next.ServeHTTP(w, r) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // The middleware for most requests to the API | ||||
| // They all pass  through here first | ||||
| // This will validate the JWT (or check for master token) | ||||
| @@ -462,218 +414,6 @@ func getNode(w http.ResponseWriter, r *http.Request) { | ||||
| 	json.NewEncoder(w).Encode(response) | ||||
| } | ||||
|  | ||||
| // swagger:route POST /api/nodes/{network} nodes createNode | ||||
| // | ||||
| // Create a node on a network. | ||||
| // | ||||
| //			Schemes: https | ||||
| // | ||||
| //			Security: | ||||
| //	  		oauth | ||||
| // | ||||
| //			Responses: | ||||
| //				200: nodeGetResponse | ||||
| func createNode(w http.ResponseWriter, r *http.Request) { | ||||
| 	w.Header().Set("Content-Type", "application/json") | ||||
|  | ||||
| 	var params = mux.Vars(r) | ||||
|  | ||||
| 	var errorResponse = models.ErrorResponse{ | ||||
| 		Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.", | ||||
| 	} | ||||
| 	networkName := params["network"] | ||||
| 	networkexists, err := logic.NetworkExists(networkName) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, r.Header.Get("user"), | ||||
| 			fmt.Sprintf("failed to fetch network [%s] info: %v", networkName, err)) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 		return | ||||
| 	} else if !networkexists { | ||||
| 		errorResponse = models.ErrorResponse{ | ||||
| 			Code: http.StatusNotFound, Message: "W1R3: Network does not exist! ", | ||||
| 		} | ||||
| 		logger.Log(0, r.Header.Get("user"), | ||||
| 			fmt.Sprintf("network [%s] does not exist", networkName)) | ||||
| 		logic.ReturnErrorResponse(w, r, errorResponse) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	//get data from body of request | ||||
| 	data := models.JoinData{} | ||||
| 	err = json.NewDecoder(r.Body).Decode(&data) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, r.Header.Get("user"), "error decoding request body: ", err.Error()) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if !logic.IsVersionComptatible(data.Host.Version) { | ||||
| 		err := errors.New("incompatible netclient version") | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	data.Node.Network = networkName | ||||
|  | ||||
| 	networkSettings, err := logic.GetNetworkSettings(networkName) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, r.Header.Get("user"), | ||||
| 			fmt.Sprintf("failed to get network [%s] settings: %v", networkName, err)) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 		return | ||||
| 	} | ||||
| 	data.Node.NetworkSettings(networkSettings) | ||||
| 	keyName, validKey := logic.IsKeyValid(networkName, data.Key) | ||||
| 	if !validKey { | ||||
| 		errorResponse = models.ErrorResponse{ | ||||
| 			Code: http.StatusUnauthorized, Message: "W1R3: Key invalid, or none provided.", | ||||
| 		} | ||||
| 		logger.Log(0, r.Header.Get("user"), | ||||
| 			fmt.Sprintf("failed to create node on network [%s]: %s", | ||||
| 				data.Node.Network, errorResponse.Message)) | ||||
| 		logic.ReturnErrorResponse(w, r, errorResponse) | ||||
| 		return | ||||
| 	} | ||||
| 	logic.DecrimentKey(networkName, data.Key) | ||||
| 	user, err := pro.GetNetworkUser(networkName, promodels.NetworkUserID(keyName)) | ||||
| 	if err == nil { | ||||
| 		if user.ID != "" { | ||||
| 			logger.Log(1, "associating new node with user", keyName) | ||||
| 			data.Node.OwnerID = string(user.ID) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	key, keyErr := logic.RetrievePublicTrafficKey() | ||||
| 	if keyErr != nil { | ||||
| 		logger.Log(0, "error retrieving key: ", keyErr.Error()) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 		return | ||||
| 	} | ||||
| 	if key == nil { | ||||
| 		logger.Log(0, "error: server traffic key is nil") | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 		return | ||||
| 	} | ||||
| 	if data.Host.TrafficKeyPublic == nil { | ||||
| 		logger.Log(0, "error: node traffic key is nil") | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 		return | ||||
| 	} | ||||
| 	server := servercfg.GetServerInfo() | ||||
| 	server.TrafficKey = key | ||||
| 	data.Node.Server = servercfg.GetServer() | ||||
| 	if !logic.HostExists(&data.Host) { | ||||
| 		logic.CheckHostPorts(&data.Host) | ||||
| 		if servercfg.GetBrokerType() == servercfg.EmqxBrokerType { | ||||
| 			// create EMQX credentials for host if it doesn't exists | ||||
| 			if err := mq.CreateEmqxUser(data.Host.ID.String(), data.Host.HostPass, false); err != nil { | ||||
| 				logger.Log(0, "failed to add host credentials to EMQX: ", data.Host.ID.String(), err.Error()) | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	if err := logic.CreateHost(&data.Host); err != nil { | ||||
| 		if errors.Is(err, logic.ErrHostExists) { | ||||
| 			logger.Log(3, "host exists .. no need to create") | ||||
| 			host, err := logic.GetHost(data.Host.ID.String()) | ||||
| 			if err != nil { | ||||
| 				logger.Log(0, r.Header.Get("user"), "failed to find host:", err.Error()) | ||||
| 				logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 				return | ||||
| 			} | ||||
| 			logic.UpdateHostFromClient(&data.Host, host) // update the in memory struct values | ||||
| 			err = logic.UpsertHost(host) | ||||
| 			if err != nil { | ||||
| 				logger.Log(0, r.Header.Get("user"), | ||||
| 					fmt.Sprintf("failed to update host [ %s ]: %v", host.ID.String(), err)) | ||||
| 				logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 				return | ||||
| 			} | ||||
| 			data.Host = *host | ||||
| 		} else { | ||||
| 			logger.Log(0, "error creating host", err.Error()) | ||||
| 			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest")) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	err = logic.AssociateNodeToHost(&data.Node, &data.Host) | ||||
| 	if err != nil { | ||||
| 		logger.Log(0, r.Header.Get("user"), | ||||
| 			fmt.Sprintf("failed to create node on network [%s]: %s", | ||||
| 				networkName, err)) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// check if key belongs to a user | ||||
| 	// if so add to their netuser data | ||||
| 	// if it fails remove the node and fail request | ||||
| 	if user != nil { | ||||
| 		var updatedUserNode bool | ||||
| 		user.Nodes = append(user.Nodes, data.Node.ID.String()) // add new node to user | ||||
| 		if err = pro.UpdateNetworkUser(networkName, user); err == nil { | ||||
| 			logger.Log(1, "added node", data.Node.ID.String(), data.Host.Name, "to user", string(user.ID)) | ||||
| 			updatedUserNode = true | ||||
| 		} | ||||
| 		if !updatedUserNode { // user was found but not updated, so delete node | ||||
| 			logger.Log(0, "failed to add node to user", keyName) | ||||
| 			logic.DeleteNode(&data.Node, true) | ||||
| 			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	hostPeerUpdate, err := logic.GetPeerUpdateForHost(context.Background(), networkName, &data.Host, nil) | ||||
| 	if err != nil && !database.IsEmptyRecord(err) { | ||||
| 		logger.Log(0, r.Header.Get("user"), | ||||
| 			fmt.Sprintf("error fetching wg peers config for host [ %s ]: %v", data.Host.ID.String(), err)) | ||||
| 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) | ||||
| 		return | ||||
| 	} | ||||
| 	data.Host.HostPass = "" // client should not change password after join | ||||
| 	// concealing hash | ||||
| 	response := models.NodeJoinResponse{ | ||||
| 		Node:         data.Node, | ||||
| 		ServerConfig: server, | ||||
| 		Host:         data.Host, | ||||
| 		Peers:        hostPeerUpdate.Peers, | ||||
| 	} | ||||
| 	logger.Log(1, r.Header.Get("user"), "created new node", data.Host.Name, data.Node.ID.String(), "on network", networkName) | ||||
| 	w.WriteHeader(http.StatusOK) | ||||
| 	json.NewEncoder(w).Encode(response) | ||||
|  | ||||
| 	go func() { | ||||
| 		if err := mq.PublishPeerUpdate(); err != nil { | ||||
| 			logger.Log(1, "failed a peer update after creation of node", data.Host.Name) | ||||
| 		} | ||||
| 	}() | ||||
| 	//runForceServerUpdate(&data.Node, true) | ||||
| 	go func() { | ||||
| 		dns := models.DNSUpdate{ | ||||
| 			Action: models.DNSInsert, | ||||
| 			Name:   data.Host.Name + "." + data.Node.Network, | ||||
| 		} | ||||
| 		if data.Node.Address.IP != nil { | ||||
| 			dns.Address = data.Node.Address.IP.String() | ||||
| 			//publish new node dns entry to all nodes on network | ||||
| 			if err := mq.PublishDNSUpdate(data.Node.Network, dns); err != nil { | ||||
| 				logger.Log(1, "failed to publish dns update on node creation", err.Error()) | ||||
| 			} | ||||
| 		} | ||||
| 		if data.Node.Address6.IP != nil { | ||||
| 			dns.Address = data.Node.Address6.IP.String() | ||||
| 			//publish new node dns entry to all nodes on network | ||||
| 			if err := mq.PublishDNSUpdate(data.Node.Network, dns); err != nil { | ||||
| 				logger.Log(1, "failed to publish dns update on node creation", err.Error()) | ||||
| 			} | ||||
| 		} | ||||
| 		//publish add dns records for network to new node | ||||
| 		if err := mq.PublishAllDNS(&data.Node); err != nil { | ||||
| 			logger.Log(1, "failed to publish dns update on node creation", err.Error()) | ||||
| 		} | ||||
| 	}() | ||||
| } | ||||
|  | ||||
| // == EGRESS == | ||||
|  | ||||
| // swagger:route POST /api/nodes/{network}/{nodeid}/creategateway nodes createEgressGateway | ||||
|   | ||||
| @@ -467,5 +467,5 @@ func socketHandler(w http.ResponseWriter, r *http.Request) { | ||||
| 		return | ||||
| 	} | ||||
| 	// Start handling the session | ||||
| 	go auth.SessionHandler(conn) | ||||
| 	// go auth.SessionHandler(conn) | ||||
| } | ||||
|   | ||||
| @@ -1,229 +0,0 @@ | ||||
| package logic | ||||
|  | ||||
| import ( | ||||
| 	"crypto/rand" | ||||
| 	"encoding/base64" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"math/big" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
|  | ||||
| 	validator "github.com/go-playground/validator/v10" | ||||
| 	"github.com/gravitl/netmaker/database" | ||||
| 	"github.com/gravitl/netmaker/logger" | ||||
| 	"github.com/gravitl/netmaker/models" | ||||
| 	"github.com/gravitl/netmaker/servercfg" | ||||
| ) | ||||
|  | ||||
| // CreateAccessKey - create access key | ||||
| func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models.AccessKey, error) { | ||||
|  | ||||
| 	if accesskey.Name == "" { | ||||
| 		accesskey.Name = genKeyName() | ||||
| 	} | ||||
|  | ||||
| 	if accesskey.Value == "" { | ||||
| 		accesskey.Value = GenKey() | ||||
| 	} | ||||
| 	if accesskey.Uses == 0 { | ||||
| 		accesskey.Uses = 1 | ||||
| 	} | ||||
|  | ||||
| 	checkkeys, err := GetKeys(network.NetID) | ||||
| 	if err != nil { | ||||
| 		return models.AccessKey{}, errors.New("could not retrieve network keys") | ||||
| 	} | ||||
|  | ||||
| 	for _, key := range checkkeys { | ||||
| 		if key.Name == accesskey.Name { | ||||
| 			return models.AccessKey{}, errors.New("duplicate AccessKey Name") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	netID := network.NetID | ||||
|  | ||||
| 	var accessToken models.AccessToken | ||||
|  | ||||
| 	accessToken.APIConnString = servercfg.GetAPIConnString() | ||||
| 	accessToken.ClientConfig.Network = netID | ||||
| 	accessToken.ClientConfig.Key = accesskey.Value | ||||
|  | ||||
| 	tokenjson, err := json.Marshal(accessToken) | ||||
| 	if err != nil { | ||||
| 		return accesskey, err | ||||
| 	} | ||||
|  | ||||
| 	accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(tokenjson)) | ||||
|  | ||||
| 	//validate accesskey | ||||
| 	v := validator.New() | ||||
| 	err = v.Struct(accesskey) | ||||
| 	if err != nil { | ||||
| 		for _, e := range err.(validator.ValidationErrors) { | ||||
| 			logger.Log(1, "validator", e.Error()) | ||||
| 		} | ||||
| 		return models.AccessKey{}, err | ||||
| 	} | ||||
|  | ||||
| 	network.AccessKeys = append(network.AccessKeys, accesskey) | ||||
| 	data, err := json.Marshal(&network) | ||||
| 	if err != nil { | ||||
| 		return models.AccessKey{}, err | ||||
| 	} | ||||
| 	if err = database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME); err != nil { | ||||
| 		return models.AccessKey{}, err | ||||
| 	} | ||||
|  | ||||
| 	return accesskey, nil | ||||
| } | ||||
|  | ||||
| // DeleteKey - deletes a key | ||||
| func DeleteKey(keyname, netname string) error { | ||||
| 	network, err := GetParentNetwork(netname) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	//basically, turn the list of access keys into the list of access keys before and after the item | ||||
| 	//have not done any error handling for if there's like...1 item. I think it works? need to test. | ||||
| 	found := false | ||||
| 	var updatedKeys []models.AccessKey | ||||
| 	for _, currentkey := range network.AccessKeys { | ||||
| 		if currentkey.Name == keyname { | ||||
| 			found = true | ||||
| 		} else { | ||||
| 			updatedKeys = append(updatedKeys, currentkey) | ||||
| 		} | ||||
| 	} | ||||
| 	if !found { | ||||
| 		return errors.New("key " + keyname + " does not exist") | ||||
| 	} | ||||
| 	network.AccessKeys = updatedKeys | ||||
| 	data, err := json.Marshal(&network) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // GetKeys - fetches keys for network | ||||
| func GetKeys(net string) ([]models.AccessKey, error) { | ||||
|  | ||||
| 	record, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, net) | ||||
| 	if err != nil { | ||||
| 		return []models.AccessKey{}, err | ||||
| 	} | ||||
| 	network, err := ParseNetwork(record) | ||||
| 	if err != nil { | ||||
| 		return []models.AccessKey{}, err | ||||
| 	} | ||||
| 	return network.AccessKeys, nil | ||||
| } | ||||
|  | ||||
| // DecrimentKey - decriments key uses | ||||
| func DecrimentKey(networkName string, keyvalue string) { | ||||
|  | ||||
| 	var network models.Network | ||||
|  | ||||
| 	network, err := GetParentNetwork(networkName) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	for i := len(network.AccessKeys) - 1; i >= 0; i-- { | ||||
|  | ||||
| 		currentkey := network.AccessKeys[i] | ||||
| 		if currentkey.Value == keyvalue { | ||||
| 			network.AccessKeys[i].Uses-- | ||||
| 			if network.AccessKeys[i].Uses < 1 { | ||||
| 				network.AccessKeys = append(network.AccessKeys[:i], | ||||
| 					network.AccessKeys[i+1:]...) | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if newNetworkData, err := json.Marshal(&network); err != nil { | ||||
| 		logger.Log(2, "failed to decrement key") | ||||
| 		return | ||||
| 	} else { | ||||
| 		database.Insert(network.NetID, string(newNetworkData), database.NETWORKS_TABLE_NAME) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // IsKeyValid - check if key is valid | ||||
| func IsKeyValid(networkname string, keyvalue string) (string, bool) { | ||||
|  | ||||
| 	network, err := GetParentNetwork(networkname) | ||||
| 	if err != nil { | ||||
| 		return "", false | ||||
| 	} | ||||
| 	accesskeys := network.AccessKeys | ||||
|  | ||||
| 	var key models.AccessKey | ||||
| 	foundkey := false | ||||
| 	isvalid := false | ||||
|  | ||||
| 	for i := len(accesskeys) - 1; i >= 0; i-- { | ||||
| 		currentkey := accesskeys[i] | ||||
| 		if currentkey.Value == keyvalue { | ||||
| 			key = currentkey | ||||
| 			foundkey = true | ||||
| 		} | ||||
| 	} | ||||
| 	if foundkey { | ||||
| 		if key.Uses > 0 { | ||||
| 			isvalid = true | ||||
| 		} | ||||
| 	} | ||||
| 	return key.Name, isvalid | ||||
| } | ||||
|  | ||||
| // RemoveKeySensitiveInfo - remove sensitive key info | ||||
| func RemoveKeySensitiveInfo(keys []models.AccessKey) []models.AccessKey { | ||||
| 	var returnKeys []models.AccessKey | ||||
| 	for _, key := range keys { | ||||
| 		key.Value = models.PLACEHOLDER_KEY_TEXT | ||||
| 		key.AccessString = models.PLACEHOLDER_TOKEN_TEXT | ||||
| 		returnKeys = append(returnKeys, key) | ||||
| 	} | ||||
| 	return returnKeys | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	maxr string = "ff578f57c15bb743beaa77d27637e02b598dffa9aebd15889187fe6eb3bdca516c3fa1a52eabef31f33b4b8c2e5b5524f1aa4f3329393912f40dbbe23d7f39723e0be05b6696b11f8eea0abe365a11d9f2735ac7e5b4e015ab19b35b84893685b37a9a0a62a566d6571d7e00d4241687f5c804f37cde9bf311c0781f51cc007c5a01a94f6cfcecea640b8e9ab7bd43e73e5df5d0e1eeb4d9b6cc44be67b7cad80808b17869561b579ffe0bbdeca5c83139e458000000000000000000000000000000000000000000000000000000000000000" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	uno        sync.Once | ||||
| 	maxentropy *big.Int | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	uno.Do(func() { | ||||
| 		maxentropy, _ = new(big.Int).SetString(maxr, 16) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // == private methods == | ||||
|  | ||||
| func genKeyName() string { | ||||
| 	entropy, _ := rand.Int(rand.Reader, maxentropy) | ||||
| 	return strings.Join([]string{"key", entropy.Text(16)[:16]}, "-") | ||||
| } | ||||
|  | ||||
| // GenKey - generates random key of length 16 | ||||
| func GenKey() string { | ||||
| 	entropy, _ := rand.Int(rand.Reader, maxentropy) | ||||
| 	return entropy.Text(16)[:16] | ||||
| } | ||||
|  | ||||
| // GenPassWord - generates random password of length 64 | ||||
| func GenPassWord() string { | ||||
| 	entropy, _ := rand.Int(rand.Reader, maxentropy) | ||||
| 	return entropy.Text(62)[:64] | ||||
| } | ||||
| @@ -1,21 +0,0 @@ | ||||
| package logic | ||||
|  | ||||
| import "testing" | ||||
|  | ||||
| func Test_genKeyName(t *testing.T) { | ||||
| 	for i := 0; i < 100; i++ { | ||||
| 		kname := genKeyName() | ||||
| 		if len(kname) != 20 { | ||||
| 			t.Fatalf("improper length of key name, expected 20 got :%d", len(kname)) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func Test_genKey(t *testing.T) { | ||||
| 	for i := 0; i < 100; i++ { | ||||
| 		kname := GenKey() | ||||
| 		if len(kname) != 16 { | ||||
| 			t.Fatalf("improper length of key name, expected 16 got :%d", len(kname)) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -159,7 +159,6 @@ func GetNetworkSettings(networkname string) (models.Network, error) { | ||||
| 	if err = json.Unmarshal([]byte(networkData), &network); err != nil { | ||||
| 		return models.Network{}, err | ||||
| 	} | ||||
| 	network.AccessKeys = []models.AccessKey{} | ||||
| 	return network, nil | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -19,7 +19,6 @@ type Network struct { | ||||
| 	NodeLimit           int32                 `json:"nodelimit" bson:"nodelimit"` | ||||
| 	DefaultPostDown     string                `json:"defaultpostdown" bson:"defaultpostdown"` | ||||
| 	DefaultKeepalive    int32                 `json:"defaultkeepalive" bson:"defaultkeepalive" validate:"omitempty,max=1000"` | ||||
| 	AccessKeys          []AccessKey           `json:"accesskeys" bson:"accesskeys"` | ||||
| 	AllowManualSignUp   string                `json:"allowmanualsignup" bson:"allowmanualsignup" validate:"checkyesorno"` | ||||
| 	IsIPv4              string                `json:"isipv4" bson:"isipv4" validate:"checkyesorno"` | ||||
| 	IsIPv6              string                `json:"isipv6" bson:"isipv6" validate:"checkyesorno"` | ||||
|   | ||||
| @@ -2,7 +2,6 @@ package models | ||||
|  | ||||
| import ( | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	jwt "github.com/golang-jwt/jwt/v4" | ||||
| 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes" | ||||
| @@ -102,15 +101,6 @@ type SuccessResponse struct { | ||||
| 	Response interface{} | ||||
| } | ||||
|  | ||||
| // AccessKey - access key struct | ||||
| type AccessKey struct { | ||||
| 	Name         string     `json:"name" bson:"name" validate:"omitempty,max=345"` | ||||
| 	Value        string     `json:"value" bson:"value" validate:"omitempty,alphanum,max=16"` | ||||
| 	AccessString string     `json:"accessstring" bson:"accessstring"` | ||||
| 	Uses         int        `json:"uses" bson:"uses" validate:"numeric,min=0"` | ||||
| 	Expiration   *time.Time `json:"expiration" bson:"expiration"` | ||||
| } | ||||
|  | ||||
| // DisplayKey - what is displayed for key | ||||
| type DisplayKey struct { | ||||
| 	Name string `json:"name" bson:"name"` | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 0xdcarns
					0xdcarns