diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 21ee06169..02c2b48c7 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -31,6 +31,7 @@ body: label: Version description: What version are you running? options: + - v0.20.6 - v0.20.5 - v0.20.4 - v0.20.3 diff --git a/README.md b/README.md index cdc995b76..840ceb301 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@
-
+
diff --git a/compose/docker-compose.netclient.yml b/compose/docker-compose.netclient.yml
index f7f0fe1f6..9144b76cd 100644
--- a/compose/docker-compose.netclient.yml
+++ b/compose/docker-compose.netclient.yml
@@ -3,7 +3,7 @@ version: "3.4"
services:
netclient:
container_name: netclient
- image: 'gravitl/netclient:v0.20.5'
+ image: 'gravitl/netclient:v0.20.6'
hostname: netmaker-1
network_mode: host
restart: on-failure
diff --git a/controllers/docs.go b/controllers/docs.go
index 1e409c47d..592922982 100644
--- a/controllers/docs.go
+++ b/controllers/docs.go
@@ -10,7 +10,7 @@
//
// Schemes: https
// BasePath: /
-// Version: 0.20.5
+// Version: 0.20.6
// Host: netmaker.io
//
// Consumes:
diff --git a/controllers/ext_client.go b/controllers/ext_client.go
index ad99ef3b5..4155c6537 100644
--- a/controllers/ext_client.go
+++ b/controllers/ext_client.go
@@ -17,6 +17,7 @@ import (
"github.com/gravitl/netmaker/models/promodels"
"github.com/gravitl/netmaker/mq"
"github.com/skip2/go-qrcode"
+ "golang.org/x/exp/slog"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
@@ -308,31 +309,28 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var params = mux.Vars(r)
- networkName := params["network"]
nodeid := params["nodeid"]
ingressExists := checkIngressExists(nodeid)
if !ingressExists {
err := errors.New("ingress does not exist")
- logger.Log(0, r.Header.Get("user"),
- fmt.Sprintf("failed to create extclient on network [%s]: %v", networkName, err))
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+ slog.Error("failed to create extclient", "user", r.Header.Get("user"), "error", err)
+ logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
- var extclient models.ExtClient
var customExtClient models.CustomExtClient
if err := json.NewDecoder(r.Body).Decode(&customExtClient); err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
- if err := validateExtClient(&extclient, &customExtClient); err != nil {
+ if err := validateCustomExtClient(&customExtClient, true); err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
+ extclient := logic.UpdateExtClient(&models.ExtClient{}, &customExtClient)
- extclient.Network = networkName
extclient.IngressGatewayID = nodeid
node, err := logic.GetNodeByID(nodeid)
if err != nil {
@@ -341,6 +339,7 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
+ extclient.Network = node.Network
host, err := logic.GetHost(node.HostID.String())
if err != nil {
logger.Log(0, r.Header.Get("user"),
@@ -351,21 +350,19 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
listenPort := logic.GetPeerListenPort(host)
extclient.IngressGatewayEndpoint = fmt.Sprintf("%s:%d", host.EndpointIP.String(), listenPort)
extclient.Enabled = true
- parentNetwork, err := logic.GetNetwork(networkName)
+ parentNetwork, err := logic.GetNetwork(node.Network)
if err == nil { // check if parent network default ACL is enabled (yes) or not (no)
extclient.Enabled = parentNetwork.DefaultACL == "yes"
}
if err := logic.SetClientDefaultACLs(&extclient); err != nil {
- logger.Log(0, r.Header.Get("user"),
- fmt.Sprintf("failed to assign ACLs to new ext client on network [%s]: %v", networkName, err))
+ slog.Error("failed to set default acls for extclient", "user", r.Header.Get("user"), "network", node.Network, "error", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
if err = logic.CreateExtClient(&extclient); err != nil {
- logger.Log(0, r.Header.Get("user"),
- fmt.Sprintf("failed to create new ext client on network [%s]: %v", networkName, err))
+ slog.Error("failed to create extclient", "user", r.Header.Get("user"), "network", node.Network, "error", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
@@ -374,13 +371,13 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("ismaster") != "yes" {
userID := r.Header.Get("user")
if isAdmin, err = checkProClientAccess(userID, extclient.ClientID, &parentNetwork); err != nil {
- logger.Log(0, userID, "attempted to create a client on network", networkName, "but they lack access")
- logic.DeleteExtClient(networkName, extclient.ClientID)
+ slog.Error("pro client access check failed", "user", userID, "network", node.Network, "error", err)
+ logic.DeleteExtClient(node.Network, extclient.ClientID)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
if !isAdmin {
- if err = pro.AssociateNetworkUserClient(userID, networkName, extclient.ClientID); err != nil {
+ if err = pro.AssociateNetworkUserClient(userID, node.Network, extclient.ClientID); err != nil {
logger.Log(0, "failed to associate client", extclient.ClientID, "to user", userID)
}
extclient.OwnerID = userID
@@ -390,7 +387,7 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
}
}
- logger.Log(0, r.Header.Get("user"), "created new ext client on network", networkName)
+ slog.Info("created extclient", "user", r.Header.Get("user"), "network", node.Network, "clientid", extclient.ClientID)
w.WriteHeader(http.StatusOK)
go func() {
if err := mq.PublishPeerUpdate(); err != nil {
@@ -419,7 +416,7 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
var params = mux.Vars(r)
var update models.CustomExtClient
- var oldExtClient models.ExtClient
+ //var oldExtClient models.ExtClient
var sendPeerUpdate bool
err := json.NewDecoder(r.Body).Decode(&update)
if err != nil {
@@ -429,50 +426,40 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
return
}
clientid := params["clientid"]
- network := params["network"]
- key, err := logic.GetRecordKey(clientid, network)
+ oldExtClient, err := logic.GetExtClientByName(clientid)
if err != nil {
- logger.Log(0, r.Header.Get("user"),
- fmt.Sprintf("failed to get record key for client [%s], network [%s]: %v",
- clientid, network, err))
+ slog.Error("failed to retrieve extclient", "user", r.Header.Get("user"), "id", clientid, "error", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
- if err := validateExtClient(&oldExtClient, &update); err != nil {
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
- return
- }
- data, err := database.FetchRecord(database.EXT_CLIENT_TABLE_NAME, key)
- if err != nil {
- logger.Log(0, r.Header.Get("user"),
- fmt.Sprintf("failed to fetch ext client record key [%s] from db for client [%s], network [%s]: %v",
- key, clientid, network, err))
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
- }
- if err = json.Unmarshal([]byte(data), &oldExtClient); err != nil {
- logger.Log(0, "error unmarshalling extclient: ",
- err.Error())
- logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
- return
+ if oldExtClient.ClientID == update.ClientID {
+ if err := validateCustomExtClient(&update, false); err != nil {
+ logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
+ return
+ }
+ } else {
+ if err := validateCustomExtClient(&update, true); err != nil {
+ logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
+ return
+ }
}
// == PRO ==
- networkName := params["network"]
+ //networkName := params["network"]
var changedID = update.ClientID != oldExtClient.ClientID
if r.Header.Get("ismaster") != "yes" {
userID := r.Header.Get("user")
- _, doesOwn := doesUserOwnClient(userID, params["clientid"], networkName)
+ _, doesOwn := doesUserOwnClient(userID, params["clientid"], oldExtClient.Network)
if !doesOwn {
logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("user not permitted"), "internal"))
return
}
}
if changedID && oldExtClient.OwnerID != "" {
- if err := pro.DissociateNetworkUserClient(oldExtClient.OwnerID, networkName, oldExtClient.ClientID); err != nil {
+ if err := pro.DissociateNetworkUserClient(oldExtClient.OwnerID, oldExtClient.Network, oldExtClient.ClientID); err != nil {
logger.Log(0, "failed to dissociate client", oldExtClient.ClientID, "from user", oldExtClient.OwnerID)
}
- if err := pro.AssociateNetworkUserClient(oldExtClient.OwnerID, networkName, update.ClientID); err != nil {
+ if err := pro.AssociateNetworkUserClient(oldExtClient.OwnerID, oldExtClient.Network, update.ClientID); err != nil {
logger.Log(0, "failed to associate client", update.ClientID, "to user", oldExtClient.OwnerID)
}
}
@@ -485,13 +472,15 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
if update.Enabled != oldExtClient.Enabled {
sendPeerUpdate = true
}
- // extra var need as logic.Update changes oldExtClient
- currentClient := oldExtClient
- newclient, err := logic.UpdateExtClient(&oldExtClient, &update)
- if err != nil {
- logger.Log(0, r.Header.Get("user"),
- fmt.Sprintf("failed to update ext client [%s], network [%s]: %v",
- clientid, network, err))
+ newclient := logic.UpdateExtClient(&oldExtClient, &update)
+ if err := logic.DeleteExtClient(oldExtClient.Network, oldExtClient.ClientID); err != nil {
+
+ slog.Error("failed to delete ext client", "user", r.Header.Get("user"), "id", oldExtClient.ClientID, "network", oldExtClient.Network, "error", err)
+ logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+ return
+ }
+ if err := logic.SaveExtClient(&newclient); err != nil {
+ slog.Error("failed to save ext client", "user", r.Header.Get("user"), "id", newclient.ClientID, "network", newclient.Network, "error", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
@@ -507,7 +496,7 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(newclient)
if changedID {
go func() {
- if err := mq.PublishExtClientDNSUpdate(currentClient, *newclient, networkName); err != nil {
+ if err := mq.PublishExtClientDNSUpdate(oldExtClient, newclient, oldExtClient.Network); err != nil {
logger.Log(1, "error pubishing dns update for extcient update", err.Error())
}
}()
@@ -647,18 +636,20 @@ func doesUserOwnClient(username, clientID, network string) (bool, bool) {
return false, logic.StringSliceContains(netUser.Clients, clientID)
}
-// validateExtClient Validates the extclient object
-func validateExtClient(extclient *models.ExtClient, customExtClient *models.CustomExtClient) error {
+// validateCustomExtClient Validates the extclient object
+func validateCustomExtClient(customExtClient *models.CustomExtClient, checkID bool) error {
//validate clientid
- if customExtClient.ClientID != "" && !validName(customExtClient.ClientID) {
- return errInvalidExtClientID
+ if customExtClient.ClientID != "" {
+ if err := isValid(customExtClient.ClientID, checkID); err != nil {
+ return fmt.Errorf("client validatation: %v", err)
+ }
}
- extclient.ClientID = customExtClient.ClientID
+ //extclient.ClientID = customExtClient.ClientID
if len(customExtClient.PublicKey) > 0 {
if _, err := wgtypes.ParseKey(customExtClient.PublicKey); err != nil {
return errInvalidExtClientPubKey
}
- extclient.PublicKey = customExtClient.PublicKey
+ //extclient.PublicKey = customExtClient.PublicKey
}
//validate extra ips
if len(customExtClient.ExtraAllowedIPs) > 0 {
@@ -667,14 +658,33 @@ func validateExtClient(extclient *models.ExtClient, customExtClient *models.Cust
return errInvalidExtClientExtraIP
}
}
- extclient.ExtraAllowedIPs = customExtClient.ExtraAllowedIPs
+ //extclient.ExtraAllowedIPs = customExtClient.ExtraAllowedIPs
}
//validate DNS
if customExtClient.DNS != "" {
if ip := net.ParseIP(customExtClient.DNS); ip == nil {
return errInvalidExtClientDNS
}
- extclient.DNS = customExtClient.DNS
+ //extclient.DNS = customExtClient.DNS
+ }
+ return nil
+}
+
+// isValid Checks if the clientid is valid
+func isValid(clientid string, checkID bool) error {
+ if !validName(clientid) {
+ return errInvalidExtClientID
+ }
+ if checkID {
+ extclients, err := logic.GetAllExtClients()
+ if err != nil {
+ return fmt.Errorf("extclients isValid: %v", err)
+ }
+ for _, extclient := range extclients {
+ if clientid == extclient.ClientID {
+ return errDuplicateExtClientName
+ }
+ }
}
return nil
}
diff --git a/controllers/regex.go b/controllers/regex.go
index 668c59845..ae913323c 100644
--- a/controllers/regex.go
+++ b/controllers/regex.go
@@ -10,6 +10,7 @@ var (
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")
+ errDuplicateExtClientName = errors.New("duplicate client name")
)
// allow only dashes and alphaneumeric for ext client and node names
diff --git a/k8s/client/netclient-daemonset.yaml b/k8s/client/netclient-daemonset.yaml
index 57efaa858..635e25769 100644
--- a/k8s/client/netclient-daemonset.yaml
+++ b/k8s/client/netclient-daemonset.yaml
@@ -16,7 +16,7 @@ spec:
hostNetwork: true
containers:
- name: netclient
- image: gravitl/netclient:v0.20.5
+ image: gravitl/netclient:v0.20.6
env:
- name: TOKEN
value: "TOKEN_VALUE"
diff --git a/k8s/client/netclient.yaml b/k8s/client/netclient.yaml
index 8ab17867c..12a6ea116 100644
--- a/k8s/client/netclient.yaml
+++ b/k8s/client/netclient.yaml
@@ -28,7 +28,7 @@ spec:
# - "