mirror of
https://github.com/gravitl/netmaker.git
synced 2025-10-04 16:33:49 +08:00
Extclient NET-63x (#2286)
* model changes * additional fields for extclient create * add DNS to extclient config * extclient name checks * update extclient * nmctl extclient * final tweaks * review comments * add extclientdns to node on ingress creation * fix to add ingress dns to api (#2296) --------- Co-authored-by: Aceix <aceixsmartX@gmail.com>
This commit is contained in:
@@ -4,10 +4,16 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/cli/functions"
|
"github.com/gravitl/netmaker/cli/functions"
|
||||||
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var extClientID string
|
var (
|
||||||
|
extClientID string
|
||||||
|
publicKey string
|
||||||
|
dns string
|
||||||
|
allowedips []string
|
||||||
|
)
|
||||||
|
|
||||||
var extClientCreateCmd = &cobra.Command{
|
var extClientCreateCmd = &cobra.Command{
|
||||||
Use: "create [NETWORK NAME] [NODE ID]",
|
Use: "create [NETWORK NAME] [NODE ID]",
|
||||||
@@ -15,12 +21,22 @@ var extClientCreateCmd = &cobra.Command{
|
|||||||
Short: "Create an External Client",
|
Short: "Create an External Client",
|
||||||
Long: `Create an External Client`,
|
Long: `Create an External Client`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
functions.CreateExtClient(args[0], args[1], extClientID)
|
extClient := models.CustomExtClient{
|
||||||
|
ClientID: extClientID,
|
||||||
|
PublicKey: publicKey,
|
||||||
|
DNS: dns,
|
||||||
|
ExtraAllowedIPs: allowedips,
|
||||||
|
}
|
||||||
|
|
||||||
|
functions.CreateExtClient(args[0], args[1], extClient)
|
||||||
fmt.Println("Success")
|
fmt.Println("Success")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
extClientCreateCmd.Flags().StringVar(&extClientID, "id", "", "ID of the external client")
|
extClientCreateCmd.Flags().StringVar(&extClientID, "id", "", "ID of the external client")
|
||||||
|
extClientCreateCmd.Flags().StringVar(&publicKey, "public_key", "", "updated public key of the external client")
|
||||||
|
extClientCreateCmd.Flags().StringVar(&dns, "dns", "", "updated DNS of the external client")
|
||||||
|
extClientCreateCmd.Flags().StringSliceVar(&allowedips, "allowedips", []string{}, "updated extra allowed IPs of the external client")
|
||||||
rootCmd.AddCommand(extClientCreateCmd)
|
rootCmd.AddCommand(extClientCreateCmd)
|
||||||
}
|
}
|
||||||
|
@@ -12,14 +12,6 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
extClientUpdateFile string
|
extClientUpdateFile string
|
||||||
description string
|
|
||||||
privateKey string
|
|
||||||
publicKey string
|
|
||||||
address string
|
|
||||||
address6 string
|
|
||||||
ingressGatewayID string
|
|
||||||
ingressGatewayEndpoint string
|
|
||||||
ownerID string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var extClientUpdateCmd = &cobra.Command{
|
var extClientUpdateCmd = &cobra.Command{
|
||||||
@@ -31,7 +23,7 @@ var extClientUpdateCmd = &cobra.Command{
|
|||||||
var (
|
var (
|
||||||
network = args[0]
|
network = args[0]
|
||||||
clientID = args[1]
|
clientID = args[1]
|
||||||
extClient = &models.ExtClient{}
|
extClient = &models.CustomExtClient{}
|
||||||
)
|
)
|
||||||
if extClientUpdateFile != "" {
|
if extClientUpdateFile != "" {
|
||||||
content, err := os.ReadFile(extClientUpdateFile)
|
content, err := os.ReadFile(extClientUpdateFile)
|
||||||
@@ -42,30 +34,19 @@ var extClientUpdateCmd = &cobra.Command{
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
extClient.ClientID = clientID
|
extClient.ClientID = extClientID
|
||||||
extClient.Description = description
|
|
||||||
extClient.PrivateKey = privateKey
|
|
||||||
extClient.PublicKey = publicKey
|
extClient.PublicKey = publicKey
|
||||||
extClient.Network = network
|
extClient.DNS = dns
|
||||||
extClient.Address = address
|
|
||||||
extClient.Address6 = address6
|
|
||||||
extClient.IngressGatewayID = ingressGatewayID
|
|
||||||
extClient.IngressGatewayEndpoint = ingressGatewayEndpoint
|
|
||||||
extClient.OwnerID = ownerID
|
|
||||||
}
|
}
|
||||||
functions.PrettyPrint(functions.UpdateExtClient(network, clientID, extClient))
|
functions.PrettyPrint(functions.UpdateExtClient(network, clientID, extClient))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
extClientUpdateCmd.Flags().StringVar(&extClientID, "id", "", "updated ID of the external client")
|
||||||
extClientUpdateCmd.Flags().StringVar(&extClientUpdateFile, "file", "", "Filepath of updated external client definition in JSON")
|
extClientUpdateCmd.Flags().StringVar(&extClientUpdateFile, "file", "", "Filepath of updated external client definition in JSON")
|
||||||
extClientUpdateCmd.Flags().StringVar(&description, "desc", "", "Description of the external client")
|
extClientUpdateCmd.Flags().StringVar(&publicKey, "public_key", "", "updated public key of the external client")
|
||||||
extClientUpdateCmd.Flags().StringVar(&privateKey, "private_key", "", "Filepath of updated external client definition in JSON")
|
extClientUpdateCmd.Flags().StringVar(&dns, "dns", "", "updated DNS of the external client")
|
||||||
extClientUpdateCmd.Flags().StringVar(&publicKey, "public_key", "", "Filepath of updated external client definition in JSON")
|
extClientUpdateCmd.Flags().StringSliceVar(&allowedips, "allowedips", []string{}, "updated extra allowed IPs of the external client")
|
||||||
extClientUpdateCmd.Flags().StringVar(&address, "ipv4_addr", "", "IPv4 address of the external client")
|
|
||||||
extClientUpdateCmd.Flags().StringVar(&address6, "ipv6_addr", "", "IPv6 address of the external client")
|
|
||||||
extClientUpdateCmd.Flags().StringVar(&ingressGatewayID, "ingress_gateway_id", "", "ID of the ingress gateway")
|
|
||||||
extClientUpdateCmd.Flags().StringVar(&ingressGatewayEndpoint, "ingress_gateway_endpoint", "", "Endpoint of the ingress gateway")
|
|
||||||
extClientUpdateCmd.Flags().StringVar(&ownerID, "owner_id", "", "External Client owner's ID")
|
|
||||||
rootCmd.AddCommand(extClientUpdateCmd)
|
rootCmd.AddCommand(extClientUpdateCmd)
|
||||||
}
|
}
|
||||||
|
@@ -45,7 +45,6 @@ var networkCreateCmd = &cobra.Command{
|
|||||||
if allowManualSignUp {
|
if allowManualSignUp {
|
||||||
network.AllowManualSignUp = "yes"
|
network.AllowManualSignUp = "yes"
|
||||||
}
|
}
|
||||||
network.DefaultExtClientDNS = defaultExtClientDNS
|
|
||||||
network.DefaultMTU = int32(defaultMTU)
|
network.DefaultMTU = int32(defaultMTU)
|
||||||
}
|
}
|
||||||
functions.PrettyPrint(functions.CreateNetwork(network))
|
functions.PrettyPrint(functions.CreateNetwork(network))
|
||||||
@@ -61,7 +60,6 @@ func init() {
|
|||||||
networkCreateCmd.Flags().BoolVar(&udpHolePunch, "udp_hole_punch", false, "Enable UDP Hole Punching ?")
|
networkCreateCmd.Flags().BoolVar(&udpHolePunch, "udp_hole_punch", false, "Enable UDP Hole Punching ?")
|
||||||
networkCreateCmd.Flags().BoolVar(&defaultACL, "default_acl", false, "Enable default Access Control List ?")
|
networkCreateCmd.Flags().BoolVar(&defaultACL, "default_acl", false, "Enable default Access Control List ?")
|
||||||
networkCreateCmd.Flags().StringVar(&defaultInterface, "interface", "", "Name of the network interface")
|
networkCreateCmd.Flags().StringVar(&defaultInterface, "interface", "", "Name of the network interface")
|
||||||
networkCreateCmd.Flags().StringVar(&defaultExtClientDNS, "ext_client_dns", "", "IPv4 address of DNS server to be used by external clients")
|
|
||||||
networkCreateCmd.Flags().IntVar(&defaultListenPort, "listen_port", 51821, "Default wireguard port each node will attempt to use")
|
networkCreateCmd.Flags().IntVar(&defaultListenPort, "listen_port", 51821, "Default wireguard port each node will attempt to use")
|
||||||
networkCreateCmd.Flags().IntVar(&nodeLimit, "node_limit", 999999999, "Maximum number of nodes that can be associated with this network")
|
networkCreateCmd.Flags().IntVar(&nodeLimit, "node_limit", 999999999, "Maximum number of nodes that can be associated with this network")
|
||||||
networkCreateCmd.Flags().IntVar(&defaultKeepalive, "keep_alive", 20, "Keep Alive in seconds")
|
networkCreateCmd.Flags().IntVar(&defaultKeepalive, "keep_alive", 20, "Keep Alive in seconds")
|
||||||
|
@@ -12,6 +12,5 @@ var (
|
|||||||
nodeLimit int
|
nodeLimit int
|
||||||
defaultKeepalive int
|
defaultKeepalive int
|
||||||
allowManualSignUp bool
|
allowManualSignUp bool
|
||||||
defaultExtClientDNS string
|
|
||||||
defaultMTU int
|
defaultMTU int
|
||||||
)
|
)
|
||||||
|
@@ -28,14 +28,8 @@ func GetExtClientConfig(networkName, clientID string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateExtClient - create an external client
|
// CreateExtClient - create an external client
|
||||||
func CreateExtClient(networkName, nodeID, extClientID string) {
|
func CreateExtClient(networkName, nodeID string, extClient models.CustomExtClient) {
|
||||||
if extClientID != "" {
|
request[any](http.MethodPost, fmt.Sprintf("/api/extclients/%s/%s", networkName, nodeID), extClient)
|
||||||
request[any](http.MethodPost, fmt.Sprintf("/api/extclients/%s/%s", networkName, nodeID), &models.CustomExtClient{
|
|
||||||
ClientID: extClientID,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
request[any](http.MethodPost, fmt.Sprintf("/api/extclients/%s/%s", networkName, nodeID), nil)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteExtClient - delete an external client
|
// DeleteExtClient - delete an external client
|
||||||
@@ -44,6 +38,6 @@ func DeleteExtClient(networkName, clientID string) *models.SuccessResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateExtClient - update an external client
|
// UpdateExtClient - update an external client
|
||||||
func UpdateExtClient(networkName, clientID string, payload *models.ExtClient) *models.ExtClient {
|
func UpdateExtClient(networkName, clientID string, payload *models.CustomExtClient) *models.ExtClient {
|
||||||
return request[models.ExtClient](http.MethodPut, fmt.Sprintf("/api/extclients/%s/%s", networkName, clientID), payload)
|
return request[models.ExtClient](http.MethodPut, fmt.Sprintf("/api/extclients/%s/%s", networkName, clientID), payload)
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@@ -230,8 +231,10 @@ func getExtClientConf(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
defaultDNS := ""
|
defaultDNS := ""
|
||||||
if network.DefaultExtClientDNS != "" {
|
if client.DNS != "" {
|
||||||
defaultDNS = "DNS = " + network.DefaultExtClientDNS
|
defaultDNS = "DNS = " + client.DNS
|
||||||
|
} else if gwnode.IngressDNS != "" {
|
||||||
|
defaultDNS = "DNS = " + gwnode.IngressDNS
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultMTU := 1420
|
defaultMTU := 1420
|
||||||
@@ -321,21 +324,14 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
|
|||||||
var extclient models.ExtClient
|
var extclient models.ExtClient
|
||||||
var customExtClient models.CustomExtClient
|
var customExtClient models.CustomExtClient
|
||||||
|
|
||||||
err := json.NewDecoder(r.Body).Decode(&customExtClient)
|
if err := json.NewDecoder(r.Body).Decode(&customExtClient); err != nil {
|
||||||
if err == nil {
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
|
||||||
if customExtClient.ClientID != "" && !validName(customExtClient.ClientID) {
|
|
||||||
logic.ReturnErrorResponse(w, r, logic.FormatError(errInvalidExtClientID, "badrequest"))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
extclient.ClientID = customExtClient.ClientID
|
if err := validateExtClient(&extclient, &customExtClient); err != nil {
|
||||||
if len(customExtClient.PublicKey) > 0 {
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
|
||||||
if _, err := wgtypes.ParseKey(customExtClient.PublicKey); err != nil {
|
|
||||||
logic.ReturnErrorResponse(w, r, logic.FormatError(errInvalidExtClientPubKey, "badrequest"))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
extclient.PublicKey = customExtClient.PublicKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extclient.Network = networkName
|
extclient.Network = networkName
|
||||||
extclient.IngressGatewayID = nodeid
|
extclient.IngressGatewayID = nodeid
|
||||||
@@ -392,7 +388,7 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
|
|||||||
logger.Log(0, "failed to associate client", extclient.ClientID, "to user", userID)
|
logger.Log(0, "failed to associate client", extclient.ClientID, "to user", userID)
|
||||||
}
|
}
|
||||||
extclient.OwnerID = userID
|
extclient.OwnerID = userID
|
||||||
if _, err := logic.UpdateExtClient(extclient.ClientID, extclient.Network, extclient.Enabled, &extclient, extclient.ACLs); err != nil {
|
if err := logic.SaveExtClient(&extclient); err != nil {
|
||||||
logger.Log(0, "failed to add owner id", userID, "to client", extclient.ClientID)
|
logger.Log(0, "failed to add owner id", userID, "to client", extclient.ClientID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,9 +422,9 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
var params = mux.Vars(r)
|
var params = mux.Vars(r)
|
||||||
|
|
||||||
var newExtClient models.ExtClient
|
var update models.CustomExtClient
|
||||||
var oldExtClient models.ExtClient
|
var oldExtClient models.ExtClient
|
||||||
err := json.NewDecoder(r.Body).Decode(&newExtClient)
|
err := json.NewDecoder(r.Body).Decode(&update)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
|
logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
|
||||||
err.Error())
|
err.Error())
|
||||||
@@ -445,8 +441,8 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
|
|||||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !validName(newExtClient.ClientID) {
|
if err := validateExtClient(&oldExtClient, &update); err != nil {
|
||||||
logic.ReturnErrorResponse(w, r, logic.FormatError(errInvalidExtClientID, "badrequest"))
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data, err := database.FetchRecord(database.EXT_CLIENT_TABLE_NAME, key)
|
data, err := database.FetchRecord(database.EXT_CLIENT_TABLE_NAME, key)
|
||||||
@@ -466,7 +462,7 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// == PRO ==
|
// == PRO ==
|
||||||
networkName := params["network"]
|
networkName := params["network"]
|
||||||
var changedID = newExtClient.ClientID != oldExtClient.ClientID
|
var changedID = update.ClientID != oldExtClient.ClientID
|
||||||
if r.Header.Get("ismaster") != "yes" {
|
if r.Header.Get("ismaster") != "yes" {
|
||||||
userID := r.Header.Get("user")
|
userID := r.Header.Get("user")
|
||||||
_, doesOwn := doesUserOwnClient(userID, params["clientid"], networkName)
|
_, doesOwn := doesUserOwnClient(userID, params["clientid"], networkName)
|
||||||
@@ -479,17 +475,16 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
|
|||||||
if err := pro.DissociateNetworkUserClient(oldExtClient.OwnerID, networkName, oldExtClient.ClientID); err != nil {
|
if err := pro.DissociateNetworkUserClient(oldExtClient.OwnerID, networkName, oldExtClient.ClientID); err != nil {
|
||||||
logger.Log(0, "failed to dissociate client", oldExtClient.ClientID, "from user", oldExtClient.OwnerID)
|
logger.Log(0, "failed to dissociate client", oldExtClient.ClientID, "from user", oldExtClient.OwnerID)
|
||||||
}
|
}
|
||||||
if err := pro.AssociateNetworkUserClient(oldExtClient.OwnerID, networkName, newExtClient.ClientID); err != nil {
|
if err := pro.AssociateNetworkUserClient(oldExtClient.OwnerID, networkName, update.ClientID); err != nil {
|
||||||
logger.Log(0, "failed to associate client", newExtClient.ClientID, "to user", oldExtClient.OwnerID)
|
logger.Log(0, "failed to associate client", update.ClientID, "to user", oldExtClient.OwnerID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// == END PRO ==
|
// == END PRO ==
|
||||||
|
|
||||||
var changedEnabled = (newExtClient.Enabled != oldExtClient.Enabled) || // indicates there was a change in enablement
|
var changedEnabled = (update.Enabled != oldExtClient.Enabled) // indicates there was a change in enablement
|
||||||
len(newExtClient.ACLs) != len(oldExtClient.ACLs)
|
|
||||||
// extra var need as logic.Update changes oldExtClient
|
// extra var need as logic.Update changes oldExtClient
|
||||||
currentClient := oldExtClient
|
currentClient := oldExtClient
|
||||||
newclient, err := logic.UpdateExtClient(newExtClient.ClientID, params["network"], newExtClient.Enabled, &oldExtClient, newExtClient.ACLs)
|
newclient, err := logic.UpdateExtClient(&oldExtClient, &update)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(0, r.Header.Get("user"),
|
logger.Log(0, r.Header.Get("user"),
|
||||||
fmt.Sprintf("failed to update ext client [%s], network [%s]: %v",
|
fmt.Sprintf("failed to update ext client [%s], network [%s]: %v",
|
||||||
@@ -497,7 +492,7 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
|
|||||||
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Log(0, r.Header.Get("user"), "updated ext client", newExtClient.ClientID)
|
logger.Log(0, r.Header.Get("user"), "updated ext client", update.ClientID)
|
||||||
if changedEnabled { // need to send a peer update to the ingress node as enablement of one of it's clients has changed
|
if changedEnabled { // need to send a peer update to the ingress node as enablement of one of it's clients has changed
|
||||||
if ingressNode, err := logic.GetNodeByID(newclient.IngressGatewayID); err == nil {
|
if ingressNode, err := logic.GetNodeByID(newclient.IngressGatewayID); err == nil {
|
||||||
if err = mq.PublishPeerUpdate(); err != nil {
|
if err = mq.PublishPeerUpdate(); err != nil {
|
||||||
@@ -509,7 +504,7 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(newclient)
|
json.NewEncoder(w).Encode(newclient)
|
||||||
if changedID {
|
if changedID {
|
||||||
go func() {
|
go func() {
|
||||||
if err := mq.PublishExtClientDNSUpdate(currentClient, newExtClient, networkName); err != nil {
|
if err := mq.PublishExtClientDNSUpdate(currentClient, *newclient, networkName); err != nil {
|
||||||
logger.Log(1, "error pubishing dns update for extcient update", err.Error())
|
logger.Log(1, "error pubishing dns update for extcient update", err.Error())
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -648,3 +643,35 @@ func doesUserOwnClient(username, clientID, network string) (bool, bool) {
|
|||||||
|
|
||||||
return false, logic.StringSliceContains(netUser.Clients, clientID)
|
return false, logic.StringSliceContains(netUser.Clients, clientID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateExtClient Validates the extclient object
|
||||||
|
func validateExtClient(extclient *models.ExtClient, customExtClient *models.CustomExtClient) error {
|
||||||
|
//validate clientid
|
||||||
|
if customExtClient.ClientID != "" && !validName(customExtClient.ClientID) {
|
||||||
|
return errInvalidExtClientID
|
||||||
|
}
|
||||||
|
extclient.ClientID = customExtClient.ClientID
|
||||||
|
if len(customExtClient.PublicKey) > 0 {
|
||||||
|
if _, err := wgtypes.ParseKey(customExtClient.PublicKey); err != nil {
|
||||||
|
return errInvalidExtClientPubKey
|
||||||
|
}
|
||||||
|
extclient.PublicKey = customExtClient.PublicKey
|
||||||
|
}
|
||||||
|
//validate extra ips
|
||||||
|
if len(customExtClient.ExtraAllowedIPs) > 0 {
|
||||||
|
for _, ip := range customExtClient.ExtraAllowedIPs {
|
||||||
|
if _, _, err := net.ParseCIDR(ip); err != nil {
|
||||||
|
return errInvalidExtClientExtraIP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extclient.ExtraAllowedIPs = customExtClient.ExtraAllowedIPs
|
||||||
|
}
|
||||||
|
//validate DNS
|
||||||
|
if customExtClient.DNS != "" {
|
||||||
|
if ip := net.ParseIP(customExtClient.DNS); ip == nil {
|
||||||
|
return errInvalidExtClientDNS
|
||||||
|
}
|
||||||
|
extclient.DNS = customExtClient.DNS
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@@ -520,13 +520,10 @@ func createIngressGateway(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
nodeid := params["nodeid"]
|
nodeid := params["nodeid"]
|
||||||
netid := params["network"]
|
netid := params["network"]
|
||||||
type failoverData struct {
|
var request models.IngressRequest
|
||||||
Failover bool `json:"failover"`
|
json.NewDecoder(r.Body).Decode(&request)
|
||||||
}
|
|
||||||
var failoverReqBody failoverData
|
|
||||||
json.NewDecoder(r.Body).Decode(&failoverReqBody)
|
|
||||||
|
|
||||||
node, err := logic.CreateIngressGateway(netid, nodeid, failoverReqBody.Failover)
|
node, err := logic.CreateIngressGateway(netid, nodeid, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log(0, r.Header.Get("user"),
|
logger.Log(0, r.Header.Get("user"),
|
||||||
fmt.Sprintf("failed to create ingress gateway on node [%s] on network [%s]: %v",
|
fmt.Sprintf("failed to create ingress gateway on node [%s] on network [%s]: %v",
|
||||||
@@ -535,7 +532,7 @@ func createIngressGateway(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if servercfg.Is_EE && failoverReqBody.Failover {
|
if servercfg.Is_EE && request.Failover {
|
||||||
if err = logic.EnterpriseResetFailoverFunc(node.Network); err != nil {
|
if err = logic.EnterpriseResetFailoverFunc(node.Network); err != nil {
|
||||||
logger.Log(1, "failed to reset failover list during failover create", node.ID.String(), node.Network)
|
logger.Log(1, "failed to reset failover list during failover create", node.ID.String(), node.Network)
|
||||||
}
|
}
|
||||||
|
@@ -7,10 +7,22 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
errInvalidExtClientPubKey = errors.New("incorrect ext client public key")
|
errInvalidExtClientPubKey = errors.New("incorrect ext client public key")
|
||||||
errInvalidExtClientID = errors.New("ext client ID must be alphanumderic and/or dashes")
|
errInvalidExtClientID = errors.New("ext client ID must be alphanumderic and/or dashes and less that 15 chars")
|
||||||
|
errInvalidExtClientExtraIP = errors.New("ext client extra ip must be a valid cidr")
|
||||||
|
errInvalidExtClientDNS = errors.New("ext client dns must be a valid ip address")
|
||||||
)
|
)
|
||||||
|
|
||||||
// allow only dashes and alphaneumeric for ext client and node names
|
// allow only dashes and alphaneumeric for ext client and node names
|
||||||
func validName(name string) bool {
|
func validName(name string) bool {
|
||||||
return regexp.MustCompile("^[a-zA-Z0-9-]+$").MatchString(name)
|
reg, err := regexp.Compile("^[a-zA-Z0-9-]+$")
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !reg.MatchString(name) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if len(name) > 15 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
51
controllers/regex_test.go
Normal file
51
controllers/regex_test.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
// TestValidName tests the validName function
|
||||||
|
func TestValidName(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
Name string
|
||||||
|
Args args
|
||||||
|
Want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "validName",
|
||||||
|
Args: args{
|
||||||
|
Name: "TestvalidName",
|
||||||
|
},
|
||||||
|
Want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "invalidName",
|
||||||
|
Args: args{
|
||||||
|
Name: "Test*Name",
|
||||||
|
},
|
||||||
|
Want: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "nametoolong",
|
||||||
|
Args: args{
|
||||||
|
Name: "TestvalidNameTestvalidName",
|
||||||
|
},
|
||||||
|
Want: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "maxlength",
|
||||||
|
Args: args{
|
||||||
|
Name: "123456789012345",
|
||||||
|
},
|
||||||
|
Want: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.Name, func(t *testing.T) {
|
||||||
|
if got := validName(tt.Args.Name); got != tt.Want {
|
||||||
|
t.Errorf("validName() = %v, want %v", got, tt.Want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@@ -19,7 +19,6 @@ var (
|
|||||||
}
|
}
|
||||||
testExternalClient = &models.ExtClient{
|
testExternalClient = &models.ExtClient{
|
||||||
ClientID: "testExtClient",
|
ClientID: "testExtClient",
|
||||||
Description: "ext client for testing",
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -174,6 +174,11 @@ func CreateExtClient(extclient *models.ExtClient) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extclient.LastModified = time.Now().Unix()
|
extclient.LastModified = time.Now().Unix()
|
||||||
|
return SaveExtClient(extclient)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SaveExtClient - saves an ext client to database
|
||||||
|
func SaveExtClient(extclient *models.ExtClient) error {
|
||||||
key, err := GetRecordKey(extclient.ClientID, extclient.Network)
|
key, err := GetRecordKey(extclient.ClientID, extclient.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -188,35 +193,27 @@ func CreateExtClient(extclient *models.ExtClient) error {
|
|||||||
return SetNetworkNodesLastModified(extclient.Network)
|
return SetNetworkNodesLastModified(extclient.Network)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateExtClient - only supports name changes right now
|
// UpdateExtClient - updates an ext client with new values
|
||||||
func UpdateExtClient(newclientid string, network string, enabled bool, client *models.ExtClient, newACLs map[string]struct{}) (*models.ExtClient, error) {
|
func UpdateExtClient(old *models.ExtClient, update *models.CustomExtClient) (*models.ExtClient, error) {
|
||||||
err := DeleteExtClient(network, client.ClientID)
|
new := old
|
||||||
|
err := DeleteExtClient(old.Network, old.ClientID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return client, err
|
return new, err
|
||||||
}
|
}
|
||||||
if newclientid != client.ClientID { // name change only
|
new.ClientID = update.ClientID
|
||||||
client.ClientID = newclientid
|
if update.PublicKey != "" && old.PublicKey != update.PublicKey {
|
||||||
client.LastModified = time.Now().Unix()
|
new.PublicKey = update.PublicKey
|
||||||
data, err := json.Marshal(&client)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
key, err := GetRecordKey(client.ClientID, client.Network)
|
if update.DNS != "" && update.DNS != old.DNS {
|
||||||
if err != nil {
|
new.DNS = update.DNS
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
if err = database.Insert(key, string(data), database.EXT_CLIENT_TABLE_NAME); err != nil {
|
if update.Enabled != old.Enabled {
|
||||||
return client, err
|
new.Enabled = update.Enabled
|
||||||
}
|
}
|
||||||
return client, nil
|
if update.ExtraAllowedIPs != nil && StringDifference(old.ExtraAllowedIPs, update.ExtraAllowedIPs) != nil {
|
||||||
|
new.ExtraAllowedIPs = update.ExtraAllowedIPs
|
||||||
}
|
}
|
||||||
client.ClientID = newclientid
|
return new, CreateExtClient(new)
|
||||||
client.Enabled = enabled
|
|
||||||
SetClientACLs(client, newACLs)
|
|
||||||
if err = CreateExtClient(client); err != nil {
|
|
||||||
return client, err
|
|
||||||
}
|
|
||||||
return client, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetExtClientsByID - gets the clients of attached gateway
|
// GetExtClientsByID - gets the clients of attached gateway
|
||||||
|
@@ -96,7 +96,7 @@ func DeleteEgressGateway(network, nodeid string) (models.Node, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateIngressGateway - creates an ingress gateway
|
// CreateIngressGateway - creates an ingress gateway
|
||||||
func CreateIngressGateway(netid string, nodeid string, failover bool) (models.Node, error) {
|
func CreateIngressGateway(netid string, nodeid string, ingress models.IngressRequest) (models.Node, error) {
|
||||||
|
|
||||||
node, err := GetNodeByID(nodeid)
|
node, err := GetNodeByID(nodeid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -120,8 +120,9 @@ func CreateIngressGateway(netid string, nodeid string, failover bool) (models.No
|
|||||||
node.IsIngressGateway = true
|
node.IsIngressGateway = true
|
||||||
node.IngressGatewayRange = network.AddressRange
|
node.IngressGatewayRange = network.AddressRange
|
||||||
node.IngressGatewayRange6 = network.AddressRange6
|
node.IngressGatewayRange6 = network.AddressRange6
|
||||||
|
node.IngressDNS = ingress.ExtclientDNS
|
||||||
node.SetLastModified()
|
node.SetLastModified()
|
||||||
if failover && servercfg.Is_EE {
|
if ingress.Failover && servercfg.Is_EE {
|
||||||
node.Failover = true
|
node.Failover = true
|
||||||
}
|
}
|
||||||
data, err := json.Marshal(&node)
|
data, err := json.Marshal(&node)
|
||||||
|
@@ -32,6 +32,7 @@ type ApiNode struct {
|
|||||||
RelayAddrs []string `json:"relayaddrs"`
|
RelayAddrs []string `json:"relayaddrs"`
|
||||||
FailoverNode string `json:"failovernode"`
|
FailoverNode string `json:"failovernode"`
|
||||||
DNSOn bool `json:"dnson"`
|
DNSOn bool `json:"dnson"`
|
||||||
|
IngressDns string `json:"ingressdns"`
|
||||||
Server string `json:"server"`
|
Server string `json:"server"`
|
||||||
InternetGateway string `json:"internetgateway"`
|
InternetGateway string `json:"internetgateway"`
|
||||||
Connected bool `json:"connected"`
|
Connected bool `json:"connected"`
|
||||||
@@ -61,6 +62,7 @@ func (a *ApiNode) ConvertToServerNode(currentNode *Node) *Node {
|
|||||||
convertedNode.IngressGatewayRange = currentNode.IngressGatewayRange
|
convertedNode.IngressGatewayRange = currentNode.IngressGatewayRange
|
||||||
convertedNode.IngressGatewayRange6 = currentNode.IngressGatewayRange6
|
convertedNode.IngressGatewayRange6 = currentNode.IngressGatewayRange6
|
||||||
convertedNode.DNSOn = a.DNSOn
|
convertedNode.DNSOn = a.DNSOn
|
||||||
|
convertedNode.IngressDNS = a.IngressDns
|
||||||
convertedNode.EgressGatewayRequest = currentNode.EgressGatewayRequest
|
convertedNode.EgressGatewayRequest = currentNode.EgressGatewayRequest
|
||||||
convertedNode.EgressGatewayNatEnabled = currentNode.EgressGatewayNatEnabled
|
convertedNode.EgressGatewayNatEnabled = currentNode.EgressGatewayNatEnabled
|
||||||
convertedNode.PersistentKeepalive = time.Second * time.Duration(a.PersistentKeepalive)
|
convertedNode.PersistentKeepalive = time.Second * time.Duration(a.PersistentKeepalive)
|
||||||
@@ -148,6 +150,7 @@ func (nm *Node) ConvertToAPINode() *ApiNode {
|
|||||||
apiNode.FailoverNode = ""
|
apiNode.FailoverNode = ""
|
||||||
}
|
}
|
||||||
apiNode.DNSOn = nm.DNSOn
|
apiNode.DNSOn = nm.DNSOn
|
||||||
|
apiNode.IngressDns = nm.IngressDNS
|
||||||
apiNode.Server = nm.Server
|
apiNode.Server = nm.Server
|
||||||
apiNode.InternetGateway = nm.InternetGateway.String()
|
apiNode.InternetGateway = nm.InternetGateway.String()
|
||||||
if isEmptyAddr(apiNode.InternetGateway) {
|
if isEmptyAddr(apiNode.InternetGateway) {
|
||||||
|
@@ -3,12 +3,13 @@ package models
|
|||||||
// ExtClient - struct for external clients
|
// ExtClient - struct for external clients
|
||||||
type ExtClient struct {
|
type ExtClient struct {
|
||||||
ClientID string `json:"clientid" bson:"clientid"`
|
ClientID string `json:"clientid" bson:"clientid"`
|
||||||
Description string `json:"description" bson:"description"`
|
|
||||||
PrivateKey string `json:"privatekey" bson:"privatekey"`
|
PrivateKey string `json:"privatekey" bson:"privatekey"`
|
||||||
PublicKey string `json:"publickey" bson:"publickey"`
|
PublicKey string `json:"publickey" bson:"publickey"`
|
||||||
Network string `json:"network" bson:"network"`
|
Network string `json:"network" bson:"network"`
|
||||||
|
DNS string `json:"dns" bson:"dns"`
|
||||||
Address string `json:"address" bson:"address"`
|
Address string `json:"address" bson:"address"`
|
||||||
Address6 string `json:"address6" bson:"address6"`
|
Address6 string `json:"address6" bson:"address6"`
|
||||||
|
ExtraAllowedIPs []string `json:"extraallowedips" bson:"extraallowedips"`
|
||||||
IngressGatewayID string `json:"ingressgatewayid" bson:"ingressgatewayid"`
|
IngressGatewayID string `json:"ingressgatewayid" bson:"ingressgatewayid"`
|
||||||
IngressGatewayEndpoint string `json:"ingressgatewayendpoint" bson:"ingressgatewayendpoint"`
|
IngressGatewayEndpoint string `json:"ingressgatewayendpoint" bson:"ingressgatewayendpoint"`
|
||||||
LastModified int64 `json:"lastmodified" bson:"lastmodified"`
|
LastModified int64 `json:"lastmodified" bson:"lastmodified"`
|
||||||
@@ -16,3 +17,12 @@ type ExtClient struct {
|
|||||||
OwnerID string `json:"ownerid" bson:"ownerid"`
|
OwnerID string `json:"ownerid" bson:"ownerid"`
|
||||||
ACLs map[string]struct{} `json:"acls,omitempty" bson:"acls,omitempty"`
|
ACLs map[string]struct{} `json:"acls,omitempty" bson:"acls,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CustomExtClient - struct for CustomExtClient params
|
||||||
|
type CustomExtClient struct {
|
||||||
|
ClientID string `json:"clientid,omitempty"`
|
||||||
|
PublicKey string `json:"publickey,omitempty"`
|
||||||
|
DNS string `json:"dns,omitempty"`
|
||||||
|
ExtraAllowedIPs []string `json:"extraallowedips,omitempty"`
|
||||||
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
|
}
|
||||||
|
@@ -23,7 +23,6 @@ type Network struct {
|
|||||||
IsIPv4 string `json:"isipv4" bson:"isipv4" validate:"checkyesorno"`
|
IsIPv4 string `json:"isipv4" bson:"isipv4" validate:"checkyesorno"`
|
||||||
IsIPv6 string `json:"isipv6" bson:"isipv6" validate:"checkyesorno"`
|
IsIPv6 string `json:"isipv6" bson:"isipv6" validate:"checkyesorno"`
|
||||||
DefaultUDPHolePunch string `json:"defaultudpholepunch" bson:"defaultudpholepunch" validate:"checkyesorno"`
|
DefaultUDPHolePunch string `json:"defaultudpholepunch" bson:"defaultudpholepunch" validate:"checkyesorno"`
|
||||||
DefaultExtClientDNS string `json:"defaultextclientdns" bson:"defaultextclientdns"`
|
|
||||||
DefaultMTU int32 `json:"defaultmtu" bson:"defaultmtu"`
|
DefaultMTU int32 `json:"defaultmtu" bson:"defaultmtu"`
|
||||||
DefaultACL string `json:"defaultacl" bson:"defaultacl" yaml:"defaultacl" validate:"checkyesorno"`
|
DefaultACL string `json:"defaultacl" bson:"defaultacl" yaml:"defaultacl" validate:"checkyesorno"`
|
||||||
ProSettings *promodels.ProNetwork `json:"prosettings,omitempty" bson:"prosettings,omitempty" yaml:"prosettings,omitempty"`
|
ProSettings *promodels.ProNetwork `json:"prosettings,omitempty" bson:"prosettings,omitempty" yaml:"prosettings,omitempty"`
|
||||||
|
@@ -69,6 +69,7 @@ type CommonNode struct {
|
|||||||
IsEgressGateway bool `json:"isegressgateway" yaml:"isegressgateway"`
|
IsEgressGateway bool `json:"isegressgateway" yaml:"isegressgateway"`
|
||||||
EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"`
|
EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"`
|
||||||
IsIngressGateway bool `json:"isingressgateway" yaml:"isingressgateway"`
|
IsIngressGateway bool `json:"isingressgateway" yaml:"isingressgateway"`
|
||||||
|
IngressDNS string `json:"ingressdns" yaml:"ingressdns"`
|
||||||
DNSOn bool `json:"dnson" yaml:"dnson"`
|
DNSOn bool `json:"dnson" yaml:"dnson"`
|
||||||
PersistentKeepalive time.Duration `json:"persistentkeepalive" yaml:"persistentkeepalive"`
|
PersistentKeepalive time.Duration `json:"persistentkeepalive" yaml:"persistentkeepalive"`
|
||||||
}
|
}
|
||||||
|
@@ -14,12 +14,6 @@ const (
|
|||||||
PLACEHOLDER_TOKEN_TEXT = "ACCESS_TOKEN"
|
PLACEHOLDER_TOKEN_TEXT = "ACCESS_TOKEN"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CustomExtClient - struct for CustomExtClient params
|
|
||||||
type CustomExtClient struct {
|
|
||||||
ClientID string `json:"clientid"`
|
|
||||||
PublicKey string `json:"publickey,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuthParams - struct for auth params
|
// AuthParams - struct for auth params
|
||||||
type AuthParams struct {
|
type AuthParams struct {
|
||||||
MacAddress string `json:"macaddress"`
|
MacAddress string `json:"macaddress"`
|
||||||
@@ -170,6 +164,12 @@ type HostRelayRequest struct {
|
|||||||
RelayedHosts []string `json:"relayed_hosts"`
|
RelayedHosts []string `json:"relayed_hosts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IngressRequest - ingress request struct
|
||||||
|
type IngressRequest struct {
|
||||||
|
ExtclientDNS string `json:"extclientdns"`
|
||||||
|
Failover bool `json:"failover"`
|
||||||
|
}
|
||||||
|
|
||||||
// ServerUpdateData - contains data to configure server
|
// ServerUpdateData - contains data to configure server
|
||||||
// and if it should set peers
|
// and if it should set peers
|
||||||
type ServerUpdateData struct {
|
type ServerUpdateData struct {
|
||||||
|
Reference in New Issue
Block a user