Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/gravitl/netmaker into NE…
Browse files Browse the repository at this point in the history
…T-1911
  • Loading branch information
abhishek9686 committed Feb 24, 2025
2 parents 9590f9e + 9a7c13b commit e50da80
Show file tree
Hide file tree
Showing 22 changed files with 328 additions and 40 deletions.
55 changes: 55 additions & 0 deletions cli/cmd/gateway/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package gateway

import (
"github.com/gravitl/netmaker/cli/functions"
"github.com/gravitl/netmaker/models"
"github.com/spf13/cobra"
"strings"
)

var externalClientDNS string
var isInternetGateway bool
var metadata string
var persistentKeepAlive uint
var mtu uint

var gatewayCreateCmd = &cobra.Command{
Use: "create [NETWORK NAME] [NODE ID] [RELAYED NODES ID (comma separated)]",
Args: cobra.ExactArgs(3),
Short: "Create a new Gateway on a Netmaker network.",
Long: `
Configures a node as a gateway in a specified network, allowing it to relay traffic for other nodes. The gateway can also function as an internet gateway if specified.
Arguments:
NETWORK NAME: The name of the network where the gateway will be created.
NODE ID: The ID of the node to be configured as a gateway.
RELAYED NODES ID: A comma-separated list of node IDs that will be relayed through this gateway.
`,
Run: func(cmd *cobra.Command, args []string) {
functions.PrettyPrint(
functions.CreateGateway(
models.IngressRequest{
ExtclientDNS: externalClientDNS,
IsInternetGateway: isInternetGateway,
Metadata: metadata,
PersistentKeepalive: int32(persistentKeepAlive),
MTU: int32(mtu),
},
models.RelayRequest{
NodeID: args[0],
NetID: args[1],
RelayedNodes: strings.Split(args[2], ","),
},
),
)
},
}

func init() {
gatewayCreateCmd.Flags().StringVarP(&externalClientDNS, "dns", "d", "", "the IP address of the DNS server to be used by external clients")
gatewayCreateCmd.Flags().BoolVarP(&isInternetGateway, "internet", "i", false, "if set, the gateway will route traffic to the internet")
gatewayCreateCmd.Flags().StringVarP(&metadata, "note", "n", "", "description or metadata to be associated with the gateway")
gatewayCreateCmd.Flags().UintVarP(&persistentKeepAlive, "keep-alive", "k", 20, "the keep-alive interval (in seconds) for maintaining persistent connections")
gatewayCreateCmd.Flags().UintVarP(&mtu, "mtu", "m", 1420, "the maximum transmission unit (MTU) size in bytes")
rootCmd.AddCommand(gatewayCreateCmd)
}
27 changes: 27 additions & 0 deletions cli/cmd/gateway/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package gateway

import (
"github.com/gravitl/netmaker/cli/functions"
"github.com/spf13/cobra"
)

var gatewayDeleteCmd = &cobra.Command{
Use: "delete [NETWORK NAME] [NODE ID]",
Args: cobra.ExactArgs(2),
Short: "Delete a Gateway.",
Long: `
Removes the gateway configuration from a node in a specified network. The node itself remains, but it will no longer function as a gateway.
Arguments:
NETWORK NAME: The name of the network from which the gateway configuration should be removed.
NODE ID: The ID of the node that is currently acting as a gateway.
`,
Aliases: []string{"rm"},
Run: func(cmd *cobra.Command, args []string) {
functions.PrettyPrint(functions.DeleteGateway(args[0], args[1]))
},
}

func init() {
rootCmd.AddCommand(gatewayDeleteCmd)
}
18 changes: 18 additions & 0 deletions cli/cmd/gateway/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package gateway

import (
"github.com/spf13/cobra"
)

// rootCmd represents the base command when called without any subcommands.
var rootCmd = &cobra.Command{
Use: "gateway",
Short: "Manage Gateways.",
Long: `Manage Gateways.`,
Aliases: []string{"gw"},
}

// GetRoot returns the root subcommand.
func GetRoot() *cobra.Command {
return rootCmd
}
11 changes: 6 additions & 5 deletions cli/cmd/node/create_ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import (
)

var nodeCreateIngressCmd = &cobra.Command{
Use: "create_remote_access_gateway [NETWORK NAME] [NODE ID]",
Args: cobra.ExactArgs(2),
Short: "Turn a Node into a Remote Access Gateway (Ingress)",
Long: `Turn a Node into a Remote Access Gateway (Ingress) for a Network.`,
Aliases: []string{"create_rag"},
Use: "create_remote_access_gateway [NETWORK NAME] [NODE ID]",
Args: cobra.ExactArgs(2),
Short: "Turn a Node into a Remote Access Gateway (Ingress)",
Long: `Turn a Node into a Remote Access Gateway (Ingress) for a Network.`,
Deprecated: "in favour of the `gateway` subcommand, in Netmaker v0.90.0.",
Aliases: []string{"create_rag"},
Run: func(cmd *cobra.Command, args []string) {
functions.PrettyPrint(functions.CreateIngress(args[0], args[1], failover))
},
Expand Down
9 changes: 5 additions & 4 deletions cli/cmd/node/create_relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import (
)

var hostCreateRelayCmd = &cobra.Command{
Use: "create_relay [NETWORK][NODE ID] [RELAYED NODE IDS (comma separated)]",
Args: cobra.ExactArgs(3),
Short: "Turn a Node into a Relay",
Long: `Turn a Node into a Relay`,
Use: "create_relay [NETWORK][NODE ID] [RELAYED NODE IDS (comma separated)]",
Args: cobra.ExactArgs(3),
Short: "Turn a Node into a Relay",
Long: `Turn a Node into a Relay`,
Deprecated: "in favour of the `gateway` subcommand, in Netmaker v0.90.0.",
Run: func(cmd *cobra.Command, args []string) {
functions.PrettyPrint(functions.CreateRelay(args[0], args[1], strings.Split(args[2], ",")))
},
Expand Down
11 changes: 6 additions & 5 deletions cli/cmd/node/delete_ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import (
)

var nodeDeleteIngressCmd = &cobra.Command{
Use: "delete_remote_access_gateway [NETWORK NAME] [NODE ID]",
Args: cobra.ExactArgs(2),
Short: "Delete Remote Access Gateway role from a Node",
Long: `Delete Remote Access Gateway role from a Node`,
Aliases: []string{"delete_rag"},
Use: "delete_remote_access_gateway [NETWORK NAME] [NODE ID]",
Args: cobra.ExactArgs(2),
Short: "Delete Remote Access Gateway role from a Node",
Long: `Delete Remote Access Gateway role from a Node`,
Deprecated: "in favour of the `gateway` subcommand, in Netmaker v0.90.0.",
Aliases: []string{"delete_rag"},
Run: func(cmd *cobra.Command, args []string) {
functions.PrettyPrint(functions.DeleteIngress(args[0], args[1]))
},
Expand Down
9 changes: 5 additions & 4 deletions cli/cmd/node/delete_relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import (
)

var hostDeleteRelayCmd = &cobra.Command{
Use: "delete_relay [NETWORK] [NODE ID]",
Args: cobra.ExactArgs(2),
Short: "Delete Relay from a node",
Long: `Delete Relay from a node`,
Use: "delete_relay [NETWORK] [NODE ID]",
Args: cobra.ExactArgs(2),
Short: "Delete Relay from a node",
Long: `Delete Relay from a node`,
Deprecated: "in favour of the `gateway` subcommand, in Netmaker v0.90.0.",
Run: func(cmd *cobra.Command, args []string) {
functions.PrettyPrint(functions.DeleteRelay(args[0], args[1]))
},
Expand Down
2 changes: 2 additions & 0 deletions cli/cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"github.com/gravitl/netmaker/cli/cmd/gateway"
"os"

"github.com/gravitl/netmaker/cli/cmd/acl"
Expand Down Expand Up @@ -55,4 +56,5 @@ func init() {
rootCmd.AddCommand(host.GetRoot())
rootCmd.AddCommand(enrollment_key.GetRoot())
rootCmd.AddCommand(failover.GetRoot())
rootCmd.AddCommand(gateway.GetRoot())
}
18 changes: 18 additions & 0 deletions cli/functions/gateway.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package functions

import (
"fmt"
"github.com/gravitl/netmaker/models"
"net/http"
)

func CreateGateway(ingressRequest models.IngressRequest, relayRequest models.RelayRequest) *models.ApiNode {
return request[models.ApiNode](http.MethodPost, fmt.Sprintf("/api/nodes/%s/%s/gateway", relayRequest.NetID, relayRequest.NodeID), &models.CreateGwReq{
IngressRequest: ingressRequest,
RelayRequest: relayRequest,
})
}

func DeleteGateway(networkID, nodeID string) *models.ApiNode {
return request[models.ApiNode](http.MethodDelete, fmt.Sprintf("/api/nodes/%s/%s/gateway", networkID, nodeID), nil)
}
1 change: 1 addition & 0 deletions controllers/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ func deleteNetwork(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, errtype))
return
}
go logic.UnlinkNetworkAndTagsFromEnrollmentKeys(network, true)
go logic.DeleteNetworkRoles(network)
go logic.DeleteDefaultNetworkPolicies(models.NetworkID(network))
//delete network from allocated ip map
Expand Down
51 changes: 49 additions & 2 deletions controllers/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func nodeHandlers(r *mux.Router) {
r.HandleFunc("/api/nodes/{network}/{nodeid}/createingress", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceIngress, http.HandlerFunc(createGateway)))).Methods(http.MethodPost)
r.HandleFunc("/api/nodes/{network}/{nodeid}/deleteingress", logic.SecurityCheck(true, http.HandlerFunc(deleteGateway))).Methods(http.MethodDelete)
r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods(http.MethodPost)
r.HandleFunc("/api/v1/nodes/{network}/status", logic.SecurityCheck(true, http.HandlerFunc(getNetworkNodeStatus))).Methods(http.MethodGet)
r.HandleFunc("/api/v1/nodes/migrate", migrate).Methods(http.MethodPost)
}

Expand Down Expand Up @@ -328,7 +329,7 @@ func getNetworkNodes(w http.ResponseWriter, r *http.Request) {
}

nodes = logic.AddStaticNodestoList(nodes)
nodes = logic.AddStatusToNodes(nodes)
nodes = logic.AddStatusToNodes(nodes, false)
// returns all the nodes in JSON/API format
apiNodes := logic.GetAllNodesAPI(nodes[:])
logger.Log(2, r.Header.Get("user"), "fetched nodes on network", networkName)
Expand Down Expand Up @@ -368,7 +369,7 @@ func getAllNodes(w http.ResponseWriter, r *http.Request) {

}
nodes = logic.AddStaticNodestoList(nodes)
nodes = logic.AddStatusToNodes(nodes)
nodes = logic.AddStatusToNodes(nodes, false)
// return all the nodes in JSON/API format
apiNodes := logic.GetAllNodesAPI(nodes[:])
logger.Log(3, r.Header.Get("user"), "fetched all nodes they have access to")
Expand All @@ -377,6 +378,52 @@ func getAllNodes(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(apiNodes)
}

// @Summary Get all nodes status on the network
// @Router /api/v1/nodes/{network}/status [get]
// @Tags Nodes
// @Securitydefinitions.oauth2.application OAuth2Application
// @Success 200 {array} models.ApiNode
// @Failure 500 {object} models.ErrorResponse
// Not quite sure if this is necessary. Probably necessary based on front end but may want to review after iteration 1 if it's being used or not
func getNetworkNodeStatus(w http.ResponseWriter, r *http.Request) {
var params = mux.Vars(r)
netID := params["network"]
// validate network
_, err := logic.GetNetwork(netID)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to get network %v", err), "badrequest"))
return
}
var nodes []models.Node
nodes, err = logic.GetNetworkNodes(netID)
if err != nil {
logger.Log(0, "error fetching all nodes info: ", err.Error())
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
username := r.Header.Get("user")
if r.Header.Get("ismaster") == "no" {
user, err := logic.GetUser(username)
if err != nil {
return
}
userPlatformRole, err := logic.GetRole(user.PlatformRoleID)
if err != nil {
return
}
if !userPlatformRole.FullAccess {
nodes = logic.GetFilteredNodesByUserAccess(*user, nodes)
}

}
nodes = logic.AddStaticNodestoList(nodes)
nodes = logic.AddStatusToNodes(nodes, false)
// return all the nodes in JSON/API format
apiNodesStatusMap := logic.GetNodesStatusAPI(nodes[:])
logger.Log(3, r.Header.Get("user"), "fetched all nodes they have access to")
logic.ReturnSuccessResponseWithJson(w, r, apiNodesStatusMap, "fetched nodes with metric status")
}

// @Summary Get an individual node
// @Router /api/nodes/{network}/{nodeid} [get]
// @Tags Nodes
Expand Down
9 changes: 9 additions & 0 deletions controllers/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,15 @@ func getUserV1(w http.ResponseWriter, r *http.Request) {
resp := models.ReturnUserWithRolesAndGroups{
ReturnUser: user,
PlatformRole: userRoleTemplate,
UserGroups: map[models.UserGroupID]models.UserGroup{},
}
for gId := range user.UserGroups {
grp, err := logic.GetUserGroup(gId)
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
resp.UserGroups[gId] = grp
}
logger.Log(2, r.Header.Get("user"), "fetched user", usernameFetched)
logic.ReturnSuccessResponseWithJson(w, r, resp, "fetched user with role info")
Expand Down
58 changes: 57 additions & 1 deletion logic/enrollmentkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -120,7 +121,6 @@ func UpdateEnrollmentKey(keyId string, relayId uuid.UUID, groups []models.TagID)
}

// GetAllEnrollmentKeys - fetches all enrollment keys from DB
// TODO drop double pointer
func GetAllEnrollmentKeys() ([]models.EnrollmentKey, error) {
currentKeys, err := getEnrollmentKeysMap()
if err != nil {
Expand Down Expand Up @@ -335,3 +335,59 @@ func RemoveTagFromEnrollmentKeys(deletedTagID models.TagID) {

}
}

func UnlinkNetworkAndTagsFromEnrollmentKeys(network string, delete bool) error {
keys, err := GetAllEnrollmentKeys()
if err != nil {
return fmt.Errorf("failed to retrieve keys: %w", err)
}

var errs []error
for _, key := range keys {
newNetworks := []string{}
newTags := []models.TagID{}
update := false

// Check and update networks
for _, net := range key.Networks {
if net == network {
update = true
continue
}
newNetworks = append(newNetworks, net)
}

// Check and update tags
for _, tag := range key.Groups {
tagParts := strings.Split(tag.String(), ".")
if len(tagParts) == 0 {
continue
}
tagNetwork := tagParts[0]
if tagNetwork == network {
update = true
continue
}
newTags = append(newTags, tag)
}

if update && len(newNetworks) == 0 && delete {
if err := DeleteEnrollmentKey(key.Value, true); err != nil {
errs = append(errs, fmt.Errorf("failed to delete key %s: %w", key.Value, err))
}
continue
}
if update {
key.Networks = newNetworks
key.Groups = newTags
if err := upsertEnrollmentKey(&key); err != nil {
errs = append(errs, fmt.Errorf("failed to update key %s: %w", key.Value, err))
}
}
}

if len(errs) > 0 {
return fmt.Errorf("errors unlinking network/tags from keys: %v", errs)
}
return nil
}
Loading

0 comments on commit e50da80

Please sign in to comment.