mirror of
https://github.com/gravitl/netmaker.git
synced 2025-10-05 16:57:51 +08:00
Combined client + server code, Added HA ability, minor bug fixes
This commit is contained in:
@@ -2,157 +2,15 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/dnslogic"
|
||||||
"github.com/gravitl/netmaker/functions"
|
"github.com/gravitl/netmaker/functions"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
"github.com/gravitl/netmaker/serverctl"
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetPeersList(networkName string, excludeRelayed bool, relayedNodeAddr string) ([]models.Node, error) {
|
|
||||||
var peers []models.Node
|
|
||||||
var relayNode models.Node
|
|
||||||
var err error
|
|
||||||
if relayedNodeAddr == "" {
|
|
||||||
peers, err = GetNodePeers(networkName, excludeRelayed)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
relayNode, err = GetNodeRelay(networkName, relayedNodeAddr)
|
|
||||||
if relayNode.Address != "" {
|
|
||||||
relayNode = setPeerInfo(relayNode)
|
|
||||||
network, err := models.GetNetwork(networkName)
|
|
||||||
if err == nil {
|
|
||||||
relayNode.AllowedIPs = append(relayNode.AllowedIPs, network.AddressRange)
|
|
||||||
} else {
|
|
||||||
relayNode.AllowedIPs = append(relayNode.AllowedIPs, relayNode.RelayAddrs...)
|
|
||||||
}
|
|
||||||
nodepeers, err := GetNodePeers(networkName, false)
|
|
||||||
if err == nil && relayNode.UDPHolePunch == "yes" {
|
|
||||||
for _, nodepeer := range nodepeers {
|
|
||||||
if nodepeer.Address == relayNode.Address {
|
|
||||||
relayNode.Endpoint = nodepeer.Endpoint
|
|
||||||
relayNode.ListenPort = nodepeer.ListenPort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
peers = append(peers, relayNode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return peers, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error) {
|
|
||||||
var peers []models.Node
|
|
||||||
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
|
||||||
if err != nil {
|
|
||||||
if database.IsEmptyRecord(err) {
|
|
||||||
return peers, nil
|
|
||||||
}
|
|
||||||
functions.PrintUserLog("", err.Error(), 2)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
udppeers, errN := database.GetPeers(networkName)
|
|
||||||
if errN != nil {
|
|
||||||
functions.PrintUserLog("", errN.Error(), 2)
|
|
||||||
}
|
|
||||||
for _, value := range collection {
|
|
||||||
var node models.Node
|
|
||||||
var peer models.Node
|
|
||||||
err := json.Unmarshal([]byte(value), &node)
|
|
||||||
if err != nil {
|
|
||||||
functions.PrintUserLog("", err.Error(), 2)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if node.IsEgressGateway == "yes" { // handle egress stuff
|
|
||||||
peer.EgressGatewayRanges = node.EgressGatewayRanges
|
|
||||||
peer.IsEgressGateway = node.IsEgressGateway
|
|
||||||
}
|
|
||||||
allow := node.IsRelayed != "yes" || !excludeRelayed
|
|
||||||
|
|
||||||
if node.Network == networkName && node.IsPending != "yes" && allow {
|
|
||||||
peer = setPeerInfo(node)
|
|
||||||
if node.UDPHolePunch == "yes" && errN == nil && functions.CheckEndpoint(udppeers[node.PublicKey]) {
|
|
||||||
endpointstring := udppeers[node.PublicKey]
|
|
||||||
endpointarr := strings.Split(endpointstring, ":")
|
|
||||||
if len(endpointarr) == 2 {
|
|
||||||
port, err := strconv.Atoi(endpointarr[1])
|
|
||||||
if err == nil {
|
|
||||||
peer.Endpoint = endpointarr[0]
|
|
||||||
peer.ListenPort = int32(port)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if node.IsRelay == "yes" {
|
|
||||||
network, err := models.GetNetwork(networkName)
|
|
||||||
if err == nil {
|
|
||||||
peer.AllowedIPs = append(peer.AllowedIPs, network.AddressRange)
|
|
||||||
} else {
|
|
||||||
peer.AllowedIPs = append(peer.AllowedIPs, node.RelayAddrs...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
peers = append(peers, peer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return peers, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func setPeerInfo(node models.Node) models.Node {
|
|
||||||
var peer models.Node
|
|
||||||
peer.RelayAddrs = node.RelayAddrs
|
|
||||||
peer.IsRelay = node.IsRelay
|
|
||||||
peer.IsRelayed = node.IsRelayed
|
|
||||||
peer.PublicKey = node.PublicKey
|
|
||||||
peer.Endpoint = node.Endpoint
|
|
||||||
peer.LocalAddress = node.LocalAddress
|
|
||||||
peer.ListenPort = node.ListenPort
|
|
||||||
peer.AllowedIPs = node.AllowedIPs
|
|
||||||
peer.UDPHolePunch = node.UDPHolePunch
|
|
||||||
peer.Address = node.Address
|
|
||||||
peer.Address6 = node.Address6
|
|
||||||
peer.EgressGatewayRanges = node.EgressGatewayRanges
|
|
||||||
peer.IsEgressGateway = node.IsEgressGateway
|
|
||||||
peer.IngressGatewayRange = node.IngressGatewayRange
|
|
||||||
peer.IsIngressGateway = node.IsIngressGateway
|
|
||||||
peer.IsPending = node.IsPending
|
|
||||||
return peer
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetExtPeersList(macaddress string, networkName string) ([]models.ExtPeersResponse, error) {
|
|
||||||
|
|
||||||
var peers []models.ExtPeersResponse
|
|
||||||
records, err := database.FetchRecords(database.EXT_CLIENT_TABLE_NAME)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return peers, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, value := range records {
|
|
||||||
var peer models.ExtPeersResponse
|
|
||||||
var extClient models.ExtClient
|
|
||||||
err = json.Unmarshal([]byte(value), &peer)
|
|
||||||
if err != nil {
|
|
||||||
functions.PrintUserLog(models.NODE_SERVER_NAME, "failed to unmarshal peer", 2)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
err = json.Unmarshal([]byte(value), &extClient)
|
|
||||||
if err != nil {
|
|
||||||
functions.PrintUserLog(models.NODE_SERVER_NAME, "failed to unmarshal ext client", 2)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if extClient.Network == networkName && extClient.IngressGatewayID == macaddress {
|
|
||||||
peers = append(peers, peer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return peers, err
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If being deleted by server, create a record in the DELETED_NODES_TABLE for the client to find
|
* If being deleted by server, create a record in the DELETED_NODES_TABLE for the client to find
|
||||||
* If being deleted by the client, delete completely
|
* If being deleted by the client, delete completely
|
||||||
@@ -183,7 +41,7 @@ func DeleteNode(key string, exterminate bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if servercfg.IsDNSMode() {
|
if servercfg.IsDNSMode() {
|
||||||
err = SetDNS()
|
err = dnslogic.SetDNS()
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -235,93 +93,3 @@ func GetIntClient(clientid string) (models.IntClient, error) {
|
|||||||
}
|
}
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateNode(node models.Node, networkName string) (models.Node, error) {
|
|
||||||
|
|
||||||
//encrypt that password so we never see it
|
|
||||||
hash, err := bcrypt.GenerateFromPassword([]byte(node.Password), 5)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
//set password to encrypted password
|
|
||||||
node.Password = string(hash)
|
|
||||||
|
|
||||||
node.Network = networkName
|
|
||||||
if node.Name == models.NODE_SERVER_NAME {
|
|
||||||
node.IsServer = "yes"
|
|
||||||
}
|
|
||||||
if servercfg.IsDNSMode() && node.DNSOn == ""{
|
|
||||||
node.DNSOn = "yes"
|
|
||||||
}
|
|
||||||
node.SetDefaults()
|
|
||||||
node.Address, err = functions.UniqueAddress(networkName)
|
|
||||||
if err != nil {
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
node.Address6, err = functions.UniqueAddress6(networkName)
|
|
||||||
if err != nil {
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
//Create a JWT for the node
|
|
||||||
tokenString, _ := functions.CreateJWT(node.MacAddress, networkName)
|
|
||||||
if tokenString == "" {
|
|
||||||
//returnErrorResponse(w, r, errorResponse)
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
err = node.Validate(false)
|
|
||||||
if err != nil {
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
key, err := functions.GetRecordKey(node.MacAddress, node.Network)
|
|
||||||
if err != nil {
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
nodebytes, err := json.Marshal(&node)
|
|
||||||
if err != nil {
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
err = database.Insert(key, string(nodebytes), database.NODES_TABLE_NAME)
|
|
||||||
if err != nil {
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
if node.IsPending != "yes" {
|
|
||||||
functions.DecrimentKey(node.Network, node.AccessKey)
|
|
||||||
}
|
|
||||||
SetNetworkNodesLastModified(node.Network)
|
|
||||||
if servercfg.IsDNSMode() {
|
|
||||||
err = SetDNS()
|
|
||||||
}
|
|
||||||
return node, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetNetworkServerPeers(networkName string) {
|
|
||||||
if currentPeersList, err := serverctl.GetPeers(networkName); err == nil {
|
|
||||||
if database.SetPeers(currentPeersList, networkName) {
|
|
||||||
functions.PrintUserLog(models.NODE_SERVER_NAME, "set new peers on network "+networkName, 1)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
functions.PrintUserLog(models.NODE_SERVER_NAME, "could not set peers on network "+networkName, 1)
|
|
||||||
functions.PrintUserLog(models.NODE_SERVER_NAME, err.Error(), 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetNetworkNodesLastModified(networkName string) error {
|
|
||||||
|
|
||||||
timestamp := time.Now().Unix()
|
|
||||||
|
|
||||||
network, err := functions.GetParentNetwork(networkName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
network.NodesLastModified = timestamp
|
|
||||||
data, err := json.Marshal(&network)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = database.Insert(networkName, string(data), database.NETWORKS_TABLE_NAME)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/logic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@@ -13,20 +14,20 @@ func TestGetPeerList(t *testing.T) {
|
|||||||
deleteAllNetworks()
|
deleteAllNetworks()
|
||||||
createNet()
|
createNet()
|
||||||
t.Run("NoNodes", func(t *testing.T) {
|
t.Run("NoNodes", func(t *testing.T) {
|
||||||
peers, err := GetPeersList("skynet", false, "")
|
peers, err := logic.GetPeersList("skynet", false, "")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Nil(t, peers)
|
assert.Nil(t, peers)
|
||||||
})
|
})
|
||||||
node := createTestNode()
|
node := createTestNode()
|
||||||
t.Run("One Node", func(t *testing.T) {
|
t.Run("One Node", func(t *testing.T) {
|
||||||
peers, err := GetPeersList("skynet", false, "")
|
peers, err := logic.GetPeersList("skynet", false, "")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, node.Address, peers[0].Address)
|
assert.Equal(t, node.Address, peers[0].Address)
|
||||||
})
|
})
|
||||||
t.Run("Multiple Nodes", func(t *testing.T) {
|
t.Run("Multiple Nodes", func(t *testing.T) {
|
||||||
createnode := models.Node{PublicKey: "RM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.0.0.2", MacAddress: "02:02:03:04:05:06", Password: "password", Network: "skynet"}
|
createnode := models.Node{PublicKey: "RM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.0.0.2", MacAddress: "02:02:03:04:05:06", Password: "password", Network: "skynet"}
|
||||||
CreateNode(createnode, "skynet")
|
logic.CreateNode(createnode, "skynet")
|
||||||
peers, err := GetPeersList("skynet", false, "")
|
peers, err := logic.GetPeersList("skynet", false, "")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, len(peers), 2)
|
assert.Equal(t, len(peers), 2)
|
||||||
foundNodeEndpoint := false
|
foundNodeEndpoint := false
|
||||||
@@ -97,7 +98,7 @@ func TestCreateNode(t *testing.T) {
|
|||||||
createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"}
|
createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"}
|
||||||
//err := ValidateNodeCreate("skynet", createnode)
|
//err := ValidateNodeCreate("skynet", createnode)
|
||||||
//assert.Nil(t, err)
|
//assert.Nil(t, err)
|
||||||
node, err := CreateNode(createnode, "skynet")
|
node, err := logic.CreateNode(createnode, "skynet")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, "10.0.0.1", node.Endpoint)
|
assert.Equal(t, "10.0.0.1", node.Endpoint)
|
||||||
assert.Equal(t, "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", node.PublicKey)
|
assert.Equal(t, "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", node.PublicKey)
|
||||||
@@ -113,17 +114,17 @@ func TestSetNetworkNodesLastModified(t *testing.T) {
|
|||||||
deleteAllNetworks()
|
deleteAllNetworks()
|
||||||
createNet()
|
createNet()
|
||||||
t.Run("InvalidNetwork", func(t *testing.T) {
|
t.Run("InvalidNetwork", func(t *testing.T) {
|
||||||
err := SetNetworkNodesLastModified("badnet")
|
err := logic.SetNetworkNodesLastModified("badnet")
|
||||||
assert.EqualError(t, err, "no result found")
|
assert.EqualError(t, err, "no result found")
|
||||||
})
|
})
|
||||||
t.Run("NetworkExists", func(t *testing.T) {
|
t.Run("NetworkExists", func(t *testing.T) {
|
||||||
err := SetNetworkNodesLastModified("skynet")
|
err := logic.SetNetworkNodesLastModified("skynet")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestNode() models.Node {
|
func createTestNode() models.Node {
|
||||||
createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"}
|
createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"}
|
||||||
node, _ := CreateNode(createnode, "skynet")
|
node, _ := logic.CreateNode(createnode, "skynet")
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
@@ -3,13 +3,13 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/dnslogic"
|
||||||
"github.com/gravitl/netmaker/functions"
|
"github.com/gravitl/netmaker/functions"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
|
||||||
"github.com/txn2/txeh"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func dnsHandlers(r *mux.Router) {
|
func dnsHandlers(r *mux.Router) {
|
||||||
@@ -63,7 +63,7 @@ func GetAllDNS() ([]models.DNSEntry, error) {
|
|||||||
return []models.DNSEntry{}, err
|
return []models.DNSEntry{}, err
|
||||||
}
|
}
|
||||||
for _, net := range networks {
|
for _, net := range networks {
|
||||||
netdns, err := GetDNS(net.NetID)
|
netdns, err := dnslogic.GetDNS(net.NetID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []models.DNSEntry{}, nil
|
return []models.DNSEntry{}, nil
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@ func getCustomDNS(w http.ResponseWriter, r *http.Request) {
|
|||||||
var dns []models.DNSEntry
|
var dns []models.DNSEntry
|
||||||
var params = mux.Vars(r)
|
var params = mux.Vars(r)
|
||||||
|
|
||||||
dns, err := GetCustomDNS(params["network"])
|
dns, err := dnslogic.GetCustomDNS(params["network"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
@@ -114,65 +114,11 @@ func getCustomDNS(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(dns)
|
json.NewEncoder(w).Encode(dns)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCustomDNS(network string) ([]models.DNSEntry, error) {
|
|
||||||
|
|
||||||
var dns []models.DNSEntry
|
|
||||||
|
|
||||||
collection, err := database.FetchRecords(database.DNS_TABLE_NAME)
|
|
||||||
if err != nil {
|
|
||||||
return dns, err
|
|
||||||
}
|
|
||||||
for _, value := range collection { // filter for entries based on network
|
|
||||||
var entry models.DNSEntry
|
|
||||||
if err := json.Unmarshal([]byte(value), &entry); err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if entry.Network == network {
|
|
||||||
dns = append(dns, entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dns, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func SetDNS() error {
|
|
||||||
hostfile := txeh.Hosts{}
|
|
||||||
var corefilestring string
|
|
||||||
networks, err := models.GetNetworks()
|
|
||||||
if err != nil && !database.IsEmptyRecord(err){
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, net := range networks {
|
|
||||||
corefilestring = corefilestring + net.NetID + " "
|
|
||||||
dns, err := GetDNS(net.NetID)
|
|
||||||
if err != nil && !database.IsEmptyRecord(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, entry := range dns {
|
|
||||||
hostfile.AddHost(entry.Address, entry.Name+"."+entry.Network)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if corefilestring == "" {
|
|
||||||
corefilestring = "example.com"
|
|
||||||
}
|
|
||||||
|
|
||||||
err = hostfile.SaveAs("./config/dnsconfig/netmaker.hosts")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if servercfg.IsSplitDNS() {
|
|
||||||
err = functions.SetCorefile(corefilestring)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDNSEntryNum(domain string, network string) (int, error) {
|
func GetDNSEntryNum(domain string, network string) (int, error) {
|
||||||
|
|
||||||
num := 0
|
num := 0
|
||||||
|
|
||||||
entries, err := GetDNS(network)
|
entries, err := dnslogic.GetDNS(network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -195,7 +141,7 @@ func getDNS(w http.ResponseWriter, r *http.Request) {
|
|||||||
var dns []models.DNSEntry
|
var dns []models.DNSEntry
|
||||||
var params = mux.Vars(r)
|
var params = mux.Vars(r)
|
||||||
|
|
||||||
dns, err := GetDNS(params["network"])
|
dns, err := dnslogic.GetDNS(params["network"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
@@ -204,22 +150,6 @@ func getDNS(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(dns)
|
json.NewEncoder(w).Encode(dns)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDNS(network string) ([]models.DNSEntry, error) {
|
|
||||||
|
|
||||||
var dns []models.DNSEntry
|
|
||||||
dns, err := GetNodeDNS(network)
|
|
||||||
if err != nil && !database.IsEmptyRecord(err) {
|
|
||||||
return dns, err
|
|
||||||
}
|
|
||||||
customdns, err := GetCustomDNS(network)
|
|
||||||
if err != nil && !database.IsEmptyRecord(err) {
|
|
||||||
return dns, err
|
|
||||||
}
|
|
||||||
|
|
||||||
dns = append(dns, customdns...)
|
|
||||||
return dns, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func createDNS(w http.ResponseWriter, r *http.Request) {
|
func createDNS(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
@@ -241,7 +171,7 @@ func createDNS(w http.ResponseWriter, r *http.Request) {
|
|||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = SetDNS()
|
err = dnslogic.SetDNS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
@@ -296,7 +226,7 @@ func updateDNS(w http.ResponseWriter, r *http.Request) {
|
|||||||
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = SetDNS()
|
err = dnslogic.SetDNS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
@@ -319,7 +249,7 @@ func deleteDNS(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
entrytext := params["domain"] + "." + params["network"]
|
entrytext := params["domain"] + "." + params["network"]
|
||||||
functions.PrintUserLog(models.NODE_SERVER_NAME, "deleted dns entry: "+entrytext, 1)
|
functions.PrintUserLog(models.NODE_SERVER_NAME, "deleted dns entry: "+entrytext, 1)
|
||||||
err = SetDNS()
|
err = dnslogic.SetDNS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
@@ -394,13 +324,13 @@ func pushDNS(w http.ResponseWriter, r *http.Request) {
|
|||||||
// Set header
|
// Set header
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
err := SetDNS()
|
err := dnslogic.SetDNS()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
functions.PrintUserLog(r.Header.Get("user"),"pushed DNS updates to nameserver",1)
|
functions.PrintUserLog(r.Header.Get("user"), "pushed DNS updates to nameserver", 1)
|
||||||
json.NewEncoder(w).Encode("DNS Pushed to CoreDNS")
|
json.NewEncoder(w).Encode("DNS Pushed to CoreDNS")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,7 +351,7 @@ func ValidateDNSCreate(entry models.DNSEntry) error {
|
|||||||
err := v.Struct(entry)
|
err := v.Struct(entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
for _, e := range err.(validator.ValidationErrors) {
|
for _, e := range err.(validator.ValidationErrors) {
|
||||||
functions.PrintUserLog("", e.Error(),1)
|
functions.PrintUserLog("", e.Error(), 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@@ -442,7 +372,7 @@ func ValidateDNSUpdate(change models.DNSEntry, entry models.DNSEntry) error {
|
|||||||
_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
|
_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
|
||||||
_, err := functions.GetParentNetwork(change.Network)
|
_, err := functions.GetParentNetwork(change.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
functions.PrintUserLog("",err.Error(),0)
|
functions.PrintUserLog("", err.Error(), 0)
|
||||||
}
|
}
|
||||||
return err == nil
|
return err == nil
|
||||||
})
|
})
|
||||||
@@ -465,7 +395,7 @@ func ValidateDNSUpdate(change models.DNSEntry, entry models.DNSEntry) error {
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
for _, e := range err.(validator.ValidationErrors) {
|
for _, e := range err.(validator.ValidationErrors) {
|
||||||
functions.PrintUserLog("", e.Error(),1)
|
functions.PrintUserLog("", e.Error(), 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/dnslogic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@@ -23,7 +24,7 @@ func TestGetCustomDNS(t *testing.T) {
|
|||||||
deleteAllNetworks()
|
deleteAllNetworks()
|
||||||
createNet()
|
createNet()
|
||||||
createTestNode()
|
createTestNode()
|
||||||
dns, err := GetCustomDNS("skynet")
|
dns, err := dnslogic.GetCustomDNS("skynet")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
t.Log(dns)
|
t.Log(dns)
|
||||||
}
|
}
|
||||||
@@ -39,7 +40,7 @@ func TestGetDNSEntryNum(t *testing.T) {
|
|||||||
func TestGetDNS(t *testing.T) {
|
func TestGetDNS(t *testing.T) {
|
||||||
database.InitializeDatabase()
|
database.InitializeDatabase()
|
||||||
deleteAllNetworks()
|
deleteAllNetworks()
|
||||||
dns, err := GetDNS("skynet")
|
dns, err := dnslogic.GetDNS("skynet")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
t.Log(dns)
|
t.Log(dns)
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/functions"
|
"github.com/gravitl/netmaker/functions"
|
||||||
|
"github.com/gravitl/netmaker/logic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/skip2/go-qrcode"
|
"github.com/skip2/go-qrcode"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
@@ -273,7 +274,7 @@ func CreateExtClient(extclient models.ExtClient) error {
|
|||||||
if err = database.Insert(key, string(data), database.EXT_CLIENT_TABLE_NAME); err != nil {
|
if err = database.Insert(key, string(data), database.EXT_CLIENT_TABLE_NAME); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = SetNetworkNodesLastModified(extclient.Network)
|
err = logic.SetNetworkNodesLastModified(extclient.Network)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/functions"
|
"github.com/gravitl/netmaker/functions"
|
||||||
|
"github.com/gravitl/netmaker/logic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
"github.com/gravitl/netmaker/serverctl"
|
"github.com/gravitl/netmaker/serverctl"
|
||||||
@@ -337,8 +338,21 @@ func deleteNetwork(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DeleteNetwork(network string) error {
|
func DeleteNetwork(network string) error {
|
||||||
nodeCount, err := functions.GetNetworkNodeCount(network)
|
nodeCount, err := functions.GetNetworkNonServerNodeCount(network)
|
||||||
if nodeCount == 0 || database.IsEmptyRecord(err) {
|
if nodeCount == 0 || database.IsEmptyRecord(err) {
|
||||||
|
// delete server nodes first then db records
|
||||||
|
servers, err := logic.GetSortedNetworkServerNodes(network)
|
||||||
|
if err == nil {
|
||||||
|
for _, s := range servers {
|
||||||
|
if err = logic.DeleteNode(s.ID, true); err != nil {
|
||||||
|
functions.PrintUserLog("[netmaker]", "could not removed server "+s.Name+" before deleting network "+network, 2)
|
||||||
|
} else {
|
||||||
|
functions.PrintUserLog("[netmaker]", "removed server "+s.Name+" before deleting network "+network, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
functions.PrintUserLog("[netmaker]", "could not remove servers before deleting network "+network, 1)
|
||||||
|
}
|
||||||
return database.DeleteRecord(database.NETWORKS_TABLE_NAME, network)
|
return database.DeleteRecord(database.NETWORKS_TABLE_NAME, network)
|
||||||
}
|
}
|
||||||
return errors.New("node check failed. All nodes must be deleted before deleting network")
|
return errors.New("node check failed. All nodes must be deleted before deleting network")
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gravitl/netmaker/functions"
|
"github.com/gravitl/netmaker/functions"
|
||||||
nodepb "github.com/gravitl/netmaker/grpc"
|
nodepb "github.com/gravitl/netmaker/grpc"
|
||||||
|
"github.com/gravitl/netmaker/logic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.Object)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node, err = CreateNode(node, node.Network)
|
node, err = logic.CreateNode(node, node.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -77,7 +78,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.Object)
|
|||||||
Data: string(nodeData),
|
Data: string(nodeData),
|
||||||
Type: nodepb.NODE_TYPE,
|
Type: nodepb.NODE_TYPE,
|
||||||
}
|
}
|
||||||
err = SetNetworkNodesLastModified(node.Network)
|
err = logic.SetNetworkNodesLastModified(node.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -134,15 +135,15 @@ func (s *NodeServiceServer) GetPeers(ctx context.Context, req *nodepb.Object) (*
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if node.IsServer == "yes" {
|
if node.IsServer == "yes" && logic.IsLeader(&node){
|
||||||
SetNetworkServerPeers(macAndNetwork[1])
|
logic.SetNetworkServerPeers(&node)
|
||||||
}
|
}
|
||||||
excludeIsRelayed := node.IsRelay != "yes"
|
excludeIsRelayed := node.IsRelay != "yes"
|
||||||
var relayedNode string
|
var relayedNode string
|
||||||
if node.IsRelayed == "yes" {
|
if node.IsRelayed == "yes" {
|
||||||
relayedNode = node.Address
|
relayedNode = node.Address
|
||||||
}
|
}
|
||||||
peers, err := GetPeersList(macAndNetwork[1], excludeIsRelayed, relayedNode)
|
peers, err := logic.GetPeersList(macAndNetwork[1], excludeIsRelayed, relayedNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -172,11 +173,10 @@ func (s *NodeServiceServer) GetExtPeers(ctx context.Context, req *nodepb.Object)
|
|||||||
if len(macAndNetwork) != 2 {
|
if len(macAndNetwork) != 2 {
|
||||||
return nil, errors.New("did not receive valid node id when fetching ext peers")
|
return nil, errors.New("did not receive valid node id when fetching ext peers")
|
||||||
}
|
}
|
||||||
peers, err := GetExtPeersList(macAndNetwork[0], macAndNetwork[1])
|
peers, err := logic.GetExtPeersList(macAndNetwork[0], macAndNetwork[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// cursor.Next() returns a boolean, if false there are no more items and loop will break
|
|
||||||
var extPeers []models.Node
|
var extPeers []models.Node
|
||||||
for i := 0; i < len(peers); i++ {
|
for i := 0; i < len(peers); i++ {
|
||||||
extPeers = append(extPeers, models.Node{
|
extPeers = append(extPeers, models.Node{
|
||||||
|
@@ -6,10 +6,11 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/dnslogic"
|
||||||
"github.com/gravitl/netmaker/functions"
|
"github.com/gravitl/netmaker/functions"
|
||||||
|
"github.com/gravitl/netmaker/logic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
@@ -267,7 +268,7 @@ func getNetworkNodes(w http.ResponseWriter, r *http.Request) {
|
|||||||
var nodes []models.Node
|
var nodes []models.Node
|
||||||
var params = mux.Vars(r)
|
var params = mux.Vars(r)
|
||||||
networkName := params["network"]
|
networkName := params["network"]
|
||||||
nodes, err := GetNetworkNodes(networkName)
|
nodes, err := logic.GetNetworkNodes(networkName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
@@ -279,29 +280,6 @@ func getNetworkNodes(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(nodes)
|
json.NewEncoder(w).Encode(nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetNetworkNodes(network string) ([]models.Node, error) {
|
|
||||||
var nodes []models.Node
|
|
||||||
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
|
||||||
if err != nil {
|
|
||||||
if database.IsEmptyRecord(err) {
|
|
||||||
return []models.Node{}, nil
|
|
||||||
}
|
|
||||||
return nodes, err
|
|
||||||
}
|
|
||||||
for _, value := range collection {
|
|
||||||
|
|
||||||
var node models.Node
|
|
||||||
err := json.Unmarshal([]byte(value), &node)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if node.Network == network {
|
|
||||||
nodes = append(nodes, node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nodes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//A separate function to get all nodes, not just nodes for a particular network.
|
//A separate function to get all nodes, not just nodes for a particular network.
|
||||||
//Not quite sure if this is necessary. Probably necessary based on front end but may want to review after iteration 1 if it's being used or not
|
//Not quite sure if this is necessary. Probably necessary based on front end but may want to review after iteration 1 if it's being used or not
|
||||||
func getAllNodes(w http.ResponseWriter, r *http.Request) {
|
func getAllNodes(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -335,7 +313,7 @@ func getUsersNodes(user models.User) ([]models.Node, error) {
|
|||||||
var nodes []models.Node
|
var nodes []models.Node
|
||||||
var err error
|
var err error
|
||||||
for _, networkName := range user.Networks {
|
for _, networkName := range user.Networks {
|
||||||
tmpNodes, err := GetNetworkNodes(networkName)
|
tmpNodes, err := logic.GetNetworkNodes(networkName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -437,7 +415,7 @@ func createNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node, err = CreateNode(node, networkName)
|
node, err = logic.CreateNode(node, networkName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
@@ -682,7 +660,7 @@ func CreateIngressGateway(netid string, macaddress string) (models.Node, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return models.Node{}, err
|
return models.Node{}, err
|
||||||
}
|
}
|
||||||
err = SetNetworkNodesLastModified(netid)
|
err = logic.SetNetworkNodesLastModified(netid)
|
||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -733,7 +711,7 @@ func DeleteIngressGateway(networkName string, macaddress string) (models.Node, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return models.Node{}, err
|
return models.Node{}, err
|
||||||
}
|
}
|
||||||
err = SetNetworkNodesLastModified(networkName)
|
err = logic.SetNetworkNodesLastModified(networkName)
|
||||||
return node, err
|
return node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -783,7 +761,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if servercfg.IsDNSMode() {
|
if servercfg.IsDNSMode() {
|
||||||
err = SetDNS()
|
err = dnslogic.SetDNS()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/logic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@@ -81,19 +82,19 @@ func TestGetNetworkNodes(t *testing.T) {
|
|||||||
deleteAllNetworks()
|
deleteAllNetworks()
|
||||||
createNet()
|
createNet()
|
||||||
t.Run("BadNet", func(t *testing.T) {
|
t.Run("BadNet", func(t *testing.T) {
|
||||||
node, err := GetNetworkNodes("badnet")
|
node, err := logic.GetNetworkNodes("badnet")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, []models.Node{}, node)
|
assert.Equal(t, []models.Node{}, node)
|
||||||
//assert.Equal(t, "mongo: no documents in result", err.Error())
|
//assert.Equal(t, "mongo: no documents in result", err.Error())
|
||||||
})
|
})
|
||||||
t.Run("NoNodes", func(t *testing.T) {
|
t.Run("NoNodes", func(t *testing.T) {
|
||||||
node, err := GetNetworkNodes("skynet")
|
node, err := logic.GetNetworkNodes("skynet")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, []models.Node{}, node)
|
assert.Equal(t, []models.Node{}, node)
|
||||||
})
|
})
|
||||||
t.Run("Success", func(t *testing.T) {
|
t.Run("Success", func(t *testing.T) {
|
||||||
createTestNode()
|
createTestNode()
|
||||||
node, err := GetNetworkNodes("skynet")
|
node, err := logic.GetNetworkNodes("skynet")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.NotEqual(t, []models.Node(nil), node)
|
assert.NotEqual(t, []models.Node(nil), node)
|
||||||
})
|
})
|
||||||
|
@@ -72,6 +72,21 @@ func CreateRelay(relay models.RelayRequest) (models.Node, error) {
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func deleteRelay(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
var params = mux.Vars(r)
|
||||||
|
nodeMac := params["macaddress"]
|
||||||
|
netid := params["network"]
|
||||||
|
node, err := DeleteRelay(netid, nodeMac)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
functions.PrintUserLog(r.Header.Get("user"), "deleted egress gateway "+nodeMac+" on network "+netid, 1)
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(node)
|
||||||
|
}
|
||||||
|
|
||||||
func SetRelayedNodes(yesOrno string, networkName string, addrs []string) error {
|
func SetRelayedNodes(yesOrno string, networkName string, addrs []string) error {
|
||||||
|
|
||||||
collections, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
collections, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
||||||
@@ -125,21 +140,6 @@ func UpdateRelay(network string, oldAddrs []string, newAddrs []string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteRelay(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
var params = mux.Vars(r)
|
|
||||||
nodeMac := params["macaddress"]
|
|
||||||
netid := params["network"]
|
|
||||||
node, err := DeleteRelay(netid, nodeMac)
|
|
||||||
if err != nil {
|
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
functions.PrintUserLog(r.Header.Get("user"), "deleted egress gateway "+nodeMac+" on network "+netid, 1)
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
json.NewEncoder(w).Encode(node)
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteRelay(network, macaddress string) (models.Node, error) {
|
func DeleteRelay(network, macaddress string) (models.Node, error) {
|
||||||
|
|
||||||
node, err := functions.GetNodeByMacAddress(network, macaddress)
|
node, err := functions.GetNodeByMacAddress(network, macaddress)
|
||||||
@@ -171,30 +171,3 @@ func DeleteRelay(network, macaddress string) (models.Node, error) {
|
|||||||
}
|
}
|
||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetNodeRelay(network string, relayedNodeAddr string) (models.Node, error) {
|
|
||||||
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
|
||||||
var relay models.Node
|
|
||||||
if err != nil {
|
|
||||||
if database.IsEmptyRecord(err) {
|
|
||||||
return relay, nil
|
|
||||||
}
|
|
||||||
functions.PrintUserLog("", err.Error(), 2)
|
|
||||||
return relay, err
|
|
||||||
}
|
|
||||||
for _, value := range collection {
|
|
||||||
err := json.Unmarshal([]byte(value), &relay)
|
|
||||||
if err != nil {
|
|
||||||
functions.PrintUserLog("", err.Error(), 2)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if relay.IsRelay == "yes" {
|
|
||||||
for _, addr := range relay.RelayAddrs {
|
|
||||||
if addr == relayedNodeAddr {
|
|
||||||
return relay, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return relay, errors.New("could not find relay for node " + relayedNodeAddr)
|
|
||||||
}
|
|
||||||
|
@@ -89,17 +89,17 @@ func VerifyAuthRequest(authRequest models.UserAuthParams) (string, error) {
|
|||||||
//Search DB for node with Mac Address. Ignore pending nodes (they should not be able to authenticate with API untill approved).
|
//Search DB for node with Mac Address. Ignore pending nodes (they should not be able to authenticate with API untill approved).
|
||||||
record, err := database.FetchRecord(database.USERS_TABLE_NAME, authRequest.UserName)
|
record, err := database.FetchRecord(database.USERS_TABLE_NAME, authRequest.UserName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.New("user " + authRequest.UserName + " not found")
|
return "", errors.New("incorrect credentials")
|
||||||
}
|
}
|
||||||
if err = json.Unmarshal([]byte(record), &result); err != nil {
|
if err = json.Unmarshal([]byte(record), &result); err != nil {
|
||||||
return "", errors.New("user " + authRequest.UserName + " not found")
|
return "", errors.New("incorrect credentials")
|
||||||
}
|
}
|
||||||
|
|
||||||
//compare password from request to stored password in database
|
//compare password from request to stored password in database
|
||||||
//might be able to have a common hash (certificates?) and compare those so that a password isn't passed in in plain text...
|
//might be able to have a common hash (certificates?) and compare those so that a password isn't passed in in plain text...
|
||||||
//TODO: Consider a way of hashing the password client side before sending, or using certificates
|
//TODO: Consider a way of hashing the password client side before sending, or using certificates
|
||||||
if err = bcrypt.CompareHashAndPassword([]byte(result.Password), []byte(authRequest.Password)); err != nil {
|
if err = bcrypt.CompareHashAndPassword([]byte(result.Password), []byte(authRequest.Password)); err != nil {
|
||||||
return "", errors.New("wrong password")
|
return "", errors.New("incorrect credentials")
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create a new JWT for the node
|
//Create a new JWT for the node
|
||||||
|
@@ -219,7 +219,7 @@ func TestVerifyAuthRequest(t *testing.T) {
|
|||||||
authRequest.Password = "password"
|
authRequest.Password = "password"
|
||||||
jwt, err := VerifyAuthRequest(authRequest)
|
jwt, err := VerifyAuthRequest(authRequest)
|
||||||
assert.Equal(t, "", jwt)
|
assert.Equal(t, "", jwt)
|
||||||
assert.EqualError(t, err, "user admin not found")
|
assert.EqualError(t, err, "incorrect credentials")
|
||||||
})
|
})
|
||||||
t.Run("Non-Admin", func(t *testing.T) {
|
t.Run("Non-Admin", func(t *testing.T) {
|
||||||
user := models.User{"nonadmin", "somepass", nil, false}
|
user := models.User{"nonadmin", "somepass", nil, false}
|
||||||
@@ -235,7 +235,7 @@ func TestVerifyAuthRequest(t *testing.T) {
|
|||||||
authRequest := models.UserAuthParams{"admin", "badpass"}
|
authRequest := models.UserAuthParams{"admin", "badpass"}
|
||||||
jwt, err := VerifyAuthRequest(authRequest)
|
jwt, err := VerifyAuthRequest(authRequest)
|
||||||
assert.Equal(t, "", jwt)
|
assert.Equal(t, "", jwt)
|
||||||
assert.EqualError(t, err, "wrong password")
|
assert.EqualError(t, err, "incorrect credentials")
|
||||||
})
|
})
|
||||||
t.Run("Success", func(t *testing.T) {
|
t.Run("Success", func(t *testing.T) {
|
||||||
authRequest := models.UserAuthParams{"admin", "password"}
|
authRequest := models.UserAuthParams{"admin", "password"}
|
||||||
|
104
dnslogic/dns.go
Normal file
104
dnslogic/dns.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package dnslogic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/functions"
|
||||||
|
"github.com/gravitl/netmaker/models"
|
||||||
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
|
"github.com/txn2/txeh"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetDNS() error {
|
||||||
|
hostfile := txeh.Hosts{}
|
||||||
|
var corefilestring string
|
||||||
|
networks, err := models.GetNetworks()
|
||||||
|
if err != nil && !database.IsEmptyRecord(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, net := range networks {
|
||||||
|
corefilestring = corefilestring + net.NetID + " "
|
||||||
|
dns, err := GetDNS(net.NetID)
|
||||||
|
if err != nil && !database.IsEmptyRecord(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, entry := range dns {
|
||||||
|
hostfile.AddHost(entry.Address, entry.Name+"."+entry.Network)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if corefilestring == "" {
|
||||||
|
corefilestring = "example.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
err = hostfile.SaveAs("./config/dnsconfig/netmaker.hosts")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if servercfg.IsSplitDNS() {
|
||||||
|
err = functions.SetCorefile(corefilestring)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDNS(network string) ([]models.DNSEntry, error) {
|
||||||
|
|
||||||
|
var dns []models.DNSEntry
|
||||||
|
dns, err := GetNodeDNS(network)
|
||||||
|
if err != nil && !database.IsEmptyRecord(err) {
|
||||||
|
return dns, err
|
||||||
|
}
|
||||||
|
customdns, err := GetCustomDNS(network)
|
||||||
|
if err != nil && !database.IsEmptyRecord(err) {
|
||||||
|
return dns, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dns = append(dns, customdns...)
|
||||||
|
return dns, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetNodeDNS(network string) ([]models.DNSEntry, error) {
|
||||||
|
|
||||||
|
var dns []models.DNSEntry
|
||||||
|
|
||||||
|
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
||||||
|
if err != nil {
|
||||||
|
return dns, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, value := range collection {
|
||||||
|
var entry models.DNSEntry
|
||||||
|
var node models.Node
|
||||||
|
if err = json.Unmarshal([]byte(value), &node); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err = json.Unmarshal([]byte(value), &entry); node.Network == network && err == nil {
|
||||||
|
dns = append(dns, entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dns, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCustomDNS(network string) ([]models.DNSEntry, error) {
|
||||||
|
|
||||||
|
var dns []models.DNSEntry
|
||||||
|
|
||||||
|
collection, err := database.FetchRecords(database.DNS_TABLE_NAME)
|
||||||
|
if err != nil {
|
||||||
|
return dns, err
|
||||||
|
}
|
||||||
|
for _, value := range collection { // filter for entries based on network
|
||||||
|
var entry models.DNSEntry
|
||||||
|
if err := json.Unmarshal([]byte(value), &entry); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry.Network == network {
|
||||||
|
dns = append(dns, entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dns, err
|
||||||
|
}
|
@@ -9,24 +9,16 @@ ENV GO111MODULE=auto
|
|||||||
|
|
||||||
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=1 /usr/local/go/bin/go build -ldflags="-w -s" -o netmaker main.go
|
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=1 /usr/local/go/bin/go build -ldflags="-w -s" -o netmaker main.go
|
||||||
|
|
||||||
WORKDIR /app/netclient
|
|
||||||
|
|
||||||
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 /usr/local/go/bin/go build -ldflags="-w -s" -o netclient main.go
|
|
||||||
#second stage
|
|
||||||
|
|
||||||
FROM alpine:3.13.6
|
FROM alpine:3.13.6
|
||||||
# add a c lib
|
# add a c lib
|
||||||
RUN apk add gcompat iptables
|
RUN apk add gcompat iptables
|
||||||
# set the working directory
|
# set the working directory
|
||||||
WORKDIR /root/
|
WORKDIR /root/
|
||||||
|
|
||||||
RUN mkdir /etc/netclient
|
RUN mkdir -p /etc/netclient/config
|
||||||
|
|
||||||
COPY --from=builder /app/netmaker .
|
COPY --from=builder /app/netmaker .
|
||||||
COPY --from=builder /app/config config
|
COPY --from=builder /app/config config
|
||||||
COPY --from=builder /app/netclient/netclient /etc/netclient/netclient
|
|
||||||
|
|
||||||
RUN chmod 0755 /etc/netclient/netclient
|
|
||||||
|
|
||||||
EXPOSE 8081
|
EXPOSE 8081
|
||||||
EXPOSE 50051
|
EXPOSE 50051
|
||||||
|
@@ -20,11 +20,6 @@ import (
|
|||||||
"github.com/gravitl/netmaker/servercfg"
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CheckEndpoint(endpoint string) bool {
|
|
||||||
endpointarr := strings.Split(endpoint, ":")
|
|
||||||
return len(endpointarr) == 2
|
|
||||||
}
|
|
||||||
|
|
||||||
func PrintUserLog(username string, message string, loglevel int) {
|
func PrintUserLog(username string, message string, loglevel int) {
|
||||||
log.SetFlags(log.Flags() &^ (log.Llongfile | log.Lshortfile))
|
log.SetFlags(log.Flags() &^ (log.Llongfile | log.Lshortfile))
|
||||||
if int32(loglevel) <= servercfg.GetVerbose() && servercfg.GetVerbose() != 0 {
|
if int32(loglevel) <= servercfg.GetVerbose() && servercfg.GetVerbose() != 0 {
|
||||||
@@ -380,7 +375,7 @@ func IsMacAddressUnique(macaddress string, networkName string) (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetNetworkNodeCount(networkName string) (int, error) {
|
func GetNetworkNonServerNodeCount(networkName string) (int, error) {
|
||||||
|
|
||||||
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
||||||
count := 0
|
count := 0
|
||||||
@@ -392,7 +387,7 @@ func GetNetworkNodeCount(networkName string) (int, error) {
|
|||||||
if err = json.Unmarshal([]byte(value), &node); err != nil {
|
if err = json.Unmarshal([]byte(value), &node); err != nil {
|
||||||
return count, err
|
return count, err
|
||||||
} else {
|
} else {
|
||||||
if node.Network == networkName {
|
if node.Network == networkName && node.IsServer != "yes" {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -491,12 +486,6 @@ func IsIpCIDR(host string) bool {
|
|||||||
return ip != nil && ipnet != nil
|
return ip != nil && ipnet != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//This is used to validate public keys (make sure they're base64 encoded like all public keys should be).
|
|
||||||
func IsBase64(s string) bool {
|
|
||||||
_, err := base64.StdEncoding.DecodeString(s)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//This checks to make sure a network name is valid.
|
//This checks to make sure a network name is valid.
|
||||||
//Switch to REGEX?
|
//Switch to REGEX?
|
||||||
func NameInNetworkCharSet(name string) bool {
|
func NameInNetworkCharSet(name string) bool {
|
||||||
|
38
logic/extpeers.go
Normal file
38
logic/extpeers.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/functions"
|
||||||
|
"github.com/gravitl/netmaker/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetExtPeersList(macaddress string, networkName string) ([]models.ExtPeersResponse, error) {
|
||||||
|
|
||||||
|
var peers []models.ExtPeersResponse
|
||||||
|
records, err := database.FetchRecords(database.EXT_CLIENT_TABLE_NAME)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return peers, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, value := range records {
|
||||||
|
var peer models.ExtPeersResponse
|
||||||
|
var extClient models.ExtClient
|
||||||
|
err = json.Unmarshal([]byte(value), &peer)
|
||||||
|
if err != nil {
|
||||||
|
functions.PrintUserLog(models.NODE_SERVER_NAME, "failed to unmarshal peer", 2)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = json.Unmarshal([]byte(value), &extClient)
|
||||||
|
if err != nil {
|
||||||
|
functions.PrintUserLog(models.NODE_SERVER_NAME, "failed to unmarshal ext client", 2)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if extClient.Network == networkName && extClient.IngressGatewayID == macaddress {
|
||||||
|
peers = append(peers, peer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return peers, err
|
||||||
|
}
|
88
logic/nodes.go
Normal file
88
logic/nodes.go
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"sort"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/functions"
|
||||||
|
"github.com/gravitl/netmaker/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetNetworkNodes(network string) ([]models.Node, error) {
|
||||||
|
var nodes []models.Node
|
||||||
|
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
||||||
|
if err != nil {
|
||||||
|
if database.IsEmptyRecord(err) {
|
||||||
|
return []models.Node{}, nil
|
||||||
|
}
|
||||||
|
return nodes, err
|
||||||
|
}
|
||||||
|
for _, value := range collection {
|
||||||
|
|
||||||
|
var node models.Node
|
||||||
|
err := json.Unmarshal([]byte(value), &node)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if node.Network == network {
|
||||||
|
nodes = append(nodes, node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSortedNetworkServerNodes(network string) ([]models.Node, error) {
|
||||||
|
var nodes []models.Node
|
||||||
|
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
||||||
|
if err != nil {
|
||||||
|
if database.IsEmptyRecord(err) {
|
||||||
|
return []models.Node{}, nil
|
||||||
|
}
|
||||||
|
return nodes, err
|
||||||
|
}
|
||||||
|
for _, value := range collection {
|
||||||
|
|
||||||
|
var node models.Node
|
||||||
|
err := json.Unmarshal([]byte(value), &node)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if node.Network == network && node.IsServer == "yes" {
|
||||||
|
nodes = append(nodes, node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Sort(models.NodesArray(nodes))
|
||||||
|
return nodes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPeers(node models.Node) ([]models.Node, error) {
|
||||||
|
if node.IsServer == "yes" && IsLeader(&node) {
|
||||||
|
SetNetworkServerPeers(&node)
|
||||||
|
}
|
||||||
|
excludeIsRelayed := node.IsRelay != "yes"
|
||||||
|
var relayedNode string
|
||||||
|
if node.IsRelayed == "yes" {
|
||||||
|
relayedNode = node.Address
|
||||||
|
}
|
||||||
|
peers, err := GetPeersList(node.Network, excludeIsRelayed, relayedNode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return peers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsLeader(node *models.Node) bool {
|
||||||
|
nodes, err := GetSortedNetworkServerNodes(node.Network)
|
||||||
|
if err != nil {
|
||||||
|
functions.PrintUserLog("[netmaker]", "ERROR: COULD NOT RETRIEVE SERVER NODES. THIS WILL BREAK HOLE PUNCHING.", 0)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, n := range nodes {
|
||||||
|
if n.LastModified > time.Now().Add(-1*time.Minute).Unix() {
|
||||||
|
return n.Address == node.Address
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len(nodes) <= 1 || nodes[1].Address == node.Address
|
||||||
|
}
|
285
logic/util.go
Normal file
285
logic/util.go
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
// package for logicing client and server code
|
||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"encoding/base64"
|
||||||
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/dnslogic"
|
||||||
|
"github.com/gravitl/netmaker/functions"
|
||||||
|
"github.com/gravitl/netmaker/models"
|
||||||
|
"github.com/gravitl/netmaker/relay"
|
||||||
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
//This is used to validate public keys (make sure they're base64 encoded like all public keys should be).
|
||||||
|
func IsBase64(s string) bool {
|
||||||
|
_, err := base64.StdEncoding.DecodeString(s)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckEndpoint(endpoint string) bool {
|
||||||
|
endpointarr := strings.Split(endpoint, ":")
|
||||||
|
return len(endpointarr) == 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetNetworkServerPeers(node *models.Node) {
|
||||||
|
if currentPeersList, err := GetSystemPeers(node); err == nil {
|
||||||
|
if database.SetPeers(currentPeersList, node.Network) {
|
||||||
|
functions.PrintUserLog(models.NODE_SERVER_NAME, "set new peers on network "+node.Network, 1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
functions.PrintUserLog(models.NODE_SERVER_NAME, "could not set peers on network "+node.Network, 1)
|
||||||
|
functions.PrintUserLog(models.NODE_SERVER_NAME, err.Error(), 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func DeleteNode(key string, exterminate bool) error {
|
||||||
|
var err error
|
||||||
|
if !exterminate {
|
||||||
|
args := strings.Split(key, "###")
|
||||||
|
node, err := GetNode(args[0], args[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
node.Action = models.NODE_DELETE
|
||||||
|
nodedata, err := json.Marshal(&node)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = database.Insert(key, string(nodedata), database.DELETED_NODES_TABLE_NAME)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := database.DeleteRecord(database.DELETED_NODES_TABLE_NAME, key); err != nil {
|
||||||
|
functions.PrintUserLog("", err.Error(), 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if servercfg.IsDNSMode() {
|
||||||
|
err = dnslogic.SetDNS()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func CreateNode(node models.Node, networkName string) (models.Node, error) {
|
||||||
|
|
||||||
|
//encrypt that password so we never see it
|
||||||
|
hash, err := bcrypt.GenerateFromPassword([]byte(node.Password), 5)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
//set password to encrypted password
|
||||||
|
node.Password = string(hash)
|
||||||
|
|
||||||
|
node.Network = networkName
|
||||||
|
if node.Name == models.NODE_SERVER_NAME {
|
||||||
|
node.IsServer = "yes"
|
||||||
|
}
|
||||||
|
if servercfg.IsDNSMode() && node.DNSOn == "" {
|
||||||
|
node.DNSOn = "yes"
|
||||||
|
}
|
||||||
|
node.SetDefaults()
|
||||||
|
node.Address, err = functions.UniqueAddress(networkName)
|
||||||
|
if err != nil {
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
node.Address6, err = functions.UniqueAddress6(networkName)
|
||||||
|
if err != nil {
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
//Create a JWT for the node
|
||||||
|
tokenString, _ := functions.CreateJWT(node.MacAddress, networkName)
|
||||||
|
if tokenString == "" {
|
||||||
|
//returnErrorResponse(w, r, errorResponse)
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
err = node.Validate(false)
|
||||||
|
if err != nil {
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
key, err := functions.GetRecordKey(node.MacAddress, node.Network)
|
||||||
|
if err != nil {
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
nodebytes, err := json.Marshal(&node)
|
||||||
|
if err != nil {
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
err = database.Insert(key, string(nodebytes), database.NODES_TABLE_NAME)
|
||||||
|
if err != nil {
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
if node.IsPending != "yes" {
|
||||||
|
functions.DecrimentKey(node.Network, node.AccessKey)
|
||||||
|
}
|
||||||
|
SetNetworkNodesLastModified(node.Network)
|
||||||
|
if servercfg.IsDNSMode() {
|
||||||
|
err = dnslogic.SetDNS()
|
||||||
|
}
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetNetworkNodesLastModified(networkName string) error {
|
||||||
|
|
||||||
|
timestamp := time.Now().Unix()
|
||||||
|
|
||||||
|
network, err := functions.GetParentNetwork(networkName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
network.NodesLastModified = timestamp
|
||||||
|
data, err := json.Marshal(&network)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = database.Insert(networkName, string(data), database.NETWORKS_TABLE_NAME)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetNode(macaddress string, network string) (models.Node, error) {
|
||||||
|
var node models.Node
|
||||||
|
|
||||||
|
key, err := functions.GetRecordKey(macaddress, network)
|
||||||
|
if err != nil {
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
data, err := database.FetchRecord(database.NODES_TABLE_NAME, key)
|
||||||
|
if err != nil {
|
||||||
|
if data == "" {
|
||||||
|
data, err = database.FetchRecord(database.DELETED_NODES_TABLE_NAME, key)
|
||||||
|
err = json.Unmarshal([]byte(data), &node)
|
||||||
|
}
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
if err = json.Unmarshal([]byte(data), &node); err != nil {
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
node.SetDefaults()
|
||||||
|
|
||||||
|
return node, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error) {
|
||||||
|
var peers []models.Node
|
||||||
|
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
||||||
|
if err != nil {
|
||||||
|
if database.IsEmptyRecord(err) {
|
||||||
|
return peers, nil
|
||||||
|
}
|
||||||
|
functions.PrintUserLog("", err.Error(), 2)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
udppeers, errN := database.GetPeers(networkName)
|
||||||
|
if errN != nil {
|
||||||
|
functions.PrintUserLog("", errN.Error(), 2)
|
||||||
|
}
|
||||||
|
for _, value := range collection {
|
||||||
|
var node models.Node
|
||||||
|
var peer models.Node
|
||||||
|
err := json.Unmarshal([]byte(value), &node)
|
||||||
|
if err != nil {
|
||||||
|
functions.PrintUserLog("", err.Error(), 2)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if node.IsEgressGateway == "yes" { // handle egress stuff
|
||||||
|
peer.EgressGatewayRanges = node.EgressGatewayRanges
|
||||||
|
peer.IsEgressGateway = node.IsEgressGateway
|
||||||
|
}
|
||||||
|
allow := node.IsRelayed != "yes" || !excludeRelayed
|
||||||
|
|
||||||
|
if node.Network == networkName && node.IsPending != "yes" && allow {
|
||||||
|
peer = setPeerInfo(node)
|
||||||
|
if node.UDPHolePunch == "yes" && errN == nil && CheckEndpoint(udppeers[node.PublicKey]) {
|
||||||
|
endpointstring := udppeers[node.PublicKey]
|
||||||
|
endpointarr := strings.Split(endpointstring, ":")
|
||||||
|
if len(endpointarr) == 2 {
|
||||||
|
port, err := strconv.Atoi(endpointarr[1])
|
||||||
|
if err == nil {
|
||||||
|
peer.Endpoint = endpointarr[0]
|
||||||
|
peer.ListenPort = int32(port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if node.IsRelay == "yes" {
|
||||||
|
network, err := models.GetNetwork(networkName)
|
||||||
|
if err == nil {
|
||||||
|
peer.AllowedIPs = append(peer.AllowedIPs, network.AddressRange)
|
||||||
|
} else {
|
||||||
|
peer.AllowedIPs = append(peer.AllowedIPs, node.RelayAddrs...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
peers = append(peers, peer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return peers, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPeersList(networkName string, excludeRelayed bool, relayedNodeAddr string) ([]models.Node, error) {
|
||||||
|
var peers []models.Node
|
||||||
|
var relayNode models.Node
|
||||||
|
var err error
|
||||||
|
if relayedNodeAddr == "" {
|
||||||
|
peers, err = GetNodePeers(networkName, excludeRelayed)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
relayNode, err = relay.GetNodeRelay(networkName, relayedNodeAddr)
|
||||||
|
if relayNode.Address != "" {
|
||||||
|
relayNode = setPeerInfo(relayNode)
|
||||||
|
network, err := models.GetNetwork(networkName)
|
||||||
|
if err == nil {
|
||||||
|
relayNode.AllowedIPs = append(relayNode.AllowedIPs, network.AddressRange)
|
||||||
|
} else {
|
||||||
|
relayNode.AllowedIPs = append(relayNode.AllowedIPs, relayNode.RelayAddrs...)
|
||||||
|
}
|
||||||
|
nodepeers, err := GetNodePeers(networkName, false)
|
||||||
|
if err == nil && relayNode.UDPHolePunch == "yes" {
|
||||||
|
for _, nodepeer := range nodepeers {
|
||||||
|
if nodepeer.Address == relayNode.Address {
|
||||||
|
relayNode.Endpoint = nodepeer.Endpoint
|
||||||
|
relayNode.ListenPort = nodepeer.ListenPort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
peers = append(peers, relayNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return peers, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func setPeerInfo(node models.Node) models.Node {
|
||||||
|
var peer models.Node
|
||||||
|
peer.RelayAddrs = node.RelayAddrs
|
||||||
|
peer.IsRelay = node.IsRelay
|
||||||
|
peer.IsServer = node.IsServer
|
||||||
|
peer.IsRelayed = node.IsRelayed
|
||||||
|
peer.PublicKey = node.PublicKey
|
||||||
|
peer.Endpoint = node.Endpoint
|
||||||
|
peer.LocalAddress = node.LocalAddress
|
||||||
|
peer.ListenPort = node.ListenPort
|
||||||
|
peer.AllowedIPs = node.AllowedIPs
|
||||||
|
peer.UDPHolePunch = node.UDPHolePunch
|
||||||
|
peer.Address = node.Address
|
||||||
|
peer.Address6 = node.Address6
|
||||||
|
peer.EgressGatewayRanges = node.EgressGatewayRanges
|
||||||
|
peer.IsEgressGateway = node.IsEgressGateway
|
||||||
|
peer.IngressGatewayRange = node.IngressGatewayRange
|
||||||
|
peer.IsIngressGateway = node.IsIngressGateway
|
||||||
|
peer.IsPending = node.IsPending
|
||||||
|
return peer
|
||||||
|
}
|
25
logic/wireguard.go
Normal file
25
logic/wireguard.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gravitl/netmaker/models"
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetSystemPeers(node *models.Node) (map[string]string, error) {
|
||||||
|
peers := make(map[string]string)
|
||||||
|
|
||||||
|
client, err := wgctrl.New()
|
||||||
|
if err != nil {
|
||||||
|
return peers, err
|
||||||
|
}
|
||||||
|
device, err := client.Device(node.Interface)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, peer := range device.Peers {
|
||||||
|
if IsBase64(peer.PublicKey.String()) && peer.Endpoint != nil && CheckEndpoint(peer.Endpoint.String()) {
|
||||||
|
peers[peer.PublicKey.String()] = peer.Endpoint.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return peers, nil
|
||||||
|
}
|
7
main.go
7
main.go
@@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
controller "github.com/gravitl/netmaker/controllers"
|
controller "github.com/gravitl/netmaker/controllers"
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/dnslogic"
|
||||||
"github.com/gravitl/netmaker/functions"
|
"github.com/gravitl/netmaker/functions"
|
||||||
nodepb "github.com/gravitl/netmaker/grpc"
|
nodepb "github.com/gravitl/netmaker/grpc"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
@@ -81,14 +82,13 @@ func startControllers() {
|
|||||||
go runGRPC(&waitnetwork)
|
go runGRPC(&waitnetwork)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the client in goroutine locally if CLIENT_MODE is "contained"
|
if servercfg.IsClientMode() == "on" {
|
||||||
if servercfg.IsClientMode() == "contained" {
|
|
||||||
waitnetwork.Add(1)
|
waitnetwork.Add(1)
|
||||||
go runClient(&waitnetwork)
|
go runClient(&waitnetwork)
|
||||||
}
|
}
|
||||||
|
|
||||||
if servercfg.IsDNSMode() {
|
if servercfg.IsDNSMode() {
|
||||||
err := controller.SetDNS()
|
err := dnslogic.SetDNS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("error occurred initializing DNS:", err)
|
log.Println("error occurred initializing DNS:", err)
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,6 @@ func startControllers() {
|
|||||||
|
|
||||||
func runClient(wg *sync.WaitGroup) {
|
func runClient(wg *sync.WaitGroup) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
log.Println("CLIENT_MODE running as contained")
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
if err := serverctl.HandleContainedClient(); err != nil {
|
if err := serverctl.HandleContainedClient(); err != nil {
|
||||||
|
@@ -7,7 +7,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"bytes"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
@@ -76,6 +76,18 @@ type Node struct {
|
|||||||
MTU int32 `json:"mtu" bson:"mtu" yaml:"mtu"`
|
MTU int32 `json:"mtu" bson:"mtu" yaml:"mtu"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NodesArray []Node
|
||||||
|
|
||||||
|
func (a NodesArray) Len() int { return len(a) }
|
||||||
|
func (a NodesArray) Less(i, j int) bool { return isLess(a[i].Address, a[j].Address) }
|
||||||
|
func (a NodesArray) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
|
||||||
|
func isLess(ipA string, ipB string) bool {
|
||||||
|
ipNetA := net.ParseIP(ipA)
|
||||||
|
ipNetB := net.ParseIP(ipB)
|
||||||
|
return bytes.Compare(ipNetA, ipNetB) < 0
|
||||||
|
}
|
||||||
|
|
||||||
func (node *Node) SetDefaultMTU() {
|
func (node *Node) SetDefaultMTU() {
|
||||||
if node.MTU == 0 {
|
if node.MTU == 0 {
|
||||||
node.MTU = 1280
|
node.MTU = 1280
|
||||||
@@ -263,9 +275,12 @@ func (node *Node) SetDefaults() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// == Parent Network settings ==
|
// == Parent Network settings ==
|
||||||
node.CheckInInterval = parentNetwork.DefaultCheckInInterval
|
if node.IsDualStack == "" {
|
||||||
node.IsDualStack = parentNetwork.IsDualStack
|
node.IsDualStack = parentNetwork.IsDualStack
|
||||||
|
}
|
||||||
|
if node.MTU == 0 {
|
||||||
node.MTU = parentNetwork.DefaultMTU
|
node.MTU = parentNetwork.DefaultMTU
|
||||||
|
}
|
||||||
// == node defaults if not set by parent ==
|
// == node defaults if not set by parent ==
|
||||||
node.SetIPForwardingDefault()
|
node.SetIPForwardingDefault()
|
||||||
node.SetDNSOnDefault()
|
node.SetDNSOnDefault()
|
||||||
@@ -535,9 +550,9 @@ func GetAllNodes() ([]Node, error) {
|
|||||||
return nodes, nil
|
return nodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetID(macaddress string, network string) (string, error) {
|
func (node *Node) GetID() (string, error) {
|
||||||
if macaddress == "" || network == "" {
|
if node.MacAddress == "" || node.Network == "" {
|
||||||
return "", errors.New("unable to get record key")
|
return "", errors.New("unable to get record key")
|
||||||
}
|
}
|
||||||
return macaddress + "###" + network, nil
|
return node.MacAddress + "###" + node.Network, nil
|
||||||
}
|
}
|
||||||
|
@@ -58,7 +58,7 @@ func Join(cfg config.ClientConfig, privateKey string) error {
|
|||||||
|
|
||||||
func getWindowsInterval() int {
|
func getWindowsInterval() int {
|
||||||
interval := 15
|
interval := 15
|
||||||
networks, err := functions.GetNetworks()
|
networks, err := ncutils.GetSystemNetworks()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return interval
|
return interval
|
||||||
}
|
}
|
||||||
@@ -90,12 +90,13 @@ func RunUserspaceDaemon() {
|
|||||||
|
|
||||||
func CheckIn(cfg config.ClientConfig) error {
|
func CheckIn(cfg config.ClientConfig) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if cfg.Network == "" {
|
if cfg.Network == "" {
|
||||||
ncutils.PrintLog("required, '-n', exiting", 0)
|
ncutils.PrintLog("required, '-n', exiting", 0)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
} else if cfg.Network == "all" {
|
} else if cfg.Network == "all" {
|
||||||
ncutils.PrintLog("running checkin for all networks", 1)
|
ncutils.PrintLog("running checkin for all networks", 1)
|
||||||
networks, err := functions.GetNetworks()
|
networks, err := ncutils.GetSystemNetworks()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ncutils.PrintLog("error retrieving networks, exiting", 1)
|
ncutils.PrintLog("error retrieving networks, exiting", 1)
|
||||||
return err
|
return err
|
||||||
@@ -138,7 +139,7 @@ func Push(cfg config.ClientConfig) error {
|
|||||||
var err error
|
var err error
|
||||||
if cfg.Network == "all" || ncutils.IsWindows() {
|
if cfg.Network == "all" || ncutils.IsWindows() {
|
||||||
ncutils.PrintLog("pushing config to server for all networks.", 0)
|
ncutils.PrintLog("pushing config to server for all networks.", 0)
|
||||||
networks, err := functions.GetNetworks()
|
networks, err := ncutils.GetSystemNetworks()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ncutils.PrintLog("error retrieving networks, exiting.", 0)
|
ncutils.PrintLog("error retrieving networks, exiting.", 0)
|
||||||
return err
|
return err
|
||||||
@@ -164,7 +165,7 @@ func Pull(cfg config.ClientConfig) error {
|
|||||||
var err error
|
var err error
|
||||||
if cfg.Network == "all" {
|
if cfg.Network == "all" {
|
||||||
ncutils.PrintLog("No network selected. Running Pull for all networks.", 0)
|
ncutils.PrintLog("No network selected. Running Pull for all networks.", 0)
|
||||||
networks, err := functions.GetNetworks()
|
networks, err := ncutils.GetSystemNetworks()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ncutils.PrintLog("Error retrieving networks. Exiting.", 1)
|
ncutils.PrintLog("Error retrieving networks. Exiting.", 1)
|
||||||
return err
|
return err
|
||||||
|
@@ -1,12 +1,15 @@
|
|||||||
package functions
|
package functions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
nodepb "github.com/gravitl/netmaker/grpc"
|
nodepb "github.com/gravitl/netmaker/grpc"
|
||||||
|
"github.com/gravitl/netmaker/logic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/auth"
|
"github.com/gravitl/netmaker/netclient/auth"
|
||||||
"github.com/gravitl/netmaker/netclient/config"
|
"github.com/gravitl/netmaker/netclient/config"
|
||||||
@@ -136,7 +139,6 @@ func CheckConfig(cliconf config.ClientConfig) error {
|
|||||||
if newNode.IsPending == "yes" {
|
if newNode.IsPending == "yes" {
|
||||||
return errors.New("node is pending")
|
return errors.New("node is pending")
|
||||||
}
|
}
|
||||||
|
|
||||||
actionCompleted := checkNodeActions(newNode, network, servercfg, ¤tNode, cfg)
|
actionCompleted := checkNodeActions(newNode, network, servercfg, ¤tNode, cfg)
|
||||||
if actionCompleted == models.NODE_DELETE {
|
if actionCompleted == models.NODE_DELETE {
|
||||||
return errors.New("node has been removed")
|
return errors.New("node has been removed")
|
||||||
@@ -164,6 +166,9 @@ func Pull(network string, manual bool) (*models.Node, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var resNode models.Node // just need to fill this with either server calls or client calls
|
||||||
|
var ctx context.Context
|
||||||
|
if cfg.Node.IsServer != "yes" {
|
||||||
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
|
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
|
||||||
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
|
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -187,10 +192,15 @@ func Pull(network string, manual bool) (*models.Node, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var resNode models.Node
|
|
||||||
if err = json.Unmarshal([]byte(readres.Data), &resNode); err != nil {
|
if err = json.Unmarshal([]byte(readres.Data), &resNode); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
} else { // handle server side read
|
||||||
|
resNode, err = logic.GetNode(node.MacAddress, node.Network)
|
||||||
|
if err != nil && !ncutils.IsEmptyRecord(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
// ensure that the OS never changes
|
// ensure that the OS never changes
|
||||||
resNode.OS = runtime.GOOS
|
resNode.OS = runtime.GOOS
|
||||||
if resNode.PullChanges == "yes" || manual {
|
if resNode.PullChanges == "yes" || manual {
|
||||||
@@ -211,6 +221,7 @@ func Pull(network string, manual bool) (*models.Node, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return &resNode, err
|
return &resNode, err
|
||||||
}
|
}
|
||||||
|
if resNode.IsServer != "yes" {
|
||||||
req := &nodepb.Object{
|
req := &nodepb.Object{
|
||||||
Data: string(nodeData),
|
Data: string(nodeData),
|
||||||
Type: nodepb.NODE_TYPE,
|
Type: nodepb.NODE_TYPE,
|
||||||
@@ -220,6 +231,11 @@ func Pull(network string, manual bool) (*models.Node, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return &resNode, err
|
return &resNode, err
|
||||||
}
|
}
|
||||||
|
} else { // handle server side update
|
||||||
|
if err = resNode.Update(&resNode); err != nil {
|
||||||
|
return &resNode, err
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if err = wireguard.SetWGConfig(network, true); err != nil {
|
if err = wireguard.SetWGConfig(network, true); err != nil {
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
@@ -244,8 +260,10 @@ func Push(network string) error {
|
|||||||
postnode := cfg.Node
|
postnode := cfg.Node
|
||||||
// always set the OS on client
|
// always set the OS on client
|
||||||
postnode.OS = runtime.GOOS
|
postnode.OS = runtime.GOOS
|
||||||
var header metadata.MD
|
postnode.SetLastCheckIn()
|
||||||
|
|
||||||
|
if postnode.IsServer != "yes" { // handle client side
|
||||||
|
var header metadata.MD
|
||||||
var wcclient nodepb.NodeServiceClient
|
var wcclient nodepb.NodeServiceClient
|
||||||
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
|
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
|
||||||
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
|
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
|
||||||
@@ -274,7 +292,6 @@ func Push(network string) error {
|
|||||||
postnode.PublicKey = privateKeyWG.PublicKey().String()
|
postnode.PublicKey = privateKeyWG.PublicKey().String()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
postnode.SetLastCheckIn()
|
|
||||||
nodeData, err := json.Marshal(&postnode)
|
nodeData, err := json.Marshal(&postnode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -293,6 +310,11 @@ func Push(network string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if err = postnode.Update(&postnode); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
err = config.ModConfig(&postnode)
|
err = config.ModConfig(&postnode)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
@@ -13,6 +12,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
nodepb "github.com/gravitl/netmaker/grpc"
|
nodepb "github.com/gravitl/netmaker/grpc"
|
||||||
|
"github.com/gravitl/netmaker/logic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/auth"
|
"github.com/gravitl/netmaker/netclient/auth"
|
||||||
"github.com/gravitl/netmaker/netclient/config"
|
"github.com/gravitl/netmaker/netclient/config"
|
||||||
@@ -138,7 +138,7 @@ func GetNode(network string) models.Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Uninstall() error {
|
func Uninstall() error {
|
||||||
networks, err := GetNetworks()
|
networks, err := ncutils.GetSystemNetworks()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ncutils.PrintLog("unable to retrieve networks: "+err.Error(), 1)
|
ncutils.PrintLog("unable to retrieve networks: "+err.Error(), 1)
|
||||||
ncutils.PrintLog("continuing uninstall without leaving networks", 1)
|
ncutils.PrintLog("continuing uninstall without leaving networks", 1)
|
||||||
@@ -163,7 +163,6 @@ func Uninstall() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func LeaveNetwork(network string) error {
|
func LeaveNetwork(network string) error {
|
||||||
//need to implement checkin on server side
|
|
||||||
cfg, err := config.ReadConfig(network)
|
cfg, err := config.ReadConfig(network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -171,19 +170,20 @@ func LeaveNetwork(network string) error {
|
|||||||
servercfg := cfg.Server
|
servercfg := cfg.Server
|
||||||
node := cfg.Node
|
node := cfg.Node
|
||||||
|
|
||||||
|
if node.IsServer != "yes" {
|
||||||
var wcclient nodepb.NodeServiceClient
|
var wcclient nodepb.NodeServiceClient
|
||||||
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
|
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
|
||||||
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
|
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Unable to establish client connection to "+servercfg.GRPCAddress+": %v", err)
|
log.Printf("Unable to establish client connection to "+servercfg.GRPCAddress+": %v", err)
|
||||||
} else {
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
wcclient = nodepb.NewNodeServiceClient(conn)
|
wcclient = nodepb.NewNodeServiceClient(conn)
|
||||||
|
|
||||||
ctx, err := auth.SetJWT(wcclient, network)
|
ctx, err := auth.SetJWT(wcclient, network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to authenticate: %v", err)
|
log.Printf("Failed to authenticate: %v", err)
|
||||||
} else {
|
} else { // handle client side
|
||||||
node.SetID()
|
node.SetID()
|
||||||
var header metadata.MD
|
var header metadata.MD
|
||||||
_, err = wcclient.DeleteNode(
|
_, err = wcclient.DeleteNode(
|
||||||
@@ -200,6 +200,13 @@ func LeaveNetwork(network string) error {
|
|||||||
ncutils.PrintLog("removed machine from "+node.Network+" network on remote server", 1)
|
ncutils.PrintLog("removed machine from "+node.Network+" network on remote server", 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else { // handle server side
|
||||||
|
node.SetID()
|
||||||
|
if err = logic.DeleteNode(node.ID, true); err != nil {
|
||||||
|
ncutils.PrintLog("error removing server on network "+node.Network, 1)
|
||||||
|
} else {
|
||||||
|
ncutils.PrintLog("removed netmaker server instance on "+node.Network, 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return RemoveLocalInstance(cfg, network)
|
return RemoveLocalInstance(cfg, network)
|
||||||
}
|
}
|
||||||
@@ -244,7 +251,7 @@ func DeleteInterface(ifacename string, postdown string) error {
|
|||||||
|
|
||||||
func List() error {
|
func List() error {
|
||||||
|
|
||||||
networks, err := GetNetworks()
|
networks, err := ncutils.GetSystemNetworks()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -267,34 +274,6 @@ func List() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetNetworks() ([]string, error) {
|
|
||||||
var networks []string
|
|
||||||
files, err := ioutil.ReadDir(ncutils.GetNetclientPathSpecific())
|
|
||||||
if err != nil {
|
|
||||||
return networks, err
|
|
||||||
}
|
|
||||||
for _, f := range files {
|
|
||||||
if strings.Contains(f.Name(), "netconfig-") {
|
|
||||||
networkname := stringAfter(f.Name(), "netconfig-")
|
|
||||||
networks = append(networks, networkname)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return networks, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringAfter(original string, substring string) string {
|
|
||||||
position := strings.LastIndex(original, substring)
|
|
||||||
if position == -1 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
adjustedPosition := position + len(substring)
|
|
||||||
|
|
||||||
if adjustedPosition >= len(original) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return original[adjustedPosition:len(original)]
|
|
||||||
}
|
|
||||||
|
|
||||||
func WipeLocal(network string) error {
|
func WipeLocal(network string) error {
|
||||||
cfg, err := config.ReadConfig(network)
|
cfg, err := config.ReadConfig(network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -302,7 +281,6 @@ func WipeLocal(network string) error {
|
|||||||
}
|
}
|
||||||
nodecfg := cfg.Node
|
nodecfg := cfg.Node
|
||||||
ifacename := nodecfg.Interface
|
ifacename := nodecfg.Interface
|
||||||
|
|
||||||
if ifacename != "" {
|
if ifacename != "" {
|
||||||
if !ncutils.IsKernel() {
|
if !ncutils.IsKernel() {
|
||||||
if err = wireguard.RemoveConf(ifacename, true); err == nil {
|
if err = wireguard.RemoveConf(ifacename, true); err == nil {
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
|
|
||||||
nodepb "github.com/gravitl/netmaker/grpc"
|
nodepb "github.com/gravitl/netmaker/grpc"
|
||||||
|
"github.com/gravitl/netmaker/logic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/auth"
|
"github.com/gravitl/netmaker/netclient/auth"
|
||||||
"github.com/gravitl/netmaker/netclient/config"
|
"github.com/gravitl/netmaker/netclient/config"
|
||||||
@@ -28,7 +29,6 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ncutils.Log("joining " + cfg.Network + " at " + cfg.Server.GRPCAddress)
|
|
||||||
err := config.Write(&cfg, cfg.Network)
|
err := config.Write(&cfg, cfg.Network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -53,7 +53,6 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
|
|||||||
cfg.Node.Endpoint = cfg.Node.LocalAddress
|
cfg.Node.Endpoint = cfg.Node.LocalAddress
|
||||||
} else {
|
} else {
|
||||||
cfg.Node.Endpoint, err = ncutils.GetPublicIP()
|
cfg.Node.Endpoint, err = ncutils.GetPublicIP()
|
||||||
|
|
||||||
}
|
}
|
||||||
if err != nil || cfg.Node.Endpoint == "" {
|
if err != nil || cfg.Node.Endpoint == "" {
|
||||||
ncutils.Log("Error setting cfg.Node.Endpoint.")
|
ncutils.Log("Error setting cfg.Node.Endpoint.")
|
||||||
@@ -82,17 +81,8 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var wcclient nodepb.NodeServiceClient
|
// differentiate between client/server here
|
||||||
|
var node models.Node // fill this node with appropriate calls
|
||||||
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
|
|
||||||
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Unable to establish client connection to "+cfg.Server.GRPCAddress+": %v", err)
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
wcclient = nodepb.NewNodeServiceClient(conn)
|
|
||||||
|
|
||||||
postnode := &models.Node{
|
postnode := &models.Node{
|
||||||
Password: cfg.Node.Password,
|
Password: cfg.Node.Password,
|
||||||
MacAddress: cfg.Node.MacAddress,
|
MacAddress: cfg.Node.MacAddress,
|
||||||
@@ -112,6 +102,19 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
|
|||||||
UDPHolePunch: cfg.Node.UDPHolePunch,
|
UDPHolePunch: cfg.Node.UDPHolePunch,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cfg.Node.IsServer != "yes" {
|
||||||
|
ncutils.Log("joining " + cfg.Network + " at " + cfg.Server.GRPCAddress)
|
||||||
|
var wcclient nodepb.NodeServiceClient
|
||||||
|
|
||||||
|
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
|
||||||
|
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Unable to establish client connection to "+cfg.Server.GRPCAddress+": %v", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
wcclient = nodepb.NewNodeServiceClient(conn)
|
||||||
|
|
||||||
if err = config.ModConfig(postnode); err != nil {
|
if err = config.ModConfig(postnode); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -133,10 +136,23 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
|
|||||||
ncutils.PrintLog("node created on remote server...updating configs", 1)
|
ncutils.PrintLog("node created on remote server...updating configs", 1)
|
||||||
|
|
||||||
nodeData := res.Data
|
nodeData := res.Data
|
||||||
var node models.Node
|
|
||||||
if err = json.Unmarshal([]byte(nodeData), &node); err != nil {
|
if err = json.Unmarshal([]byte(nodeData), &node); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
} else { // handle server side node creation
|
||||||
|
ncutils.Log("adding a server instance on network " + postnode.Network)
|
||||||
|
if err = config.ModConfig(postnode); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
node, err = logic.CreateNode(*postnode, cfg.Network)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = logic.SetNetworkNodesLastModified(node.Network)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get free port based on returned default listen port
|
// get free port based on returned default listen port
|
||||||
node.ListenPort, err = ncutils.GetFreePort(node.ListenPort)
|
node.ListenPort, err = ncutils.GetFreePort(node.ListenPort)
|
||||||
@@ -177,9 +193,8 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ncutils.Log("retrieving remote peers")
|
ncutils.Log("retrieving peers")
|
||||||
peers, hasGateway, gateways, err := server.GetPeers(node.MacAddress, cfg.Network, cfg.Server.GRPCAddress, node.IsDualStack == "yes", node.IsIngressGateway == "yes")
|
peers, hasGateway, gateways, err := server.GetPeers(node.MacAddress, cfg.Network, cfg.Server.GRPCAddress, node.IsDualStack == "yes", node.IsIngressGateway == "yes", node.IsServer == "yes")
|
||||||
|
|
||||||
if err != nil && !ncutils.IsEmptyRecord(err) {
|
if err != nil && !ncutils.IsEmptyRecord(err) {
|
||||||
ncutils.Log("failed to retrieve peers")
|
ncutils.Log("failed to retrieve peers")
|
||||||
return err
|
return err
|
||||||
|
@@ -24,7 +24,7 @@ func main() {
|
|||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Name = "Netclient CLI"
|
app.Name = "Netclient CLI"
|
||||||
app.Usage = "Netmaker's netclient agent and CLI. Used to perform interactions with Netmaker server and set local WireGuard config."
|
app.Usage = "Netmaker's netclient agent and CLI. Used to perform interactions with Netmaker server and set local WireGuard config."
|
||||||
app.Version = "v0.8.1"
|
app.Version = "v0.8.3"
|
||||||
|
|
||||||
cliFlags := []cli.Flag{
|
cliFlags := []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
|
@@ -368,3 +368,31 @@ func PrintLog(message string, loglevel int) {
|
|||||||
log.Println("[netclient]", message)
|
log.Println("[netclient]", message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSystemNetworks() ([]string, error) {
|
||||||
|
var networks []string
|
||||||
|
files, err := ioutil.ReadDir(GetNetclientPathSpecific())
|
||||||
|
if err != nil {
|
||||||
|
return networks, err
|
||||||
|
}
|
||||||
|
for _, f := range files {
|
||||||
|
if strings.Contains(f.Name(), "netconfig-") {
|
||||||
|
networkname := stringAfter(f.Name(), "netconfig-")
|
||||||
|
networks = append(networks, networkname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return networks, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringAfter(original string, substring string) string {
|
||||||
|
position := strings.LastIndex(original, substring)
|
||||||
|
if position == -1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
adjustedPosition := position + len(substring)
|
||||||
|
|
||||||
|
if adjustedPosition >= len(original) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return original[adjustedPosition:len(original)]
|
||||||
|
}
|
@@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
nodepb "github.com/gravitl/netmaker/grpc"
|
nodepb "github.com/gravitl/netmaker/grpc"
|
||||||
|
"github.com/gravitl/netmaker/logic"
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
"github.com/gravitl/netmaker/netclient/auth"
|
"github.com/gravitl/netmaker/netclient/auth"
|
||||||
"github.com/gravitl/netmaker/netclient/config"
|
"github.com/gravitl/netmaker/netclient/config"
|
||||||
@@ -40,6 +41,7 @@ func CheckIn(network string) (*models.Node, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
node := cfg.Node
|
node := cfg.Node
|
||||||
|
if cfg.Node.IsServer != "yes" {
|
||||||
wcclient, err := getGrpcClient(cfg)
|
wcclient, err := getGrpcClient(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -65,6 +67,7 @@ func CheckIn(network string) (*models.Node, error) {
|
|||||||
if err = json.Unmarshal([]byte(response.GetData()), &node); err != nil {
|
if err = json.Unmarshal([]byte(response.GetData()), &node); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return &node, err
|
return &node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,11 +119,11 @@ func RemoveNetwork(network string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
func GetPeers(macaddress string, network string, server string, dualstack bool, isIngressGateway bool) ([]wgtypes.PeerConfig, bool, []string, error) {
|
|
||||||
|
func GetPeers(macaddress string, network string, server string, dualstack bool, isIngressGateway bool, isServer bool) ([]wgtypes.PeerConfig, bool, []string, error) {
|
||||||
hasGateway := false
|
hasGateway := false
|
||||||
var gateways []string
|
var gateways []string
|
||||||
var peers []wgtypes.PeerConfig
|
var peers []wgtypes.PeerConfig
|
||||||
var wcclient nodepb.NodeServiceClient
|
|
||||||
cfg, err := config.ReadConfig(network)
|
cfg, err := config.ReadConfig(network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Issue retrieving config for network: "+network+". Please investigate: %v", err)
|
log.Fatalf("Issue retrieving config for network: "+network+". Please investigate: %v", err)
|
||||||
@@ -132,7 +135,9 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)
|
log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)
|
||||||
}
|
}
|
||||||
|
var nodes []models.Node // fill this either from server or client
|
||||||
|
if !isServer { // set peers client side
|
||||||
|
var wcclient nodepb.NodeServiceClient
|
||||||
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
|
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
|
||||||
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
|
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
|
||||||
|
|
||||||
@@ -161,11 +166,17 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
|
|||||||
log.Println(err)
|
log.Println(err)
|
||||||
return nil, hasGateway, gateways, err
|
return nil, hasGateway, gateways, err
|
||||||
}
|
}
|
||||||
var nodes []models.Node
|
|
||||||
if err := json.Unmarshal([]byte(response.GetData()), &nodes); err != nil {
|
if err := json.Unmarshal([]byte(response.GetData()), &nodes); err != nil {
|
||||||
log.Println("Error unmarshaling data for peers")
|
log.Println("Error unmarshaling data for peers")
|
||||||
return nil, hasGateway, gateways, err
|
return nil, hasGateway, gateways, err
|
||||||
}
|
}
|
||||||
|
} else { // set peers serverside
|
||||||
|
nodes, err = logic.GetPeers(nodecfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, hasGateway, gateways, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
pubkey, err := wgtypes.ParseKey(node.PublicKey)
|
pubkey, err := wgtypes.ParseKey(node.PublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -240,7 +251,7 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
|
|||||||
}
|
}
|
||||||
allowedips = append(allowedips, addr6)
|
allowedips = append(allowedips, addr6)
|
||||||
}
|
}
|
||||||
if nodecfg.IsServer == "yes" {
|
if nodecfg.IsServer == "yes" && !(node.IsServer == "yes"){
|
||||||
peer = wgtypes.PeerConfig{
|
peer = wgtypes.PeerConfig{
|
||||||
PublicKey: pubkey,
|
PublicKey: pubkey,
|
||||||
PersistentKeepaliveInterval: &keepaliveserver,
|
PersistentKeepaliveInterval: &keepaliveserver,
|
||||||
@@ -283,12 +294,15 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
|
|||||||
}
|
}
|
||||||
func GetExtPeers(macaddress string, network string, server string, dualstack bool) ([]wgtypes.PeerConfig, error) {
|
func GetExtPeers(macaddress string, network string, server string, dualstack bool) ([]wgtypes.PeerConfig, error) {
|
||||||
var peers []wgtypes.PeerConfig
|
var peers []wgtypes.PeerConfig
|
||||||
var wcclient nodepb.NodeServiceClient
|
|
||||||
cfg, err := config.ReadConfig(network)
|
cfg, err := config.ReadConfig(network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Issue retrieving config for network: "+network+". Please investigate: %v", err)
|
log.Fatalf("Issue retrieving config for network: "+network+". Please investigate: %v", err)
|
||||||
}
|
}
|
||||||
nodecfg := cfg.Node
|
nodecfg := cfg.Node
|
||||||
|
var extPeers []models.Node
|
||||||
|
if nodecfg.IsServer != "yes" { // fill extPeers with client side logic
|
||||||
|
var wcclient nodepb.NodeServiceClient
|
||||||
|
|
||||||
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
|
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
|
||||||
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
|
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
|
||||||
@@ -317,10 +331,26 @@ func GetExtPeers(macaddress string, network string, server string, dualstack boo
|
|||||||
log.Println(err)
|
log.Println(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var extPeers []models.Node
|
|
||||||
if err = json.Unmarshal([]byte(responseObject.Data), &extPeers); err != nil {
|
if err = json.Unmarshal([]byte(responseObject.Data), &extPeers); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
} else { // fill extPeers with server side logic
|
||||||
|
tempPeers, err := logic.GetExtPeersList(nodecfg.MacAddress, nodecfg.Network)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for i := 0; i < len(tempPeers); i++ {
|
||||||
|
extPeers = append(extPeers, models.Node{
|
||||||
|
Address: tempPeers[i].Address,
|
||||||
|
Address6: tempPeers[i].Address6,
|
||||||
|
Endpoint: tempPeers[i].Endpoint,
|
||||||
|
PublicKey: tempPeers[i].PublicKey,
|
||||||
|
PersistentKeepalive: tempPeers[i].KeepAlive,
|
||||||
|
ListenPort: tempPeers[i].ListenPort,
|
||||||
|
LocalAddress: tempPeers[i].LocalAddress,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, extPeer := range extPeers {
|
for _, extPeer := range extPeers {
|
||||||
pubkey, err := wgtypes.ParseKey(extPeer.PublicKey)
|
pubkey, err := wgtypes.ParseKey(extPeer.PublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -267,7 +267,7 @@ func SetWGConfig(network string, peerupdate bool) error {
|
|||||||
servercfg := cfg.Server
|
servercfg := cfg.Server
|
||||||
nodecfg := cfg.Node
|
nodecfg := cfg.Node
|
||||||
|
|
||||||
peers, hasGateway, gateways, err := server.GetPeers(nodecfg.MacAddress, nodecfg.Network, servercfg.GRPCAddress, nodecfg.IsDualStack == "yes", nodecfg.IsIngressGateway == "yes")
|
peers, hasGateway, gateways, err := server.GetPeers(nodecfg.MacAddress, nodecfg.Network, servercfg.GRPCAddress, nodecfg.IsDualStack == "yes", nodecfg.IsIngressGateway == "yes", nodecfg.IsServer == "yes")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
37
relay/relay.go
Normal file
37
relay/relay.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package relay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/gravitl/netmaker/database"
|
||||||
|
"github.com/gravitl/netmaker/functions"
|
||||||
|
"github.com/gravitl/netmaker/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetNodeRelay(network string, relayedNodeAddr string) (models.Node, error) {
|
||||||
|
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
|
||||||
|
var relay models.Node
|
||||||
|
if err != nil {
|
||||||
|
if database.IsEmptyRecord(err) {
|
||||||
|
return relay, nil
|
||||||
|
}
|
||||||
|
functions.PrintUserLog("", err.Error(), 2)
|
||||||
|
return relay, err
|
||||||
|
}
|
||||||
|
for _, value := range collection {
|
||||||
|
err := json.Unmarshal([]byte(value), &relay)
|
||||||
|
if err != nil {
|
||||||
|
functions.PrintUserLog("", err.Error(), 2)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if relay.IsRelay == "yes" {
|
||||||
|
for _, addr := range relay.RelayAddrs {
|
||||||
|
if addr == relayedNodeAddr {
|
||||||
|
return relay, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return relay, errors.New("could not find relay for node " + relayedNodeAddr)
|
||||||
|
}
|
@@ -74,7 +74,7 @@ func GetAPIConnString() string {
|
|||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
func GetVersion() string {
|
func GetVersion() string {
|
||||||
version := "0.8.1"
|
version := "0.8.3"
|
||||||
if config.Config.Server.Version != "" {
|
if config.Config.Server.Version != "" {
|
||||||
version = config.Config.Server.Version
|
version = config.Config.Server.Version
|
||||||
}
|
}
|
||||||
|
@@ -6,11 +6,11 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"github.com/gravitl/netmaker/database"
|
"github.com/gravitl/netmaker/database"
|
||||||
"github.com/gravitl/netmaker/functions"
|
|
||||||
"github.com/gravitl/netmaker/models"
|
"github.com/gravitl/netmaker/models"
|
||||||
|
nccommand "github.com/gravitl/netmaker/netclient/command"
|
||||||
|
"github.com/gravitl/netmaker/netclient/config"
|
||||||
"github.com/gravitl/netmaker/netclient/ncutils"
|
"github.com/gravitl/netmaker/netclient/ncutils"
|
||||||
"github.com/gravitl/netmaker/servercfg"
|
"github.com/gravitl/netmaker/servercfg"
|
||||||
)
|
)
|
||||||
@@ -91,18 +91,8 @@ func copy(src, dst string) (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RemoveNetwork(network string) (bool, error) {
|
func RemoveNetwork(network string) (bool, error) {
|
||||||
netclientPath := ncutils.GetNetclientPath()
|
err := nccommand.Leave(config.ClientConfig{Network: network})
|
||||||
_, err := os.Stat(netclientPath + "/netclient")
|
|
||||||
if err != nil {
|
|
||||||
log.Println("could not find " + netclientPath + "/netclient")
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
_, err = ncutils.RunCmd(netclientPath+"/netclient leave -n "+network, true)
|
|
||||||
if err == nil {
|
|
||||||
log.Println("Server removed from network " + network)
|
|
||||||
}
|
|
||||||
return true, err
|
return true, err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitServerNetclient() error {
|
func InitServerNetclient() error {
|
||||||
@@ -114,82 +104,89 @@ func InitServerNetclient() error {
|
|||||||
log.Println("could not find or create", netclientDir)
|
log.Println("could not find or create", netclientDir)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = os.Stat(netclientDir + "/netclient")
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
err = InstallNetclient()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = os.Chmod(netclientDir+"/netclient", 0755)
|
|
||||||
if err != nil {
|
|
||||||
log.Println("could not change netclient binary permissions")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleContainedClient() error {
|
func HandleContainedClient() error {
|
||||||
|
servernets, err := models.GetNetworks()
|
||||||
|
if err != nil && !database.IsEmptyRecord(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(servernets) > 0 {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
log.SetFlags(log.Flags() &^ (log.Llongfile | log.Lshortfile))
|
log.SetFlags(log.Flags() &^ (log.Llongfile | log.Lshortfile))
|
||||||
|
err := SyncNetworks(servernets)
|
||||||
netclientPath := ncutils.GetNetclientPath()
|
if err != nil && servercfg.GetVerbose() >= 1 {
|
||||||
checkinCMD := exec.Command(netclientPath+"/netclient", "checkin", "-n", "all")
|
log.Printf("[server netclient] error syncing networks %s \n", err)
|
||||||
if servercfg.GetVerbose() >= 2 {
|
|
||||||
checkinCMD.Stdout = os.Stdout
|
|
||||||
}
|
|
||||||
checkinCMD.Stderr = os.Stderr
|
|
||||||
err := checkinCMD.Start()
|
|
||||||
if err != nil {
|
|
||||||
if servercfg.GetVerbose() >= 2 {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = checkinCMD.Wait()
|
|
||||||
if err != nil {
|
|
||||||
if servercfg.GetVerbose() >= 2 {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
}
|
||||||
|
err = nccommand.CheckIn(config.ClientConfig{Network: "all"})
|
||||||
|
if err != nil && servercfg.GetVerbose() >= 1 {
|
||||||
|
log.Printf("[server netclient] error occurred %s \n", err)
|
||||||
}
|
}
|
||||||
if servercfg.GetVerbose() >= 3 {
|
if servercfg.GetVerbose() >= 3 {
|
||||||
log.Println("[server netclient]", "completed a checkin call")
|
log.Println("[server netclient]", "completed a checkin call")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SyncNetworks(servernets []models.Network) error {
|
||||||
|
|
||||||
|
localnets, err := ncutils.GetSystemNetworks()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// check networks to join
|
||||||
|
for _, servernet := range servernets {
|
||||||
|
exists := false
|
||||||
|
for _, localnet := range localnets {
|
||||||
|
if servernet.NetID == localnet {
|
||||||
|
exists = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
success, err := AddNetwork(servernet.NetID)
|
||||||
|
if err != nil || !success {
|
||||||
|
if err == nil {
|
||||||
|
err = errors.New("network add failed for " + servernet.NetID)
|
||||||
|
}
|
||||||
|
log.Printf("[server] error adding network %s during sync %s \n", servernet.NetID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check networks to leave
|
||||||
|
for _, localnet := range localnets {
|
||||||
|
exists := false
|
||||||
|
for _, servernet := range servernets {
|
||||||
|
if servernet.NetID == localnet {
|
||||||
|
exists = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !exists {
|
||||||
|
success, err := RemoveNetwork(localnet)
|
||||||
|
if err != nil || !success {
|
||||||
|
if err == nil {
|
||||||
|
err = errors.New("network delete failed for " + localnet)
|
||||||
|
}
|
||||||
|
log.Printf("[server] error removing network %s during sync %s \n", localnet, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddNetwork(network string) (bool, error) {
|
func AddNetwork(network string) (bool, error) {
|
||||||
pubip, err := servercfg.GetPublicIP()
|
err := nccommand.Join(config.ClientConfig{
|
||||||
if err != nil {
|
Network: network,
|
||||||
log.Println("could not get public IP.")
|
Daemon: "off",
|
||||||
return false, err
|
Node: models.Node{
|
||||||
}
|
Network: network,
|
||||||
netclientPath := ncutils.GetNetclientPath()
|
IsServer: "yes",
|
||||||
|
Name: models.NODE_SERVER_NAME,
|
||||||
token, err := functions.CreateServerToken(network)
|
},
|
||||||
if err != nil {
|
}, "")
|
||||||
log.Println("could not create server token for " + network)
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
functions.PrintUserLog(models.NODE_SERVER_NAME, "executing network join: "+netclientPath+"netclient "+"join "+"-t "+token+" -name "+models.NODE_SERVER_NAME+" -endpoint "+pubip, 0)
|
|
||||||
var joinCMD *exec.Cmd
|
|
||||||
if servercfg.IsClientMode() == "contained" {
|
|
||||||
joinCMD = exec.Command(netclientPath+"/netclient", "join", "-t", token, "-name", models.NODE_SERVER_NAME, "-endpoint", pubip, "-daemon", "off", "-dnson", "no")
|
|
||||||
} else {
|
|
||||||
joinCMD = exec.Command(netclientPath+"/netclient", "join", "-t", token, "-name", models.NODE_SERVER_NAME, "-endpoint", pubip)
|
|
||||||
}
|
|
||||||
joinCMD.Stdout = os.Stdout
|
|
||||||
joinCMD.Stderr = os.Stderr
|
|
||||||
err = joinCMD.Start()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
log.Println("Waiting for join command to finish...")
|
|
||||||
err = joinCMD.Wait()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Command finished with error: %v", err)
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
log.Println("Server added to network " + network)
|
log.Println("Server added to network " + network)
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
@@ -1,30 +0,0 @@
|
|||||||
package serverctl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gravitl/netmaker/functions"
|
|
||||||
"golang.zx2c4.com/wireguard/wgctrl"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetPeers(networkName string) (map[string]string, error) {
|
|
||||||
peers := make(map[string]string)
|
|
||||||
network, err := functions.GetParentNetwork(networkName)
|
|
||||||
if err != nil {
|
|
||||||
return peers, err
|
|
||||||
}
|
|
||||||
iface := network.DefaultInterface
|
|
||||||
|
|
||||||
client, err := wgctrl.New()
|
|
||||||
if err != nil {
|
|
||||||
return peers, err
|
|
||||||
}
|
|
||||||
device, err := client.Device(iface)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for _, peer := range device.Peers {
|
|
||||||
if functions.IsBase64(peer.PublicKey.String()) && peer.Endpoint != nil && functions.CheckEndpoint(peer.Endpoint.String()) {
|
|
||||||
peers[peer.PublicKey.String()] = peer.Endpoint.String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return peers, nil
|
|
||||||
}
|
|
@@ -191,7 +191,7 @@ func TestAuthenticateUser(t *testing.T) {
|
|||||||
password: "xxxxxxx",
|
password: "xxxxxxx",
|
||||||
code: http.StatusBadRequest,
|
code: http.StatusBadRequest,
|
||||||
tokenExpected: false,
|
tokenExpected: false,
|
||||||
errMessage: "Wrong Password",
|
errMessage: "Incorrect Credentials",
|
||||||
},
|
},
|
||||||
AuthorizeTestCase{
|
AuthorizeTestCase{
|
||||||
testname: "Valid User",
|
testname: "Valid User",
|
||||||
|
Reference in New Issue
Block a user