Quellcode durchsuchen

v0.20.1 (#2360)

* free tier limit exceeded: status code now 403

* reformat, TODOs

* - nm-certs for zerossl
- added config for email, domain
- updated linux deps

* return {} if no records found for acls/metrics

* Revert "return {} if no records found for acls/metrics"

pushed to wrong branch
This reverts commit 7602e97950a178b141a46bb872dd43e200951e08.

* return {} if no records found for acls/metrics

* add type to enrollement key

* add type to enrollement key

* update version

* - request and mount certs
- handle caddy challenge
- docker fixes
- pull nm-certs.sh

* Revert "add type to enrollement key"

This reverts commit 0cf342dd6e5dcbc1a3b3962350e6dcb7739380df.

* nm-certs.sh
- support EE and new domains
- minor fixes

* shfmt reformat

* add type to APIEnrollementKey

* if -- else to determine type

* spellcheck

* - support EE
- config namespaces
- write config after confirm
- minor fixes

* nm-certs.sh
- config fixes
- crontab symlink

* release workflows

* use forked repo

* Revert "use forked repo"

This reverts commit 730aca7ed88bc01ffbd4c2a66a2e429aafd82da6.

* - fixes
- user msgs

* review comments

* Bump github.com/txn2/txeh from 1.3.0 to 1.4.0

Bumps [github.com/txn2/txeh](https://github.com/txn2/txeh) from 1.3.0 to 1.4.0.
- [Release notes](https://github.com/txn2/txeh/releases)
- [Changelog](https://github.com/txn2/txeh/blob/master/goreleaser.yml)
- [Commits](https://github.com/txn2/txeh/compare/v1.3.0...v1.4.0)

---
updated-dependencies:
- dependency-name: github.com/txn2/txeh
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>

* Bump alpine from 3.17.2 to 3.17.3

Bumps alpine from 3.17.2 to 3.17.3.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>

* - nm-certs.sh switched to dockerized certbot
- nm-quick.sh removed certbot from deps

* fixed missing domain

* - shallow clone for local installs
- added certs to other compose files

* missing domain, auto ToS

* fallback to letsencrypt

* removed turris OS

* fix typo

* send host update when deleting relay

* fixed shallow clone for branches

* disable cleanup for tests

* fixed local install

* - fixed cert mounting
- fixed caddy restart in nm-certs.sh
- aligned all configs

* fixed caddy start/stop

* - added NM_SKIP_BUILD
- fixed docker stop

* fixed NM_SKIP_BUILD

* - fixed ServerBrokerEndpoint config (#2283)

- mq credentials in compose

* NET-129: Turn Signal Actions (#2290)

* add signal action field

* add negotiation signal action

* typo fix

* change signal action name

* NET-147 full config for nm-quick.sh (#2291)

* - moved all vars to config
- compose override
- use the config in compose, caddy
- aligned local / remote setup
- proper docker cleanup
- support for a relative installation path

* - config handling
- error handling / env cleanups
- reduced compose files
- misc

* fixed debugs

* fixed UI_IMAGE_TAG / IMAGE_TAG

* Bump alpine from 3.17.3 to 3.18.0 (#2299)

Bumps alpine from 3.17.3 to 3.18.0.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump golang.org/x/crypto from 0.8.0 to 0.9.0 (#2298)

Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.8.0 to 0.9.0.
- [Commits](https://github.com/golang/crypto/compare/v0.8.0...v0.9.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* 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 <[email protected]>

* versions (#2302)

* Bump golang.org/x/oauth2 from 0.7.0 to 0.8.0 (#2297)

Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.7.0 to 0.8.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* nm-certs permission (#2308)

* nm-certs permission

* single quotes error

* update develop (#2319) (#2320)

* Release v0.20.0 (#2304)

* free tier limit exceeded: status code now 403

* reformat, TODOs

* - nm-certs for zerossl
- added config for email, domain
- updated linux deps

* return {} if no records found for acls/metrics

* Revert "return {} if no records found for acls/metrics"

pushed to wrong branch
This reverts commit 7602e97950a178b141a46bb872dd43e200951e08.

* return {} if no records found for acls/metrics

* add type to enrollement key

* add type to enrollement key

* update version

* - request and mount certs
- handle caddy challenge
- docker fixes
- pull nm-certs.sh

* Revert "add type to enrollement key"

This reverts commit 0cf342dd6e5dcbc1a3b3962350e6dcb7739380df.

* nm-certs.sh
- support EE and new domains
- minor fixes

* shfmt reformat

* add type to APIEnrollementKey

* if -- else to determine type

* spellcheck

* - support EE
- config namespaces
- write config after confirm
- minor fixes

* nm-certs.sh
- config fixes
- crontab symlink

* release workflows

* use forked repo

* Revert "use forked repo"

This reverts commit 730aca7ed88bc01ffbd4c2a66a2e429aafd82da6.

* - fixes
- user msgs

* review comments

* Bump github.com/txn2/txeh from 1.3.0 to 1.4.0

Bumps [github.com/txn2/txeh](https://github.com/txn2/txeh) from 1.3.0 to 1.4.0.
- [Release notes](https://github.com/txn2/txeh/releases)
- [Changelog](https://github.com/txn2/txeh/blob/master/goreleaser.yml)
- [Commits](https://github.com/txn2/txeh/compare/v1.3.0...v1.4.0)

---
updated-dependencies:
- dependency-name: github.com/txn2/txeh
  dependency-type: direct:production
  update-type: version-update:semver-minor
...



* Bump alpine from 3.17.2 to 3.17.3

Bumps alpine from 3.17.2 to 3.17.3.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...



* - nm-certs.sh switched to dockerized certbot
- nm-quick.sh removed certbot from deps

* fixed missing domain

* - shallow clone for local installs
- added certs to other compose files

* missing domain, auto ToS

* fallback to letsencrypt

* removed turris OS

* fix typo

* send host update when deleting relay

* fixed shallow clone for branches

* disable cleanup for tests

* fixed local install

* - fixed cert mounting
- fixed caddy restart in nm-certs.sh
- aligned all configs

* fixed caddy start/stop

* - added NM_SKIP_BUILD
- fixed docker stop

* fixed NM_SKIP_BUILD

* - fixed ServerBrokerEndpoint config (#2283)

- mq credentials in compose

* NET-129: Turn Signal Actions (#2290)

* add signal action field

* add negotiation signal action

* typo fix

* change signal action name

* NET-147 full config for nm-quick.sh (#2291)

* - moved all vars to config
- compose override
- use the config in compose, caddy
- aligned local / remote setup
- proper docker cleanup
- support for a relative installation path

* - config handling
- error handling / env cleanups
- reduced compose files
- misc

* fixed debugs

* fixed UI_IMAGE_TAG / IMAGE_TAG

* Bump alpine from 3.17.3 to 3.18.0 (#2299)

Bumps alpine from 3.17.3 to 3.18.0.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...




* Bump golang.org/x/crypto from 0.8.0 to 0.9.0 (#2298)

Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.8.0 to 0.9.0.
- [Commits](https://github.com/golang/crypto/compare/v0.8.0...v0.9.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...




* 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)

---------



* versions (#2302)

* Bump golang.org/x/oauth2 from 0.7.0 to 0.8.0 (#2297)

Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.7.0 to 0.8.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...




---------








* nm-certs permission (#2305)

* quotes (#2309)

* Release v0.20.0 (#2317)

* free tier limit exceeded: status code now 403

* reformat, TODOs

* - nm-certs for zerossl
- added config for email, domain
- updated linux deps

* return {} if no records found for acls/metrics

* Revert "return {} if no records found for acls/metrics"

pushed to wrong branch
This reverts commit 7602e97950a178b141a46bb872dd43e200951e08.

* return {} if no records found for acls/metrics

* add type to enrollement key

* add type to enrollement key

* update version

* - request and mount certs
- handle caddy challenge
- docker fixes
- pull nm-certs.sh

* Revert "add type to enrollement key"

This reverts commit 0cf342dd6e5dcbc1a3b3962350e6dcb7739380df.

* nm-certs.sh
- support EE and new domains
- minor fixes

* shfmt reformat

* add type to APIEnrollementKey

* if -- else to determine type

* spellcheck

* - support EE
- config namespaces
- write config after confirm
- minor fixes

* nm-certs.sh
- config fixes
- crontab symlink

* release workflows

* use forked repo

* Revert "use forked repo"

This reverts commit 730aca7ed88bc01ffbd4c2a66a2e429aafd82da6.

* - fixes
- user msgs

* review comments

* Bump github.com/txn2/txeh from 1.3.0 to 1.4.0

Bumps [github.com/txn2/txeh](https://github.com/txn2/txeh) from 1.3.0 to 1.4.0.
- [Release notes](https://github.com/txn2/txeh/releases)
- [Changelog](https://github.com/txn2/txeh/blob/master/goreleaser.yml)
- [Commits](https://github.com/txn2/txeh/compare/v1.3.0...v1.4.0)

---
updated-dependencies:
- dependency-name: github.com/txn2/txeh
  dependency-type: direct:production
  update-type: version-update:semver-minor
...



* Bump alpine from 3.17.2 to 3.17.3

Bumps alpine from 3.17.2 to 3.17.3.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...



* - nm-certs.sh switched to dockerized certbot
- nm-quick.sh removed certbot from deps

* fixed missing domain

* - shallow clone for local installs
- added certs to other compose files

* missing domain, auto ToS

* fallback to letsencrypt

* removed turris OS

* fix typo

* send host update when deleting relay

* fixed shallow clone for branches

* disable cleanup for tests

* fixed local install

* - fixed cert mounting
- fixed caddy restart in nm-certs.sh
- aligned all configs

* fixed caddy start/stop

* - added NM_SKIP_BUILD
- fixed docker stop

* fixed NM_SKIP_BUILD

* - fixed ServerBrokerEndpoint config (#2283)

- mq credentials in compose

* NET-129: Turn Signal Actions (#2290)

* add signal action field

* add negotiation signal action

* typo fix

* change signal action name

* NET-147 full config for nm-quick.sh (#2291)

* - moved all vars to config
- compose override
- use the config in compose, caddy
- aligned local / remote setup
- proper docker cleanup
- support for a relative installation path

* - config handling
- error handling / env cleanups
- reduced compose files
- misc

* fixed debugs

* fixed UI_IMAGE_TAG / IMAGE_TAG

* Bump alpine from 3.17.3 to 3.18.0 (#2299)

Bumps alpine from 3.17.3 to 3.18.0.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...




* Bump golang.org/x/crypto from 0.8.0 to 0.9.0 (#2298)

Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.8.0 to 0.9.0.
- [Commits](https://github.com/golang/crypto/compare/v0.8.0...v0.9.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...




* 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)

---------



* versions (#2302)

* Bump golang.org/x/oauth2 from 0.7.0 to 0.8.0 (#2297)

Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.7.0 to 0.8.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...




* Fixed nm-certs relative path (#2311)

* nm-certs permission (#2308)

* nm-certs permission

* single quotes error

* fixed relative path

---------



---------









---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Matthew R Kasun <[email protected]>
Co-authored-by: Tobias Cudnik <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Abhishek K <[email protected]>
Co-authored-by: Aceix <[email protected]>
Co-authored-by: Christopher Blaha <[email protected]>

* NET-53 Fixed user update returns old data (#2312)

* fixed gids in user update

* review comments

* review comments

* review comments

* Bump github.com/stretchr/testify from 1.8.2 to 1.8.3 (#2329)

Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.2 to 1.8.3.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.2...v1.8.3)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump github.com/coreos/go-oidc/v3 from 3.5.0 to 3.6.0 (#2327)

Bumps [github.com/coreos/go-oidc/v3](https://github.com/coreos/go-oidc) from 3.5.0 to 3.6.0.
- [Release notes](https://github.com/coreos/go-oidc/releases)
- [Commits](https://github.com/coreos/go-oidc/compare/v3.5.0...v3.6.0)

---
updated-dependencies:
- dependency-name: github.com/coreos/go-oidc/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* NET-246: Use the default config as a fallback (#2332)

* - fall back to default values
- nm-quick version
- fixed TURN_PASSWORD

* apk update

* retain existing password

* Bump github.com/go-playground/validator/v10 from 10.13.0 to 10.14.0 (#2328)

Bumps [github.com/go-playground/validator/v10](https://github.com/go-playground/validator) from 10.13.0 to 10.14.0.
- [Release notes](https://github.com/go-playground/validator/releases)
- [Commits](https://github.com/go-playground/validator/compare/v10.13.0...v10.14.0)

---
updated-dependencies:
- dependency-name: github.com/go-playground/validator/v10
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* NET-163: Return 403 instead of 401 (#2326)

* return 401 instead of 403

* fixed http.StatusForbidden

* Tagged build version (temp)

* Unauthorized_Err when applicable

* untagged version

* remove server info discord message (#2339)

* remove server info discord message

* delete droplets 5 hours after failure

* run_attempt vice run_number

* Fixed SSL fallback to letsencrypt

* fix error with user update (#2348)

* fix: user update

* fix: user update

* NET-186: Wg public listen port (#2344)

* fetch public listen of wg if present

* check if wg pub listen port has been changed on host update

* wg public port to host api model for visibility

* rm comment

* update version/firewall in use if changed on checkin (#2335)

* NET-152 enrollment keys for non admins (#2346)

* return 401 instead of 403

* fixed http.StatusForbidden

* Tagged build version (temp)

* Unauthorized_Err when applicable

* untagged version

* fixed PUT /api/users/networks/user1

* - expired token redirs to login
- added `/api/enrollment_keys` for non-admins
- unit test for enrollment keys for non-admins

* handle user perms in `/hosts`

* removed debug

* misc

* - support masteradmin
- return hosts with partial access

* added `ismaster` to middleware

* Ignore stale nodes instead of 500 (#2357)

* remove node check from getHosts (#2359)

* version and release note updates (#2358)

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Matthew R Kasun <[email protected]>
Co-authored-by: Alex Feiszli <[email protected]>
Co-authored-by: Tobias Cudnik <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Abhishek K <[email protected]>
Co-authored-by: Aceix <[email protected]>
Co-authored-by: Christopher Blaha <[email protected]>
Co-authored-by: Tobias Cudnik <[email protected]>
github-actions[bot] vor 2 Jahren
Ursprung
Commit
d378cf3c9a

+ 3 - 1
.dockerignore

@@ -1,2 +1,4 @@
 config/dnsconfig/
-data/
+data/
+/.git
+/*.tar

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

@@ -31,6 +31,7 @@ body:
       label: Version
       description: What version are you running?
       options:
+        - v0.20.1
         - v0.20.0
         - v0.19.0
         - v0.18.7

+ 3 - 21
.github/workflows/deletedroplets.yml

@@ -23,17 +23,8 @@ jobs:
           webhook_token: ${{ secrets.DISCORD_WEBHOOK_TOKEN }}
           color: "#42f545"
           username: "GitHub Bot"
-          message: "${{ github.repository }}: ${{ github.event.workflow_run.name }} was successful"
+          message: "${{ github.repository }}: ${{ github.event.workflow_run.name }} was successful: droplets from this workflow (tag ${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}) will be deleted in 15 min"
           file: ./results/results.log
-      - name: discord server message
-        uses: appleboy/discord-action@master
-        with:
-          webhook_id: ${{ secrets.DISCORD_WEBHOOK_ID }}
-          webhook_token: ${{ secrets.DISCORD_WEBHOOK_TOKEN }}
-          color: "#42f545"
-          username: "GitHub Bot"
-          message: "droplets from this workflow (tag ${{ github.event.workflow_run.id }}-{{ $github.event.workflow_run.run_number }}) will be deleted in 15 min"
-          file: ./server/serverinfo.txt
       - name: delete droplets
         if: success() || failure()
         run: |
@@ -62,17 +53,8 @@ jobs:
           webhook_token: ${{ secrets.DISCORD_WEBHOOK_TOKEN }}
           color: "#990000"
           username: "GitHub Bot"
-          message: "${{ github.repository }}: ${{ github.event.workflow_run.name }} failed"
+          message: "${{ github.repository }}: ${{ github.event.workflow_run.name }} failed: droplets from this workflow (tag ${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt}}) will be deleted in 5 hours"
           file: ./results/results.log
-      - name: discord server message
-        uses: appleboy/discord-action@master
-        with:
-          webhook_id: ${{ secrets.DISCORD_WEBHOOK_ID }}
-          webhook_token: ${{ secrets.DISCORD_WEBHOOK_TOKEN }}
-          color: "#990000"
-          username: "GitHub Bot"
-          message: "droplets from this workflow (tag ${{ github.event.workflow_run.id }}-{{ $github.event.workflow_run.run_number }}) will be deleted in 6 hours"
-          file: ./server/serverinfo.txt
       - name: discord error message
         uses: appleboy/discord-action@master
         with:
@@ -85,7 +67,7 @@ jobs:
       - name: delete droplets
         if: success() || failure()
         run: |
-          sleep 6h
+          sleep 5h
           curl -X GET \
             -H "Content-Type: application/json" \
             -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \

+ 1 - 1
README.md

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

+ 1 - 0
cli/functions/http_client.go

@@ -148,6 +148,7 @@ retry:
 	if res.StatusCode == http.StatusUnauthorized && !retried && ctx.MasterKey == "" {
 		req.Header.Set("Authorization", "Bearer "+getAuthToken(ctx, true))
 		retried = true
+		// TODO add a retry limit, drop goto
 		goto retry
 	}
 	resBodyBytes, err := io.ReadAll(res.Body)

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

@@ -3,7 +3,7 @@ version: "3.4"
 services:
   netclient:
     container_name: netclient
-    image: 'gravitl/netclient:v0.20.0'
+    image: 'gravitl/netclient:v0.20.1'
     hostname: netmaker-1
     network_mode: host
     restart: on-failure

+ 1 - 1
controllers/docs.go

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

+ 19 - 6
controllers/enrollmentkeys.go

@@ -17,7 +17,7 @@ import (
 
 func enrollmentKeyHandlers(r *mux.Router) {
 	r.HandleFunc("/api/v1/enrollment-keys", logic.SecurityCheck(true, http.HandlerFunc(createEnrollmentKey))).Methods(http.MethodPost)
-	r.HandleFunc("/api/v1/enrollment-keys", logic.SecurityCheck(true, http.HandlerFunc(getEnrollmentKeys))).Methods(http.MethodGet)
+	r.HandleFunc("/api/v1/enrollment-keys", logic.SecurityCheck(false, http.HandlerFunc(getEnrollmentKeys))).Methods(http.MethodGet)
 	r.HandleFunc("/api/v1/enrollment-keys/{keyID}", logic.SecurityCheck(true, http.HandlerFunc(deleteEnrollmentKey))).Methods(http.MethodDelete)
 	r.HandleFunc("/api/v1/host/register/{token}", http.HandlerFunc(handleHostRegister)).Methods(http.MethodPost)
 }
@@ -34,24 +34,37 @@ func enrollmentKeyHandlers(r *mux.Router) {
 //			Responses:
 //				200: getEnrollmentKeysSlice
 func getEnrollmentKeys(w http.ResponseWriter, r *http.Request) {
-	currentKeys, err := logic.GetAllEnrollmentKeys()
+	keys, err := logic.GetAllEnrollmentKeys()
 	if err != nil {
 		logger.Log(0, r.Header.Get("user"), "failed to fetch enrollment keys: ", err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 	}
-	for i := range currentKeys {
-		currentKey := currentKeys[i]
-		if err = logic.Tokenize(currentKey, servercfg.GetAPIHost()); err != nil {
+	isMasterAdmin := r.Header.Get("ismaster") == "yes"
+	// regular user flow
+	user, err := logic.GetUser(r.Header.Get("user"))
+	if err != nil && !isMasterAdmin {
+		logger.Log(0, r.Header.Get("user"), "failed to fetch user: ", err.Error())
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
+	// TODO drop double pointer
+	ret := []*models.EnrollmentKey{}
+	for _, key := range keys {
+		if !isMasterAdmin && !logic.UserHasNetworksAccess(key.Networks, user) {
+			continue
+		}
+		if err = logic.Tokenize(key, servercfg.GetAPIHost()); err != nil {
 			logger.Log(0, r.Header.Get("user"), "failed to get token values for keys:", err.Error())
 			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 			return
 		}
+		ret = append(ret, key)
 	}
 	// return JSON/API formatted keys
 	logger.Log(2, r.Header.Get("user"), "fetched enrollment keys")
 	w.WriteHeader(http.StatusOK)
-	json.NewEncoder(w).Encode(currentKeys)
+	json.NewEncoder(w).Encode(ret)
 }
 
 // swagger:route DELETE /api/v1/enrollment-keys/{keyID} enrollmentKeys deleteEnrollmentKey

+ 30 - 1
controllers/hosts.go

@@ -19,7 +19,7 @@ import (
 )
 
 func hostHandlers(r *mux.Router) {
-	r.HandleFunc("/api/hosts", logic.SecurityCheck(true, http.HandlerFunc(getHosts))).Methods(http.MethodGet)
+	r.HandleFunc("/api/hosts", logic.SecurityCheck(false, http.HandlerFunc(getHosts))).Methods(http.MethodGet)
 	r.HandleFunc("/api/hosts/keys", logic.SecurityCheck(true, http.HandlerFunc(updateAllKeys))).Methods(http.MethodPut)
 	r.HandleFunc("/api/hosts/{hostid}/keys", logic.SecurityCheck(true, http.HandlerFunc(updateKeys))).Methods(http.MethodPut)
 	r.HandleFunc("/api/hosts/{hostid}", logic.SecurityCheck(true, http.HandlerFunc(updateHost))).Methods(http.MethodPut)
@@ -52,9 +52,38 @@ func getHosts(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 	}
+	//isMasterAdmin := r.Header.Get("ismaster") == "yes"
+	//user, err := logic.GetUser(r.Header.Get("user"))
+	//if err != nil && !isMasterAdmin {
+	//	logger.Log(0, r.Header.Get("user"), "failed to fetch user: ", err.Error())
+	//	logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+	//	return
+	//}
 	// return JSON/API formatted hosts
+	//ret := []models.ApiHost{}
 	apiHosts := logic.GetAllHostsAPI(currentHosts[:])
 	logger.Log(2, r.Header.Get("user"), "fetched all hosts")
+	//for _, host := range apiHosts {
+	//	nodes := host.Nodes
+	//	// work on the copy
+	//	host.Nodes = []string{}
+	//	for _, nid := range nodes {
+	//		node, err := logic.GetNodeByID(nid)
+	//		if err != nil {
+	//			logger.Log(0, r.Header.Get("user"), "failed to fetch node: ", err.Error())
+	//			// TODO find the reason for the DB error, skip this node for now
+	//			continue
+	//		}
+	//		if !isMasterAdmin && !logic.UserHasNetworksAccess([]string{node.Network}, user) {
+	//			continue
+	//		}
+	//		host.Nodes = append(host.Nodes, nid)
+	//	}
+	//	// add to the response only if has perms to some nodes / networks
+	//	if len(host.Nodes) > 0 {
+	//		ret = append(ret, host)
+	//	}
+	//}
 	logic.SortApiHosts(apiHosts[:])
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(apiHosts)

+ 1 - 4
controllers/network.go

@@ -40,10 +40,7 @@ func networkHandlers(r *mux.Router) {
 //			Responses:
 //				200: getNetworksSliceResponse
 func getNetworks(w http.ResponseWriter, r *http.Request) {
-
-	headerNetworks := r.Header.Get("networks")
-	networksSlice := []string{}
-	marshalErr := json.Unmarshal([]byte(headerNetworks), &networksSlice)
+	networksSlice, marshalErr := getHeaderNetworks(r)
 	if marshalErr != nil {
 		logger.Log(0, r.Header.Get("user"), "error unmarshalling networks: ",
 			marshalErr.Error())

+ 1 - 1
controllers/node.go

@@ -157,7 +157,7 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
 func authorize(hostAllowed, networkCheck bool, authNetwork string, next http.Handler) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 		var errorResponse = models.ErrorResponse{
-			Code: http.StatusUnauthorized, Message: logic.Unauthorized_Msg,
+			Code: http.StatusForbidden, Message: logic.Forbidden_Msg,
 		}
 
 		var params = mux.Vars(r)

+ 1 - 1
controllers/server.go

@@ -56,7 +56,7 @@ func getStatus(w http.ResponseWriter, r *http.Request) {
 func allowUsers(next http.Handler) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 		var errorResponse = models.ErrorResponse{
-			Code: http.StatusInternalServerError, Message: logic.Unauthorized_Msg,
+			Code: http.StatusUnauthorized, Message: logic.Unauthorized_Msg,
 		}
 		bearerToken := r.Header.Get("Authorization")
 		var tokenSplit = strings.Split(bearerToken, " ")

+ 21 - 4
controllers/user.go

@@ -290,16 +290,16 @@ func updateUserNetworks(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 	}
-	var userchange models.User
+	userChange := &models.User{}
 	// we decode our body request params
-	err = json.NewDecoder(r.Body).Decode(&userchange)
+	err = json.NewDecoder(r.Body).Decode(userChange)
 	if err != nil {
 		logger.Log(0, username, "error decoding request body: ",
 			err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
 		return
 	}
-	err = logic.UpdateUserNetworks(userchange.Networks, userchange.Groups, userchange.IsAdmin, &models.ReturnUser{
+	err = logic.UpdateUserNetworks(userChange.Networks, userChange.Groups, userChange.IsAdmin, &models.ReturnUser{
 		Groups:   user.Groups,
 		IsAdmin:  user.IsAdmin,
 		Networks: user.Networks,
@@ -313,7 +313,13 @@ func updateUserNetworks(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	logger.Log(1, username, "status was updated")
-	json.NewEncoder(w).Encode(user)
+	// re-read and return the new user struct
+	if userChange, err = logic.GetUser(username); err != nil {
+		logger.Log(0, username, "failed to fetch user: ", err.Error())
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
+	json.NewEncoder(w).Encode(userChange)
 }
 
 // swagger:route PUT /api/users/{username} user updateUser
@@ -485,3 +491,14 @@ func socketHandler(w http.ResponseWriter, r *http.Request) {
 	// Start handling the session
 	go auth.SessionHandler(conn)
 }
+
+// getHeaderNetworks returns a slice of networks parsed form the request header.
+func getHeaderNetworks(r *http.Request) ([]string, error) {
+	headerNetworks := r.Header.Get("networks")
+	networksSlice := []string{}
+	err := json.Unmarshal([]byte(headerNetworks), &networksSlice)
+	if err != nil {
+		return nil, err
+	}
+	return networksSlice, nil
+}

+ 5 - 5
go.mod

@@ -4,7 +4,7 @@ go 1.19
 
 require (
 	github.com/eclipse/paho.mqtt.golang v1.4.2
-	github.com/go-playground/validator/v10 v10.13.0
+	github.com/go-playground/validator/v10 v10.14.0
 	github.com/golang-jwt/jwt/v4 v4.5.0
 	github.com/google/uuid v1.3.0
 	github.com/gorilla/handlers v1.5.1
@@ -13,7 +13,7 @@ require (
 	github.com/mattn/go-sqlite3 v1.14.16
 	github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
-	github.com/stretchr/testify v1.8.2
+	github.com/stretchr/testify v1.8.3
 	github.com/txn2/txeh v1.4.0
 	golang.org/x/crypto v0.9.0
 	golang.org/x/net v0.10.0 // indirect
@@ -33,7 +33,7 @@ require (
 )
 
 require (
-	github.com/coreos/go-oidc/v3 v3.5.0
+	github.com/coreos/go-oidc/v3 v3.6.0
 	github.com/gorilla/websocket v1.5.0
 	github.com/pkg/errors v0.9.1
 	golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e
@@ -50,9 +50,9 @@ require (
 
 require (
 	cloud.google.com/go/compute/metadata v0.2.1 // indirect
+	github.com/gabriel-vasile/mimetype v1.4.2 // indirect
 	github.com/go-jose/go-jose/v3 v3.0.0 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
-	github.com/kr/pretty v0.3.1 // indirect
 	github.com/rivo/uniseg v0.2.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 )
@@ -67,7 +67,7 @@ require (
 	github.com/google/go-cmp v0.5.9 // indirect
 	github.com/hashicorp/go-version v1.6.0
 	github.com/josharian/native v1.0.0 // indirect
-	github.com/leodido/go-urn v1.2.3 // indirect
+	github.com/leodido/go-urn v1.2.4 // indirect
 	github.com/mattn/go-runewidth v0.0.13 // indirect
 	github.com/mdlayher/genetlink v1.2.0 // indirect
 	github.com/mdlayher/netlink v1.6.0 // indirect

+ 11 - 42
go.sum

@@ -1,6 +1,5 @@
 cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0=
 cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
-cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
 cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48=
 cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
 filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
@@ -8,11 +7,10 @@ filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5E
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/c-robinson/iplib v1.0.6 h1:FfZV9BWNrah3BgLCFl5/nDXe4RbOi/C9n+DeXFOv5CQ=
 github.com/c-robinson/iplib v1.0.6/go.mod h1:i3LuuFL1hRT5gFpBRnEydzw8R6yhGkF4szNDIbF8pgo=
-github.com/coreos/go-oidc/v3 v3.5.0 h1:VxKtbccHZxs8juq7RdJntSqtXFtde9YpNpGn0yqgEHw=
-github.com/coreos/go-oidc/v3 v3.5.0/go.mod h1:ecXRtV4romGPeO6ieExAsUK9cb/3fp9hXNz1tlv8PIM=
+github.com/coreos/go-oidc/v3 v3.6.0 h1:AKVxfYw1Gmkn/w96z0DbT/B/xFnzTd3MkZvWLjF4n/o=
+github.com/coreos/go-oidc/v3 v3.6.0/go.mod h1:ZpHUsHBucTUj6WOkrP4E20UPynbLZzhTQ1XKCXkxyPc=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -23,6 +21,8 @@ github.com/eclipse/paho.mqtt.golang v1.4.2/go.mod h1:JGt0RsEwEX+Xa/agj90YJ9d9DH2
 github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
 github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
 github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
+github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
 github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo=
 github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
 github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
@@ -30,8 +30,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/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/validator/v10 v10.13.0 h1:cFRQdfaSMCOSfGCCLB20MHvuoHb/s5G8L5pu2ppK5AQ=
-github.com/go-playground/validator/v10 v10.13.0/go.mod h1:dwu7+CG8/CtBiJFZDz4e+5Upb6OLw04gtBYw0mcG/z4=
+github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
+github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
 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/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -42,7 +42,6 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
-github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
@@ -62,15 +61,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
 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/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
-github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
-github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
-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.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/leodido/go-urn v1.2.3 h1:6BE2vPT0lqoz3fmOesHZiaiFh7889ssCo2GMvLCfiuA=
-github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
+github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
+github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
 github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
 github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
@@ -91,7 +83,6 @@ github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE9
 github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
 github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
-github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -101,8 +92,6 @@ github.com/posthog/posthog-go v0.0.0-20211028072449-93c17c49e2b0/go.mod h1:oa2sA
 github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
 github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
-github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
-github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f h1:BSnJgAfHzEp7o8PYJ7YfwAVHhqu7BYUTggcn/LGlUWY=
 github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f/go.mod h1:UW/gxgQwSePTvL1KA8QEHsXeYHP4xkoXgbDdN781p34=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -118,47 +107,37 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
 github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/txn2/txeh v1.4.0 h1:0tdvpA4HGJrj8X3kmrU6o/JFStI009nKxwDpMK5CnRU=
 github.com/txn2/txeh v1.4.0/go.mod h1:Mgq0hY184zCrDBLgvkIp+9NYGHoYbJcu4xKqUcx1shc=
 github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g=
 github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-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-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
 golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
 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/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211111083644-e5c967477495/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-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.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
 golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk=
 golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
 golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
-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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -173,26 +152,18 @@ golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220207234003-57398862261d/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.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
 golang.org/x/sys v0.8.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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 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.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.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-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/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.zx2c4.com/go118/netip v0.0.0-20211111135330-a4a02eeacf9d/go.mod h1:5yyfuiqVIJ7t+3MqrpTQ+QqRkMWiESiyDvPNvKYCecg=
@@ -206,12 +177,10 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6
 google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
 google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 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/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

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

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

+ 1 - 1
k8s/client/netclient.yaml

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

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

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

+ 15 - 0
logic/enrollmentkey.go

@@ -5,6 +5,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"golang.org/x/exp/slices"
 	"time"
 
 	"github.com/gravitl/netmaker/database"
@@ -68,6 +69,7 @@ func CreateEnrollmentKey(uses int, expiration time.Time, networks, tags []string
 }
 
 // GetAllEnrollmentKeys - fetches all enrollment keys from DB
+// TODO drop double pointer
 func GetAllEnrollmentKeys() ([]*models.EnrollmentKey, error) {
 	currentKeys, err := getEnrollmentKeysMap()
 	if err != nil {
@@ -222,3 +224,16 @@ func getEnrollmentKeysMap() (map[string]*models.EnrollmentKey, error) {
 	}
 	return currentKeys, nil
 }
+
+// UserHasNetworksAccess - checks if a user `u` has access to all `networks`
+func UserHasNetworksAccess(networks []string, u *models.User) bool {
+	if u.IsAdmin {
+		return true
+	}
+	for _, n := range networks {
+		if !slices.Contains(u.Networks, n) {
+			return false
+		}
+	}
+	return true
+}

+ 74 - 0
logic/enrollmentkey_test.go

@@ -204,3 +204,77 @@ func TestDeTokenize_EnrollmentKeys(t *testing.T) {
 
 	removeAllEnrollments()
 }
+
+func TestHasNetworksAccess(t *testing.T) {
+	type Case struct {
+		// network names
+		n []string
+		u models.User
+	}
+	pass := []Case{
+		{
+			n: []string{"n1", "n2"},
+			u: models.User{
+				Networks: []string{"n1", "n2"},
+				IsAdmin:  false,
+			},
+		},
+		{
+			n: []string{"n1", "n2"},
+			u: models.User{
+				Networks: []string{},
+				IsAdmin:  true,
+			},
+		},
+		{
+			n: []string{"n1", "n2"},
+			u: models.User{
+				Networks: []string{"n1", "n2", "n3"},
+				IsAdmin:  false,
+			},
+		},
+		{
+			n: []string{"n2"},
+			u: models.User{
+				Networks: []string{"n2"},
+				IsAdmin:  false,
+			},
+		},
+	}
+	deny := []Case{
+		{
+			n: []string{"n1", "n2"},
+			u: models.User{
+				Networks: []string{"n2"},
+				IsAdmin:  false,
+			},
+		},
+		{
+			n: []string{"n1", "n2"},
+			u: models.User{
+				Networks: []string{},
+				IsAdmin:  false,
+			},
+		},
+		{
+			n: []string{"n1", "n2"},
+			u: models.User{
+				Networks: []string{"n3"},
+				IsAdmin:  false,
+			},
+		},
+		{
+			n: []string{"n2"},
+			u: models.User{
+				Networks: []string{"n1"},
+				IsAdmin:  false,
+			},
+		},
+	}
+	for _, tc := range pass {
+		assert.True(t, UserHasNetworksAccess(tc.n, &tc.u))
+	}
+	for _, tc := range deny {
+		assert.False(t, UserHasNetworksAccess(tc.n, &tc.u))
+	}
+}

+ 4 - 0
logic/hosts.go

@@ -173,6 +173,10 @@ func UpdateHostFromClient(newHost, currHost *models.Host) (sendPeerUpdate bool)
 		currHost.ListenPort = newHost.ListenPort
 		sendPeerUpdate = true
 	}
+	if newHost.WgPublicListenPort != 0 && currHost.WgPublicListenPort != newHost.WgPublicListenPort {
+		currHost.WgPublicListenPort = newHost.WgPublicListenPort
+		sendPeerUpdate = true
+	}
 	if newHost.ProxyListenPort != 0 && currHost.ProxyListenPort != newHost.ProxyListenPort {
 		currHost.ProxyListenPort = newHost.ProxyListenPort
 		sendPeerUpdate = true

+ 14 - 1
logic/peers.go

@@ -220,11 +220,12 @@ func GetPeerUpdateForHost(ctx context.Context, network string, host *models.Host
 				}
 				peerConfig.Endpoint = &net.UDPAddr{
 					IP:   peerHost.EndpointIP,
-					Port: peerHost.ListenPort,
+					Port: getPeerWgListenPort(peerHost),
 				}
 
 				if uselocal {
 					peerConfig.Endpoint.IP = peer.LocalAddress.IP
+					peerConfig.Endpoint.Port = peerHost.ListenPort
 				}
 				allowedips := GetAllowedIPs(&node, &peer, nil)
 				if peer.IsIngressGateway {
@@ -425,9 +426,21 @@ func GetPeerUpdateForHost(ctx context.Context, network string, host *models.Host
 	return hostPeerUpdate, nil
 }
 
+// getPeerWgListenPort - fetches the wg listen port for the host
+func getPeerWgListenPort(host *models.Host) int {
+	peerPort := host.ListenPort
+	if host.WgPublicListenPort != 0 {
+		peerPort = host.WgPublicListenPort
+	}
+	return peerPort
+}
+
 // GetPeerListenPort - given a host, retrieve it's appropriate listening port
 func GetPeerListenPort(host *models.Host) int {
 	peerPort := host.ListenPort
+	if host.WgPublicListenPort != 0 {
+		peerPort = host.WgPublicListenPort
+	}
 	if host.ProxyEnabled {
 		if host.PublicListenPort != 0 {
 			peerPort = host.PublicListenPort

+ 14 - 6
logic/security.go

@@ -18,6 +18,8 @@ const (
 	ALL_NETWORK_ACCESS = "THIS_USER_HAS_ALL"
 
 	master_uname     = "masteradministrator"
+	Forbidden_Msg    = "forbidden"
+	Forbidden_Err    = models.Error(Forbidden_Msg)
 	Unauthorized_Msg = "unauthorized"
 	Unauthorized_Err = models.Error(Unauthorized_Msg)
 )
@@ -27,8 +29,9 @@ func SecurityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
 
 	return func(w http.ResponseWriter, r *http.Request) {
 		var errorResponse = models.ErrorResponse{
-			Code: http.StatusUnauthorized, Message: Unauthorized_Msg,
+			Code: http.StatusForbidden, Message: Forbidden_Msg,
 		}
+		r.Header.Set("ismaster", "no")
 
 		var params = mux.Vars(r)
 		bearerToken := r.Header.Get("Authorization")
@@ -51,6 +54,10 @@ func SecurityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
 			ReturnErrorResponse(w, r, errorResponse)
 			return
 		}
+		// detect masteradmin
+		if len(networks) > 0 && networks[0] == ALL_NETWORK_ACCESS {
+			r.Header.Set("ismaster", "yes")
+		}
 		networksJson, err := json.Marshal(&networks)
 		if err != nil {
 			ReturnErrorResponse(w, r, errorResponse)
@@ -66,7 +73,7 @@ func SecurityCheck(reqAdmin bool, next http.Handler) http.HandlerFunc {
 func NetUserSecurityCheck(isNodes, isClients bool, next http.Handler) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 		var errorResponse = models.ErrorResponse{
-			Code: http.StatusUnauthorized, Message: "unauthorized",
+			Code: http.StatusForbidden, Message: Forbidden_Msg,
 		}
 		r.Header.Set("ismaster", "no")
 
@@ -145,6 +152,7 @@ func UserPermissions(reqAdmin bool, netname string, token string) ([]string, str
 	}
 	//all endpoints here require master so not as complicated
 	if authenticateMaster(authToken) {
+		// TODO log in as an actual admin user
 		return []string{ALL_NETWORK_ACCESS}, master_uname, nil
 	}
 	username, networks, isadmin, err := VerifyUserToken(authToken)
@@ -152,7 +160,7 @@ func UserPermissions(reqAdmin bool, netname string, token string) ([]string, str
 		return nil, username, Unauthorized_Err
 	}
 	if !isadmin && reqAdmin {
-		return nil, username, Unauthorized_Err
+		return nil, username, Forbidden_Err
 	}
 	userNetworks = networks
 	if isadmin {
@@ -160,10 +168,10 @@ func UserPermissions(reqAdmin bool, netname string, token string) ([]string, str
 	}
 	// check network admin access
 	if len(netname) > 0 && (len(userNetworks) == 0 || !authenticateNetworkUser(netname, userNetworks)) {
-		return nil, username, Unauthorized_Err
+		return nil, username, Forbidden_Err
 	}
 	if isEE && len(netname) > 0 && !pro.IsUserNetAdmin(netname, username) {
-		return nil, "", Unauthorized_Err
+		return nil, "", Forbidden_Err
 	}
 	return userNetworks, username, nil
 }
@@ -193,7 +201,7 @@ func authenticateDNSToken(tokenString string) bool {
 func ContinueIfUserMatch(next http.Handler) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 		var errorResponse = models.ErrorResponse{
-			Code: http.StatusUnauthorized, Message: Unauthorized_Msg,
+			Code: http.StatusForbidden, Message: Forbidden_Msg,
 		}
 		var params = mux.Vars(r)
 		var requestedUser = params["username"]

+ 1 - 0
logic/users.go

@@ -12,6 +12,7 @@ import (
 )
 
 // GetUser - gets a user
+// TODO support "masteradmin"
 func GetUser(username string) (*models.User, error) {
 
 	var user models.User

+ 1 - 1
main.go

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

+ 28 - 26
models/api_host.go

@@ -7,32 +7,33 @@ import (
 
 // ApiHost - the host struct for API usage
 type ApiHost struct {
-	ID               string   `json:"id"`
-	Verbosity        int      `json:"verbosity"`
-	FirewallInUse    string   `json:"firewallinuse"`
-	Version          string   `json:"version"`
-	Name             string   `json:"name"`
-	OS               string   `json:"os"`
-	Debug            bool     `json:"debug"`
-	IsStatic         bool     `json:"isstatic"`
-	ListenPort       int      `json:"listenport"`
-	LocalListenPort  int      `json:"locallistenport"`
-	ProxyListenPort  int      `json:"proxy_listen_port"`
-	PublicListenPort int      `json:"public_listen_port" yaml:"public_listen_port"`
-	MTU              int      `json:"mtu" yaml:"mtu"`
-	Interfaces       []Iface  `json:"interfaces" yaml:"interfaces"`
-	DefaultInterface string   `json:"defaultinterface" yaml:"defautlinterface"`
-	EndpointIP       string   `json:"endpointip" yaml:"endpointip"`
-	PublicKey        string   `json:"publickey"`
-	MacAddress       string   `json:"macaddress"`
-	InternetGateway  string   `json:"internetgateway"`
-	Nodes            []string `json:"nodes"`
-	ProxyEnabled     bool     `json:"proxy_enabled" yaml:"proxy_enabled"`
-	IsDefault        bool     `json:"isdefault" yaml:"isdefault"`
-	IsRelayed        bool     `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"`
-	RelayedBy        string   `json:"relayed_by" bson:"relayed_by" yaml:"relayed_by"`
-	IsRelay          bool     `json:"isrelay" bson:"isrelay" yaml:"isrelay"`
-	RelayedHosts     []string `json:"relay_hosts" bson:"relay_hosts" yaml:"relay_hosts"`
+	ID                 string   `json:"id"`
+	Verbosity          int      `json:"verbosity"`
+	FirewallInUse      string   `json:"firewallinuse"`
+	Version            string   `json:"version"`
+	Name               string   `json:"name"`
+	OS                 string   `json:"os"`
+	Debug              bool     `json:"debug"`
+	IsStatic           bool     `json:"isstatic"`
+	ListenPort         int      `json:"listenport"`
+	LocalListenPort    int      `json:"locallistenport"`
+	ProxyListenPort    int      `json:"proxy_listen_port"`
+	PublicListenPort   int      `json:"public_listen_port" yaml:"public_listen_port"`
+	WgPublicListenPort int      `json:"wg_public_listen_port" yaml:"wg_public_listen_port"`
+	MTU                int      `json:"mtu" yaml:"mtu"`
+	Interfaces         []Iface  `json:"interfaces" yaml:"interfaces"`
+	DefaultInterface   string   `json:"defaultinterface" yaml:"defautlinterface"`
+	EndpointIP         string   `json:"endpointip" yaml:"endpointip"`
+	PublicKey          string   `json:"publickey"`
+	MacAddress         string   `json:"macaddress"`
+	InternetGateway    string   `json:"internetgateway"`
+	Nodes              []string `json:"nodes"`
+	ProxyEnabled       bool     `json:"proxy_enabled" yaml:"proxy_enabled"`
+	IsDefault          bool     `json:"isdefault" yaml:"isdefault"`
+	IsRelayed          bool     `json:"isrelayed" bson:"isrelayed" yaml:"isrelayed"`
+	RelayedBy          string   `json:"relayed_by" bson:"relayed_by" yaml:"relayed_by"`
+	IsRelay            bool     `json:"isrelay" bson:"isrelay" yaml:"isrelay"`
+	RelayedHosts       []string `json:"relay_hosts" bson:"relay_hosts" yaml:"relay_hosts"`
 }
 
 // Host.ConvertNMHostToAPI - converts a Netmaker host to an API editable host
@@ -60,6 +61,7 @@ func (h *Host) ConvertNMHostToAPI() *ApiHost {
 	a.Nodes = h.Nodes
 	a.ProxyEnabled = h.ProxyEnabled
 	a.PublicListenPort = h.PublicListenPort
+	a.WgPublicListenPort = h.WgPublicListenPort
 	a.ProxyListenPort = h.ProxyListenPort
 	a.PublicKey = h.PublicKey.String()
 	a.Verbosity = h.Verbosity

+ 37 - 36
models/host.go

@@ -41,42 +41,43 @@ const WIREGUARD_INTERFACE = "netmaker"
 
 // Host - represents a host on the network
 type Host struct {
-	ID               uuid.UUID        `json:"id" yaml:"id"`
-	Verbosity        int              `json:"verbosity" yaml:"verbosity"`
-	FirewallInUse    string           `json:"firewallinuse" yaml:"firewallinuse"`
-	Version          string           `json:"version" yaml:"version"`
-	IPForwarding     bool             `json:"ipforwarding" yaml:"ipforwarding"`
-	DaemonInstalled  bool             `json:"daemoninstalled" yaml:"daemoninstalled"`
-	AutoUpdate       bool             `json:"autoupdate" yaml:"autoupdate"`
-	HostPass         string           `json:"hostpass" yaml:"hostpass"`
-	Name             string           `json:"name" yaml:"name"`
-	OS               string           `json:"os" yaml:"os"`
-	Interface        string           `json:"interface" yaml:"interface"`
-	Debug            bool             `json:"debug" yaml:"debug"`
-	ListenPort       int              `json:"listenport" yaml:"listenport"`
-	PublicListenPort int              `json:"public_listen_port" yaml:"public_listen_port"`
-	ProxyListenPort  int              `json:"proxy_listen_port" yaml:"proxy_listen_port"`
-	MTU              int              `json:"mtu" yaml:"mtu"`
-	PublicKey        wgtypes.Key      `json:"publickey" yaml:"publickey"`
-	MacAddress       net.HardwareAddr `json:"macaddress" yaml:"macaddress"`
-	TrafficKeyPublic []byte           `json:"traffickeypublic" yaml:"traffickeypublic"`
-	InternetGateway  net.UDPAddr      `json:"internetgateway" yaml:"internetgateway"`
-	Nodes            []string         `json:"nodes" yaml:"nodes"`
-	IsRelayed        bool             `json:"isrelayed" yaml:"isrelayed"`
-	RelayedBy        string           `json:"relayed_by" yaml:"relayed_by"`
-	IsRelay          bool             `json:"isrelay" yaml:"isrelay"`
-	RelayedHosts     []string         `json:"relay_hosts" yaml:"relay_hosts"`
-	Interfaces       []Iface          `json:"interfaces" yaml:"interfaces"`
-	DefaultInterface string           `json:"defaultinterface" yaml:"defaultinterface"`
-	EndpointIP       net.IP           `json:"endpointip" yaml:"endpointip"`
-	ProxyEnabled     bool             `json:"proxy_enabled" yaml:"proxy_enabled"`
-	ProxyEnabledSet  bool             `json:"proxy_enabled_updated" yaml:"proxy_enabled_updated"`
-	IsDocker         bool             `json:"isdocker" yaml:"isdocker"`
-	IsK8S            bool             `json:"isk8s" yaml:"isk8s"`
-	IsStatic         bool             `json:"isstatic" yaml:"isstatic"`
-	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"`
+	ID                 uuid.UUID        `json:"id" yaml:"id"`
+	Verbosity          int              `json:"verbosity" yaml:"verbosity"`
+	FirewallInUse      string           `json:"firewallinuse" yaml:"firewallinuse"`
+	Version            string           `json:"version" yaml:"version"`
+	IPForwarding       bool             `json:"ipforwarding" yaml:"ipforwarding"`
+	DaemonInstalled    bool             `json:"daemoninstalled" yaml:"daemoninstalled"`
+	AutoUpdate         bool             `json:"autoupdate" yaml:"autoupdate"`
+	HostPass           string           `json:"hostpass" yaml:"hostpass"`
+	Name               string           `json:"name" yaml:"name"`
+	OS                 string           `json:"os" yaml:"os"`
+	Interface          string           `json:"interface" yaml:"interface"`
+	Debug              bool             `json:"debug" yaml:"debug"`
+	ListenPort         int              `json:"listenport" yaml:"listenport"`
+	PublicListenPort   int              `json:"public_listen_port" yaml:"public_listen_port"`
+	WgPublicListenPort int              `json:"wg_public_listen_port" yaml:"wg_public_listen_port"`
+	ProxyListenPort    int              `json:"proxy_listen_port" yaml:"proxy_listen_port"`
+	MTU                int              `json:"mtu" yaml:"mtu"`
+	PublicKey          wgtypes.Key      `json:"publickey" yaml:"publickey"`
+	MacAddress         net.HardwareAddr `json:"macaddress" yaml:"macaddress"`
+	TrafficKeyPublic   []byte           `json:"traffickeypublic" yaml:"traffickeypublic"`
+	InternetGateway    net.UDPAddr      `json:"internetgateway" yaml:"internetgateway"`
+	Nodes              []string         `json:"nodes" yaml:"nodes"`
+	IsRelayed          bool             `json:"isrelayed" yaml:"isrelayed"`
+	RelayedBy          string           `json:"relayed_by" yaml:"relayed_by"`
+	IsRelay            bool             `json:"isrelay" yaml:"isrelay"`
+	RelayedHosts       []string         `json:"relay_hosts" yaml:"relay_hosts"`
+	Interfaces         []Iface          `json:"interfaces" yaml:"interfaces"`
+	DefaultInterface   string           `json:"defaultinterface" yaml:"defaultinterface"`
+	EndpointIP         net.IP           `json:"endpointip" yaml:"endpointip"`
+	ProxyEnabled       bool             `json:"proxy_enabled" yaml:"proxy_enabled"`
+	ProxyEnabledSet    bool             `json:"proxy_enabled_updated" yaml:"proxy_enabled_updated"`
+	IsDocker           bool             `json:"isdocker" yaml:"isdocker"`
+	IsK8S              bool             `json:"isk8s" yaml:"isk8s"`
+	IsStatic           bool             `json:"isstatic" yaml:"isstatic"`
+	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

+ 9 - 0
mq/handlers.go

@@ -428,6 +428,15 @@ func handleHostCheckin(h, currentHost *models.Host) bool {
 	for i := range h.Interfaces {
 		h.Interfaces[i].AddressString = h.Interfaces[i].Address.String()
 	}
+	/// version or firewall in use change does not require a peerUpdate
+	if h.Version != currentHost.Version || h.FirewallInUse != currentHost.FirewallInUse {
+		currentHost.FirewallInUse = h.FirewallInUse
+		currentHost.Version = h.Version
+		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) ||

+ 8 - 5
release.md

@@ -1,13 +1,16 @@
 
-# Netmaker v0.20.0
+
+# Netmaker v0.20.1
 
 ## whats new
-- New UI
-- revamped compose-files and install scripts
-- TURN
+- 
     
 ## whats fixed
-- Caddy does not handle netmaker exporter well for EE
+- enrollment keys for non-admins 
+- client version displayed correctly in UI
+- upd hole punching improvments
+- SSL fallback to letsencrypt
+- permission handling for non-admin users
 
 ## known issues
 - Migration causes a listen port of 0 for some upgraded hosts

+ 11 - 11
scripts/nm-certs.sh

@@ -30,16 +30,16 @@ fi
 CERTBOT_PARAMS=$(cat <<EOF
 certonly --standalone \
 	--non-interactive --agree-tos \
-	-m "$NM_EMAIL" \
-	-d "stun.$NM_DOMAIN" \
-	-d "api.$NM_DOMAIN" \
-	-d "broker.$NM_DOMAIN" \
-	-d "dashboard.$NM_DOMAIN" \
-	-d "turn.$NM_DOMAIN" \
-	-d "turnapi.$NM_DOMAIN" \
-	-d "netmaker-exporter.$NM_DOMAIN" \
-	-d "grafana.$NM_DOMAIN" \
-	-d "prometheus.$NM_DOMAIN"
+	-m $NM_EMAIL \
+	-d stun.$NM_DOMAIN \
+	-d api.$NM_DOMAIN \
+	-d broker.$NM_DOMAIN \
+	-d dashboard.$NM_DOMAIN \
+	-d turn.$NM_DOMAIN \
+	-d turnapi.$NM_DOMAIN \
+	-d netmaker-exporter.$NM_DOMAIN \
+	-d grafana.$NM_DOMAIN \
+	-d prometheus.$NM_DOMAIN
 EOF
 )
 
@@ -75,7 +75,7 @@ if [ ! -f "$CERT_DIR"/fullchain.pem ]; then
 	sudo docker run -it --rm --name certbot \
 		-p 80:80 -p 443:443 \
 		-v "$SCRIPT_DIR/letsencrypt:/etc/letsencrypt" \
-		certbot/certbot "$CERTBOT_PARAMS"
+		certbot/certbot $CERTBOT_PARAMS
 	if [ ! -f "$CERT_DIR"/fullchain.pem ]; then
 		echo "Missing file: $CERT_DIR/fullchain.pem"
 		echo "SSL certificates failed"

+ 4 - 5
scripts/nm-quick.sh

@@ -210,7 +210,7 @@ configure_netclient() {
 	echo "making host a default"
 	echo "Host ID: $HOST_ID"
 	# set as a default host
-	set +e
+	set +e376298193
 	nmctl host update $HOST_ID --default
 	sleep 5
 	nmctl node create_ingress netmaker $NODE_ID
@@ -546,7 +546,7 @@ set_install_vars() {
 		echo "            grafana.$NETMAKER_BASE_DOMAIN"
 	fi
 
-	echo "-----------------------------------------------------"
+	echo "-----------------------------------------------------"376298193
 
 	if [[ "$DOMAIN_TYPE" == "custom" ]]; then
 		echo "before continuing, confirm DNS is configured correctly, with records pointing to $SERVER_HOST"
@@ -730,8 +730,7 @@ install_netmaker() {
 	if [ "$BUILD_TYPE" = "local" ]; then
 		local_install_setup
 	else
-                # local BASE_URL="https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG"
-                local BASE_URL="https://raw.githubusercontent.com/gravitl/netmaker/release-v0.20.0"
+		local BASE_URL="https://raw.githubusercontent.com/gravitl/netmaker/$BUILD_TAG"
 
 		local COMPOSE_URL="$BASE_URL/compose/docker-compose.yml"
 		local CADDY_URL="$BASE_URL/docker/Caddyfile"
@@ -816,7 +815,7 @@ setup_mesh() {
 
 		wait_seconds 5
 	fi
-
+376298193
 	echo "Obtaining a netmaker enrollment key..."
 
 	local tokenJson=$(nmctl enrollment_key create --unlimited --networks netmaker)

+ 1 - 1
scripts/nm-upgrade-0-17-1-to-0-19-0.sh

@@ -1,6 +1,6 @@
 #!/bin/bash
 
-LATEST="v0.20.0"
+LATEST="v0.20.1"
 INSTALL_PATH="/root"
 
 trap restore_old_netmaker_instructions

+ 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.
     title: Netmaker
-    version: 0.20.0
+    version: 0.20.1
 paths:
     /api/dns:
         get: