Merge branch 'develop' into gra-1088_dns_updates

This commit is contained in:
Matthew R Kasun 2023-02-15 06:42:09 -05:00
commit bd9cf14c02
57 changed files with 547 additions and 1138 deletions

View file

@ -31,6 +31,7 @@ body:
label: Version
description: What version are you running?
options:
- v0.18.0
- v0.17.1
- v0.17.0
- v0.16.3

View file

@ -17,7 +17,7 @@
<p align="center">
<a href="https://github.com/gravitl/netmaker/releases">
<img src="https://img.shields.io/badge/Version-0.17.1-informational?style=flat-square" />
<img src="https://img.shields.io/badge/Version-0.18.0-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" />

View file

@ -0,0 +1,20 @@
package host
import (
"github.com/gravitl/netmaker/cli/functions"
"github.com/spf13/cobra"
)
var addHostNetworkCmd = &cobra.Command{
Use: "add_network HostID Network",
Args: cobra.ExactArgs(2),
Short: "Add a network to a host",
Long: `Add a network to a host`,
Run: func(cmd *cobra.Command, args []string) {
functions.PrettyPrint(functions.AddHostToNetwork(args[0], args[1]))
},
}
func init() {
rootCmd.AddCommand(addHostNetworkCmd)
}

View file

@ -0,0 +1,20 @@
package host
import (
"github.com/gravitl/netmaker/cli/functions"
"github.com/spf13/cobra"
)
var deleteHostNetworkCmd = &cobra.Command{
Use: "delete_network HostID Network",
Args: cobra.ExactArgs(2),
Short: "Delete a network from a host",
Long: `Delete a network from a host`,
Run: func(cmd *cobra.Command, args []string) {
functions.PrettyPrint(functions.DeleteHostFromNetwork(args[0], args[1]))
},
}
func init() {
rootCmd.AddCommand(deleteHostNetworkCmd)
}

View file

@ -1,22 +0,0 @@
package host
import (
"strings"
"github.com/gravitl/netmaker/cli/functions"
"github.com/spf13/cobra"
)
var hostUpdateNetworksCmd = &cobra.Command{
Use: "update_network HostID Networks(comma separated list)",
Args: cobra.ExactArgs(2),
Short: "Update a host's networks",
Long: `Update a host's networks`,
Run: func(cmd *cobra.Command, args []string) {
functions.PrettyPrint(functions.UpdateHostNetworks(args[0], strings.Split(args[1], ",")))
},
}
func init() {
rootCmd.AddCommand(hostUpdateNetworksCmd)
}

View file

@ -26,11 +26,14 @@ func UpdateHost(hostID string, body *models.ApiHost) *models.ApiHost {
return request[models.ApiHost](http.MethodPut, "/api/hosts/"+hostID, body)
}
// UpdateHostNetworks - update a host's networks
func UpdateHostNetworks(hostID string, networks []string) *hostNetworksUpdatePayload {
return request[hostNetworksUpdatePayload](http.MethodPut, "/api/hosts/"+hostID+"/networks", &hostNetworksUpdatePayload{
Networks: networks,
})
// AddHostToNetwork - add a network to host
func AddHostToNetwork(hostID, network string) *hostNetworksUpdatePayload {
return request[hostNetworksUpdatePayload](http.MethodPost, "/api/hosts/"+hostID+"/networks/"+network, nil)
}
// DeleteHostFromNetwork - deletes a network from host
func DeleteHostFromNetwork(hostID, network string) *hostNetworksUpdatePayload {
return request[hostNetworksUpdatePayload](http.MethodDelete, "/api/hosts/"+hostID+"/networks/"+network, nil)
}
// CreateRelay - turn a host into a relay

View file

@ -3,14 +3,15 @@ version: "3.4"
services:
netmaker:
container_name: netmaker
image: gravitl/netmaker:v0.17.1-ee
image: gravitl/netmaker:v0.18.0-ee
restart: always
volumes:
- dnsconfig:/root/config/dnsconfig
- sqldata:/root/data
- mosquitto_data:/etc/netmaker
environment:
SERVER_NAME: "broker.NETMAKER_BASE_DOMAIN"
BROKER_NAME: "broker.NETMAKER_BASE_DOMAIN"
SERVER_NAME: "NETMAKER_BASE_DOMAIN"
STUN_DOMAIN: "stun.NETMAKER_BASE_DOMAIN"
SERVER_HOST: "SERVER_PUBLIC_IP"
SERVER_API_CONN_STRING: "api.NETMAKER_BASE_DOMAIN:443"
COREDNS_ADDR: "SERVER_PUBLIC_IP"
@ -25,16 +26,18 @@ services:
MQ_HOST: "mq"
MQ_PORT: "443"
MQ_SERVER_PORT: "1883"
MQ_PASSWORD: "REPLACE_MQ_PASSWORD"
MQ_USERNAME: "REPLACE_MQ_USERNAME"
STUN_PORT: "3478"
VERBOSITY: "1"
METRICS_EXPORTER: "on"
LICENSE_KEY: "YOUR_LICENSE_KEY"
NETMAKER_ACCOUNT_ID: "YOUR_ACCOUNT_ID"
MQ_ADMIN_PASSWORD: "REPLACE_MQ_ADMIN_PASSWORD"
ports:
- "51821-51830:51821-51830/udp"
- "3478:3478/udp"
netmaker-ui:
container_name: netmaker-ui
image: gravitl/netmaker-ui:v0.17.1
image: gravitl/netmaker-ui:v0.18.0
depends_on:
- netmaker
links:
@ -70,11 +73,11 @@ services:
restart: unless-stopped
command: ["/mosquitto/config/wait.sh"]
environment:
NETMAKER_SERVER_HOST: "https://api.NETMAKER_BASE_DOMAIN"
MQ_PASSWORD: "REPLACE_MQ_PASSWORD"
MQ_USERNAME: "REPLACE_MQ_USERNAME"
volumes:
- /root/mosquitto.conf:/mosquitto/config/mosquitto.conf
- /root/wait.sh:/mosquitto/config/wait.sh
- mosquitto_data:/mosquitto/data
- mosquitto_logs:/mosquitto/log
ports:
- "1883:1883"
@ -125,7 +128,6 @@ volumes:
caddy_conf: {}
sqldata: {}
dnsconfig: {}
mosquitto_data: {}
mosquitto_logs: {}
prometheus_data: {}
grafana_data: {}

View file

@ -3,14 +3,15 @@ version: "3.4"
services:
netmaker: # The Primary Server for running Netmaker
container_name: netmaker
image: gravitl/netmaker:v0.17.1
image: gravitl/netmaker:v0.18.0
restart: always
volumes: # Volume mounts necessary for sql, coredns, and mqtt
- dnsconfig:/root/config/dnsconfig
- sqldata:/root/data
- shared_certs:/etc/netmaker
environment: # Necessary capabilities to set iptables when running in container
SERVER_NAME: "broker.NETMAKER_BASE_DOMAIN" # The domain/host IP indicating the mq broker address
BROKER_NAME: "broker.NETMAKER_BASE_DOMAIN" # The domain/host IP indicating the mq broker address
SERVER_NAME: "NETMAKER_BASE_DOMAIN" # The base domain of netmaker
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_API_CONN_STRING: "api.NETMAKER_BASE_DOMAIN:443"
@ -26,8 +27,11 @@ services:
DATABASE: "sqlite" # Database to use - sqlite, postgres, or rqlite
NODE_ID: "netmaker-server-1" # used for HA - identifies this server vs other servers
MQ_HOST: "mq" # the address of the mq server. If running from docker compose it will be "mq". Otherwise, need to input address. If using "host networking", it will find and detect the IP of the mq container.
MQ_SERVER_PORT: "1883" # the reachable port of MQ by the server - change if internal MQ port changes (or use external port if MQ is not on the same machine)
MQ_PORT: "443" # the reachable port of MQ - change if external MQ port changes (port on proxy, not necessarily the one exposed in docker-compose)
MQ_SERVER_PORT: "1883" # the reachable port of MQ by the server - change if internal MQ port changes (or use external port if MQ is not on the same machine)
MQ_USERNAME: "REPLACE_MQ_USERNAME" # the username to set for MQ access
MQ_PASSWORD: "REPLACE_MQ_PASSWORD" # the password to set for MQ access
STUN_PORT: "3478" # the reachable port of STUN on the server
VERBOSITY: "1" # logging verbosity level - 1, 2, or 3
# this section is for OAuth
AUTH_PROVIDER: "" # "<azure-ad|github|google|oidc>"
@ -37,10 +41,10 @@ services:
AZURE_TENANT: "" # "<only for azure, you may optionally specify the tenant for the OAuth>"
OIDC_ISSUER: "" # https://oidc.yourprovider.com - URL of oidc provider
ports:
- "51821-51830:51821-51830/udp" # wireguard ports
- "3478:3478/udp" # the stun port
netmaker-ui: # The Netmaker UI Component
container_name: netmaker-ui
image: gravitl/netmaker-ui:v0.17.1
image: gravitl/netmaker-ui:v0.18.0
depends_on:
- netmaker
links:
@ -68,17 +72,20 @@ services:
restart: always
volumes:
- dnsconfig:/root/dnsconfig
mq: # the MQTT broker for netmaker
mq: # the mqtt broker for netmaker
container_name: mq
image: eclipse-mosquitto:2.0.15-openssl
depends_on:
- netmaker
restart: unless-stopped
command: ["/mosquitto/config/wait.sh"]
environment:
MQ_PASSWORD: "REPLACE_MQ_PASSWORD" # must be same value as in netmaker env
MQ_USERNAME: "REPLACE_MQ_USERNAME" # must be same value as in netmaker env
volumes:
- /root/mosquitto.conf:/mosquitto/config/mosquitto.conf # need to pull conf file from github before running (under docker/mosquitto.conf)
- mosquitto_data:/mosquitto/data
- /root/mosquitto.conf:/mosquitto/config/mosquitto.conf
- /root/wait.sh:/mosquitto/config/wait.sh
- mosquitto_logs:/mosquitto/log
- shared_certs:/mosquitto/certs
ports:
- "1883:1883"
- "8883:8883"
@ -88,5 +95,4 @@ volumes:
shared_certs: {} # netmaker certs generated for MQ comms - used by nodes/servers
sqldata: {} # storage for embedded sqlite
dnsconfig: {} # storage for coredns
mosquitto_data: {} # storage for mqtt data
mosquitto_logs: {} # storage for mqtt logs

View file

@ -3,12 +3,11 @@ version: "3.4"
services:
netmaker:
container_name: netmaker
image: gravitl/netmaker:v0.17.1
image: gravitl/netmaker:v0.18.0
restart: always
volumes:
- dnsconfig:/root/config/dnsconfig
- sqldata:/root/data
- mosquitto_data:/etc/netmaker
environment:
BROKER_NAME: "broker.NETMAKER_BASE_DOMAIN"
SERVER_NAME: "NETMAKER_BASE_DOMAIN"
@ -25,18 +24,17 @@ services:
DATABASE: "sqlite"
NODE_ID: "netmaker-server-1"
MQ_HOST: "mq"
MQ_PORT: "443"
MQ_PORT: "443"
MQ_SERVER_PORT: "1883"
STUN_PORT: "3478"
VERBOSITY: "1"
MQ_ADMIN_PASSWORD: "REPLACE_MQ_ADMIN_PASSWORD"
STUN_PORT: "3478"
PROXY: "on"
MQ_PASSWORD: "REPLACE_MQ_PASSWORD"
MQ_USERNAME: "REPLACE_MQ_USERNAME"
ports:
- "51821-51830:51821-51830/udp"
- "3478:3478/udp"
netmaker-ui:
container_name: netmaker-ui
image: gravitl/netmaker-ui:v0.17.1
image: gravitl/netmaker-ui:v0.18.0
depends_on:
- netmaker
links:
@ -72,16 +70,15 @@ services:
restart: unless-stopped
command: ["/mosquitto/config/wait.sh"]
environment:
NETMAKER_SERVER_HOST: "https://api.NETMAKER_BASE_DOMAIN"
MQ_PASSWORD: "REPLACE_MQ_PASSWORD"
MQ_USERNAME: "REPLACE_MQ_USERNAME"
volumes:
- /root/mosquitto.conf:/mosquitto/config/mosquitto.conf
- /root/wait.sh:/mosquitto/config/wait.sh
- mosquitto_data:/mosquitto/data
- mosquitto_logs:/mosquitto/log
volumes:
caddy_data: {}
caddy_conf: {}
sqldata: {}
dnsconfig: {}
mosquitto_data: {}
mosquitto_logs: {}

View file

@ -67,7 +67,8 @@ type ServerConfig struct {
Server string `yaml:"server"`
Broker string `yam:"broker"`
PublicIPService string `yaml:"publicipservice"`
MQAdminPassword string `yaml:"mqadminpassword"`
MQPassword string `yaml:"mqpassword"`
MQUserName string `yaml:"mqusername"`
MetricsExporter string `yaml:"metrics_exporter"`
BasicAuth string `yaml:"basic_auth"`
LicenseValue string `yaml:"license_value"`

View file

@ -6,7 +6,6 @@ import (
"testing"
"github.com/google/uuid"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/stretchr/testify/assert"
@ -16,7 +15,6 @@ import (
var dnsHost models.Host
func TestGetAllDNS(t *testing.T) {
database.InitializeDatabase()
deleteAllDNS(t)
deleteAllNetworks()
createNet()
@ -47,7 +45,6 @@ func TestGetAllDNS(t *testing.T) {
}
func TestGetNodeDNS(t *testing.T) {
database.InitializeDatabase()
deleteAllDNS(t)
deleteAllNetworks()
createNet()
@ -94,7 +91,6 @@ func TestGetNodeDNS(t *testing.T) {
})
}
func TestGetCustomDNS(t *testing.T) {
database.InitializeDatabase()
deleteAllDNS(t)
deleteAllNetworks()
t.Run("NoNetworks", func(t *testing.T) {
@ -133,7 +129,6 @@ func TestGetCustomDNS(t *testing.T) {
}
func TestGetDNSEntryNum(t *testing.T) {
database.InitializeDatabase()
deleteAllDNS(t)
deleteAllNetworks()
createNet()
@ -152,7 +147,6 @@ func TestGetDNSEntryNum(t *testing.T) {
})
}
func TestGetDNS(t *testing.T) {
database.InitializeDatabase()
deleteAllDNS(t)
deleteAllNetworks()
createNet()
@ -196,7 +190,6 @@ func TestGetDNS(t *testing.T) {
}
func TestCreateDNS(t *testing.T) {
database.InitializeDatabase()
deleteAllDNS(t)
deleteAllNetworks()
createNet()
@ -207,7 +200,6 @@ func TestCreateDNS(t *testing.T) {
}
func TestSetDNS(t *testing.T) {
database.InitializeDatabase()
deleteAllDNS(t)
deleteAllNetworks()
t.Run("NoNetworks", func(t *testing.T) {
@ -255,7 +247,6 @@ func TestSetDNS(t *testing.T) {
}
func TestGetDNSEntry(t *testing.T) {
database.InitializeDatabase()
deleteAllDNS(t)
deleteAllNetworks()
createNet()
@ -285,7 +276,6 @@ func TestGetDNSEntry(t *testing.T) {
}
func TestDeleteDNS(t *testing.T) {
database.InitializeDatabase()
deleteAllDNS(t)
deleteAllNetworks()
createNet()
@ -307,7 +297,6 @@ func TestDeleteDNS(t *testing.T) {
}
func TestValidateDNSUpdate(t *testing.T) {
database.InitializeDatabase()
deleteAllDNS(t)
deleteAllNetworks()
createNet()
@ -369,7 +358,6 @@ func TestValidateDNSUpdate(t *testing.T) {
}
func TestValidateDNSCreate(t *testing.T) {
database.InitializeDatabase()
_ = logic.DeleteDNS("mynode", "skynet")
t.Run("NoNetwork", func(t *testing.T) {
entry := models.DNSEntry{"10.0.0.2", "", "myhost", "badnet"}

View file

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

View file

@ -214,7 +214,7 @@ func getExtClientConf(w http.ResponseWriter, r *http.Request) {
if network.DefaultKeepalive != 0 {
keepalive = "PersistentKeepalive = " + strconv.Itoa(int(network.DefaultKeepalive))
}
gwendpoint := host.EndpointIP.String() + ":" + strconv.Itoa(host.ListenPort)
gwendpoint := host.EndpointIP.String() + ":" + strconv.Itoa(logic.GetPeerListenPort(host))
newAllowedIPs := network.AddressRange
if newAllowedIPs != "" && network.AddressRange6 != "" {
newAllowedIPs += ","

View file

@ -97,7 +97,6 @@ func updateHost(w http.ResponseWriter, r *http.Request) {
if updateRelay {
logic.UpdateHostRelay(currHost.ID.String(), currHost.RelayedHosts, newHost.RelayedHosts)
}
// publish host update through MQ
if err := mq.HostUpdate(&models.HostUpdate{
Action: models.UpdateHost,
@ -190,10 +189,6 @@ func deleteHost(w http.ResponseWriter, r *http.Request) {
logger.Log(0, r.Header.Get("user"), "failed to send delete host update: ", currHost.ID.String(), err.Error())
}
if err = mq.DeleteMqClient(currHost.ID.String()); err != nil {
logger.Log(0, "error removing DynSec credentials for host:", currHost.Name, err.Error())
}
apiHostData := currHost.ConvertNMHostToAPI()
logger.Log(2, r.Header.Get("user"), "removed host", currHost.Name)
w.WriteHeader(http.StatusOK)
@ -242,6 +237,11 @@ func addHostToNetwork(w http.ResponseWriter, r *http.Request) {
}); err != nil {
logger.Log(0, r.Header.Get("user"), "failed to update host to join network:", hostid, network, err.Error())
}
go func() { // notify of peer change
if err := mq.PublishPeerUpdate(); err != nil {
logger.Log(1, "error publishing peer update ", err.Error())
}
}()
logger.Log(2, r.Header.Get("user"), fmt.Sprintf("added host %s to network %s", currHost.Name, network))
w.WriteHeader(http.StatusOK)

View file

@ -403,13 +403,25 @@ func createNetwork(w http.ResponseWriter, r *http.Request) {
return
}
if err = logic.AddDefaultHostsToNetwork(network.NetID, servercfg.GetServer()); err != nil {
logger.Log(0, fmt.Sprintf("failed to add default hosts to network [%v]: %v",
network.NetID, err.Error()))
defaultHosts := logic.GetDefaultHosts()
for i := range defaultHosts {
currHost := &defaultHosts[i]
newNode, err := logic.UpdateHostNetwork(currHost, network.NetID, true)
if err != nil {
logger.Log(0, r.Header.Get("user"), "failed to add host to network:", currHost.ID.String(), network.NetID, err.Error())
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
logger.Log(1, "added new node", newNode.ID.String(), "to host", currHost.Name)
if err = mq.HostUpdate(&models.HostUpdate{
Action: models.JoinHostToNetwork,
Host: *currHost,
Node: *newNode,
}); err != nil {
logger.Log(0, r.Header.Get("user"), "failed to add host to network:", currHost.ID.String(), network.NetID, err.Error())
}
}
// TODO: Send message notifying host of new peers/network conf
logger.Log(1, r.Header.Get("user"), "created network", network.NetID)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(network)

View file

@ -1,11 +1,13 @@
package controller
import (
"context"
"os"
"testing"
"github.com/google/uuid"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/stretchr/testify/assert"
@ -20,8 +22,27 @@ type NetworkValidationTestCase struct {
var netHost models.Host
func TestMain(m *testing.M) {
database.InitializeDatabase()
defer database.CloseDB()
logic.CreateAdmin(&models.User{
UserName: "admin",
Password: "password",
IsAdmin: true,
Networks: []string{},
Groups: []string{},
})
peerUpdate := make(chan *models.Node)
go logic.ManageZombies(context.Background(), peerUpdate)
go func() {
for update := range peerUpdate {
//do nothing
logger.Log(3, "received node update", update.Action)
}
}()
}
func TestCreateNetwork(t *testing.T) {
initialize()
deleteAllNetworks()
var network models.Network
@ -34,7 +55,6 @@ func TestCreateNetwork(t *testing.T) {
assert.Nil(t, err)
}
func TestGetNetwork(t *testing.T) {
initialize()
createNet()
t.Run("GetExistingNetwork", func(t *testing.T) {
@ -50,7 +70,6 @@ func TestGetNetwork(t *testing.T) {
}
func TestDeleteNetwork(t *testing.T) {
initialize()
createNet()
//create nodes
t.Run("NetworkwithNodes", func(t *testing.T) {
@ -66,7 +85,6 @@ func TestDeleteNetwork(t *testing.T) {
}
func TestCreateKey(t *testing.T) {
initialize()
createNet()
keys, _ := logic.GetKeys("skynet")
for _, key := range keys {
@ -138,7 +156,6 @@ func TestCreateKey(t *testing.T) {
}
func TestGetKeys(t *testing.T) {
initialize()
deleteAllNetworks()
createNet()
network, err := logic.GetNetwork("skynet")
@ -161,7 +178,6 @@ func TestGetKeys(t *testing.T) {
})
}
func TestDeleteKey(t *testing.T) {
initialize()
createNet()
network, err := logic.GetNetwork("skynet")
assert.Nil(t, err)
@ -183,7 +199,6 @@ func TestDeleteKey(t *testing.T) {
func TestSecurityCheck(t *testing.T) {
//these seem to work but not sure it the tests are really testing the functionality
initialize()
os.Setenv("MASTER_KEY", "secretkey")
t.Run("NoNetwork", func(t *testing.T) {
networks, username, err := logic.UserPermissions(false, "", "Bearer secretkey")
@ -214,7 +229,6 @@ func TestValidateNetwork(t *testing.T) {
//t.Skip()
//This functions is not called by anyone
//it panics as validation function 'display_name_valid' is not defined
initialize()
//yes := true
//no := false
//deleteNet(t)
@ -291,7 +305,6 @@ func TestValidateNetwork(t *testing.T) {
func TestIpv6Network(t *testing.T) {
//these seem to work but not sure it the tests are really testing the functionality
initialize()
os.Setenv("MASTER_KEY", "secretkey")
deleteAllNetworks()
createNet()
@ -318,21 +331,6 @@ func deleteAllNetworks() {
}
}
func initialize() {
database.InitializeDatabase()
createAdminUser()
}
func createAdminUser() {
logic.CreateAdmin(&models.User{
UserName: "admin",
Password: "password",
IsAdmin: true,
Networks: []string{},
Groups: []string{},
})
}
func createNet() {
var network models.Network
network.NetID = "skynet"

View file

@ -577,8 +577,6 @@ func createNode(w http.ResponseWriter, r *http.Request) {
}
server := servercfg.GetServerInfo()
server.TrafficKey = key
// consume password before hashing for mq client creation
hostPassword := data.Host.HostPass
data.Node.Server = servercfg.GetServer()
if !logic.HostExists(&data.Host) {
logic.CheckHostPorts(&data.Host)
@ -606,18 +604,6 @@ func createNode(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
} else {
// Create client for this host in Mq
if err := mq.CreateMqClient(&mq.MqClient{
ID: data.Host.ID.String(),
Text: data.Host.Name,
Password: hostPassword,
Networks: []string{networkName},
}); err != nil {
logger.Log(0, fmt.Sprintf("failed to create DynSec client: %v", err.Error()))
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
}
err = logic.AssociateNodeToHost(&data.Node, &data.Host)

View file

@ -21,7 +21,6 @@ func TestCreateEgressGateway(t *testing.T) {
var gateway models.EgressGatewayRequest
gateway.Ranges = []string{"10.100.100.0/24"}
gateway.NetID = "skynet"
database.InitializeDatabase()
deleteAllNetworks()
createNet()
t.Run("NoNodes", func(t *testing.T) {
@ -78,7 +77,6 @@ func TestCreateEgressGateway(t *testing.T) {
}
func TestDeleteEgressGateway(t *testing.T) {
var gateway models.EgressGatewayRequest
database.InitializeDatabase()
deleteAllNetworks()
createNet()
testnode := createTestNode()
@ -110,7 +108,6 @@ func TestDeleteEgressGateway(t *testing.T) {
}
func TestGetNetworkNodes(t *testing.T) {
database.InitializeDatabase()
deleteAllNetworks()
createNet()
t.Run("BadNet", func(t *testing.T) {

View file

@ -123,12 +123,24 @@ func createHostRelay(w http.ResponseWriter, r *http.Request) {
return
}
if err := mq.HostUpdate(&models.HostUpdate{
Action: models.UpdateHost,
Host: *relayHost,
}); err != nil {
logger.Log(0, "failed to send host update: ", relayHost.ID.String(), err.Error())
}
logger.Log(1, r.Header.Get("user"), "created relay on host", relay.HostID)
go func(relayHostID string) {
relatedhosts := logic.GetRelatedHosts(relayHostID)
for _, relatedHost := range relatedhosts {
relatedHost.ProxyEnabled = true
logic.UpsertHost(&relatedHost)
if err := mq.HostUpdate(&models.HostUpdate{
Action: models.UpdateHost,
Host: relatedHost,
}); err != nil {
logger.Log(0, "failed to send host update: ", relatedHost.ID.String(), err.Error())
}
}
if err := mq.PublishPeerUpdate(); err != nil {
logger.Log(0, "fail to publish peer update: ", err.Error())

View file

@ -6,8 +6,10 @@ import (
"strings"
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mq"
"github.com/gravitl/netmaker/servercfg"
)
@ -19,6 +21,35 @@ func serverHandlers(r *mux.Router) {
}))
r.HandleFunc("/api/server/getconfig", allowUsers(http.HandlerFunc(getConfig))).Methods(http.MethodGet)
r.HandleFunc("/api/server/getserverinfo", authorize(true, false, "node", http.HandlerFunc(getServerInfo))).Methods(http.MethodGet)
r.HandleFunc("/api/server/status", http.HandlerFunc(getStatus)).Methods(http.MethodGet)
}
// swagger:route GET /api/server/status server getStatus
//
// Get the server configuration.
//
// Schemes: https
//
// Security:
// oauth
//
// Responses:
// 200: serverConfigResponse
func getStatus(w http.ResponseWriter, r *http.Request) {
// TODO
// - check health of broker
type status struct {
DB bool `json:"db_connected"`
Broker bool `json:"broker_connected"`
}
currentServerStatus := status{
DB: database.IsConnected(),
Broker: mq.IsConnected(),
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(&currentServerStatus)
}
// allowUsers - allow all authenticated (valid) users - only used by getConfig, may be able to remove during refactor

View file

@ -3,7 +3,6 @@ package controller
import (
"testing"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/stretchr/testify/assert"
@ -18,7 +17,6 @@ func deleteAllUsers() {
func TestHasAdmin(t *testing.T) {
//delete all current users
database.InitializeDatabase()
users, _ := logic.GetUsers()
for _, user := range users {
success, err := logic.DeleteUser(user.UserName)
@ -48,7 +46,7 @@ func TestHasAdmin(t *testing.T) {
})
t.Run("multiple admins", func(t *testing.T) {
var user = models.User{"admin1", "password", nil, true, nil}
err := logic.CreateUser(&user)
err := logic.CreateUser(&user)
assert.Nil(t, err)
found, err := logic.HasAdmin()
assert.Nil(t, err)
@ -57,7 +55,6 @@ func TestHasAdmin(t *testing.T) {
}
func TestCreateUser(t *testing.T) {
database.InitializeDatabase()
deleteAllUsers()
user := models.User{"admin", "password", nil, true, nil}
t.Run("NoUser", func(t *testing.T) {
@ -72,7 +69,6 @@ func TestCreateUser(t *testing.T) {
}
func TestCreateAdmin(t *testing.T) {
database.InitializeDatabase()
deleteAllUsers()
var user models.User
t.Run("NoAdmin", func(t *testing.T) {
@ -90,7 +86,6 @@ func TestCreateAdmin(t *testing.T) {
}
func TestDeleteUser(t *testing.T) {
database.InitializeDatabase()
deleteAllUsers()
t.Run("NonExistent User", func(t *testing.T) {
deleted, err := logic.DeleteUser("admin")
@ -107,7 +102,6 @@ func TestDeleteUser(t *testing.T) {
}
func TestValidateUser(t *testing.T) {
database.InitializeDatabase()
var user models.User
t.Run("Valid Create", func(t *testing.T) {
user.UserName = "admin"
@ -155,7 +149,6 @@ func TestValidateUser(t *testing.T) {
}
func TestGetUser(t *testing.T) {
database.InitializeDatabase()
deleteAllUsers()
t.Run("NonExistantUser", func(t *testing.T) {
admin, err := logic.GetUser("admin")
@ -172,7 +165,6 @@ func TestGetUser(t *testing.T) {
}
func TestGetUsers(t *testing.T) {
database.InitializeDatabase()
deleteAllUsers()
t.Run("NonExistantUser", func(t *testing.T) {
admin, err := logic.GetUsers()
@ -203,7 +195,6 @@ func TestGetUsers(t *testing.T) {
}
func TestUpdateUser(t *testing.T) {
database.InitializeDatabase()
deleteAllUsers()
user := models.User{"admin", "password", nil, true, nil}
newuser := models.User{"hello", "world", []string{"wirecat, netmaker"}, true, []string{}}
@ -246,7 +237,6 @@ func TestUpdateUser(t *testing.T) {
// }
func TestVerifyAuthRequest(t *testing.T) {
database.InitializeDatabase()
deleteAllUsers()
var authRequest models.UserAuthParams
t.Run("EmptyUserName", func(t *testing.T) {

View file

@ -4,6 +4,7 @@ import (
"crypto/rand"
"encoding/json"
"errors"
"sync"
"time"
"github.com/google/uuid"
@ -80,8 +81,12 @@ const (
FETCH_ALL = "fetchall"
// CLOSE_DB - graceful close of db const
CLOSE_DB = "closedb"
// isconnected
isConnected = "isconnected"
)
var dbMutex sync.RWMutex
func getCurrentDB() map[string]interface{} {
switch servercfg.GetDB() {
case "rqlite":
@ -148,6 +153,8 @@ func IsJSONString(value string) bool {
// Insert - inserts object into db
func Insert(key string, value string, tableName string) error {
dbMutex.Lock()
defer dbMutex.Unlock()
if key != "" && value != "" && IsJSONString(value) {
return getCurrentDB()[INSERT].(func(string, string, string) error)(key, value, tableName)
} else {
@ -157,6 +164,8 @@ func Insert(key string, value string, tableName string) error {
// InsertPeer - inserts peer into db
func InsertPeer(key string, value string) error {
dbMutex.Lock()
defer dbMutex.Unlock()
if key != "" && value != "" && IsJSONString(value) {
return getCurrentDB()[INSERT_PEER].(func(string, string) error)(key, value)
} else {
@ -166,11 +175,15 @@ func InsertPeer(key string, value string) error {
// DeleteRecord - deletes a record from db
func DeleteRecord(tableName string, key string) error {
dbMutex.Lock()
defer dbMutex.Unlock()
return getCurrentDB()[DELETE].(func(string, string) error)(tableName, key)
}
// DeleteAllRecords - removes a table and remakes
func DeleteAllRecords(tableName string) error {
dbMutex.Lock()
defer dbMutex.Unlock()
err := getCurrentDB()[DELETE_ALL].(func(string) error)(tableName)
if err != nil {
return err
@ -196,6 +209,8 @@ func FetchRecord(tableName string, key string) (string, error) {
// FetchRecords - fetches all records in given table
func FetchRecords(tableName string) (map[string]string, error) {
dbMutex.RLock()
defer dbMutex.RUnlock()
return getCurrentDB()[FETCH_ALL].(func(string) (map[string]string, error))(tableName)
}
@ -241,3 +256,8 @@ func initializeUUID() error {
func CloseDB() {
getCurrentDB()[CLOSE_DB].(func())()
}
// IsConnected - tell if the database is connected or not
func IsConnected() bool {
return getCurrentDB()[isConnected].(func() bool)()
}

View file

@ -22,6 +22,7 @@ var PG_FUNCTIONS = map[string]interface{}{
DELETE_ALL: pgDeleteAllRecords,
FETCH_ALL: pgFetchRecords,
CLOSE_DB: pgCloseDB,
isConnected: pgIsConnected,
}
func getPGConnString() string {
@ -135,3 +136,8 @@ func pgFetchRecords(tableName string) (map[string]string, error) {
func pgCloseDB() {
PGDB.Close()
}
func pgIsConnected() bool {
stats := PGDB.Stats()
return stats.OpenConnections > 0
}

View file

@ -20,6 +20,7 @@ var RQLITE_FUNCTIONS = map[string]interface{}{
DELETE_ALL: rqliteDeleteAllRecords,
FETCH_ALL: rqliteFetchRecords,
CLOSE_DB: rqliteCloseDB,
isConnected: rqliteConnected,
}
func initRqliteDatabase() error {
@ -104,3 +105,8 @@ func rqliteFetchRecords(tableName string) (map[string]string, error) {
func rqliteCloseDB() {
RQliteDatabase.Close()
}
func rqliteConnected() bool {
leader, err := RQliteDatabase.Leader()
return err == nil && len(leader) > 0
}

View file

@ -25,6 +25,7 @@ var SQLITE_FUNCTIONS = map[string]interface{}{
DELETE_ALL: sqliteDeleteAllRecords,
FETCH_ALL: sqliteFetchRecords,
CLOSE_DB: sqliteCloseDB,
isConnected: sqliteConnected,
}
func initSqliteDB() error {
@ -135,3 +136,8 @@ func sqliteFetchRecords(tableName string) (map[string]string, error) {
func sqliteCloseDB() {
SqliteDB.Close()
}
func sqliteConnected() bool {
stats := SqliteDB.Stats()
return stats.OpenConnections > 0
}

View file

@ -7,5 +7,4 @@ listener 1883
protocol websockets
allow_anonymous false
plugin /usr/lib/mosquitto_dynamic_security.so
plugin_opt_config_file /mosquitto/data/dynamic-security.json
password_file /mosquitto/password.txt

View file

@ -1,18 +1,13 @@
#!/bin/ash
wait_for_netmaker() {
echo "SERVER: ${NETMAKER_SERVER_HOST}"
until curl --output /dev/null --silent --fail --head \
--location "${NETMAKER_SERVER_HOST}/api/server/health"; do
echo "Waiting for netmaker server to startup"
sleep 1
done
encrypt_password() {
echo "${MQ_USERNAME}:${MQ_PASSWORD}" > /mosquitto/password.txt
mosquitto_passwd -U /mosquitto/password.txt
}
main(){
# wait for netmaker to startup
apk add curl
wait_for_netmaker
encrypt_password
echo "Starting MQ..."
# Run the main container command.
/docker-entrypoint.sh

View file

@ -1,10 +1,12 @@
package functions
import (
"context"
"encoding/json"
"testing"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
)
@ -19,11 +21,27 @@ var (
}
)
func TestMain(m *testing.M) {
database.InitializeDatabase()
defer database.CloseDB()
logic.CreateAdmin(&models.User{
UserName: "admin",
Password: "password",
IsAdmin: true,
Networks: []string{},
Groups: []string{},
})
peerUpdate := make(chan *models.Node)
go logic.ManageZombies(context.Background(), peerUpdate)
go func() {
for update := range peerUpdate {
//do nothing
logger.Log(3, "received node update", update.Action)
}
}()
}
func TestNetworkExists(t *testing.T) {
err := database.InitializeDatabase()
if err != nil {
t.Fatalf("error initilizing database: %s", err)
}
database.DeleteRecord(database.NETWORKS_TABLE_NAME, testNetwork.NetID)
defer database.CloseDB()
exists, err := logic.NetworkExists(testNetwork.NetID)
@ -53,10 +71,6 @@ func TestNetworkExists(t *testing.T) {
}
func TestGetAllExtClients(t *testing.T) {
err := database.InitializeDatabase()
if err != nil {
t.Fatalf("error initilizing database: %s", err)
}
defer database.CloseDB()
database.DeleteRecord(database.EXT_CLIENT_TABLE_NAME, testExternalClient.ClientID)

17
go.mod
View file

@ -4,7 +4,7 @@ go 1.19
require (
github.com/eclipse/paho.mqtt.golang v1.4.2
github.com/go-playground/validator/v10 v10.11.1
github.com/go-playground/validator/v10 v10.11.2
github.com/golang-jwt/jwt/v4 v4.4.3
github.com/google/uuid v1.3.0
github.com/gorilla/handlers v1.5.1
@ -15,11 +15,11 @@ require (
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.8.1
github.com/txn2/txeh v1.3.0
golang.org/x/crypto v0.3.0
golang.org/x/net v0.4.0 // indirect
golang.org/x/oauth2 v0.3.0
golang.org/x/sys v0.3.0 // indirect
golang.org/x/text v0.5.0 // indirect
golang.org/x/crypto v0.6.0
golang.org/x/net v0.6.0 // indirect
golang.org/x/oauth2 v0.4.0
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.zx2c4.com/wireguard v0.0.0-20220920152132-bb719d3a6e2c // indirect
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20220324164955-056925b7df31
google.golang.org/protobuf v1.28.1 // indirect
@ -29,7 +29,6 @@ require (
require (
filippo.io/edwards25519 v1.0.0
github.com/c-robinson/iplib v1.0.6
github.com/go-ping/ping v1.1.0
github.com/posthog/posthog-go v0.0.0-20211028072449-93c17c49e2b0
)
@ -60,8 +59,8 @@ require (
cloud.google.com/go/compute v1.12.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/hashicorp/go-version v1.6.0

50
go.sum
View file

@ -17,7 +17,6 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
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=
@ -29,16 +28,13 @@ github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
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-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
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.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU=
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -52,7 +48,6 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8
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.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
@ -73,13 +68,10 @@ github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf
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.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
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.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
@ -106,7 +98,6 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
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/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
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=
@ -116,9 +107,7 @@ 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.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
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 v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
@ -160,10 +149,9 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
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-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
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=
@ -172,17 +160,18 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
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-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
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 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8=
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk=
golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M=
golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec=
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=
@ -193,10 +182,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -205,8 +192,9 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc
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 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.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=
@ -215,8 +203,9 @@ 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 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
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=
@ -240,11 +229,8 @@ google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gortc.io/stun v1.23.0 h1:CpRQFjakCZMwVKTwInKbcCzlBklj62LGzD3NPdFyGrE=

View file

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

View file

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

View file

@ -81,7 +81,7 @@ spec:
value: "Kubernetes"
- name: VERBOSITY
value: "3"
image: gravitl/netmaker:v0.17.1
image: gravitl/netmaker:v0.18.0
imagePullPolicy: Always
name: netmaker
ports:

View file

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

View file

@ -1,17 +1,38 @@
package logic
import (
"context"
"net"
"testing"
"github.com/google/uuid"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/models"
"github.com/matryer/is"
)
func TestCheckPorts(t *testing.T) {
func TestMain(m *testing.M) {
database.InitializeDatabase()
defer database.CloseDB()
CreateAdmin(&models.User{
UserName: "admin",
Password: "password",
IsAdmin: true,
Networks: []string{},
Groups: []string{},
})
peerUpdate := make(chan *models.Node)
go ManageZombies(context.Background(), peerUpdate)
go func() {
for update := range peerUpdate {
//do nothing
logger.Log(3, "received node update", update.Action)
}
}()
}
func TestCheckPorts(t *testing.T) {
h := models.Host{
ID: uuid.New(),
EndpointIP: net.ParseIP("192.168.1.1"),

View file

@ -96,6 +96,7 @@ func CreateHost(h *models.Host) error {
return err
}
h.HostPass = string(hash)
checkForZombieHosts(h)
return UpsertHost(h)
}
@ -216,6 +217,7 @@ func UpdateHostNetwork(h *models.Host, network string, add bool) (*models.Node,
newNode := models.Node{}
newNode.Server = servercfg.GetServer()
newNode.Network = network
newNode.HostID = h.ID
if err := AssociateNodeToHost(&newNode, h); err != nil {
return nil, err
}
@ -308,21 +310,6 @@ func GetDefaultHosts() []models.Host {
return defaultHostList[:]
}
// AddDefaultHostsToNetwork - adds a node to network for every default host on Netmaker server
func AddDefaultHostsToNetwork(network, server string) error {
// add default hosts to network
defaultHosts := GetDefaultHosts()
for i := range defaultHosts {
newNode := models.Node{}
newNode.Network = network
newNode.Server = server
if err := AssociateNodeToHost(&newNode, &defaultHosts[i]); err != nil {
return err
}
}
return nil
}
// GetHostNetworks - fetches all the networks
func GetHostNetworks(hostID string) []string {
currHost, err := GetHost(hostID)

View file

@ -534,7 +534,7 @@ func createNode(node *models.Node) error {
if err != nil {
return err
}
CheckZombies(node, host.MacAddress)
CheckZombies(node)
nodebytes, err := json.Marshal(&node)
if err != nil {

View file

@ -201,7 +201,7 @@ func GetProxyUpdateForHost(host *models.Host) (models.ProxyManagerPayload, error
if host.IsRelayed {
relayHost, err := GetHost(host.RelayedBy)
if err == nil {
relayEndpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayHost.EndpointIP, getPeerListenPort(relayHost)))
relayEndpoint, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayHost.EndpointIP, GetPeerListenPort(relayHost)))
if err != nil {
logger.Log(1, "failed to resolve relay node endpoint: ", err.Error())
}
@ -219,7 +219,7 @@ func GetProxyUpdateForHost(host *models.Host) (models.ProxyManagerPayload, error
relayedHost := relayedHost
payload, err := GetPeerUpdateForHost(&relayedHost)
if err == nil {
relayedEndpoint, udpErr := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayedHost.EndpointIP, getPeerListenPort(&relayedHost)))
relayedEndpoint, udpErr := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayedHost.EndpointIP, GetPeerListenPort(&relayedHost)))
if udpErr == nil {
relayPeersMap[relayedHost.PublicKey.String()] = models.RelayedConf{
RelayedPeerEndpoint: relayedEndpoint,
@ -259,14 +259,14 @@ func GetProxyUpdateForHost(host *models.Host) (models.ProxyManagerPayload, error
if currPeerConf, found = peerConfMap[peerHost.PublicKey.String()]; !found {
currPeerConf = models.PeerConf{
Proxy: peerHost.ProxyEnabled,
PublicListenPort: int32(getPeerListenPort(peerHost)),
PublicListenPort: int32(GetPeerListenPort(peerHost)),
}
}
if peerHost.IsRelayed && peerHost.RelayedBy != host.ID.String() {
relayHost, err := GetHost(peerHost.RelayedBy)
if err == nil {
relayTo, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayHost.EndpointIP, getPeerListenPort(peerHost)))
relayTo, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", relayHost.EndpointIP, GetPeerListenPort(relayHost)))
if err == nil {
currPeerConf.IsRelayed = true
currPeerConf.RelayedTo = relayTo
@ -370,7 +370,7 @@ func GetPeerUpdateForHost(host *models.Host) (models.HostPeerUpdate, error) {
}
peerConfig.Endpoint = &net.UDPAddr{
IP: peerHost.EndpointIP,
Port: getPeerListenPort(peerHost),
Port: GetPeerListenPort(peerHost),
}
if uselocal {
@ -390,7 +390,21 @@ func GetPeerUpdateForHost(host *models.Host) (models.HostPeerUpdate, error) {
}
peerConfig.AllowedIPs = allowedips
if node.IsIngressGateway || node.IsEgressGateway {
if peer.IsIngressGateway {
_, extPeerIDAndAddrs, err := getExtPeers(&peer)
if err == nil {
for _, extPeerIdAndAddr := range extPeerIDAndAddrs {
nodePeerMap[extPeerIdAndAddr.ID] = models.PeerRouteInfo{
PeerAddr: net.IPNet{
IP: net.ParseIP(extPeerIdAndAddr.Address),
Mask: getCIDRMaskFromAddr(extPeerIdAndAddr.Address),
},
PeerKey: extPeerIdAndAddr.ID,
Allow: true,
}
}
}
}
nodePeerMap[peerHost.PublicKey.String()] = models.PeerRouteInfo{
PeerAddr: net.IPNet{
IP: net.ParseIP(peer.PrimaryAddress()),
@ -429,6 +443,16 @@ func GetPeerUpdateForHost(host *models.Host) (models.HostPeerUpdate, error) {
if node.IsIngressGateway {
extPeers, extPeerIDAndAddrs, err = getExtPeers(&node)
if err == nil {
for _, extPeerIdAndAddr := range extPeerIDAndAddrs {
nodePeerMap[extPeerIdAndAddr.ID] = models.PeerRouteInfo{
PeerAddr: net.IPNet{
IP: net.ParseIP(extPeerIdAndAddr.Address),
Mask: getCIDRMaskFromAddr(extPeerIdAndAddr.Address),
},
PeerKey: extPeerIdAndAddr.ID,
Allow: true,
}
}
hostPeerUpdate.Peers = append(hostPeerUpdate.Peers, extPeers...)
for _, extPeerIdAndAddr := range extPeerIDAndAddrs {
hostPeerUpdate.PeerIDs[extPeerIdAndAddr.ID] = make(map[string]models.IDandAddr)
@ -459,19 +483,6 @@ func GetPeerUpdateForHost(host *models.Host) (models.HostPeerUpdate, error) {
}
}
if node.IsEgressGateway {
if node.IsIngressGateway {
for _, extPeerIdAndAddr := range extPeerIDAndAddrs {
nodePeerMap[extPeerIdAndAddr.ID] = models.PeerRouteInfo{
PeerAddr: net.IPNet{
IP: net.ParseIP(extPeerIdAndAddr.Address),
Mask: getCIDRMaskFromAddr(extPeerIdAndAddr.Address),
},
PeerKey: extPeerIdAndAddr.ID,
Allow: true,
}
}
}
hostPeerUpdate.EgressInfo[node.ID.String()] = models.EgressInfo{
EgressID: node.ID.String(),
Network: node.PrimaryNetworkRange(),
@ -488,7 +499,7 @@ func GetPeerUpdateForHost(host *models.Host) (models.HostPeerUpdate, error) {
return hostPeerUpdate, nil
}
func getPeerListenPort(host *models.Host) int {
func GetPeerListenPort(host *models.Host) int {
peerPort := host.ListenPort
if host.ProxyEnabled {
if host.PublicListenPort != 0 {
@ -557,7 +568,7 @@ func GetPeerUpdate(node *models.Node, host *models.Host) (models.PeerUpdate, err
Port: peerHost.ListenPort,
}
if peerHost.ProxyEnabled {
peerConfig.Endpoint.Port = getPeerListenPort(peerHost)
peerConfig.Endpoint.Port = GetPeerListenPort(peerHost)
}
if uselocal {
peerConfig.Endpoint.IP = peer.LocalAddress.IP
@ -690,7 +701,7 @@ func GetPeerUpdateLegacy(node *models.Node) (models.PeerUpdate, error) {
if node.LocalAddress.String() != peer.LocalAddress.String() && peer.LocalAddress.IP != nil {
peerHost.EndpointIP = peer.LocalAddress.IP
if peerHost.ListenPort != 0 {
peerHost.ListenPort = getPeerListenPort(peerHost)
peerHost.ListenPort = GetPeerListenPort(peerHost)
}
} else {
continue
@ -723,7 +734,7 @@ func GetPeerUpdateLegacy(node *models.Node) (models.PeerUpdate, error) {
// or, if port is for some reason zero use the LocalListenPort
// but only do this if LocalListenPort is not zero
if ((!setUDPPort) || peerHost.ListenPort == 0) && peerHost.ListenPort != 0 {
peerHost.ListenPort = getPeerListenPort(peerHost)
peerHost.ListenPort = GetPeerListenPort(peerHost)
}
endpoint := peerHost.EndpointIP.String() + ":" + strconv.FormatInt(int64(peerHost.ListenPort), 10)

View file

@ -10,8 +10,12 @@ import (
"github.com/stretchr/testify/assert"
)
func TestNetworkUserLogic(t *testing.T) {
func TestMain(m *testing.M) {
database.InitializeDatabase()
defer database.CloseDB()
}
func TestNetworkUserLogic(t *testing.T) {
networkUser := promodels.NetworkUser{
ID: "helloworld",
}

View file

@ -3,13 +3,11 @@ package pro
import (
"testing"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/models/promodels"
"github.com/stretchr/testify/assert"
)
func TestUserGroupLogic(t *testing.T) {
database.InitializeDatabase()
t.Run("User Groups initialized successfully", func(t *testing.T) {
err := InitializeGroups()

View file

@ -2,7 +2,6 @@ package logic
import (
"context"
"net"
"time"
"github.com/google/uuid"
@ -18,15 +17,16 @@ const (
)
var (
zombies []uuid.UUID
removeZombie chan uuid.UUID = make(chan (uuid.UUID), 10)
newZombie chan uuid.UUID = make(chan (uuid.UUID), 10)
zombies []uuid.UUID
hostZombies []uuid.UUID
newZombie chan uuid.UUID = make(chan (uuid.UUID), 10)
newHostZombie chan uuid.UUID = make(chan (uuid.UUID), 10)
)
// CheckZombies - checks if new node has same macaddress as existing node
// CheckZombies - checks if new node has same hostid as existing node
// if so, existing node is added to zombie node quarantine list
// also cleans up nodes past their expiration date
func CheckZombies(newnode *models.Node, mac net.HardwareAddr) {
func CheckZombies(newnode *models.Node) {
nodes, err := GetNetworkNodes(newnode.Network)
if err != nil {
logger.Log(1, "Failed to retrieve network nodes", newnode.Network, err.Error())
@ -44,6 +44,35 @@ func CheckZombies(newnode *models.Node, mac net.HardwareAddr) {
}
}
// checkForZombieHosts - checks if new host has the same macAddress as an existing host
// if true, existing host is added to host zombie collection
func checkForZombieHosts(h *models.Host) {
hosts, err := GetAllHosts()
if err != nil {
logger.Log(3, "errror retrieving all hosts", err.Error())
}
for _, existing := range hosts {
if existing.ID == h.ID {
//probably an unnecessary check as new host should not be in database yet, but just in case
//skip self
continue
}
if existing.MacAddress.String() == h.MacAddress.String() {
//add to hostZombies
newHostZombie <- existing.ID
//add all nodes belonging to host to zombile list
for _, node := range existing.Nodes {
id, err := uuid.Parse(node)
if err != nil {
logger.Log(3, "error parsing uuid from host.Nodes", err.Error())
continue
}
newHostZombie <- id
}
}
}
}
// ManageZombies - goroutine which adds/removes/deletes nodes from the zombie node quarantine list
func ManageZombies(ctx context.Context, peerUpdate chan *models.Node) {
logger.Log(2, "Zombie management started")
@ -51,24 +80,12 @@ func ManageZombies(ctx context.Context, peerUpdate chan *models.Node) {
for {
select {
case <-ctx.Done():
close(peerUpdate)
return
case id := <-newZombie:
logger.Log(1, "adding", id.String(), "to zombie quaratine list")
zombies = append(zombies, id)
case id := <-removeZombie:
found := false
if len(zombies) > 0 {
for i := len(zombies) - 1; i >= 0; i-- {
if zombies[i] == id {
logger.Log(1, "removing zombie from quaratine list", zombies[i].String())
zombies = append(zombies[:i], zombies[i+1:]...)
found = true
}
}
}
if !found {
logger.Log(3, "no zombies found")
}
case id := <-newHostZombie:
hostZombies = append(hostZombies, id)
case <-time.After(time.Second * ZOMBIE_TIMEOUT):
logger.Log(3, "checking for zombie nodes")
if len(zombies) > 0 {
@ -92,6 +109,23 @@ func ManageZombies(ctx context.Context, peerUpdate chan *models.Node) {
}
}
}
if len(hostZombies) > 0 {
logger.Log(3, "checking host zombies")
for i := len(hostZombies) - 1; i >= 0; i-- {
host, err := GetHost(hostZombies[i].String())
if err != nil {
logger.Log(1, "error retrieving zombie host", err.Error())
logger.Log(1, "deleting ", host.ID.String(), " from zombie list")
zombies = append(zombies[:i], zombies[i+1:]...)
continue
}
if len(host.Nodes) == 0 {
if err := RemoveHost(host); err != nil {
logger.Log(0, "error deleting zombie host", host.ID.String(), err.Error())
}
}
}
}
}
}
}
@ -115,10 +149,10 @@ func InitializeZombies() {
}
if node.HostID == othernode.HostID {
if node.LastCheckIn.After(othernode.LastCheckIn) {
zombies = append(zombies, othernode.ID)
newZombie <- othernode.ID
logger.Log(1, "adding", othernode.ID.String(), "to zombie list")
} else {
zombies = append(zombies, node.ID)
newZombie <- node.ID
logger.Log(1, "adding", node.ID.String(), "to zombie list")
}
}

View file

@ -118,11 +118,6 @@ func startControllers() {
logger.Log(0, "error occurred initializing DNS: ", err.Error())
}
}
if servercfg.IsMessageQueueBackend() {
if err := mq.Configure(); err != nil {
logger.FatalLog("failed to configure MQ: ", err.Error())
}
}
//Run Rest Server
if servercfg.IsRestBackend() {
@ -172,7 +167,6 @@ func runMessageQueue(wg *sync.WaitGroup) {
defer wg.Done()
brokerHost, secure := servercfg.GetMessageQueueEndpoint()
logger.Log(0, "connecting to mq broker at", brokerHost, "with TLS?", fmt.Sprintf("%v", secure))
mq.SetUpAdminClient()
mq.SetupMQTT()
ctx, cancel := context.WithCancel(context.Background())
go mq.Keepalive(ctx)

View file

@ -1,12 +1,9 @@
package metrics
import (
"fmt"
"sync"
"time"
"github.com/go-ping/ping"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/models"
)
@ -84,28 +81,3 @@ func ResetMetricForNode(server, peerKey, peerID string) {
// MetricCollectionInterval - collection interval for metrics
const MetricCollectionInterval = time.Second * 25
// PeerConnectionStatus - get peer connection status by pinging
func PeerConnectionStatus(address string) (connected bool) {
fmt.Println("PINGER ADDR: ", address)
pinger, err := ping.NewPinger(address)
if err != nil {
logger.Log(0, "could not initiliaze ping peer address", address, err.Error())
connected = false
} else {
pinger.Timeout = time.Second * 2
err = pinger.Run()
if err != nil {
logger.Log(0, "failed to ping on peer address", address, err.Error())
return false
} else {
pingStats := pinger.Statistics()
if pingStats.PacketsRecv > 0 {
connected = true
return
}
}
}
return
}

View file

@ -1,6 +1,9 @@
package models
import "net"
import (
"net"
"strings"
)
// ApiHost - the host struct for API usage
type ApiHost struct {
@ -76,7 +79,11 @@ func (a *ApiHost) ConvertAPIHostToNMHost(currentHost *Host) *Host {
h.ID = currentHost.ID
h.HostPass = currentHost.HostPass
h.DaemonInstalled = currentHost.DaemonInstalled
h.EndpointIP = net.ParseIP(a.EndpointIP)
if len(a.EndpointIP) == 0 || strings.Contains(a.EndpointIP, "nil") {
h.EndpointIP = currentHost.EndpointIP
} else {
h.EndpointIP = net.ParseIP(a.EndpointIP)
}
h.Debug = a.Debug
h.FirewallInUse = a.FirewallInUse
h.IPForwarding = currentHost.IPForwarding

View file

@ -58,7 +58,8 @@ func (a *ApiNode) ConvertToServerNode(currentNode *Node) *Node {
convertedNode.Failover = a.Failover
convertedNode.IsEgressGateway = a.IsEgressGateway
convertedNode.IsIngressGateway = a.IsIngressGateway
convertedNode.EgressGatewayRanges = a.EgressGatewayRanges
// prevents user from changing ranges, must delete and recreate
convertedNode.EgressGatewayRanges = currentNode.EgressGatewayRanges
convertedNode.IngressGatewayRange = currentNode.IngressGatewayRange
convertedNode.IngressGatewayRange6 = currentNode.IngressGatewayRange6
convertedNode.DNSOn = a.DNSOn

View file

@ -2,7 +2,7 @@ package models
// moved from controllers need work
//func TestUpdateNetwork(t *testing.T) {
// database.InitializeDatabase()
// initialize()
// createNet()
// network := getNet()
// t.Run("NetID", func(t *testing.T) {

View file

@ -229,6 +229,8 @@ type ServerConfig struct {
DNSMode string `yaml:"dnsmode"`
Version string `yaml:"version"`
MQPort string `yaml:"mqport"`
MQUserName string `yaml:"mq_username"`
MQPassword string `yaml:"mq_password"`
Server string `yaml:"server"`
Broker string `yaml:"broker"`
Is_EE bool `yaml:"isee"`

View file

@ -1,214 +0,0 @@
package mq
import (
"crypto/sha512"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"os"
"time"
mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/netclient/ncutils"
"github.com/gravitl/netmaker/servercfg"
"golang.org/x/crypto/pbkdf2"
)
// mq client for admin
var mqAdminClient mqtt.Client
const (
// constant for client command
CreateClientCmd = "createClient"
// constant for disable command
DisableClientCmd = "disableClient"
// constant for delete client command
DeleteClientCmd = "deleteClient"
// constant for modify client command
ModifyClientCmd = "modifyClient"
// constant for create role command
CreateRoleCmd = "createRole"
// constant for delete role command
DeleteRoleCmd = "deleteRole"
// constant for admin user name
mqAdminUserName = "Netmaker-Admin"
// constant for server user name
mqNetmakerServerUserName = "Netmaker-Server"
// constant for exporter user name
mqExporterUserName = "Netmaker-Exporter"
// DynamicSecSubTopic - constant for dynamic security subscription topic
dynamicSecSubTopic = "$CONTROL/dynamic-security/#"
// DynamicSecPubTopic - constant for dynamic security subscription topic
dynamicSecPubTopic = "$CONTROL/dynamic-security/v1"
)
// struct for dynamic security file
type dynJSON struct {
Clients []client `json:"clients"`
Roles []role `json:"roles"`
DefaultAcl defaultAccessAcl `json:"defaultACLAccess"`
}
// struct for client role
type clientRole struct {
Rolename string `json:"rolename"`
}
// struct for MQ client
type client struct {
Username string `json:"username"`
TextName string `json:"textName"`
Password string `json:"password"`
Salt string `json:"salt"`
Iterations int `json:"iterations"`
Roles []clientRole `json:"roles"`
}
// struct for MQ role
type role struct {
Rolename string `json:"rolename"`
Acls []Acl `json:"acls"`
}
// struct for default acls
type defaultAccessAcl struct {
PublishClientSend bool `json:"publishClientSend"`
PublishClientReceive bool `json:"publishClientReceive"`
Subscribe bool `json:"subscribe"`
Unsubscribe bool `json:"unsubscribe"`
}
// MqDynSecGroup - struct for MQ client group
type MqDynSecGroup struct {
Groupname string `json:"groupname"`
Priority int `json:"priority"`
}
// MqDynSecRole - struct for MQ client role
type MqDynSecRole struct {
Rolename string `json:"rolename"`
Priority int `json:"priority"`
}
// Acl - struct for MQ acls
type Acl struct {
AclType string `json:"acltype"`
Topic string `json:"topic"`
Priority int `json:"priority,omitempty"`
Allow bool `json:"allow"`
}
// MqDynSecCmd - struct for MQ dynamic security command
type MqDynSecCmd struct {
Command string `json:"command"`
Username string `json:"username"`
Password string `json:"password"`
RoleName string `json:"rolename,omitempty"`
Acls []Acl `json:"acls,omitempty"`
Clientid string `json:"clientid"`
Textname string `json:"textname"`
Textdescription string `json:"textdescription"`
Groups []MqDynSecGroup `json:"groups"`
Roles []MqDynSecRole `json:"roles"`
}
// MqDynsecPayload - struct for dynamic security command payload
type MqDynsecPayload struct {
Commands []MqDynSecCmd `json:"commands"`
}
// encodePasswordToPBKDF2 - encodes the given password with PBKDF2 hashing for MQ
func encodePasswordToPBKDF2(password string, salt string, iterations int, keyLength int) string {
binaryEncoded := pbkdf2.Key([]byte(password), []byte(salt), iterations, keyLength, sha512.New)
return base64.StdEncoding.EncodeToString(binaryEncoded)
}
// Configure - configures the dynamic initial configuration for MQ
func Configure() error {
logger.Log(0, "Configuring MQ...")
dynConfig := dynConfigInI
path := functions.GetNetmakerPath() + ncutils.GetSeparator() + dynamicSecurityFile
password := servercfg.GetMqAdminPassword()
if password == "" {
return errors.New("MQ admin password not provided")
}
if logic.CheckIfFileExists(path) {
data, err := os.ReadFile(path)
if err == nil {
var cfg dynJSON
err = json.Unmarshal(data, &cfg)
if err == nil {
logger.Log(0, "MQ config exists already, So Updating Existing Config...")
dynConfig = cfg
}
}
}
exporter := false
for i, cI := range dynConfig.Clients {
if cI.Username == mqAdminUserName || cI.Username == mqNetmakerServerUserName {
salt := logic.RandomString(12)
hashed := encodePasswordToPBKDF2(password, salt, 101, 64)
cI.Password = hashed
cI.Iterations = 101
cI.Salt = base64.StdEncoding.EncodeToString([]byte(salt))
dynConfig.Clients[i] = cI
} else if servercfg.Is_EE && cI.Username == mqExporterUserName {
exporter = true
exporterPassword := servercfg.GetLicenseKey()
salt := logic.RandomString(12)
hashed := encodePasswordToPBKDF2(exporterPassword, salt, 101, 64)
cI.Password = hashed
cI.Iterations = 101
cI.Salt = base64.StdEncoding.EncodeToString([]byte(salt))
dynConfig.Clients[i] = cI
}
}
if servercfg.Is_EE && !exporter {
exporterPassword := servercfg.GetLicenseKey()
salt := logic.RandomString(12)
hashed := encodePasswordToPBKDF2(exporterPassword, salt, 101, 64)
exporterMQClient.Password = hashed
exporterMQClient.Iterations = 101
exporterMQClient.Salt = base64.StdEncoding.EncodeToString([]byte(salt))
dynConfig.Clients = append(dynConfig.Clients, exporterMQClient)
}
data, err := json.MarshalIndent(dynConfig, "", " ")
if err != nil {
return err
}
return os.WriteFile(path, data, 0755)
}
// publishes the message to dynamic security topic
func publishEventToDynSecTopic(payload MqDynsecPayload) error {
d, err := json.Marshal(payload)
if err != nil {
return err
}
var connecterr error
if token := mqAdminClient.Publish(dynamicSecPubTopic, 2, false, d); !token.WaitTimeout(MQ_TIMEOUT*time.Second) || token.Error() != nil {
if token.Error() == nil {
connecterr = errors.New("connect timeout")
} else {
connecterr = token.Error()
}
}
return connecterr
}
// watchDynSecTopic - message handler for dynamic security responses
func watchDynSecTopic(client mqtt.Client, msg mqtt.Message) {
logger.Log(1, fmt.Sprintf("----->WatchDynSecTopic Message: %+v", string(msg.Payload())))
}

View file

@ -1,47 +0,0 @@
package mq
// MqClient - type for taking in an MQ client's data
type MqClient struct {
ID string
Text string
Password string
Networks []string
}
// DeleteMqClient - removes a client from the DynSec system
func DeleteMqClient(hostID string) error {
event := MqDynsecPayload{
Commands: []MqDynSecCmd{
{
Command: DeleteClientCmd,
Username: hostID,
},
},
}
return publishEventToDynSecTopic(event)
}
// CreateMqClient - creates an MQ DynSec client
func CreateMqClient(client *MqClient) error {
event := MqDynsecPayload{
Commands: []MqDynSecCmd{
{
Command: CreateClientCmd,
Username: client.ID,
Password: client.Password,
Textname: client.Text,
Roles: []MqDynSecRole{
{
Rolename: genericRole,
Priority: -1,
},
},
Groups: make([]MqDynSecGroup, 0),
},
},
}
return publishEventToDynSecTopic(event)
}

View file

@ -1,187 +0,0 @@
package mq
import (
"errors"
"time"
mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/gravitl/netmaker/servercfg"
)
const (
// constant for admin role
adminRole = "admin"
// constant for generic role
genericRole = "generic"
// const for dynamic security file
dynamicSecurityFile = "dynamic-security.json"
)
var (
// default configuration of dynamic security
dynConfigInI = dynJSON{
Clients: []client{
{
Username: mqAdminUserName,
TextName: "netmaker admin user",
Password: "",
Salt: "",
Iterations: 0,
Roles: []clientRole{
{
Rolename: adminRole,
},
},
},
{
Username: mqNetmakerServerUserName,
TextName: "netmaker server user",
Password: "",
Salt: "",
Iterations: 0,
Roles: []clientRole{
{
Rolename: genericRole,
},
},
},
exporterMQClient,
},
Roles: []role{
{
Rolename: adminRole,
Acls: fetchAdminAcls(),
},
{
Rolename: genericRole,
Acls: fetchGenericAcls(),
},
},
DefaultAcl: defaultAccessAcl{
PublishClientSend: false,
PublishClientReceive: true,
Subscribe: false,
Unsubscribe: true,
},
}
exporterMQClient = client{
Username: mqExporterUserName,
TextName: "netmaker metrics exporter",
Password: "",
Salt: "",
Iterations: 101,
Roles: []clientRole{
{
Rolename: genericRole,
},
},
}
)
// GetAdminClient - fetches admin client of the MQ
func GetAdminClient() (mqtt.Client, error) {
opts := mqtt.NewClientOptions()
setMqOptions(mqAdminUserName, servercfg.GetMqAdminPassword(), opts)
mqclient := mqtt.NewClient(opts)
var connecterr error
if token := mqclient.Connect(); !token.WaitTimeout(MQ_TIMEOUT*time.Second) || token.Error() != nil {
if token.Error() == nil {
connecterr = errors.New("connect timeout")
} else {
connecterr = token.Error()
}
}
return mqclient, connecterr
}
// genericAcls - fetches generice role related acls
func fetchGenericAcls() []Acl {
return []Acl{
{
AclType: "publishClientSend",
Topic: "#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: "#",
Priority: -1,
Allow: true,
},
{
AclType: "subscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
},
{
AclType: "unsubscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
},
}
}
// fetchAdminAcls - fetches admin role related acls
func fetchAdminAcls() []Acl {
return []Acl{
{
AclType: "publishClientSend",
Topic: "$CONTROL/dynamic-security/#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: "$CONTROL/dynamic-security/#",
Priority: -1,
Allow: true,
},
{
AclType: "subscribePattern",
Topic: "$CONTROL/dynamic-security/#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: "$SYS/#",
Priority: -1,
Allow: true,
},
{
AclType: "subscribePattern",
Topic: "$SYS/#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientReceive",
Topic: "#",
Priority: -1,
Allow: true,
},
{
AclType: "subscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
},
{
AclType: "unsubscribePattern",
Topic: "#",
Priority: -1,
Allow: true,
},
{
AclType: "publishClientSend",
Topic: "#",
Priority: -1,
Allow: true,
},
}
}

View file

@ -168,12 +168,6 @@ func UpdateHost(client mqtt.Client, msg mqtt.Message) {
logger.Log(0, "failed to pulish peer update: ", err.Error())
}
}
if sendPeerUpdate {
err := PublishPeerUpdate()
if err != nil {
logger.Log(0, "failed to pulish peer update: ", err.Error())
}
}
// if servercfg.Is_EE && ifaceDelta {
// if err = logic.EnterpriseResetAllPeersFailovers(currentHost.ID.String(), currentHost.Network); err != nil {
// logger.Log(1, "failed to reset failover list during node update", currentHost.ID.String(), currentHost.Network)

View file

@ -2,7 +2,6 @@ package mq
import (
"context"
"fmt"
"time"
mqtt "github.com/eclipse/paho.mqtt.golang"
@ -23,39 +22,6 @@ var peer_force_send = 0
var mqclient mqtt.Client
// SetUpAdminClient - sets up admin client for the MQ
func SetUpAdminClient() {
opts := mqtt.NewClientOptions()
setMqOptions(mqAdminUserName, servercfg.GetMqAdminPassword(), opts)
mqAdminClient = mqtt.NewClient(opts)
opts.SetOnConnectHandler(func(client mqtt.Client) {
if token := client.Subscribe(dynamicSecSubTopic, 2, mqtt.MessageHandler(watchDynSecTopic)); token.WaitTimeout(MQ_TIMEOUT*time.Second) && token.Error() != nil {
client.Disconnect(240)
logger.Log(0, fmt.Sprintf("Dynamic security client subscription failed: %v ", token.Error()))
}
opts.SetOrderMatters(true)
opts.SetResumeSubs(true)
})
tperiod := time.Now().Add(10 * time.Second)
for {
if token := mqAdminClient.Connect(); !token.WaitTimeout(MQ_TIMEOUT*time.Second) || token.Error() != nil {
logger.Log(2, "Admin: unable to connect to broker, retrying ...")
if time.Now().After(tperiod) {
if token.Error() == nil {
logger.FatalLog("Admin: could not connect to broker, token timeout, exiting ...")
} else {
logger.FatalLog("Admin: could not connect to broker, exiting ...", token.Error().Error())
}
}
} else {
break
}
time.Sleep(2 * time.Second)
}
}
func setMqOptions(user, password string, opts *mqtt.ClientOptions) {
broker, _ := servercfg.GetMessageQueueEndpoint()
opts.AddBroker(broker)
@ -73,7 +39,7 @@ func setMqOptions(user, password string, opts *mqtt.ClientOptions) {
// SetupMQTT creates a connection to broker and return client
func SetupMQTT() {
opts := mqtt.NewClientOptions()
setMqOptions(mqNetmakerServerUserName, servercfg.GetMqAdminPassword(), opts)
setMqOptions(servercfg.GetMqUserName(), servercfg.GetMqPassword(), opts)
opts.SetOnConnectHandler(func(client mqtt.Client) {
if token := client.Subscribe("ping/#", 2, mqtt.MessageHandler(Ping)); token.WaitTimeout(MQ_TIMEOUT*time.Second) && token.Error() != nil {
client.Disconnect(240)
@ -129,3 +95,8 @@ func Keepalive(ctx context.Context) {
}
}
}
// IsConnected - function for determining if the mqclient is connected or not
func IsConnected() bool {
return mqclient != nil && mqclient.IsConnected()
}

View file

@ -1,5 +1,51 @@
#!/bin/bash
# setup_netclient - installs netclient locally
setup_netclient() {
# DEV_TEMP - Temporary instructions for testing
# wget https://fileserver.netmaker.org/testing/netclient
# chmod +x netclient
# ./netclient install
# RELEASE_REPLACE - Use this once release is ready
# if [ -f /etc/debian_version ]; then
# curl -sL 'https://apt.netmaker.org/gpg.key' | sudo tee /etc/apt/trusted.gpg.d/netclient.asc
# curl -sL 'https://apt.netmaker.org/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/netclient.list
# sudo apt update
# sudo apt install netclient
# elif [ -f /etc/centos-release ]; then
# curl -sL 'https://rpm.netmaker.org/gpg.key' | sudo tee /tmp/gpg.key
# curl -sL 'https://rpm.netmaker.org/netclient-repo' | sudo tee /etc/yum.repos.d/netclient.repo
# sudo rpm --import /tmp/gpg.key
# sudo dnf check-update
# sudo dnf install netclient
# elif [ -f /etc/fedora-release ]; then
# curl -sL 'https://rpm.netmaker.org/gpg.key' | sudo tee /tmp/gpg.key
# curl -sL 'https://rpm.netmaker.org/netclient-repo' | sudo tee /etc/yum.repos.d/netclient.repo
# sudo rpm --import /tmp/gpg.key
# sudo dnf check-update
# sudo dnf install netclient
# elif [ -f /etc/redhat-release ]; then
# curl -sL 'https://rpm.netmaker.org/gpg.key' | sudo tee /tmp/gpg.key
# curl -sL 'https://rpm.netmaker.org/netclient-repo' | sudo tee /etc/yum.repos.d/netclient.repo
# sudo rpm --import /tmp/gpg.key
# sudo dnf check-update(
# sudo dnf install netclient
# elif [ -f /etc/arch-release ]; then
# yay -S netclient
# else
# echo "OS not supported for automatic install"
# exit 1
# fi
# if [ -z "${install_cmd}" ]; then
# echo "OS unsupported for automatic dependency install"
# exit 1
# fi
}
cat << "EOF"
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -184,13 +230,11 @@ wait_seconds 3
set -e
NETMAKER_BASE_DOMAIN=nm.$(curl -s ifconfig.me | tr . -).nip.io
NETMAKER_BASE_DOMAIN=nm.$(dig myip.opendns.com @resolver1.opendns.com +short | tr . -).nip.io
COREDNS_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')
SERVER_PUBLIC_IP=$(curl -s ifconfig.me)
SERVER_PUBLIC_IP=$(dig myip.opendns.com @resolver1.opendns.com +short)
MASTER_KEY=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 30 ; echo '')
MQ_PASSWORD=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 30 ; echo '')
DOMAIN_TYPE=""
echo "-----------------------------------------------------"
echo "Would you like to use your own domain for netmaker, or an auto-generated domain?"
echo "To use your own domain, add a Wildcard DNS record (e.x: *.netmaker.example.com) pointing to $SERVER_PUBLIC_IP"
@ -267,6 +311,49 @@ else
EMAIL="$GET_EMAIL"
fi
wait_seconds 1
unset GET_MQ_USERNAME
unset GET_MQ_PASSWORD
unset CONFIRM_MQ_PASSWORD
echo "Enter Credentials For MQ..."
read -p "MQ Username (click 'enter' to use 'netmaker'): " GET_MQ_USERNAME
if [ -z "$GET_MQ_USERNAME" ]; then
echo "using default username for mq"
MQ_USERNAME="netmaker"
else
MQ_USERNAME="$GET_MQ_USERNAME"
fi
select domain_option in "Auto Generated Password" "Input Your Own Password"; do
case $REPLY in
1)
echo "generating random password for mq"
MQ_PASSWORD=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 30 ; echo '')
break
;;
2)
while true
do
echo "Enter your Password For MQ: "
read -s GET_MQ_PASSWORD
echo "Enter your password again to confirm: "
read -s CONFIRM_MQ_PASSWORD
if [ ${GET_MQ_PASSWORD} != ${CONFIRM_MQ_PASSWORD} ]; then
echo "wrong password entered, try again..."
continue
fi
MQ_PASSWORD="$GET_MQ_PASSWORD"
echo "MQ Password Saved Successfully!!"
break
done
break
;;
*) echo "invalid option $REPLY";;
esac
done
wait_seconds 2
echo "-----------------------------------------------------------------"
@ -301,8 +388,9 @@ if [ "$INSTALL_TYPE" = "ee" ]; then
CADDY_URL="https://raw.githubusercontent.com/gravitl/netmaker/master/docker/Caddyfile-EE"
fi
wget -O /root/docker-compose.yml $COMPOSE_URL && wget -O /root/mosquitto.conf https://raw.githubusercontent.com/gravitl/netmaker/master/docker/mosquitto.conf && wget -O /root/Caddyfile $CADDY_URL && wget -q -O /root/wait.sh https://raw.githubusercontent.com/gravitl/netmaker/master/docker/wait.sh && chmod +x /root/wait.sh
wget -O /root/docker-compose.yml $COMPOSE_URL && wget -O /root/mosquitto.conf https://raw.githubusercontent.com/gravitl/netmaker/master/docker/mosquitto.conf && wget -O /root/Caddyfile $CADDY_URL
wget -O /root/wait.sh https://raw.githubusercontent.com/gravitl/netmaker/master/docker/wait.sh
chmod +x /root/wait.sh
mkdir -p /etc/netmaker
echo "Setting docker-compose and Caddyfile..."
@ -312,7 +400,8 @@ sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/Caddyfile
sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/docker-compose.yml
sed -i "s/REPLACE_MASTER_KEY/$MASTER_KEY/g" /root/docker-compose.yml
sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/Caddyfile
sed -i "s/REPLACE_MQ_ADMIN_PASSWORD/$MQ_PASSWORD/g" /root/docker-compose.yml
sed -i "s/REPLACE_MQ_PASSWORD/$MQ_PASSWORD/g" /root/docker-compose.yml
sed -i "s/REPLACE_MQ_USERNAME/$MQ_USERNAME/g" /root/docker-compose.yml
if [ "$INSTALL_TYPE" = "ee" ]; then
sed -i "s~YOUR_LICENSE_KEY~$LICENSE_KEY~g" /root/docker-compose.yml
sed -i "s/YOUR_ACCOUNT_ID/$ACCOUNT_ID/g" /root/docker-compose.yml
@ -366,36 +455,28 @@ ACCESS_TOKEN=$(jq -r '.accessstring' <<< ${curlresponse})
wait_seconds 3
echo "Configuring netmaker server as ingress gateway"
# echo "Installing Netclient"
# setup_netclient
for i in 1 2 3 4 5 6
do
echo " waiting for server node to become available"
wait_seconds 10
curlresponse=$(curl -s -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/nodes/netmaker)
SERVER_ID=$(jq -r '.[0].id' <<< ${curlresponse})
echo " Server ID: $SERVER_ID"
if [ $SERVER_ID == "null" ]; then
SERVER_ID=""
fi
if [[ "$i" -ge "6" && -z "$SERVER_ID" ]]; then
echo " Netmaker is having issues configuring itself, please investigate (docker logs netmaker)"
echo " Exiting..."
exit 1
elif [ -z "$SERVER_ID" ]; then
echo " server node not yet configured, retrying..."
elif [[ ! -z "$SERVER_ID" ]]; then
echo " server node is now availble, continuing"
break
fi
done
# echo "Adding Netclient to Network"
# netclient join -t $ACCESS_TOKEN
# # TODO - Get Host ID
if [[ ! -z "$SERVER_ID" ]]; then
curl -o /dev/null -s -X POST -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/nodes/netmaker/$SERVER_ID/createingress
fi
# echo "Setting Netclient as Default Host"
# HOST_ID=$(grep 'id:' /etc/netclient/netclient.yml | awk '{print $2}')
# echo $HOST_ID
# # TODO - API call to make host default
# echo "Setting Netclient as Ingress Gateway"
# if [[ ! -z "$SERVER_ID" ]]; then
# curl -o /dev/null -s -X POST -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/nodes/netmaker/$HOST_ID/createingress
# fi
)}
set +e
test_connection

View file

@ -1,304 +0,0 @@
#!/bin/bash
echo "checking for root permissions..."
echo "setting flags..."
while getopts d:e:m:v:c: flag
do
case "${flag}" in
d) domain=${OPTARG};;
e) email=${OPTARG};;
m) addmesh=${OPTARG};;
v) addvpn=${OPTARG};;
c) num_clients=${OPTARG};;
esac
done
echo "checking for root permissions..."
if [ $EUID -ne 0 ]; then
echo "This script must be run as root"
exit 1
fi
echo "checking dependencies..."
declare -A osInfo;
osInfo[/etc/debian_version]="apt-get install -y"u
osInfo[/etc/alpine-release]="apk --update add"
osInfo[/etc/centos-release]="yum install -y"
osInfo[/etc/fedora-release]="dnf install -y"
for f in ${!osInfo[@]}
do
if [[ -f $f ]];then
install_cmd=${osInfo[$f]}
fi
done
if [ -f /etc/debian_version ]; then
apt update
elif [ -f /etc/alpine-release ]; then
apk update
elif [ -f /etc/centos-release ]; then
yum update
elif [ -f /etc/fedora-release ]; then
dnf update
fi
dependencies=( "docker.io" "docker-compose" "wireguard" "jq" )
for dependency in ${dependencies[@]}; do
is_installed=$(dpkg-query -W --showformat='${Status}\n' ${dependency} | grep "install ok installed")
if [ "${is_installed}" == "install ok installed" ]; then
echo " " ${dependency} is installed
else
echo " " ${dependency} is not installed. Attempting install.
${install_cmd} ${dependency}
sleep 5
is_installed=$(dpkg-query -W --showformat='${Status}\n' ${dependency} | grep "install ok installed")
if [ "${is_installed}" == "install ok installed" ]; then
echo " " ${dependency} is installed
elif [ -x "$(command -v ${dependency})" ]; then
echo " " ${dependency} is installed
else
echo " " failed to install ${dependency}. Exiting.
exit 1
fi
fi
done
set -e
NETMAKER_BASE_DOMAIN=nm.$(curl -s ifconfig.me | tr . -).nip.io
COREDNS_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')
SERVER_PUBLIC_IP=$(curl -s ifconfig.me)
MASTER_KEY=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 30 ; echo '')
EMAIL="$(echo $RANDOM | md5sum | head -c 32)@email.com"
MQ_ADMIN_PASSWORD=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 64 ; echo '')
if [ -n "$domain" ]; then
NETMAKER_BASE_DOMAIN=$domain
fi
if [ -n "$email" ]; then
EMAIL=$email
fi
if [ -n "$addmesh" ]; then
MESH_SETUP=$addmesh
else
MESH_SETUP="true"
fi
if [ -n "$addvpn" ]; then
VPN_SETUP=$addvpn
else
VPN_SETUP="false"
fi
if [ -n "$num_clients" ]; then
NUM_CLIENTS=$num_clients
else
NUM_CLIENTS=5
fi
echo " ----------------------------"
echo " SETUP ARGUMENTS"
echo " ----------------------------"
echo " domain: $NETMAKER_BASE_DOMAIN"
echo " email: $EMAIL"
echo " coredns ip: $COREDNS_IP"
echo " public ip: $SERVER_PUBLIC_IP"
echo " master key: $MASTER_KEY"
echo " setup mesh?: $MESH_SETUP"
echo " setup vpn?: $VPN_SETUP"
if [ "${VPN_SETUP}" == "true" ]; then
echo " # clients: $NUM_CLIENTS"
fi
echo " ----------------------------"
sleep 5
echo "setting mosquitto.conf..."
wget -q -O /root/mosquitto.conf https://raw.githubusercontent.com/gravitl/netmaker/master/docker/mosquitto.conf
wget -q -O /root/Caddyfile https://raw.githubusercontent.com/gravitl/netmaker/master/docker/Caddyfile
wget -q -O /root/wait.sh https://raw.githubusercontent.com/gravitl/netmaker/master/docker/wait.sh
chmod +x /root/wait.sh
echo "setting docker-compose..."
mkdir -p /etc/netmaker
wget -q -O /root/docker-compose.yml https://raw.githubusercontent.com/gravitl/netmaker/master/compose/docker-compose.yml
sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/docker-compose.yml
sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/Caddyfile
sed -i "s/SERVER_PUBLIC_IP/$SERVER_PUBLIC_IP/g" /root/docker-compose.yml
sed -i "s/COREDNS_IP/$COREDNS_IP/g" /root/docker-compose.yml
sed -i "s/REPLACE_MASTER_KEY/$MASTER_KEY/g" /root/docker-compose.yml
sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/Caddyfile
sed -i "s/REPLACE_MQ_ADMIN_PASSWORD/$MQ_ADMIN_PASSWORD/g" /root/docker-compose.yml
echo "starting containers..."
docker-compose -f /root/docker-compose.yml up -d
test_connection() {
echo "testing Caddy setup (please be patient, this may take 1-2 minutes)"
for i in 1 2 3 4 5 6 7 8
do
curlresponse=$(curl -vIs https://api.${NETMAKER_BASE_DOMAIN} 2>&1)
if [[ "$i" == 8 ]]; then
echo " Caddy is having an issue setting up certificates, please investigate (docker logs caddy)"
echo " exiting..."
exit 1
elif [[ "$curlresponse" == *"failed to verify the legitimacy of the server"* ]]; then
echo " certificates not yet configured, retrying..."
elif [[ "$curlresponse" == *"left intact"* ]]; then
echo " certificates ok"
break
else
secs=$(($i*5+10))
echo " issue establishing connection...retrying in $secs seconds..."
fi
sleep $secs
done
}
set +e
test_connection
cat << "EOF"
__ __ ______ ______ __ __ ______ __ __ ______ ______
/\ "-.\ \ /\ ___\ /\__ _\ /\ "-./ \ /\ __ \ /\ \/ / /\ ___\ /\ == \
\ \ \-. \ \ \ __\ \/_/\ \/ \ \ \-./\ \ \ \ __ \ \ \ _"-. \ \ __\ \ \ __<
\ \_\\"\_\ \ \_____\ \ \_\ \ \_\ \ \_\ \ \_\ \_\ \ \_\ \_\ \ \_____\ \ \_\ \_\
\/_/ \/_/ \/_____/ \/_/ \/_/ \/_/ \/_/\/_/ \/_/\/_/ \/_____/ \/_/ /_/
EOF
echo "visit https://dashboard.$NETMAKER_BASE_DOMAIN to log in"
echo "visit https://grafana.$NETMAKER_BASE_DOMAIN to view metrics on grafana dashboard"
echo "visit https://prometheus.$NETMAKER_BASE_DOMAIN to view metrics on prometheus"
sleep 7
setup_mesh() {( set -e
echo "creating netmaker network (10.101.0.0/16)"
curl -s -o /dev/null -d '{"addressrange":"10.101.0.0/16","netid":"netmaker"}' -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/networks
sleep 5
echo "creating netmaker access key"
curlresponse=$(curl -s -d '{"uses":99999,"name":"netmaker-key"}' -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/networks/netmaker/keys)
ACCESS_TOKEN=$(jq -r '.accessstring' <<< ${curlresponse})
sleep 5
echo "configuring netmaker server as ingress gateway"
curlresponse=$(curl -s -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/nodes/netmaker)
SERVER_ID=$(jq -r '.[0].id' <<< ${curlresponse})
curl -o /dev/null -s -X POST -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/nodes/netmaker/$SERVER_ID/createingress
sleep 5
echo "finished configuring server and network. You can now add clients."
echo ""
echo "For Linux, Mac, Windows, and FreeBSD:"
echo " 1. Install the netclient: https://docs.netmaker.org/netclient.html#installation"
echo " 2. Join the network: netclient join -t $ACCESS_TOKEN"
echo ""
echo "For Android and iOS clients, perform the following steps:"
echo " 1. Log into UI at dashboard.$NETMAKER_BASE_DOMAIN"
echo " 2. Navigate to \"EXTERNAL CLIENTS\" tab"
echo " 3. Select the gateway and create clients"
echo " 4. Scan the QR Code from WireGuard app in iOS or Android"
echo ""
echo "Netmaker setup is now complete. You are ready to begin using Netmaker."
)}
setup_vpn() {( set -e
echo "creating vpn network (10.201.0.0/16)"
curl -s -o /dev/null -d '{"addressrange":"10.201.0.0/16","netid":"vpn","defaultextclientdns":"10.201.255.254"}' -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/networks
sleep 5
echo "configuring netmaker server as vpn inlet..."
curlresponse=$(curl -s -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/nodes/vpn)
SERVER_ID=$(jq -r '.[0].id' <<< ${curlresponse})
curl -s -o /dev/null -X POST -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/nodes/vpn/$SERVER_ID/createingress
echo "waiting 5 seconds for server to apply configuration..."
sleep 5
echo "configuring netmaker server vpn gateway..."
[ -z "$GATEWAY_IFACE" ] && GATEWAY_IFACE=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)')
echo "gateway iface: $GATEWAY_IFACE"
curlresponse=$(curl -s -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/nodes/vpn)
SERVER_ID=$(jq -r '.[0].id' <<< ${curlresponse})
EGRESS_JSON=$( jq -n \
--arg gw "$GATEWAY_IFACE" \
'{ranges: ["0.0.0.0/0"], interface: $gw}' )
echo "egress json: $EGRESS_JSON"
curl -s -o /dev/null -X POST -d "$EGRESS_JSON" -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/nodes/vpn/$SERVER_ID/creategateway
sleep 3
echo "creating client configs..."
for ((a=1; a <= $NUM_CLIENTS; a++))
do
CLIENT_JSON=$( jq -n \
--arg clientid "vpnclient-$a" \
'{clientid: $clientid}' )
curl -s -o /dev/null -d "$CLIENT_JSON" -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/extclients/vpn/$SERVER_ID
sleep 2
done
echo "finished configuring vpn server."
echo ""
echo "To configure clients, perform the following steps:"
echo " 1. log into dashboard.$NETMAKER_BASE_DOMAIN"
echo " 2. Navigate to \"EXTERNAL CLIENTS\" tab"
echo " 3. Download or scan a client config (vpnclient-x) to the appropriate device"
echo " 4. Follow the steps for your system to configure WireGuard on the appropriate device"
echo " 5. Create and delete clients as necessary. Changes to netmaker server settings require regenerating ext clients."
)}
if [ "${MESH_SETUP}" != "false" ]; then
setup_mesh
fi
if [ "${VPN_SETUP}" == "true" ]; then
setup_vpn
fi
echo ""
echo "Netmaker setup is now complete. You are ready to begin using Netmaker."

View file

@ -88,6 +88,8 @@ func GetServerInfo() models.ServerConfig {
var cfg models.ServerConfig
cfg.Server = GetServer()
cfg.Broker = GetBroker()
cfg.MQUserName = GetMqUserName()
cfg.MQPassword = GetMqPassword()
cfg.API = GetAPIConnString()
cfg.CoreDNSAddr = GetCoreDNSAddr()
cfg.APIPort = GetAPIPort()
@ -589,13 +591,24 @@ func GetMQServerPort() string {
return port
}
// GetMqAdminPassword - fetches the MQ Admin password
func GetMqAdminPassword() string {
// GetMqPassword - fetches the MQ password
func GetMqPassword() string {
password := ""
if os.Getenv("MQ_ADMIN_PASSWORD") != "" {
password = os.Getenv("MQ_ADMIN_PASSWORD")
} else if config.Config.Server.MQAdminPassword != "" {
password = config.Config.Server.MQAdminPassword
if os.Getenv("MQ_PASSWORD") != "" {
password = os.Getenv("MQ_PASSWORD")
} else if config.Config.Server.MQPassword != "" {
password = config.Config.Server.MQPassword
}
return password
}
// GetMqUserName - fetches the MQ username
func GetMqUserName() string {
password := ""
if os.Getenv("MQ_USERNAME") != "" {
password = os.Getenv("MQ_USERNAME")
} else if config.Config.Server.MQUserName != "" {
password = config.Config.Server.MQUserName
}
return password
}

View file

@ -3,7 +3,6 @@ package stunserver
import (
"context"
"fmt"
"log"
"net"
"os"
"os/signal"
@ -71,7 +70,6 @@ func (s *Server) serveConn(c net.PacketConn, res, req *stun.Message) error {
logger.Log(1, "ReadFrom: %v", err.Error())
return nil
}
log.Printf("read %d bytes from %s\n", n, addr)
if _, err = req.Write(buf[:n]); err != nil {
logger.Log(1, "Write: %v", err.Error())
return err

View file

@ -718,7 +718,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.17.1
version: 0.18.0
paths:
/api/dns:
get: