Browse Source

Merge pull request #2198 from gravitl/release_v0.18.6

v0.18.6
Alex Feiszli 2 years ago
parent
commit
3496cc7725

+ 1 - 0
.github/ISSUE_TEMPLATE/bug-report.yml

@@ -31,6 +31,7 @@ body:
       label: Version
       label: Version
       description: What version are you running?
       description: What version are you running?
       options:
       options:
+        - v0.18.6
         - v0.18.5
         - v0.18.5
         - v0.18.4
         - v0.18.4
         - v0.18.3
         - v0.18.3

+ 1 - 1
.github/workflows/release-assets.yml

@@ -31,7 +31,7 @@ jobs:
         run: |
         run: |
           git fetch --force --tags
           git fetch --force --tags
       - name: Setup go
       - name: Setup go
-        uses: actions/setup-go@v3
+        uses: actions/setup-go@v4
         with:
         with:
           go-version: 1.19
           go-version: 1.19
       - name: GoReleaser (full release)
       - name: GoReleaser (full release)

+ 1 - 1
.github/workflows/release-branch.yml

@@ -21,7 +21,7 @@ jobs:
         with:
         with:
           ref: develop
           ref: develop
       - name: setup go
       - name: setup go
-        uses: actions/setup-go@v3
+        uses: actions/setup-go@v4
         with:
         with:
           go-version: 1.19
           go-version: 1.19
       - name: setup git
       - name: setup git

+ 4 - 4
.github/workflows/test.yml

@@ -13,7 +13,7 @@ jobs:
       - name: Checkout
       - name: Checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
       - name: Setup Go
       - name: Setup Go
-        uses: actions/setup-go@v3
+        uses: actions/setup-go@v4
         with:
         with:
           go-version: 1.19
           go-version: 1.19
       - name: Build
       - name: Build
@@ -27,7 +27,7 @@ jobs:
       - name: Checkout
       - name: Checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
       - name: Setup go
       - name: Setup go
-        uses: actions/setup-go@v3
+        uses: actions/setup-go@v4
         with:
         with:
           go-version: 1.19
           go-version: 1.19
       - name: Build
       - name: Build
@@ -44,7 +44,7 @@ jobs:
       - name: Checkout
       - name: Checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
       - name: Setup Go
       - name: Setup Go
-        uses: actions/setup-go@v3
+        uses: actions/setup-go@v4
         with:
         with:
           go-version: 1.19
           go-version: 1.19
       - name: run tests
       - name: run tests
@@ -63,7 +63,7 @@ jobs:
       - name: Checkout
       - name: Checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
       - name: Setup Go
       - name: Setup Go
-        uses: actions/setup-go@v3
+        uses: actions/setup-go@v4
         with:
         with:
           go-version: 1.19
           go-version: 1.19
       - name: run static checks
       - name: run static checks

+ 1 - 1
.github/workflows/upgraderelease.yml

@@ -20,7 +20,7 @@ jobs:
       - run: |
       - run: |
           git fetch --force --tags
           git fetch --force --tags
       - name: Setup go
       - name: Setup go
-        uses: actions/setup-go@v3
+        uses: actions/setup-go@v4
         with:
         with:
           go-version: 1.19
           go-version: 1.19
       - name: goreleaser
       - name: goreleaser

+ 1 - 1
README.md

@@ -17,7 +17,7 @@
 
 
 <p align="center">
 <p align="center">
   <a href="https://github.com/gravitl/netmaker/releases">
   <a href="https://github.com/gravitl/netmaker/releases">
-    <img src="https://img.shields.io/badge/Version-0.18.5-informational?style=flat-square" />
+    <img src="https://img.shields.io/badge/Version-0.18.6-informational?style=flat-square" />
   </a>
   </a>
   <a href="https://hub.docker.com/r/gravitl/netmaker/tags">
   <a href="https://hub.docker.com/r/gravitl/netmaker/tags">
     <img src="https://img.shields.io/docker/pulls/gravitl/netmaker?label=downloads" />
     <img src="https://img.shields.io/docker/pulls/gravitl/netmaker?label=downloads" />

+ 2 - 2
compose/docker-compose-emqx.yml

@@ -3,7 +3,7 @@ version: "3.4"
 services:
 services:
   netmaker:
   netmaker:
     container_name: netmaker
     container_name: netmaker
-    image: gravitl/netmaker:v0.18.5
+    image: gravitl/netmaker:v0.18.6
     restart: always
     restart: always
     volumes:
     volumes:
       - dnsconfig:/root/config/dnsconfig
       - dnsconfig:/root/config/dnsconfig
@@ -35,7 +35,7 @@ services:
       - "3478:3478/udp"
       - "3478:3478/udp"
   netmaker-ui:
   netmaker-ui:
     container_name: netmaker-ui
     container_name: netmaker-ui
-    image: gravitl/netmaker-ui:v0.18.4
+    image: gravitl/netmaker-ui:v0.18.6
     depends_on:
     depends_on:
       - netmaker
       - netmaker
     links:
     links:

+ 14 - 15
compose/docker-compose.ee.yml

@@ -9,9 +9,7 @@ services:
       - dnsconfig:/root/config/dnsconfig
       - dnsconfig:/root/config/dnsconfig
       - sqldata:/root/data
       - sqldata:/root/data
     environment:
     environment:
-      BROKER_ENDPOINT: "wss://broker.NETMAKER_BASE_DOMAIN/mqtt"
-      BROKER_TYPE: "emqx"
-      EMQX_REST_ENDPOINT: "http://mq:18083"
+      BROKER_ENDPOINT: "wss://broker.NETMAKER_BASE_DOMAIN"
       SERVER_NAME: "NETMAKER_BASE_DOMAIN"
       SERVER_NAME: "NETMAKER_BASE_DOMAIN"
       STUN_LIST: "stun.NETMAKER_BASE_DOMAIN:3478,stun1.netmaker.io:3478,stun2.netmaker.io:3478,stun1.l.google.com:19302,stun2.l.google.com:19302"
       STUN_LIST: "stun.NETMAKER_BASE_DOMAIN:3478,stun1.netmaker.io:3478,stun2.netmaker.io:3478,stun1.l.google.com:19302,stun2.l.google.com:19302"
       SERVER_HOST: "SERVER_PUBLIC_IP"
       SERVER_HOST: "SERVER_PUBLIC_IP"
@@ -25,7 +23,7 @@ services:
       DISPLAY_KEYS: "on"
       DISPLAY_KEYS: "on"
       DATABASE: "sqlite"
       DATABASE: "sqlite"
       NODE_ID: "netmaker-server-1"
       NODE_ID: "netmaker-server-1"
-      SERVER_BROKER_ENDPOINT: "ws://mq:8083/mqtt"
+      SERVER_BROKER_ENDPOINT: "ws://mq:1883"
       MQ_USERNAME: "REPLACE_MQ_USERNAME"
       MQ_USERNAME: "REPLACE_MQ_USERNAME"
       MQ_PASSWORD: "REPLACE_MQ_PASSWORD"
       MQ_PASSWORD: "REPLACE_MQ_PASSWORD"
       STUN_PORT: "3478"
       STUN_PORT: "3478"
@@ -68,17 +66,18 @@ services:
       - dnsconfig:/root/dnsconfig
       - dnsconfig:/root/dnsconfig
   mq:
   mq:
     container_name: mq
     container_name: mq
-    image: emqx/emqx:5.0.9
+    image: eclipse-mosquitto:2.0.15-openssl
+    depends_on:
+      - netmaker
     restart: unless-stopped
     restart: unless-stopped
+    command: ["/mosquitto/config/wait.sh"]
     environment:
     environment:
-      EMQX_NAME: "emqx"
-      EMQX_DASHBOARD__DEFAULT_PASSWORD: "REPLACE_MQ_PASSWORD"
-      EMQX_DASHBOARD__DEFAULT_USERNAME: "REPLACE_MQ_USERNAME"
-    ports:
-      - "1883:1883" # MQTT
-      - "8883:8883" # SSL MQTT
-      - "8083:8083" # Websockets
-      - "18083:18083" # Dashboard/REST_API
+      MQ_PASSWORD: "REPLACE_MQ_PASSWORD"
+      MQ_USERNAME: "REPLACE_MQ_USERNAME"
+    volumes:
+      - /root/mosquitto.conf:/mosquitto/config/mosquitto.conf
+      - /root/wait.sh:/mosquitto/config/wait.sh
+      - mosquitto_logs:/mosquitto/log
   prometheus:
   prometheus:
     container_name: prometheus
     container_name: prometheus
     image: gravitl/netmaker-prometheus:latest
     image: gravitl/netmaker-prometheus:latest
@@ -112,8 +111,8 @@ services:
     depends_on:
     depends_on:
       - netmaker
       - netmaker
     environment:
     environment:
-      SERVER_BROKER_ENDPOINT: "ws://mq:8083/mqtt"
-      BROKER_ENDPOINT: "wss://broker.NETMAKER_BASE_DOMAIN/mqtt"
+      SERVER_BROKER_ENDPOINT: "ws://mq:1883"
+      BROKER_ENDPOINT: "wss://broker.NETMAKER_BASE_DOMAIN"
       PROMETHEUS: "on"
       PROMETHEUS: "on"
       VERBOSITY: "1"
       VERBOSITY: "1"
       API_PORT: "8085"
       API_PORT: "8085"

+ 1 - 1
compose/docker-compose.netclient.yml

@@ -3,7 +3,7 @@ version: "3.4"
 services:
 services:
   netclient:
   netclient:
     container_name: netclient
     container_name: netclient
-    image: 'gravitl/netclient:v0.18.5'
+    image: 'gravitl/netclient:v0.18.6'
     hostname: netmaker-1
     hostname: netmaker-1
     network_mode: host
     network_mode: host
     restart: always
     restart: always

+ 1 - 1
controllers/docs.go

@@ -10,7 +10,7 @@
 //
 //
 //	Schemes: https
 //	Schemes: https
 //	BasePath: /
 //	BasePath: /
-//	Version: 0.18.5
+//	Version: 0.18.6
 //	Host: netmaker.io
 //	Host: netmaker.io
 //
 //
 //	Consumes:
 //	Consumes:

+ 13 - 11
controllers/node.go

@@ -564,7 +564,7 @@ func deleteIngressGateway(w http.ResponseWriter, r *http.Request) {
 	var params = mux.Vars(r)
 	var params = mux.Vars(r)
 	nodeid := params["nodeid"]
 	nodeid := params["nodeid"]
 	netid := params["network"]
 	netid := params["network"]
-	node, wasFailover, err := logic.DeleteIngressGateway(netid, nodeid)
+	node, wasFailover, removedClients, err := logic.DeleteIngressGateway(netid, nodeid)
 	if err != nil {
 	if err != nil {
 		logger.Log(0, r.Header.Get("user"),
 		logger.Log(0, r.Header.Get("user"),
 			fmt.Sprintf("failed to delete ingress gateway on node [%s] on network [%s]: %v",
 			fmt.Sprintf("failed to delete ingress gateway on node [%s] on network [%s]: %v",
@@ -584,6 +584,18 @@ func deleteIngressGateway(w http.ResponseWriter, r *http.Request) {
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(apiNode)
 	json.NewEncoder(w).Encode(apiNode)
 
 
+	if len(removedClients) > 0 {
+		host, err := logic.GetHost(node.HostID.String())
+		if err == nil {
+			go mq.PublishSingleHostPeerUpdate(
+				context.Background(),
+				host,
+				nil,
+				removedClients[:],
+			)
+		}
+	}
+
 	runUpdates(&node, true)
 	runUpdates(&node, true)
 }
 }
 
 
@@ -641,16 +653,6 @@ func updateNode(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 newNode.IsIngressGateway {
-		host.ProxyEnabled = true
-		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
-		}
-	}
 	relayedUpdate := false
 	relayedUpdate := false
 	if currentNode.IsRelayed && (currentNode.Address.String() != newNode.Address.String() || currentNode.Address6.String() != newNode.Address6.String()) {
 	if currentNode.IsRelayed && (currentNode.Address.String() != newNode.Address.String() || currentNode.Address6.String() != newNode.Address6.String()) {
 		relayedUpdate = true
 		relayedUpdate = true

+ 16 - 0
controllers/user.go

@@ -331,7 +331,18 @@ func updateUser(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Type", "application/json")
 	var params = mux.Vars(r)
 	var params = mux.Vars(r)
 	// start here
 	// start here
+	jwtUser, _, isadmin, err := logic.VerifyJWT(r.Header.Get("Authorization"))
+	if err != nil {
+		logger.Log(0, "verifyJWT error", err.Error())
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
 	username := params["username"]
 	username := params["username"]
+	if username != jwtUser && !isadmin {
+		logger.Log(0, "non-admin user", jwtUser, "attempted to update user", username)
+		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("not authorizied"), "unauthorized"))
+		return
+	}
 	user, err := logic.GetUser(username)
 	user, err := logic.GetUser(username)
 	if err != nil {
 	if err != nil {
 		logger.Log(0, username,
 		logger.Log(0, username,
@@ -354,6 +365,11 @@ func updateUser(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 		return
 	}
 	}
+	if userchange.IsAdmin && !isadmin {
+		logger.Log(0, "non-admin user", jwtUser, "attempted get admin privilages")
+		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("not authorizied"), "unauthorized"))
+		return
+	}
 	userchange.Networks = nil
 	userchange.Networks = nil
 	user, err = logic.UpdateUser(&userchange, user)
 	user, err = logic.UpdateUser(&userchange, user)
 	if err != nil {
 	if err != nil {

+ 9 - 9
go.mod

@@ -4,7 +4,7 @@ go 1.19
 
 
 require (
 require (
 	github.com/eclipse/paho.mqtt.golang v1.4.2
 	github.com/eclipse/paho.mqtt.golang v1.4.2
-	github.com/go-playground/validator/v10 v10.11.2
+	github.com/go-playground/validator/v10 v10.12.0
 	github.com/golang-jwt/jwt/v4 v4.5.0
 	github.com/golang-jwt/jwt/v4 v4.5.0
 	github.com/google/uuid v1.3.0
 	github.com/google/uuid v1.3.0
 	github.com/gorilla/handlers v1.5.1
 	github.com/gorilla/handlers v1.5.1
@@ -15,11 +15,11 @@ require (
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
 	github.com/stretchr/testify v1.8.2
 	github.com/stretchr/testify v1.8.2
 	github.com/txn2/txeh v1.3.0
 	github.com/txn2/txeh v1.3.0
-	golang.org/x/crypto v0.7.0
-	golang.org/x/net v0.8.0 // indirect
-	golang.org/x/oauth2 v0.6.0
-	golang.org/x/sys v0.6.0 // indirect
-	golang.org/x/text v0.8.0 // indirect
+	golang.org/x/crypto v0.8.0
+	golang.org/x/net v0.9.0 // indirect
+	golang.org/x/oauth2 v0.7.0
+	golang.org/x/sys v0.7.0 // indirect
+	golang.org/x/text v0.9.0 // indirect
 	golang.zx2c4.com/wireguard v0.0.0-20220920152132-bb719d3a6e2c // indirect
 	golang.zx2c4.com/wireguard v0.0.0-20220920152132-bb719d3a6e2c // indirect
 	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220324164955-056925b7df31
 	golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220324164955-056925b7df31
 	google.golang.org/protobuf v1.28.1 // indirect
 	google.golang.org/protobuf v1.28.1 // indirect
@@ -44,13 +44,13 @@ require (
 	github.com/guumaster/tablewriter v0.0.10
 	github.com/guumaster/tablewriter v0.0.10
 	github.com/matryer/is v1.4.1
 	github.com/matryer/is v1.4.1
 	github.com/olekukonko/tablewriter v0.0.5
 	github.com/olekukonko/tablewriter v0.0.5
-	github.com/spf13/cobra v1.6.1
+	github.com/spf13/cobra v1.7.0
 )
 )
 
 
 require (
 require (
 	cloud.google.com/go/compute/metadata v0.2.1 // indirect
 	cloud.google.com/go/compute/metadata v0.2.1 // indirect
 	github.com/go-jose/go-jose/v3 v3.0.0 // indirect
 	github.com/go-jose/go-jose/v3 v3.0.0 // indirect
-	github.com/inconshreveable/mousetrap v1.0.1 // indirect
+	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/kr/pretty v0.3.1 // indirect
 	github.com/kr/pretty v0.3.1 // indirect
 	github.com/rivo/uniseg v0.2.0 // indirect
 	github.com/rivo/uniseg v0.2.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
@@ -66,7 +66,7 @@ require (
 	github.com/google/go-cmp v0.5.9 // indirect
 	github.com/google/go-cmp v0.5.9 // indirect
 	github.com/hashicorp/go-version v1.6.0
 	github.com/hashicorp/go-version v1.6.0
 	github.com/josharian/native v1.0.0 // indirect
 	github.com/josharian/native v1.0.0 // indirect
-	github.com/leodido/go-urn v1.2.1 // indirect
+	github.com/leodido/go-urn v1.2.2 // indirect
 	github.com/mattn/go-runewidth v0.0.13 // indirect
 	github.com/mattn/go-runewidth v0.0.13 // indirect
 	github.com/mdlayher/genetlink v1.2.0 // indirect
 	github.com/mdlayher/genetlink v1.2.0 // indirect
 	github.com/mdlayher/netlink v1.6.0 // indirect
 	github.com/mdlayher/netlink v1.6.0 // indirect

+ 20 - 19
go.sum

@@ -34,8 +34,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
 github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
-github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
-github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
+github.com/go-playground/validator/v10 v10.12.0 h1:E4gtWgxWxp8YSxExrQFv5BpCahla0PVF2oTTEYaWQGI=
+github.com/go-playground/validator/v10 v10.12.0/go.mod h1:hCAPuzYvKdP33pxWa+2+6AIKXEKqjIUyqsNCtbsSJrA=
 github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -64,8 +64,8 @@ github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mO
 github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
-github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
+github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
 github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk=
 github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk=
 github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
 github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -75,8 +75,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
-github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
+github.com/leodido/go-urn v1.2.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4=
+github.com/leodido/go-urn v1.2.2/go.mod h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ=
 github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
 github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
 github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -118,14 +118,15 @@ github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f/go.mod h1:UW/gxgQw
 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
-github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
-github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
+github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
+github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -155,8 +156,8 @@ golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
-golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
+golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
+golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
 golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
 golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
 golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
 golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@@ -172,11 +173,11 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
 golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
 golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
 golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
-golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
-golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
+golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
 golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk=
 golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk=
-golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
-golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
+golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
+golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -198,8 +199,8 @@ golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
-golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
 golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
@@ -209,8 +210,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
-golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
@@ -232,8 +233,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
 google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
 google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
 google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

+ 1 - 1
k8s/client/netclient-daemonset.yaml

@@ -16,7 +16,7 @@ spec:
       hostNetwork: true
       hostNetwork: true
       containers:
       containers:
       - name: netclient
       - name: netclient
-        image: gravitl/netclient:v0.18.5
+        image: gravitl/netclient:v0.18.6
         env:
         env:
         - name: TOKEN
         - name: TOKEN
           value: "TOKEN_VALUE"
           value: "TOKEN_VALUE"

+ 1 - 1
k8s/client/netclient.yaml

@@ -28,7 +28,7 @@ spec:
       #           - "<node label value>"
       #           - "<node label value>"
       containers:
       containers:
       - name: netclient
       - name: netclient
-        image: gravitl/netclient:v0.18.5
+        image: gravitl/netclient:v0.18.6
         env:
         env:
         - name: TOKEN
         - name: TOKEN
           value: "TOKEN_VALUE"
           value: "TOKEN_VALUE"

+ 1 - 1
k8s/server/netmaker-server.yaml

@@ -79,7 +79,7 @@ spec:
           value: "Kubernetes"
           value: "Kubernetes"
         - name: VERBOSITY
         - name: VERBOSITY
           value: "3"
           value: "3"
-        image: gravitl/netmaker:v0.18.5
+        image: gravitl/netmaker:v0.18.6
         imagePullPolicy: Always
         imagePullPolicy: Always
         name: netmaker
         name: netmaker
         ports:
         ports:

+ 1 - 1
k8s/server/netmaker-ui.yaml

@@ -15,7 +15,7 @@ spec:
     spec:
     spec:
       containers:
       containers:
       - name: netmaker-ui
       - name: netmaker-ui
-        image: gravitl/netmaker-ui:v0.18.5
+        image: gravitl/netmaker-ui:v0.18.6
         ports:
         ports:
         - containerPort: 443
         - containerPort: 443
         env:
         env:

+ 2 - 3
logic/extpeers.go

@@ -141,7 +141,7 @@ func CreateExtClient(extclient *models.ExtClient) error {
 		}
 		}
 		extclient.PrivateKey = privateKey.String()
 		extclient.PrivateKey = privateKey.String()
 		extclient.PublicKey = privateKey.PublicKey().String()
 		extclient.PublicKey = privateKey.PublicKey().String()
-	} else {
+	} else if len(extclient.PrivateKey) == 0 && len(extclient.PublicKey) > 0 {
 		extclient.PrivateKey = "[ENTER PRIVATE KEY]"
 		extclient.PrivateKey = "[ENTER PRIVATE KEY]"
 	}
 	}
 
 
@@ -194,8 +194,7 @@ func UpdateExtClient(newclientid string, network string, enabled bool, client *m
 	if err != nil {
 	if err != nil {
 		return client, err
 		return client, err
 	}
 	}
-	if newclientid != client.ClientID {
-		//name change only
+	if newclientid != client.ClientID { // name change only
 		client.ClientID = newclientid
 		client.ClientID = newclientid
 		client.LastModified = time.Now().Unix()
 		client.LastModified = time.Now().Unix()
 		data, err := json.Marshal(&client)
 		data, err := json.Marshal(&client)

+ 17 - 14
logic/gateway.go

@@ -134,22 +134,22 @@ func CreateIngressGateway(netid string, nodeid string, failover bool) (models.No
 }
 }
 
 
 // DeleteIngressGateway - deletes an ingress gateway
 // DeleteIngressGateway - deletes an ingress gateway
-func DeleteIngressGateway(networkName string, nodeid string) (models.Node, bool, error) {
+func DeleteIngressGateway(networkName string, nodeid string) (models.Node, bool, []models.ExtClient, error) {
+	removedClients := []models.ExtClient{}
 	node, err := GetNodeByID(nodeid)
 	node, err := GetNodeByID(nodeid)
 	if err != nil {
 	if err != nil {
-		return models.Node{}, false, err
+		return models.Node{}, false, removedClients, err
 	}
 	}
-	//host, err := GetHost(node.ID.String())
-	//if err != nil {
-	//return models.Node{}, false, err
-	//}
-	//network, err := GetParentNetwork(networkName)
-	if err != nil {
-		return models.Node{}, false, err
+	clients, err := GetExtClientsByID(nodeid, networkName)
+	if err != nil && !database.IsEmptyRecord(err) {
+		return models.Node{}, false, removedClients, err
 	}
 	}
+
+	removedClients = clients
+
 	// delete ext clients belonging to ingress gateway
 	// delete ext clients belonging to ingress gateway
 	if err = DeleteGatewayExtClients(node.ID.String(), networkName); err != nil {
 	if err = DeleteGatewayExtClients(node.ID.String(), networkName); err != nil {
-		return models.Node{}, false, err
+		return models.Node{}, false, removedClients, err
 	}
 	}
 	logger.Log(3, "deleting ingress gateway")
 	logger.Log(3, "deleting ingress gateway")
 	wasFailover := node.Failover
 	wasFailover := node.Failover
@@ -169,20 +169,23 @@ func DeleteIngressGateway(networkName string, nodeid string) (models.Node, bool,
 
 
 	data, err := json.Marshal(&node)
 	data, err := json.Marshal(&node)
 	if err != nil {
 	if err != nil {
-		return models.Node{}, false, err
+		return models.Node{}, false, removedClients, err
 	}
 	}
 	err = database.Insert(node.ID.String(), string(data), database.NODES_TABLE_NAME)
 	err = database.Insert(node.ID.String(), string(data), database.NODES_TABLE_NAME)
 	if err != nil {
 	if err != nil {
-		return models.Node{}, wasFailover, err
+		return models.Node{}, wasFailover, removedClients, err
 	}
 	}
 	err = SetNetworkNodesLastModified(networkName)
 	err = SetNetworkNodesLastModified(networkName)
-	return node, wasFailover, err
+	return node, wasFailover, removedClients, err
 }
 }
 
 
 // DeleteGatewayExtClients - deletes ext clients based on gateway (mac) of ingress node and network
 // DeleteGatewayExtClients - deletes ext clients based on gateway (mac) of ingress node and network
 func DeleteGatewayExtClients(gatewayID string, networkName string) error {
 func DeleteGatewayExtClients(gatewayID string, networkName string) error {
 	currentExtClients, err := GetNetworkExtClients(networkName)
 	currentExtClients, err := GetNetworkExtClients(networkName)
-	if err != nil && !database.IsEmptyRecord(err) {
+	if database.IsEmptyRecord(err) {
+		return nil
+	}
+	if err != nil {
 		return err
 		return err
 	}
 	}
 	for _, extClient := range currentExtClients {
 	for _, extClient := range currentExtClients {

+ 4 - 0
logic/hosts.go

@@ -178,6 +178,10 @@ func UpdateHostFromClient(newHost, currHost *models.Host) (sendPeerUpdate bool)
 	if newHost.Name != "" {
 	if newHost.Name != "" {
 		currHost.Name = newHost.Name
 		currHost.Name = newHost.Name
 	}
 	}
+	if len(newHost.NatType) > 0 && newHost.NatType != currHost.NatType {
+		currHost.NatType = newHost.NatType
+		sendPeerUpdate = true
+	}
 
 
 	return
 	return
 }
 }

+ 13 - 0
logic/jwts.go

@@ -3,6 +3,7 @@ package logic
 import (
 import (
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
+	"strings"
 	"time"
 	"time"
 
 
 	"github.com/golang-jwt/jwt/v4"
 	"github.com/golang-jwt/jwt/v4"
@@ -101,6 +102,18 @@ func CreateUserJWT(username string, networks []string, isadmin bool) (response s
 	return "", err
 	return "", err
 }
 }
 
 
+// VerifyJWT verifies Auth Header
+func VerifyJWT(bearerToken string) (username string, networks []string, isadmin bool, err error) {
+	token := ""
+	tokenSplit := strings.Split(bearerToken, " ")
+	if len(tokenSplit) > 1 {
+		token = tokenSplit[1]
+	} else {
+		return "", nil, false, errors.New("invalid auth header")
+	}
+	return VerifyUserToken(token)
+}
+
 // VerifyUserToken func will used to Verify the JWT Token while using APIS
 // VerifyUserToken func will used to Verify the JWT Token while using APIS
 func VerifyUserToken(tokenString string) (username string, networks []string, isadmin bool, err error) {
 func VerifyUserToken(tokenString string) (username string, networks []string, isadmin bool, err error) {
 	claims := &models.UserClaims{}
 	claims := &models.UserClaims{}

+ 68 - 65
logic/peers.go

@@ -140,7 +140,7 @@ func ResetPeerUpdateContext() {
 }
 }
 
 
 // GetPeerUpdateForHost - gets the consolidated peer update for the host from all networks
 // GetPeerUpdateForHost - gets the consolidated peer update for the host from all networks
-func GetPeerUpdateForHost(ctx context.Context, network string, host *models.Host, deletedNode *models.Node, deletedClient *models.ExtClient) (models.HostPeerUpdate, error) {
+func GetPeerUpdateForHost(ctx context.Context, network string, host *models.Host, deletedNode *models.Node, deletedClients []models.ExtClient) (models.HostPeerUpdate, error) {
 	if host == nil {
 	if host == nil {
 		return models.HostPeerUpdate{}, errors.New("host is nil")
 		return models.HostPeerUpdate{}, errors.New("host is nil")
 	}
 	}
@@ -325,68 +325,68 @@ func GetPeerUpdateForHost(ctx context.Context, network string, host *models.Host
 					hostPeerUpdate.NodePeers = append(hostPeerUpdate.NodePeers, nodePeer)
 					hostPeerUpdate.NodePeers = append(hostPeerUpdate.NodePeers, nodePeer)
 				}
 				}
 			}
 			}
-			var extPeers []wgtypes.PeerConfig
-			var extPeerIDAndAddrs []models.IDandAddr
-			if node.IsIngressGateway {
-				extPeers, extPeerIDAndAddrs, err = getExtPeers(&node)
-				if err == nil {
-					for _, extPeerIdAndAddr := range extPeerIDAndAddrs {
-						extPeerIdAndAddr := extPeerIdAndAddr
-						nodePeerMap[extPeerIdAndAddr.ID] = models.PeerRouteInfo{
-							PeerAddr: net.IPNet{
-								IP:   net.ParseIP(extPeerIdAndAddr.Address),
-								Mask: getCIDRMaskFromAddr(extPeerIdAndAddr.Address),
-							},
-							PeerKey: extPeerIdAndAddr.ID,
-							Allow:   true,
-							ID:      extPeerIdAndAddr.ID,
-						}
+		}
+		var extPeers []wgtypes.PeerConfig
+		var extPeerIDAndAddrs []models.IDandAddr
+		if node.IsIngressGateway {
+			extPeers, extPeerIDAndAddrs, err = getExtPeers(&node)
+			if err == nil {
+				for _, extPeerIdAndAddr := range extPeerIDAndAddrs {
+					extPeerIdAndAddr := extPeerIdAndAddr
+					nodePeerMap[extPeerIdAndAddr.ID] = models.PeerRouteInfo{
+						PeerAddr: net.IPNet{
+							IP:   net.ParseIP(extPeerIdAndAddr.Address),
+							Mask: getCIDRMaskFromAddr(extPeerIdAndAddr.Address),
+						},
+						PeerKey: extPeerIdAndAddr.ID,
+						Allow:   true,
+						ID:      extPeerIdAndAddr.ID,
+					}
+				}
+				hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, extPeers...)
+				for _, extPeerIdAndAddr := range extPeerIDAndAddrs {
+					extPeerIdAndAddr := extPeerIdAndAddr
+					hostPeerUpdate.HostPeerIDs[extPeerIdAndAddr.ID] = make(map[string]models.IDandAddr)
+					hostPeerUpdate.HostPeerIDs[extPeerIdAndAddr.ID][extPeerIdAndAddr.ID] = models.IDandAddr{
+						ID:      extPeerIdAndAddr.ID,
+						Address: extPeerIdAndAddr.Address,
+						Name:    extPeerIdAndAddr.Name,
+						Network: node.Network,
 					}
 					}
-					hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, extPeers...)
-					for _, extPeerIdAndAddr := range extPeerIDAndAddrs {
-						extPeerIdAndAddr := extPeerIdAndAddr
-						hostPeerUpdate.HostPeerIDs[extPeerIdAndAddr.ID] = make(map[string]models.IDandAddr)
-						hostPeerUpdate.HostPeerIDs[extPeerIdAndAddr.ID][extPeerIdAndAddr.ID] = models.IDandAddr{
-							ID:      extPeerIdAndAddr.ID,
-							Address: extPeerIdAndAddr.Address,
-							Name:    extPeerIdAndAddr.Name,
-							Network: node.Network,
-						}
 
 
-						hostPeerUpdate.IngressInfo.ExtPeers[extPeerIdAndAddr.ID] = models.ExtClientInfo{
-							Masquerade: true,
-							IngGwAddr: net.IPNet{
-								IP:   net.ParseIP(node.PrimaryAddress()),
-								Mask: getCIDRMaskFromAddr(node.PrimaryAddress()),
-							},
-							Network: node.PrimaryNetworkRange(),
-							ExtPeerAddr: net.IPNet{
-								IP:   net.ParseIP(extPeerIdAndAddr.Address),
-								Mask: getCIDRMaskFromAddr(extPeerIdAndAddr.Address),
-							},
-							ExtPeerKey: extPeerIdAndAddr.ID,
-							Peers:      filterNodeMapForClientACLs(extPeerIdAndAddr.ID, node.Network, nodePeerMap),
-						}
-						if node.Network == network {
-							hostPeerUpdate.PeerIDs[extPeerIdAndAddr.ID] = extPeerIdAndAddr
-							hostPeerUpdate.NodePeers = append(hostPeerUpdate.NodePeers, extPeers...)
-						}
+					hostPeerUpdate.IngressInfo.ExtPeers[extPeerIdAndAddr.ID] = models.ExtClientInfo{
+						Masquerade: true,
+						IngGwAddr: net.IPNet{
+							IP:   net.ParseIP(node.PrimaryAddress()),
+							Mask: getCIDRMaskFromAddr(node.PrimaryAddress()),
+						},
+						Network: node.PrimaryNetworkRange(),
+						ExtPeerAddr: net.IPNet{
+							IP:   net.ParseIP(extPeerIdAndAddr.Address),
+							Mask: getCIDRMaskFromAddr(extPeerIdAndAddr.Address),
+						},
+						ExtPeerKey: extPeerIdAndAddr.ID,
+						Peers:      filterNodeMapForClientACLs(extPeerIdAndAddr.ID, node.Network, nodePeerMap),
+					}
+					if node.Network == network {
+						hostPeerUpdate.PeerIDs[extPeerIdAndAddr.ID] = extPeerIdAndAddr
+						hostPeerUpdate.NodePeers = append(hostPeerUpdate.NodePeers, extPeers...)
 					}
 					}
-				} else if !database.IsEmptyRecord(err) {
-					logger.Log(1, "error retrieving external clients:", err.Error())
 				}
 				}
+			} else if !database.IsEmptyRecord(err) {
+				logger.Log(1, "error retrieving external clients:", err.Error())
 			}
 			}
-			if node.IsEgressGateway {
-				hostPeerUpdate.EgressInfo[node.ID.String()] = models.EgressInfo{
-					EgressID: node.ID.String(),
-					Network:  node.PrimaryNetworkRange(),
-					EgressGwAddr: net.IPNet{
-						IP:   net.ParseIP(node.PrimaryAddress()),
-						Mask: getCIDRMaskFromAddr(node.PrimaryAddress()),
-					},
-					GwPeers:     nodePeerMap,
-					EgressGWCfg: node.EgressGatewayRequest,
-				}
+		}
+		if node.IsEgressGateway {
+			hostPeerUpdate.EgressInfo[node.ID.String()] = models.EgressInfo{
+				EgressID: node.ID.String(),
+				Network:  node.PrimaryNetworkRange(),
+				EgressGwAddr: net.IPNet{
+					IP:   net.ParseIP(node.PrimaryAddress()),
+					Mask: getCIDRMaskFromAddr(node.PrimaryAddress()),
+				},
+				GwPeers:     nodePeerMap,
+				EgressGWCfg: node.EgressGatewayRequest,
 			}
 			}
 		}
 		}
 	}
 	}
@@ -408,13 +408,16 @@ func GetPeerUpdateForHost(ctx context.Context, network string, host *models.Host
 		hostPeerUpdate.NodePeers[i] = peer
 		hostPeerUpdate.NodePeers[i] = peer
 	}
 	}
 
 
-	if deletedClient != nil {
-		key, err := wgtypes.ParseKey(deletedClient.PublicKey)
-		if err == nil {
-			hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, wgtypes.PeerConfig{
-				PublicKey: key,
-				Remove:    true,
-			})
+	if len(deletedClients) > 0 {
+		for i := range deletedClients {
+			deletedClient := deletedClients[i]
+			key, err := wgtypes.ParseKey(deletedClient.PublicKey)
+			if err == nil {
+				hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, wgtypes.PeerConfig{
+					PublicKey: key,
+					Remove:    true,
+				})
+			}
 		}
 		}
 	}
 	}
 
 

+ 1 - 1
logic/security.go

@@ -187,7 +187,7 @@ func authenticateDNSToken(tokenString string) bool {
 	if len(tokens) < 2 {
 	if len(tokens) < 2 {
 		return false
 		return false
 	}
 	}
-	return tokens[1] == servercfg.GetDNSKey()
+	return len(servercfg.GetDNSKey()) > 0 && tokens[1] == servercfg.GetDNSKey()
 }
 }
 
 
 func ContinueIfUserMatch(next http.Handler) http.HandlerFunc {
 func ContinueIfUserMatch(next http.Handler) http.HandlerFunc {

+ 1 - 1
main.go

@@ -27,7 +27,7 @@ import (
 	stunserver "github.com/gravitl/netmaker/stun-server"
 	stunserver "github.com/gravitl/netmaker/stun-server"
 )
 )
 
 
-var version = "v0.18.5"
+var version = "v0.18.6"
 
 
 // Start DB Connection and start API Request Handler
 // Start DB Connection and start API Request Handler
 func main() {
 func main() {

+ 2 - 0
models/api_host.go

@@ -112,6 +112,8 @@ func (a *ApiHost) ConvertAPIHostToNMHost(currentHost *Host) *Host {
 	h.IsRelayed = a.IsRelayed
 	h.IsRelayed = a.IsRelayed
 	h.ProxyEnabled = a.ProxyEnabled
 	h.ProxyEnabled = a.ProxyEnabled
 	h.IsDefault = a.IsDefault
 	h.IsDefault = a.IsDefault
+	h.NatType = currentHost.NatType
+	h.TurnEndpoint = currentHost.TurnEndpoint
 
 
 	return &h
 	return &h
 }
 }

+ 16 - 0
models/host.go

@@ -2,6 +2,7 @@ package models
 
 
 import (
 import (
 	"net"
 	"net"
+	"net/netip"
 
 
 	"github.com/google/uuid"
 	"github.com/google/uuid"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
@@ -22,6 +23,19 @@ var OS_Types = struct {
 	IoT:     "iot",
 	IoT:     "iot",
 }
 }
 
 
+// NAT_Types - the type of NAT in which a HOST currently resides (simplified)
+var NAT_Types = struct {
+	Public     string
+	Symmetric  string
+	Asymmetric string
+	Double     string
+}{
+	Public:     "public",
+	Symmetric:  "symmetric",
+	Asymmetric: "asymmetric",
+	Double:     "double",
+}
+
 // WIREGUARD_INTERFACE name of wireguard interface
 // WIREGUARD_INTERFACE name of wireguard interface
 const WIREGUARD_INTERFACE = "netmaker"
 const WIREGUARD_INTERFACE = "netmaker"
 
 
@@ -60,6 +74,8 @@ type Host struct {
 	IsK8S            bool             `json:"isk8s" yaml:"isk8s"`
 	IsK8S            bool             `json:"isk8s" yaml:"isk8s"`
 	IsStatic         bool             `json:"isstatic" yaml:"isstatic"`
 	IsStatic         bool             `json:"isstatic" yaml:"isstatic"`
 	IsDefault        bool             `json:"isdefault" yaml:"isdefault"`
 	IsDefault        bool             `json:"isdefault" yaml:"isdefault"`
+	NatType          string           `json:"nat_type,omitempty" yaml:"nat_type,omitempty"`
+	TurnEndpoint     *netip.AddrPort  `json:"turn_endpoint,omitempty" yaml:"turn_endpoint,omitempty"`
 }
 }
 
 
 // FormatBool converts a boolean to a [yes|no] string
 // FormatBool converts a boolean to a [yes|no] string

+ 15 - 9
mq/handlers.go

@@ -396,16 +396,22 @@ func handleHostCheckin(h, currentHost *models.Host) bool {
 	for i := range h.Interfaces {
 	for i := range h.Interfaces {
 		h.Interfaces[i].AddressString = h.Interfaces[i].Address.String()
 		h.Interfaces[i].AddressString = h.Interfaces[i].Address.String()
 	}
 	}
-	ifaceDelta := len(h.Interfaces) != len(currentHost.Interfaces) || !h.EndpointIP.Equal(currentHost.EndpointIP)
-	currentHost.EndpointIP = h.EndpointIP
-	currentHost.Interfaces = h.Interfaces
-	currentHost.DefaultInterface = h.DefaultInterface
-	if err := logic.UpsertHost(currentHost); err != nil {
-		logger.Log(0, "failed to update host after check-in", h.Name, h.ID.String(), err.Error())
-		return false
+	ifaceDelta := len(h.Interfaces) != len(currentHost.Interfaces) ||
+		!h.EndpointIP.Equal(currentHost.EndpointIP) ||
+		(len(h.NatType) > 0 && h.NatType != currentHost.NatType) ||
+		h.DefaultInterface != currentHost.DefaultInterface
+	if ifaceDelta { // only save if something changes
+		currentHost.EndpointIP = h.EndpointIP
+		currentHost.Interfaces = h.Interfaces
+		currentHost.DefaultInterface = h.DefaultInterface
+		currentHost.NatType = h.NatType
+		if err := logic.UpsertHost(currentHost); err != nil {
+			logger.Log(0, "failed to update host after check-in", h.Name, h.ID.String(), err.Error())
+			return false
+		}
+		logger.Log(1, "updated host after check-in", currentHost.Name, currentHost.ID.String())
 	}
 	}
 
 
-	logger.Log(0, "ping processed for host", h.Name, h.ID.String())
+	logger.Log(2, "check-in processed for host", h.Name, h.ID.String())
 	return ifaceDelta
 	return ifaceDelta
-
 }
 }

+ 3 - 3
mq/publishers.go

@@ -71,7 +71,7 @@ func PublishDeletedClientPeerUpdate(delClient *models.ExtClient) error {
 	logic.ResetPeerUpdateContext()
 	logic.ResetPeerUpdateContext()
 	for _, host := range hosts {
 	for _, host := range hosts {
 		host := host
 		host := host
-		if err = PublishSingleHostPeerUpdate(logic.PeerUpdateCtx, &host, nil, delClient); err != nil {
+		if err = PublishSingleHostPeerUpdate(logic.PeerUpdateCtx, &host, nil, []models.ExtClient{*delClient}); err != nil {
 			logger.Log(1, "failed to publish peer update to host", host.ID.String(), ": ", err.Error())
 			logger.Log(1, "failed to publish peer update to host", host.ID.String(), ": ", err.Error())
 		}
 		}
 	}
 	}
@@ -79,9 +79,9 @@ func PublishDeletedClientPeerUpdate(delClient *models.ExtClient) error {
 }
 }
 
 
 // PublishSingleHostPeerUpdate --- determines and publishes a peer update to one host
 // PublishSingleHostPeerUpdate --- determines and publishes a peer update to one host
-func PublishSingleHostPeerUpdate(ctx context.Context, host *models.Host, deletedNode *models.Node, deletedClient *models.ExtClient) error {
+func PublishSingleHostPeerUpdate(ctx context.Context, host *models.Host, deletedNode *models.Node, deletedClients []models.ExtClient) error {
 
 
-	peerUpdate, err := logic.GetPeerUpdateForHost(ctx, "", host, deletedNode, deletedClient)
+	peerUpdate, err := logic.GetPeerUpdateForHost(ctx, "", host, deletedNode, deletedClients)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}

+ 15 - 14
release.md

@@ -1,27 +1,28 @@
-# Netmaker v0.18.5
-
-## **Wait till out of pre-release to fully upgrade**
+# Netmaker v0.18.6
 
 
 ## whats new
 ## whats new
-- Logic for ext client ACLs (not really usable until new UI is finished)
-- Default proxy mode, enables users to determine if all Hosts should have proxy enabled/disabled/auto by default
-  - specify with DEFAULT_PROXY_MODE="on/off/auto" 
+- no new features
     
     
 ## whats fixed
 ## whats fixed
-- Proxy Peer calculation improvements
-- DNS is populated correctly after registration by enrollment key
-- Migrate is functional for Windows/Mac **note** Ports may be set to 0 after an upgrade, can be adjusted via UI to fix
-- Interface data is sent on netclient register
-- Upgrade script
-- Latency issue with Node <-> Node Metrics
-- Ports set from server for Hosts on register/join are actually used
+- a few ext client/ingress issues
+  - viewing addresses (UI)
+  - when deleting an ingress gateway, ext clients are now removed from peers immediately
+  - ext client peers should be populated immediately after creation
+  - ext clients no longer reset public key when disabled/enabled
+  - can delete an ingress without clients
+- removed unnecessary host update
+- host nat type is now collected from clients
+- fix peer update issue where caclulation was happening to frequently
+- nm-quick && nm-upgrade 
+- EMQX image change && api routes
 
 
 ## known issues
 ## known issues
 - Caddy does not handle netmaker exporter well for EE
 - Caddy does not handle netmaker exporter well for EE
-- Migration causes a listen port of 0 for upgraded hosts
+- Migration causes a listen port of 0 for some upgraded hosts
 - Docker clients can not re-join after deletion
 - Docker clients can not re-join after deletion
 - Innacurate Ext Client Metrics 
 - Innacurate Ext Client Metrics 
 - Issue with Mac + IPv6 addressing
 - Issue with Mac + IPv6 addressing
 - Nodes on same local network may not always connect
 - Nodes on same local network may not always connect
 - List populates egress ranges twice
 - List populates egress ranges twice
 - If you do NOT set STUN_LIST on server, it could lead to strange behavior on client
 - If you do NOT set STUN_LIST on server, it could lead to strange behavior on client
+- No internet gateways/default routes

+ 6 - 4
scripts/nm-upgrade.sh

@@ -22,7 +22,7 @@ backup_v17_files() {
   mkdir $INSTALL_PATH/netmaker_0.17.1_backup
   mkdir $INSTALL_PATH/netmaker_0.17.1_backup
   cp $INSTALL_PATH/docker-compose.yml  $INSTALL_PATH/netmaker_0.17.1_backup/docker-compose.yml
   cp $INSTALL_PATH/docker-compose.yml  $INSTALL_PATH/netmaker_0.17.1_backup/docker-compose.yml
   cp $INSTALL_PATH/Caddyfile $INSTALL_PATH/netmaker_0.17.1_backup/Caddyfile
   cp $INSTALL_PATH/Caddyfile $INSTALL_PATH/netmaker_0.17.1_backup/Caddyfile
-  cp $INSTALL_PATH/mosquitto.conf %INSTALL_PATH/netmaker_0.17.1_backup/mosquitto.conf
+  cp $INSTALL_PATH/mosquitto.conf $INSTALL_PATH/netmaker_0.17.1_backup/mosquitto.conf
   cp $INSTALL_PATH/wait.sh $INSTALL_PATH/netmaker_0.17.1_backup/wait.sh
   cp $INSTALL_PATH/wait.sh $INSTALL_PATH/netmaker_0.17.1_backup/wait.sh
 }
 }
 
 
@@ -38,7 +38,7 @@ backup_volumes() {
 restore_old_netmaker_instructions() {
 restore_old_netmaker_instructions() {
   echo "There was a problem with the installation. Your config files and volumes have been backed up."
   echo "There was a problem with the installation. Your config files and volumes have been backed up."
   echo "To restore Netmaker back to v0.17.1, copy all the netmaker volume backups (caddy_conf-backup, caddy_data-backup, dnsconfig-backup, mosquitto_data-backup, mosquitto_logs-backup, and sqldata-backup) back to their regular names with out the -backup."
   echo "To restore Netmaker back to v0.17.1, copy all the netmaker volume backups (caddy_conf-backup, caddy_data-backup, dnsconfig-backup, mosquitto_data-backup, mosquitto_logs-backup, and sqldata-backup) back to their regular names with out the -backup."
-  echo "Your config files should be located in ${INSALL_PATH}/netmaker_0.17.1_backup. Simply run cp ${INSALL_PATH}/netmaker_0.17.1_backup/* . (include the .) and run docker-compose up -d."
+  echo "Your config files should be located in ${INSTALL_PATH}/netmaker_0.17.1_backup. Simply run cp ${INSTALL_PATH}/netmaker_0.17.1_backup/* . (include the .) and run docker-compose up -d."
   echo "Your netmaker should be back to v0.17.1"
   echo "Your netmaker should be back to v0.17.1"
 }
 }
 
 
@@ -119,7 +119,7 @@ install_dependencies() {
     echo "version: $(docker version)"
     echo "version: $(docker version)"
   else
   else
     echo "Docker not found. adding to dependencies"
     echo "Docker not found. adding to dependencies"
-    $dependencies += " docker.io"
+    dependencies+=" docker.io"
   fi
   fi
 
 
   ${update_cmd}
   ${update_cmd}
@@ -407,7 +407,8 @@ set_compose() {
   STUN_PORT=3478
   STUN_PORT=3478
 
 
   # RELEASE_REPLACE - Use this once release is ready
   # RELEASE_REPLACE - Use this once release is ready
-  #sed -i "s/v0.17.1/v0.18.5/g" $INSTALL_PATH/docker-compose.yml
+
+  #sed -i "s/v0.17.1/v0.18.6/g" /root/docker-compose.yml
   yq ".services.netmaker.environment.SERVER_NAME = \"$SERVER_NAME\"" -i $INSTALL_PATH/docker-compose.yml
   yq ".services.netmaker.environment.SERVER_NAME = \"$SERVER_NAME\"" -i $INSTALL_PATH/docker-compose.yml
   yq ".services.netmaker.environment += {\"BROKER_ENDPOINT\": \"wss://$BROKER_NAME\"}" -i $INSTALL_PATH/docker-compose.yml  
   yq ".services.netmaker.environment += {\"BROKER_ENDPOINT\": \"wss://$BROKER_NAME\"}" -i $INSTALL_PATH/docker-compose.yml  
   yq ".services.netmaker.environment += {\"SERVER_BROKER_ENDPOINT\": \"ws://mq:1883\"}" -i $INSTALL_PATH/docker-compose.yml  
   yq ".services.netmaker.environment += {\"SERVER_BROKER_ENDPOINT\": \"ws://mq:1883\"}" -i $INSTALL_PATH/docker-compose.yml  
@@ -420,6 +421,7 @@ set_compose() {
   yq ".services.mq.environment += {\"MQ_PASSWORD\": \"$MQ_PASSWORD\"}" -i $INSTALL_PATH/docker-compose.yml  
   yq ".services.mq.environment += {\"MQ_PASSWORD\": \"$MQ_PASSWORD\"}" -i $INSTALL_PATH/docker-compose.yml  
   yq ".services.mq.environment += {\"MQ_USERNAME\": \"$MQ_USERNAME\"}" -i $INSTALL_PATH/docker-compose.yml  
   yq ".services.mq.environment += {\"MQ_USERNAME\": \"$MQ_USERNAME\"}" -i $INSTALL_PATH/docker-compose.yml  
 
 
+
   #remove unnecessary ports
   #remove unnecessary ports
   yq eval 'del( .services.netmaker.ports[] | select(. == "51821*") )' -i $INSTALL_PATH/docker-compose.yml
   yq eval 'del( .services.netmaker.ports[] | select(. == "51821*") )' -i $INSTALL_PATH/docker-compose.yml
   yq eval 'del( .services.mq.ports[] | select(. == "8883*") )' -i $INSTALL_PATH/docker-compose.yml
   yq eval 'del( .services.mq.ports[] | select(. == "8883*") )' -i $INSTALL_PATH/docker-compose.yml

+ 1 - 1
servercfg/serverconf.go

@@ -277,7 +277,7 @@ func GetMasterKey() string {
 
 
 // GetDNSKey - gets the configured dns key of server
 // GetDNSKey - gets the configured dns key of server
 func GetDNSKey() string {
 func GetDNSKey() string {
-	key := "secretkey"
+	key := ""
 	if os.Getenv("DNS_KEY") != "" {
 	if os.Getenv("DNS_KEY") != "" {
 		key = os.Getenv("DNS_KEY")
 		key = os.Getenv("DNS_KEY")
 	} else if config.Config.Server.DNSKey != "" {
 	} else if config.Config.Server.DNSKey != "" {

+ 1 - 1
swagger.yaml

@@ -704,7 +704,7 @@ info:
 
 
         API calls must be authenticated via a header of the format -H “Authorization: Bearer <YOUR_SECRET_KEY>” There are two methods to obtain YOUR_SECRET_KEY: 1. Using the masterkey. By default, this value is “secret key,” but you should change this on your instance and keep it secure. This value can be set via env var at startup or in a config file (config/environments/< env >.yaml). See the [Netmaker](https://docs.netmaker.org/index.html) documentation for more details. 2. Using a JWT received for a node. This can be retrieved by calling the /api/nodes/<network>/authenticate endpoint, as documented below.
         API calls must be authenticated via a header of the format -H “Authorization: Bearer <YOUR_SECRET_KEY>” There are two methods to obtain YOUR_SECRET_KEY: 1. Using the masterkey. By default, this value is “secret key,” but you should change this on your instance and keep it secure. This value can be set via env var at startup or in a config file (config/environments/< env >.yaml). See the [Netmaker](https://docs.netmaker.org/index.html) documentation for more details. 2. Using a JWT received for a node. This can be retrieved by calling the /api/nodes/<network>/authenticate endpoint, as documented below.
     title: Netmaker
     title: Netmaker
-    version: 0.18.5
+    version: 0.18.6
 paths:
 paths:
     /api/dns:
     /api/dns:
         get:
         get: