merge conflicts resolved

This commit is contained in:
Abhishek Kondur 2023-04-25 11:12:22 +04:00
commit 9e0038f39c
39 changed files with 285 additions and 119 deletions

View file

@ -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.7
- v0.18.6 - v0.18.6
- v0.18.5 - v0.18.5
- v0.18.4 - v0.18.4

View file

@ -53,6 +53,6 @@ jobs:
uses: gravitl/devops/.github/workflows/branchtest.yml@master uses: gravitl/devops/.github/workflows/branchtest.yml@master
with: with:
tag: ${{ github.run_id }}-${{ github.run_attempt }} tag: ${{ github.run_id }}-${{ github.run_attempt }}
network: terraform network: netmaker
secrets: inherit secrets: inherit

View file

@ -11,6 +11,29 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }} if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps: steps:
- name: get logs
uses: dawidd6/action-download-artifact@v2
with:
run_id: ${{ github.event.workflow_run.id}}
if_no_artifact_found: warn
- name: discord success 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: " ${{ github.event.workflow_run.name }} was successful"
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 will be deleted in 15 min"
file: ./server/serverinfo.txt
- name: delete droplets - name: delete droplets
run: | run: |
sleep 15m sleep 15m
@ -20,12 +43,44 @@ jobs:
"https://api.digitalocean.com/v2/droplets?tag_name=$TAG" "https://api.digitalocean.com/v2/droplets?tag_name=$TAG"
env: env:
DIGITALOCEAN_TOKEN: ${{ secrets.DIGITALOCEAN_TOKEN }} DIGITALOCEAN_TOKEN: ${{ secrets.DIGITALOCEAN_TOKEN }}
TAG: ${{ github.event.workflow_run.run_id }}-${{ github.event.workflow_run.run_attempt }} TAG: ${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}
on-failure: on-failure:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' }} if: ${{ github.event.workflow_run.conclusion == 'failure' }}
steps: steps:
- name: get logs
uses: dawidd6/action-download-artifact@v2
with:
run_id: ${{ github.event.workflow_run.id}}
if_no_artifact_found: warn
- name: discord failure 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: " ${{ github.event.workflow_run.name }} failed"
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 will be deleted in 6 hours"
file: ./server/serverinfo.txt
- name: discord error 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: "errors from ${{ github.event.workflow_run.name }}"
file: ./results/errors.log
- name: delete droplets - name: delete droplets
run: | run: |
sleep 6h sleep 6h
@ -35,4 +90,4 @@ jobs:
"https://api.digitalocean.com/v2/droplets?tag_name=$TAG" "https://api.digitalocean.com/v2/droplets?tag_name=$TAG"
env: env:
DIGITALOCEAN_TOKEN: ${{ secrets.DIGITALOCEAN_TOKEN }} DIGITALOCEAN_TOKEN: ${{ secrets.DIGITALOCEAN_TOKEN }}
TAG: ${{ github.event.workflow_run.run_id }}-${{ github.event.workflow_run.run_attempt }} TAG: ${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}

View file

@ -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.6-informational?style=flat-square" /> <img src="https://img.shields.io/badge/Version-0.18.7-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" />

View file

@ -3,8 +3,8 @@ version: "3.4"
services: services:
netmaker: netmaker:
container_name: netmaker container_name: netmaker
image: gravitl/netmaker:v0.18.6 image: gravitl/netmaker:v0.18.7
restart: always restart: on-failure
volumes: volumes:
- dnsconfig:/root/config/dnsconfig - dnsconfig:/root/config/dnsconfig
- sqldata:/root/data - sqldata:/root/data
@ -19,6 +19,7 @@ services:
COREDNS_ADDR: "SERVER_PUBLIC_IP" COREDNS_ADDR: "SERVER_PUBLIC_IP"
DNS_MODE: "on" DNS_MODE: "on"
SERVER_HTTP_HOST: "api.NETMAKER_BASE_DOMAIN" SERVER_HTTP_HOST: "api.NETMAKER_BASE_DOMAIN"
NETCLIENT_AUTO_UPDATE: "enabled"
API_PORT: "8081" API_PORT: "8081"
MASTER_KEY: "REPLACE_MASTER_KEY" MASTER_KEY: "REPLACE_MASTER_KEY"
CORS_ALLOWED_ORIGIN: "*" CORS_ALLOWED_ORIGIN: "*"
@ -35,7 +36,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.6 image: gravitl/netmaker-ui:v0.18.7
depends_on: depends_on:
- netmaker - netmaker
links: links:

View file

@ -4,7 +4,7 @@ services:
netmaker: netmaker:
container_name: netmaker container_name: netmaker
image: gravitl/netmaker:REPLACE_SERVER_IMAGE_TAG image: gravitl/netmaker:REPLACE_SERVER_IMAGE_TAG
restart: always restart: on-failure
volumes: volumes:
- dnsconfig:/root/config/dnsconfig - dnsconfig:/root/config/dnsconfig
- sqldata:/root/data - sqldata:/root/data
@ -17,6 +17,7 @@ services:
COREDNS_ADDR: "SERVER_PUBLIC_IP" COREDNS_ADDR: "SERVER_PUBLIC_IP"
DNS_MODE: "on" DNS_MODE: "on"
SERVER_HTTP_HOST: "api.NETMAKER_BASE_DOMAIN" SERVER_HTTP_HOST: "api.NETMAKER_BASE_DOMAIN"
NETCLIENT_AUTO_UPDATE: "enabled"
API_PORT: "8081" API_PORT: "8081"
MASTER_KEY: "REPLACE_MASTER_KEY" MASTER_KEY: "REPLACE_MASTER_KEY"
CORS_ALLOWED_ORIGIN: "*" CORS_ALLOWED_ORIGIN: "*"

View file

@ -3,10 +3,10 @@ version: "3.4"
services: services:
netclient: netclient:
container_name: netclient container_name: netclient
image: 'gravitl/netclient:v0.18.6' image: 'gravitl/netclient:v0.18.7'
hostname: netmaker-1 hostname: netmaker-1
network_mode: host network_mode: host
restart: always restart: on-failure
environment: environment:
TOKEN: "TOKEN_VALUE" TOKEN: "TOKEN_VALUE"
volumes: volumes:

View file

@ -4,7 +4,7 @@ services:
netmaker: # The Primary Server for running Netmaker netmaker: # The Primary Server for running Netmaker
container_name: netmaker container_name: netmaker
image: gravitl/netmaker:REPLACE_SERVER_IMAGE_TAG image: gravitl/netmaker:REPLACE_SERVER_IMAGE_TAG
restart: always restart: on-failure
volumes: # Volume mounts necessary for sql, coredns, and mqtt volumes: # Volume mounts necessary for sql, coredns, and mqtt
- dnsconfig:/root/config/dnsconfig - dnsconfig:/root/config/dnsconfig
- sqldata:/root/data - sqldata:/root/data
@ -14,6 +14,7 @@ services:
SERVER_NAME: "NETMAKER_BASE_DOMAIN" # The base domain of netmaker SERVER_NAME: "NETMAKER_BASE_DOMAIN" # The base domain of netmaker
SERVER_HOST: "SERVER_PUBLIC_IP" # Set to public IP of machine. SERVER_HOST: "SERVER_PUBLIC_IP" # Set to public IP of machine.
SERVER_HTTP_HOST: "api.NETMAKER_BASE_DOMAIN" # Overrides SERVER_HOST if set. Useful for making HTTP available via different interfaces/networks. SERVER_HTTP_HOST: "api.NETMAKER_BASE_DOMAIN" # Overrides SERVER_HOST if set. Useful for making HTTP available via different interfaces/networks.
NETCLIENT_AUTO_UPDATE: "enabled" # Enable auto update of netclient ? ENUM:- enabled,disabled | default: enabled
SERVER_API_CONN_STRING: "api.NETMAKER_BASE_DOMAIN:443" SERVER_API_CONN_STRING: "api.NETMAKER_BASE_DOMAIN:443"
COREDNS_ADDR: "SERVER_PUBLIC_IP" # Address of the CoreDNS server. Defaults to SERVER_HOST COREDNS_ADDR: "SERVER_PUBLIC_IP" # Address of the CoreDNS server. Defaults to SERVER_HOST
DNS_MODE: "on" # Enables DNS Mode, meaning all nodes will set hosts file for private dns settings. DNS_MODE: "on" # Enables DNS Mode, meaning all nodes will set hosts file for private dns settings.

View file

@ -4,7 +4,7 @@ services:
netmaker: netmaker:
container_name: netmaker container_name: netmaker
image: gravitl/netmaker:REPLACE_SERVER_IMAGE_TAG image: gravitl/netmaker:REPLACE_SERVER_IMAGE_TAG
restart: always restart: on-failure
volumes: volumes:
- dnsconfig:/root/config/dnsconfig - dnsconfig:/root/config/dnsconfig
- sqldata:/root/data - sqldata:/root/data
@ -17,6 +17,7 @@ services:
COREDNS_ADDR: "SERVER_PUBLIC_IP" COREDNS_ADDR: "SERVER_PUBLIC_IP"
DNS_MODE: "on" DNS_MODE: "on"
SERVER_HTTP_HOST: "api.NETMAKER_BASE_DOMAIN" SERVER_HTTP_HOST: "api.NETMAKER_BASE_DOMAIN"
NETCLIENT_AUTO_UPDATE: "enabled"
API_PORT: "8081" API_PORT: "8081"
MASTER_KEY: "REPLACE_MASTER_KEY" MASTER_KEY: "REPLACE_MASTER_KEY"
CORS_ALLOWED_ORIGIN: "*" CORS_ALLOWED_ORIGIN: "*"

View file

@ -40,6 +40,7 @@ type ServerConfig struct {
ServerBrokerEndpoint string `yaml:"serverbrokerendpoint"` ServerBrokerEndpoint string `yaml:"serverbrokerendpoint"`
BrokerType string `yaml:"brokertype"` BrokerType string `yaml:"brokertype"`
EmqxRestEndpoint string `yaml:"emqxrestendpoint"` EmqxRestEndpoint string `yaml:"emqxrestendpoint"`
NetclientAutoUpdate string `yaml:"netclientautoupdate"`
MasterKey string `yaml:"masterkey"` MasterKey string `yaml:"masterkey"`
DNSKey string `yaml:"dnskey"` DNSKey string `yaml:"dnskey"`
AllowedOrigin string `yaml:"allowedorigin"` AllowedOrigin string `yaml:"allowedorigin"`

View file

@ -70,6 +70,7 @@ func getAllDNS(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return return
} }
logic.SortDNSEntrys(dns[:])
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(dns) json.NewEncoder(w).Encode(dns)
} }

View file

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

View file

@ -117,6 +117,7 @@ func getAllExtClients(w http.ResponseWriter, r *http.Request) {
} }
//Return all the extclients in JSON format //Return all the extclients in JSON format
logic.SortExtClient(clients[:])
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(clients) json.NewEncoder(w).Encode(clients)
} }

View file

@ -20,6 +20,8 @@ import (
func hostHandlers(r *mux.Router) { func hostHandlers(r *mux.Router) {
r.HandleFunc("/api/hosts", logic.SecurityCheck(true, http.HandlerFunc(getHosts))).Methods(http.MethodGet) r.HandleFunc("/api/hosts", logic.SecurityCheck(true, 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) r.HandleFunc("/api/hosts/{hostid}", logic.SecurityCheck(true, http.HandlerFunc(updateHost))).Methods(http.MethodPut)
r.HandleFunc("/api/hosts/{hostid}", logic.SecurityCheck(true, http.HandlerFunc(deleteHost))).Methods(http.MethodDelete) r.HandleFunc("/api/hosts/{hostid}", logic.SecurityCheck(true, http.HandlerFunc(deleteHost))).Methods(http.MethodDelete)
r.HandleFunc("/api/hosts/{hostid}/networks/{network}", logic.SecurityCheck(true, http.HandlerFunc(addHostToNetwork))).Methods(http.MethodPost) r.HandleFunc("/api/hosts/{hostid}/networks/{network}", logic.SecurityCheck(true, http.HandlerFunc(addHostToNetwork))).Methods(http.MethodPost)
@ -53,6 +55,7 @@ func getHosts(w http.ResponseWriter, r *http.Request) {
// return JSON/API formatted hosts // return JSON/API formatted hosts
apiHosts := logic.GetAllHostsAPI(currentHosts[:]) apiHosts := logic.GetAllHostsAPI(currentHosts[:])
logger.Log(2, r.Header.Get("user"), "fetched all hosts") logger.Log(2, r.Header.Get("user"), "fetched all hosts")
logic.SortApiHosts(apiHosts[:])
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(apiHosts) json.NewEncoder(w).Encode(apiHosts)
} }
@ -448,9 +451,15 @@ func authenticateHost(response http.ResponseWriter, request *http.Request) {
response.Write(successJSONResponse) response.Write(successJSONResponse)
} }
<<<<<<< HEAD
// swagger:route POST /api/hosts/{hostid}/signalpeer signalPeer // swagger:route POST /api/hosts/{hostid}/signalpeer signalPeer
// //
// send signal to peer. // send signal to peer.
=======
// swagger:route POST /api/hosts/keys host updateAllKeys
//
// Update keys for a network.
>>>>>>> 6abbf075e061ffe58c35b3e75493ba5ffa175022
// //
// Schemes: https // Schemes: https
// //
@ -458,6 +467,7 @@ func authenticateHost(response http.ResponseWriter, request *http.Request) {
// oauth // oauth
// //
// Responses: // Responses:
<<<<<<< HEAD
// 200: nodeResponse // 200: nodeResponse
func signalPeer(w http.ResponseWriter, r *http.Request) { func signalPeer(w http.ResponseWriter, r *http.Request) {
var params = mux.Vars(r) var params = mux.Vars(r)
@ -512,4 +522,71 @@ func signalPeer(w http.ResponseWriter, r *http.Request) {
} }
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(signal) json.NewEncoder(w).Encode(signal)
=======
// 200: networkBodyResponse
func updateAllKeys(w http.ResponseWriter, r *http.Request) {
var errorResponse = models.ErrorResponse{}
w.Header().Set("Content-Type", "application/json")
hosts, err := logic.GetAllHosts()
if err != nil {
errorResponse.Code = http.StatusBadRequest
errorResponse.Message = err.Error()
logger.Log(0, r.Header.Get("user"),
"error retrieving hosts ", err.Error())
logic.ReturnErrorResponse(w, r, errorResponse)
return
}
go func() {
hostUpdate := models.HostUpdate{}
hostUpdate.Action = models.UpdateKeys
for _, host := range hosts {
hostUpdate.Host = host
logger.Log(2, "updating host", host.ID.String(), " for a key update")
if err = mq.HostUpdate(&hostUpdate); err != nil {
logger.Log(0, "failed to send update to node during a network wide key update", host.ID.String(), err.Error())
}
}
}()
logger.Log(2, r.Header.Get("user"), "updated keys for all hosts")
w.WriteHeader(http.StatusOK)
}
// swagger:route POST /api/hosts/{hostid}keys host updateKeys
//
// Update keys for a network.
//
// Schemes: https
//
// Security:
// oauth
//
// Responses:
// 200: networkBodyResponse
func updateKeys(w http.ResponseWriter, r *http.Request) {
var errorResponse = models.ErrorResponse{}
w.Header().Set("Content-Type", "application/json")
var params = mux.Vars(r)
hostid := params["hostid"]
host, err := logic.GetHost(hostid)
if err != nil {
logger.Log(0, "failed to retrieve host", hostid, err.Error())
errorResponse.Code = http.StatusBadRequest
errorResponse.Message = err.Error()
logger.Log(0, r.Header.Get("user"),
"error retrieving hosts ", err.Error())
logic.ReturnErrorResponse(w, r, errorResponse)
return
}
go func() {
hostUpdate := models.HostUpdate{
Action: models.UpdateKeys,
Host: *host,
}
if err = mq.HostUpdate(&hostUpdate); err != nil {
logger.Log(0, "failed to send host key update", host.ID.String(), err.Error())
}
}()
logger.Log(2, r.Header.Get("user"), "updated key on host", host.Name)
w.WriteHeader(http.StatusOK)
>>>>>>> 6abbf075e061ffe58c35b3e75493ba5ffa175022
} }

View file

@ -23,7 +23,6 @@ func networkHandlers(r *mux.Router) {
r.HandleFunc("/api/networks", logic.SecurityCheck(true, checkFreeTierLimits(networks_l, http.HandlerFunc(createNetwork)))).Methods(http.MethodPost) r.HandleFunc("/api/networks", logic.SecurityCheck(true, checkFreeTierLimits(networks_l, http.HandlerFunc(createNetwork)))).Methods(http.MethodPost)
r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(false, http.HandlerFunc(getNetwork))).Methods(http.MethodGet) r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(false, http.HandlerFunc(getNetwork))).Methods(http.MethodGet)
r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(true, http.HandlerFunc(deleteNetwork))).Methods(http.MethodDelete) r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(true, http.HandlerFunc(deleteNetwork))).Methods(http.MethodDelete)
r.HandleFunc("/api/networks/{networkname}/keyupdate", logic.SecurityCheck(true, http.HandlerFunc(keyUpdate))).Methods(http.MethodPost)
// ACLs // ACLs
r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(updateNetworkACL))).Methods(http.MethodPut) r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(updateNetworkACL))).Methods(http.MethodPut)
r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(getNetworkACL))).Methods(http.MethodGet) r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(getNetworkACL))).Methods(http.MethodGet)
@ -70,6 +69,7 @@ func getNetworks(w http.ResponseWriter, r *http.Request) {
} }
logger.Log(2, r.Header.Get("user"), "fetched networks.") logger.Log(2, r.Header.Get("user"), "fetched networks.")
logic.SortNetworks(allnetworks[:])
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(allnetworks) json.NewEncoder(w).Encode(allnetworks)
} }
@ -103,44 +103,6 @@ func getNetwork(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(network) json.NewEncoder(w).Encode(network)
} }
// swagger:route POST /api/networks/{networkname}/keyupdate networks keyUpdate
//
// Update keys for a network.
//
// Schemes: https
//
// Security:
// oauth
//
// Responses:
// 200: networkBodyResponse
func keyUpdate(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var params = mux.Vars(r)
netname := params["networkname"]
network, err := logic.KeyUpdate(netname)
if err != nil {
logger.Log(0, r.Header.Get("user"), fmt.Sprintf("failed to update keys for network [%s]: %v",
netname, err))
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
logger.Log(2, r.Header.Get("user"), "updated key on network", netname)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(network)
nodes, err := logic.GetNetworkNodes(netname)
if err != nil {
logger.Log(0, "failed to retrieve network nodes for network", netname, err.Error())
return
}
for _, node := range nodes {
logger.Log(2, "updating node ", node.ID.String(), " for a key update")
if err = mq.NodeUpdate(&node); err != nil {
logger.Log(1, "failed to send update to node during a network wide key update", node.ID.String(), err.Error())
}
}
}
// swagger:route PUT /api/networks/{networkname}/acls networks updateNetworkACL // swagger:route PUT /api/networks/{networkname}/acls networks updateNetworkACL
// //
// Update a network ACL (Access Control List). // Update a network ACL (Access Control List).

View file

@ -340,6 +340,7 @@ func getAllNodes(w http.ResponseWriter, r *http.Request) {
// return all the nodes in JSON/API format // return all the nodes in JSON/API format
apiNodes := logic.GetAllNodesAPI(nodes[:]) apiNodes := logic.GetAllNodesAPI(nodes[:])
logger.Log(3, r.Header.Get("user"), "fetched all nodes they have access to") logger.Log(3, r.Header.Get("user"), "fetched all nodes they have access to")
logic.SortApiNodes(apiNodes[:])
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(apiNodes) json.NewEncoder(w).Encode(apiNodes)
} }

View file

@ -186,6 +186,7 @@ func getUsers(w http.ResponseWriter, r *http.Request) {
return return
} }
logic.SortUsers(users[:])
logger.Log(2, r.Header.Get("user"), "fetched users") logger.Log(2, r.Header.Get("user"), "fetched users")
json.NewEncoder(w).Encode(users) json.NewEncoder(w).Encode(users)
} }

View file

@ -44,17 +44,17 @@ func ValidateLicense() error {
netmakerAccountID := servercfg.GetNetmakerAccountID() netmakerAccountID := servercfg.GetNetmakerAccountID()
logger.Log(0, "proceeding with Netmaker license validation...") logger.Log(0, "proceeding with Netmaker license validation...")
if len(licenseKeyValue) == 0 || len(netmakerAccountID) == 0 { if len(licenseKeyValue) == 0 || len(netmakerAccountID) == 0 {
logger.FatalLog(errValidation.Error()) logger.FatalLog0(errValidation.Error())
} }
apiPublicKey, err := getLicensePublicKey(licenseKeyValue) apiPublicKey, err := getLicensePublicKey(licenseKeyValue)
if err != nil { if err != nil {
logger.FatalLog(errValidation.Error()) logger.FatalLog0(errValidation.Error())
} }
tempPubKey, tempPrivKey, err := FetchApiServerKeys() tempPubKey, tempPrivKey, err := FetchApiServerKeys()
if err != nil { if err != nil {
logger.FatalLog(errValidation.Error()) logger.FatalLog0(errValidation.Error())
} }
licenseSecret := LicenseSecret{ licenseSecret := LicenseSecret{
@ -64,32 +64,32 @@ func ValidateLicense() error {
secretData, err := json.Marshal(&licenseSecret) secretData, err := json.Marshal(&licenseSecret)
if err != nil { if err != nil {
logger.FatalLog(errValidation.Error()) logger.FatalLog0(errValidation.Error())
} }
encryptedData, err := ncutils.BoxEncrypt(secretData, apiPublicKey, tempPrivKey) encryptedData, err := ncutils.BoxEncrypt(secretData, apiPublicKey, tempPrivKey)
if err != nil { if err != nil {
logger.FatalLog(errValidation.Error()) logger.FatalLog0(errValidation.Error())
} }
validationResponse, err := validateLicenseKey(encryptedData, tempPubKey) validationResponse, err := validateLicenseKey(encryptedData, tempPubKey)
if err != nil || len(validationResponse) == 0 { if err != nil || len(validationResponse) == 0 {
logger.FatalLog(errValidation.Error()) logger.FatalLog0(errValidation.Error())
} }
var licenseResponse ValidatedLicense var licenseResponse ValidatedLicense
if err = json.Unmarshal(validationResponse, &licenseResponse); err != nil { if err = json.Unmarshal(validationResponse, &licenseResponse); err != nil {
logger.FatalLog(errValidation.Error()) logger.FatalLog0(errValidation.Error())
} }
respData, err := ncutils.BoxDecrypt(base64decode(licenseResponse.EncryptedLicense), apiPublicKey, tempPrivKey) respData, err := ncutils.BoxDecrypt(base64decode(licenseResponse.EncryptedLicense), apiPublicKey, tempPrivKey)
if err != nil { if err != nil {
logger.FatalLog(errValidation.Error()) logger.FatalLog0(errValidation.Error())
} }
license := LicenseKey{} license := LicenseKey{}
if err = json.Unmarshal(respData, &license); err != nil { if err = json.Unmarshal(respData, &license); err != nil {
logger.FatalLog(errValidation.Error()) logger.FatalLog0(errValidation.Error())
} }
Limits.Networks = math.MaxInt Limits.Networks = math.MaxInt

2
go.mod
View file

@ -9,7 +9,7 @@ require (
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
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/lib/pq v1.10.7 github.com/lib/pq v1.10.8
github.com/mattn/go-sqlite3 v1.14.16 github.com/mattn/go-sqlite3 v1.14.16
github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e

4
go.sum
View file

@ -96,8 +96,8 @@ 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.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4= github.com/leodido/go-urn v1.2.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4=
github.com/leodido/go-urn v1.2.2/go.mod h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ= 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.8 h1:3fdt97i/cwSU83+E0hZTC/Xpc9mTZxc6UWSCRcSbxiE=
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.8/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=
github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=

View file

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

View file

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

View file

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

View file

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

View file

@ -138,6 +138,12 @@ func FatalLog(message ...string) {
os.Exit(2) os.Exit(2)
} }
// FatalLog0 - exits os after logging
func FatalLog0(message ...string) {
fmt.Printf("[%s] Fatal: %s \n", program, MakeString(" ", message...))
os.Exit(0)
}
// == private == // == private ==
// resetLogs - reallocates logs map // resetLogs - reallocates logs map

View file

@ -1,6 +1,10 @@
package logic package logic
import "github.com/gravitl/netmaker/models" import (
"sort"
"github.com/gravitl/netmaker/models"
)
// functions defined here, handle client ACLs, should be set on ee // functions defined here, handle client ACLs, should be set on ee
@ -51,3 +55,10 @@ func IsClientNodeAllowedByID(clientID, networkName, clientOrNodeID string) bool
} }
return IsClientNodeAllowed(&client, clientOrNodeID) return IsClientNodeAllowed(&client, clientOrNodeID)
} }
// SortExtClient - Sorts slice of ExtClients by their ClientID alphabetically with numbers first
func SortExtClient(unsortedExtClient []models.ExtClient) {
sort.Slice(unsortedExtClient, func(i, j int) bool {
return unsortedExtClient[i].ClientID < unsortedExtClient[j].ClientID
})
}

View file

@ -3,6 +3,7 @@ package logic
import ( import (
"encoding/json" "encoding/json"
"os" "os"
"sort"
validator "github.com/go-playground/validator/v10" validator "github.com/go-playground/validator/v10"
"github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/database"
@ -194,6 +195,13 @@ func GetDNSEntryNum(domain string, network string) (int, error) {
return num, nil return num, nil
} }
// SortDNSEntrys - Sorts slice of DNSEnteys by their Address alphabetically with numbers first
func SortDNSEntrys(unsortedDNSEntrys []models.DNSEntry) {
sort.Slice(unsortedDNSEntrys, func(i, j int) bool {
return unsortedDNSEntrys[i].Address < unsortedDNSEntrys[j].Address
})
}
// ValidateDNSCreate - checks if an entry is valid // ValidateDNSCreate - checks if an entry is valid
func ValidateDNSCreate(entry models.DNSEntry) error { func ValidateDNSCreate(entry models.DNSEntry) error {

View file

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"sort"
"strconv" "strconv"
"github.com/devilcove/httpclient" "github.com/devilcove/httpclient"
@ -106,6 +107,7 @@ func CreateHost(h *models.Host) error {
return err return err
} }
h.HostPass = string(hash) h.HostPass = string(hash)
h.AutoUpdate = servercfg.AutoUpdateEnabled()
// if another server has already updated proxyenabled, leave it alone // if another server has already updated proxyenabled, leave it alone
if !h.ProxyEnabledSet { if !h.ProxyEnabledSet {
log.Println("checking default proxy", servercfg.GetServerConfig().DefaultProxyMode) log.Println("checking default proxy", servercfg.GetServerConfig().DefaultProxyMode)
@ -160,6 +162,10 @@ func UpdateHost(newHost, currentHost *models.Host) {
// UpdateHostFromClient - used for updating host on server with update recieved from client // UpdateHostFromClient - used for updating host on server with update recieved from client
func UpdateHostFromClient(newHost, currHost *models.Host) (sendPeerUpdate bool) { func UpdateHostFromClient(newHost, currHost *models.Host) (sendPeerUpdate bool) {
if newHost.PublicKey != currHost.PublicKey {
currHost.PublicKey = newHost.PublicKey
sendPeerUpdate = true
}
if newHost.ListenPort != 0 && currHost.ListenPort != newHost.ListenPort { if newHost.ListenPort != 0 && currHost.ListenPort != newHost.ListenPort {
currHost.ListenPort = newHost.ListenPort currHost.ListenPort = newHost.ListenPort
sendPeerUpdate = true sendPeerUpdate = true
@ -490,3 +496,10 @@ func DeRegisterHostWithTurn(hostID string) error {
} }
return nil return nil
} }
// SortApiHosts - Sorts slice of ApiHosts by their ID alphabetically with numbers first
func SortApiHosts(unsortedHosts []models.ApiHost) {
sort.Slice(unsortedHosts, func(i, j int) bool {
return unsortedHosts[i].ID < unsortedHosts[j].ID
})
}

View file

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"sort"
"strings" "strings"
"github.com/c-robinson/iplib" "github.com/c-robinson/iplib"
@ -554,15 +555,6 @@ func ParseNetwork(value string) (models.Network, error) {
return network, err return network, err
} }
// KeyUpdate - updates keys on network
func KeyUpdate(netname string) (models.Network, error) {
err := networkNodesUpdateAction(netname, models.NODE_UPDATE_KEY)
if err != nil {
return models.Network{}, err
}
return models.Network{}, nil
}
// SaveNetwork - save network struct to database // SaveNetwork - save network struct to database
func SaveNetwork(network *models.Network) error { func SaveNetwork(network *models.Network) error {
data, err := json.Marshal(network) data, err := json.Marshal(network)
@ -586,39 +578,11 @@ func NetworkExists(name string) (bool, error) {
return len(network) > 0, nil return len(network) > 0, nil
} }
// == Private == // SortNetworks - Sorts slice of Networks by their NetID alphabetically with numbers first
func SortNetworks(unsortedNetworks []models.Network) {
func networkNodesUpdateAction(networkName string, action string) error { sort.Slice(unsortedNetworks, func(i, j int) bool {
return unsortedNetworks[i].NetID < unsortedNetworks[j].NetID
collections, err := database.FetchRecords(database.NODES_TABLE_NAME) })
if err != nil {
if database.IsEmptyRecord(err) {
return nil
}
return err
}
for k, value := range collections {
var node models.Node
err := json.Unmarshal([]byte(value), &node)
if err != nil {
if IsLegacyNode(k) { // ignore legacy nodes
continue
}
fmt.Println("error in node address assignment!")
return err
}
if action == models.NODE_UPDATE_KEY {
continue
}
if node.Network == networkName {
node.Action = action
data, err := json.Marshal(&node)
if err != nil {
return err
}
database.Insert(node.ID.String(), string(data), database.NODES_TABLE_NAME)
}
}
return nil
} }
// == Private ==

View file

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"sort"
"time" "time"
validator "github.com/go-playground/validator/v10" validator "github.com/go-playground/validator/v10"
@ -546,4 +547,11 @@ func createNode(node *models.Node) error {
return err return err
} }
// SortApiNodes - Sorts slice of ApiNodes by their ID alphabetically with numbers first
func SortApiNodes(unsortedNodes []models.ApiNode) {
sort.Slice(unsortedNodes, func(i, j int) bool {
return unsortedNodes[i].ID < unsortedNodes[j].ID
})
}
// == END PRO == // == END PRO ==

View file

@ -2,6 +2,7 @@ package logic
import ( import (
"encoding/json" "encoding/json"
"sort"
"github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logger"
@ -77,3 +78,10 @@ func SetUserDefaults(user *models.User) {
user.Groups = []string{pro.DEFAULT_ALLOWED_GROUPS} user.Groups = []string{pro.DEFAULT_ALLOWED_GROUPS}
} }
} }
// SortUsers - Sorts slice of Users by username
func SortUsers(unsortedUsers []models.ReturnUser) {
sort.Slice(unsortedUsers, func(i, j int) bool {
return unsortedUsers[i].UserName < unsortedUsers[j].UserName
})
}

View file

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

View file

@ -47,6 +47,7 @@ type Host struct {
Version string `json:"version" yaml:"version"` Version string `json:"version" yaml:"version"`
IPForwarding bool `json:"ipforwarding" yaml:"ipforwarding"` IPForwarding bool `json:"ipforwarding" yaml:"ipforwarding"`
DaemonInstalled bool `json:"daemoninstalled" yaml:"daemoninstalled"` DaemonInstalled bool `json:"daemoninstalled" yaml:"daemoninstalled"`
AutoUpdate bool `json:"autoupdate" yaml:"autoupdate"`
HostPass string `json:"hostpass" yaml:"hostpass"` HostPass string `json:"hostpass" yaml:"hostpass"`
Name string `json:"name" yaml:"name"` Name string `json:"name" yaml:"name"`
OS string `json:"os" yaml:"os"` OS string `json:"os" yaml:"os"`
@ -118,6 +119,8 @@ const (
CheckIn = "CHECK_IN" CheckIn = "CHECK_IN"
// REGISTER_WITH_TURN - registers host with turn server if configured // REGISTER_WITH_TURN - registers host with turn server if configured
RegisterWithTurn = "REGISTER_WITH_TURN" RegisterWithTurn = "REGISTER_WITH_TURN"
// UpdateKeys - update wireguard private/public keys
UpdateKeys = "UPDATE_KEYS"
) )
// HostUpdate - struct for host update // HostUpdate - struct for host update

View file

@ -19,8 +19,6 @@ const (
// MAX_NAME_LENGTH - max name length of node // MAX_NAME_LENGTH - max name length of node
MAX_NAME_LENGTH = 62 MAX_NAME_LENGTH = 62
// == ACTIONS == (can only be set by server) // == ACTIONS == (can only be set by server)
// NODE_UPDATE_KEY - action to update key
NODE_UPDATE_KEY = "updatekey"
// NODE_DELETE - delete node action // NODE_DELETE - delete node action
NODE_DELETE = "delete" NODE_DELETE = "delete"
// NODE_IS_PENDING - node pending status // NODE_IS_PENDING - node pending status

View file

@ -16,6 +16,7 @@ import (
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/ncutils" "github.com/gravitl/netmaker/netclient/ncutils"
"github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/servercfg"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
) )
// DefaultHandler default message queue handler -- NOT USED // DefaultHandler default message queue handler -- NOT USED
@ -117,6 +118,28 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) {
} }
} }
case models.UpdateHost: case models.UpdateHost:
if hostUpdate.Host.PublicKey != currentHost.PublicKey {
//remove old peer entry
peerUpdate := models.HostPeerUpdate{
ServerVersion: servercfg.GetVersion(),
Peers: []wgtypes.PeerConfig{
{
PublicKey: currentHost.PublicKey,
Remove: true,
},
},
}
data, err := json.Marshal(&peerUpdate)
if err != nil {
logger.Log(2, "json error", err.Error())
}
hosts := logic.GetRelatedHosts(hostUpdate.Host.ID.String())
server := servercfg.GetServer()
for _, host := range hosts {
publish(&host, fmt.Sprintf("peers/host/%s/%s", host.ID.String(), server), data)
}
}
sendPeerUpdate = logic.UpdateHostFromClient(&hostUpdate.Host, currentHost) sendPeerUpdate = logic.UpdateHostFromClient(&hostUpdate.Host, currentHost)
err := logic.UpsertHost(currentHost) err := logic.UpsertHost(currentHost)
if err != nil { if err != nil {

View file

@ -1,9 +1,14 @@
# Netmaker v0.18.7 # Netmaker v0.18.7
## whats new ## whats new
- internet gateways (0.0.0.0/0) for egress
- deprecated editing of network parameters - deprecated editing of network parameters
- allow extra ips for extclient (not enabled in UI)
## whats fixed ## whats fixed
- nm-quick - determine lastest version from releases
- wireguard public/private key rotation
- ee-license checks
## known issues ## known issues
- Caddy does not handle netmaker exporter well for EE - Caddy does not handle netmaker exporter well for EE
@ -14,4 +19,3 @@
- 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

View file

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
LATEST="v0.18.6" LATEST=$(curl -s https://api.github.com/repos/gravitl/netmaker/releases/latest | grep "tag_name" | cut -d : -f 2,3 | tr -d [:space:],\")
print_logo() {( print_logo() {(
cat << "EOF" cat << "EOF"

View file

@ -46,6 +46,11 @@ func GetServerConfig() config.ServerConfig {
cfg.StunPort = GetStunPort() cfg.StunPort = GetStunPort()
cfg.BrokerType = GetBrokerType() cfg.BrokerType = GetBrokerType()
cfg.EmqxRestEndpoint = GetEmqxRestEndpoint() cfg.EmqxRestEndpoint = GetEmqxRestEndpoint()
if AutoUpdateEnabled() {
cfg.NetclientAutoUpdate = "enabled"
} else {
cfg.NetclientAutoUpdate = "disabled"
}
if IsRestBackend() { if IsRestBackend() {
cfg.RestBackend = "on" cfg.RestBackend = "on"
} }
@ -405,6 +410,17 @@ func GetVerbosity() int32 {
return int32(verbosity) return int32(verbosity)
} }
// AutoUpdateEnabled returns a boolean indicating whether netclient auto update is enabled or disabled
// default is enabled
func AutoUpdateEnabled() bool {
if os.Getenv("NETCLIENT_AUTO_UPDATE") == "disabled" {
return false
} else if config.Config.Server.NetclientAutoUpdate == "disabled" {
return false
}
return true
}
// IsDNSMode - should it run with DNS // IsDNSMode - should it run with DNS
func IsDNSMode() bool { func IsDNSMode() bool {
isdns := true isdns := true

View file

@ -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.6 version: 0.18.7
paths: paths:
/api/dns: /api/dns:
get: get: