Combined client + server code, Added HA ability, minor bug fixes

This commit is contained in:
0xdcarns
2021-10-05 15:02:09 -04:00
parent cd99a6ba9a
commit 989676e77f
34 changed files with 1101 additions and 821 deletions

View File

@@ -2,157 +2,15 @@ package controller
import (
"encoding/json"
"strconv"
"strings"
"time"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/dnslogic"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/models"
"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 the client, delete completely
@@ -183,7 +41,7 @@ func DeleteNode(key string, exterminate bool) error {
return err
}
if servercfg.IsDNSMode() {
err = SetDNS()
err = dnslogic.SetDNS()
}
return err
}
@@ -235,93 +93,3 @@ func GetIntClient(clientid string) (models.IntClient, error) {
}
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
}

View File

@@ -4,6 +4,7 @@ import (
"testing"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/stretchr/testify/assert"
)
@@ -13,20 +14,20 @@ func TestGetPeerList(t *testing.T) {
deleteAllNetworks()
createNet()
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, peers)
})
node := createTestNode()
t.Run("One Node", func(t *testing.T) {
peers, err := GetPeersList("skynet", false, "")
peers, err := logic.GetPeersList("skynet", false, "")
assert.Nil(t, err)
assert.Equal(t, node.Address, peers[0].Address)
})
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(createnode, "skynet")
peers, err := GetPeersList("skynet", false, "")
logic.CreateNode(createnode, "skynet")
peers, err := logic.GetPeersList("skynet", false, "")
assert.Nil(t, err)
assert.Equal(t, len(peers), 2)
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"}
//err := ValidateNodeCreate("skynet", createnode)
//assert.Nil(t, err)
node, err := CreateNode(createnode, "skynet")
node, err := logic.CreateNode(createnode, "skynet")
assert.Nil(t, err)
assert.Equal(t, "10.0.0.1", node.Endpoint)
assert.Equal(t, "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", node.PublicKey)
@@ -113,17 +114,17 @@ func TestSetNetworkNodesLastModified(t *testing.T) {
deleteAllNetworks()
createNet()
t.Run("InvalidNetwork", func(t *testing.T) {
err := SetNetworkNodesLastModified("badnet")
err := logic.SetNetworkNodesLastModified("badnet")
assert.EqualError(t, err, "no result found")
})
t.Run("NetworkExists", func(t *testing.T) {
err := SetNetworkNodesLastModified("skynet")
err := logic.SetNetworkNodesLastModified("skynet")
assert.Nil(t, err)
})
}
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"}
node, _ := CreateNode(createnode, "skynet")
node, _ := logic.CreateNode(createnode, "skynet")
return node
}

View File

@@ -3,13 +3,13 @@ package controller
import (
"encoding/json"
"net/http"
"github.com/go-playground/validator/v10"
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/dnslogic"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
"github.com/txn2/txeh"
)
func dnsHandlers(r *mux.Router) {
@@ -63,7 +63,7 @@ func GetAllDNS() ([]models.DNSEntry, error) {
return []models.DNSEntry{}, err
}
for _, net := range networks {
netdns, err := GetDNS(net.NetID)
netdns, err := dnslogic.GetDNS(net.NetID)
if err != nil {
return []models.DNSEntry{}, nil
}
@@ -103,7 +103,7 @@ func getCustomDNS(w http.ResponseWriter, r *http.Request) {
var dns []models.DNSEntry
var params = mux.Vars(r)
dns, err := GetCustomDNS(params["network"])
dns, err := dnslogic.GetCustomDNS(params["network"])
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
@@ -114,65 +114,11 @@ func getCustomDNS(w http.ResponseWriter, r *http.Request) {
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) {
num := 0
entries, err := GetDNS(network)
entries, err := dnslogic.GetDNS(network)
if err != nil {
return 0, err
}
@@ -195,7 +141,7 @@ func getDNS(w http.ResponseWriter, r *http.Request) {
var dns []models.DNSEntry
var params = mux.Vars(r)
dns, err := GetDNS(params["network"])
dns, err := dnslogic.GetDNS(params["network"])
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
@@ -204,22 +150,6 @@ func getDNS(w http.ResponseWriter, r *http.Request) {
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) {
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"))
return
}
err = SetDNS()
err = dnslogic.SetDNS()
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
@@ -296,7 +226,7 @@ func updateDNS(w http.ResponseWriter, r *http.Request) {
returnErrorResponse(w, r, formatError(err, "badrequest"))
return
}
err = SetDNS()
err = dnslogic.SetDNS()
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
@@ -319,7 +249,7 @@ func deleteDNS(w http.ResponseWriter, r *http.Request) {
}
entrytext := params["domain"] + "." + params["network"]
functions.PrintUserLog(models.NODE_SERVER_NAME, "deleted dns entry: "+entrytext, 1)
err = SetDNS()
err = dnslogic.SetDNS()
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
@@ -394,7 +324,7 @@ func pushDNS(w http.ResponseWriter, r *http.Request) {
// Set header
w.Header().Set("Content-Type", "application/json")
err := SetDNS()
err := dnslogic.SetDNS()
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))

View File

@@ -4,6 +4,7 @@ import (
"testing"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/dnslogic"
"github.com/gravitl/netmaker/models"
"github.com/stretchr/testify/assert"
)
@@ -23,7 +24,7 @@ func TestGetCustomDNS(t *testing.T) {
deleteAllNetworks()
createNet()
createTestNode()
dns, err := GetCustomDNS("skynet")
dns, err := dnslogic.GetCustomDNS("skynet")
assert.Nil(t, err)
t.Log(dns)
}
@@ -39,7 +40,7 @@ func TestGetDNSEntryNum(t *testing.T) {
func TestGetDNS(t *testing.T) {
database.InitializeDatabase()
deleteAllNetworks()
dns, err := GetDNS("skynet")
dns, err := dnslogic.GetDNS("skynet")
assert.Nil(t, err)
t.Log(dns)
}

View File

@@ -13,6 +13,7 @@ import (
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/skip2/go-qrcode"
"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 {
return err
}
err = SetNetworkNodesLastModified(extclient.Network)
err = logic.SetNetworkNodesLastModified(extclient.Network)
return err
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
"github.com/gravitl/netmaker/serverctl"
@@ -337,8 +338,21 @@ func deleteNetwork(w http.ResponseWriter, r *http.Request) {
}
func DeleteNetwork(network string) error {
nodeCount, err := functions.GetNetworkNodeCount(network)
nodeCount, err := functions.GetNetworkNonServerNodeCount(network)
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 errors.New("node check failed. All nodes must be deleted before deleting network")

View File

@@ -8,6 +8,7 @@ import (
"github.com/gravitl/netmaker/functions"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/logic"
"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 {
return nil, err
}
@@ -77,7 +78,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.Object)
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
}
err = SetNetworkNodesLastModified(node.Network)
err = logic.SetNetworkNodesLastModified(node.Network)
if err != nil {
return nil, err
}
@@ -134,15 +135,15 @@ func (s *NodeServiceServer) GetPeers(ctx context.Context, req *nodepb.Object) (*
if err != nil {
return nil, err
}
if node.IsServer == "yes" {
SetNetworkServerPeers(macAndNetwork[1])
if node.IsServer == "yes" && logic.IsLeader(&node){
logic.SetNetworkServerPeers(&node)
}
excludeIsRelayed := node.IsRelay != "yes"
var relayedNode string
if node.IsRelayed == "yes" {
relayedNode = node.Address
}
peers, err := GetPeersList(macAndNetwork[1], excludeIsRelayed, relayedNode)
peers, err := logic.GetPeersList(macAndNetwork[1], excludeIsRelayed, relayedNode)
if err != nil {
return nil, err
}
@@ -172,11 +173,10 @@ func (s *NodeServiceServer) GetExtPeers(ctx context.Context, req *nodepb.Object)
if len(macAndNetwork) != 2 {
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 {
return nil, err
}
// cursor.Next() returns a boolean, if false there are no more items and loop will break
var extPeers []models.Node
for i := 0; i < len(peers); i++ {
extPeers = append(extPeers, models.Node{

View File

@@ -6,10 +6,11 @@ import (
"net/http"
"strings"
"time"
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/dnslogic"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
"golang.org/x/crypto/bcrypt"
@@ -267,7 +268,7 @@ func getNetworkNodes(w http.ResponseWriter, r *http.Request) {
var nodes []models.Node
var params = mux.Vars(r)
networkName := params["network"]
nodes, err := GetNetworkNodes(networkName)
nodes, err := logic.GetNetworkNodes(networkName)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
@@ -279,29 +280,6 @@ func getNetworkNodes(w http.ResponseWriter, r *http.Request) {
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.
//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) {
@@ -335,7 +313,7 @@ func getUsersNodes(user models.User) ([]models.Node, error) {
var nodes []models.Node
var err error
for _, networkName := range user.Networks {
tmpNodes, err := GetNetworkNodes(networkName)
tmpNodes, err := logic.GetNetworkNodes(networkName)
if err != nil {
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 {
returnErrorResponse(w, r, formatError(err, "internal"))
return
@@ -682,7 +660,7 @@ func CreateIngressGateway(netid string, macaddress string) (models.Node, error)
if err != nil {
return models.Node{}, err
}
err = SetNetworkNodesLastModified(netid)
err = logic.SetNetworkNodesLastModified(netid)
return node, err
}
@@ -733,7 +711,7 @@ func DeleteIngressGateway(networkName string, macaddress string) (models.Node, e
if err != nil {
return models.Node{}, err
}
err = SetNetworkNodesLastModified(networkName)
err = logic.SetNetworkNodesLastModified(networkName)
return node, err
}
@@ -783,7 +761,7 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
}
if servercfg.IsDNSMode() {
err = SetDNS()
err = dnslogic.SetDNS()
}
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))

View File

@@ -4,6 +4,7 @@ import (
"testing"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/stretchr/testify/assert"
)
@@ -81,19 +82,19 @@ func TestGetNetworkNodes(t *testing.T) {
deleteAllNetworks()
createNet()
t.Run("BadNet", func(t *testing.T) {
node, err := GetNetworkNodes("badnet")
node, err := logic.GetNetworkNodes("badnet")
assert.Nil(t, err)
assert.Equal(t, []models.Node{}, node)
//assert.Equal(t, "mongo: no documents in result", err.Error())
})
t.Run("NoNodes", func(t *testing.T) {
node, err := GetNetworkNodes("skynet")
node, err := logic.GetNetworkNodes("skynet")
assert.Nil(t, err)
assert.Equal(t, []models.Node{}, node)
})
t.Run("Success", func(t *testing.T) {
createTestNode()
node, err := GetNetworkNodes("skynet")
node, err := logic.GetNetworkNodes("skynet")
assert.Nil(t, err)
assert.NotEqual(t, []models.Node(nil), node)
})

View File

@@ -72,6 +72,21 @@ func CreateRelay(relay models.RelayRequest) (models.Node, error) {
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 {
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) {
node, err := functions.GetNodeByMacAddress(network, macaddress)
@@ -171,30 +171,3 @@ func DeleteRelay(network, macaddress string) (models.Node, error) {
}
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)
}

View File

@@ -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).
record, err := database.FetchRecord(database.USERS_TABLE_NAME, authRequest.UserName)
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 {
return "", errors.New("user " + authRequest.UserName + " not found")
return "", errors.New("incorrect credentials")
}
//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...
//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 {
return "", errors.New("wrong password")
return "", errors.New("incorrect credentials")
}
//Create a new JWT for the node

View File

@@ -219,7 +219,7 @@ func TestVerifyAuthRequest(t *testing.T) {
authRequest.Password = "password"
jwt, err := VerifyAuthRequest(authRequest)
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) {
user := models.User{"nonadmin", "somepass", nil, false}
@@ -235,7 +235,7 @@ func TestVerifyAuthRequest(t *testing.T) {
authRequest := models.UserAuthParams{"admin", "badpass"}
jwt, err := VerifyAuthRequest(authRequest)
assert.Equal(t, "", jwt)
assert.EqualError(t, err, "wrong password")
assert.EqualError(t, err, "incorrect credentials")
})
t.Run("Success", func(t *testing.T) {
authRequest := models.UserAuthParams{"admin", "password"}

104
dnslogic/dns.go Normal file
View 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
}

View File

@@ -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
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
# add a c lib
RUN apk add gcompat iptables
# set the working directory
WORKDIR /root/
RUN mkdir /etc/netclient
RUN mkdir -p /etc/netclient/config
COPY --from=builder /app/netmaker .
COPY --from=builder /app/config config
COPY --from=builder /app/netclient/netclient /etc/netclient/netclient
RUN chmod 0755 /etc/netclient/netclient
EXPOSE 8081
EXPOSE 50051

View File

@@ -20,11 +20,6 @@ import (
"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) {
log.SetFlags(log.Flags() &^ (log.Llongfile | log.Lshortfile))
if int32(loglevel) <= servercfg.GetVerbose() && servercfg.GetVerbose() != 0 {
@@ -380,7 +375,7 @@ func IsMacAddressUnique(macaddress string, networkName string) (bool, error) {
return true, nil
}
func GetNetworkNodeCount(networkName string) (int, error) {
func GetNetworkNonServerNodeCount(networkName string) (int, error) {
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
count := 0
@@ -392,7 +387,7 @@ func GetNetworkNodeCount(networkName string) (int, error) {
if err = json.Unmarshal([]byte(value), &node); err != nil {
return count, err
} else {
if node.Network == networkName {
if node.Network == networkName && node.IsServer != "yes" {
count++
}
}
@@ -491,12 +486,6 @@ func IsIpCIDR(host string) bool {
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.
//Switch to REGEX?
func NameInNetworkCharSet(name string) bool {

38
logic/extpeers.go Normal file
View 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
View 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
View 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
View 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
}

View File

@@ -15,6 +15,7 @@ import (
controller "github.com/gravitl/netmaker/controllers"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/dnslogic"
"github.com/gravitl/netmaker/functions"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/models"
@@ -81,14 +82,13 @@ func startControllers() {
go runGRPC(&waitnetwork)
}
// Run the client in goroutine locally if CLIENT_MODE is "contained"
if servercfg.IsClientMode() == "contained" {
if servercfg.IsClientMode() == "on" {
waitnetwork.Add(1)
go runClient(&waitnetwork)
}
if servercfg.IsDNSMode() {
err := controller.SetDNS()
err := dnslogic.SetDNS()
if err != nil {
log.Println("error occurred initializing DNS:", err)
}
@@ -115,7 +115,6 @@ func startControllers() {
func runClient(wg *sync.WaitGroup) {
defer wg.Done()
log.Println("CLIENT_MODE running as contained")
go func() {
for {
if err := serverctl.HandleContainedClient(); err != nil {

View File

@@ -7,7 +7,7 @@ import (
"net"
"strings"
"time"
"bytes"
"github.com/go-playground/validator/v10"
"github.com/gravitl/netmaker/database"
"golang.org/x/crypto/bcrypt"
@@ -76,6 +76,18 @@ type Node struct {
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() {
if node.MTU == 0 {
node.MTU = 1280
@@ -263,9 +275,12 @@ func (node *Node) SetDefaults() {
}
}
// == Parent Network settings ==
node.CheckInInterval = parentNetwork.DefaultCheckInInterval
if node.IsDualStack == "" {
node.IsDualStack = parentNetwork.IsDualStack
}
if node.MTU == 0 {
node.MTU = parentNetwork.DefaultMTU
}
// == node defaults if not set by parent ==
node.SetIPForwardingDefault()
node.SetDNSOnDefault()
@@ -535,9 +550,9 @@ func GetAllNodes() ([]Node, error) {
return nodes, nil
}
func GetID(macaddress string, network string) (string, error) {
if macaddress == "" || network == "" {
func (node *Node) GetID() (string, error) {
if node.MacAddress == "" || node.Network == "" {
return "", errors.New("unable to get record key")
}
return macaddress + "###" + network, nil
return node.MacAddress + "###" + node.Network, nil
}

View File

@@ -58,7 +58,7 @@ func Join(cfg config.ClientConfig, privateKey string) error {
func getWindowsInterval() int {
interval := 15
networks, err := functions.GetNetworks()
networks, err := ncutils.GetSystemNetworks()
if err != nil {
return interval
}
@@ -90,12 +90,13 @@ func RunUserspaceDaemon() {
func CheckIn(cfg config.ClientConfig) error {
var err error
if cfg.Network == "" {
ncutils.PrintLog("required, '-n', exiting", 0)
os.Exit(1)
} else if cfg.Network == "all" {
ncutils.PrintLog("running checkin for all networks", 1)
networks, err := functions.GetNetworks()
networks, err := ncutils.GetSystemNetworks()
if err != nil {
ncutils.PrintLog("error retrieving networks, exiting", 1)
return err
@@ -138,7 +139,7 @@ func Push(cfg config.ClientConfig) error {
var err error
if cfg.Network == "all" || ncutils.IsWindows() {
ncutils.PrintLog("pushing config to server for all networks.", 0)
networks, err := functions.GetNetworks()
networks, err := ncutils.GetSystemNetworks()
if err != nil {
ncutils.PrintLog("error retrieving networks, exiting.", 0)
return err
@@ -164,7 +165,7 @@ func Pull(cfg config.ClientConfig) error {
var err error
if cfg.Network == "all" {
ncutils.PrintLog("No network selected. Running Pull for all networks.", 0)
networks, err := functions.GetNetworks()
networks, err := ncutils.GetSystemNetworks()
if err != nil {
ncutils.PrintLog("Error retrieving networks. Exiting.", 1)
return err

View File

@@ -1,12 +1,15 @@
package functions
import (
"context"
"encoding/json"
"errors"
"os"
"runtime"
"strings"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/auth"
"github.com/gravitl/netmaker/netclient/config"
@@ -136,7 +139,6 @@ func CheckConfig(cliconf config.ClientConfig) error {
if newNode.IsPending == "yes" {
return errors.New("node is pending")
}
actionCompleted := checkNodeActions(newNode, network, servercfg, &currentNode, cfg)
if actionCompleted == models.NODE_DELETE {
return errors.New("node has been removed")
@@ -164,6 +166,9 @@ func Pull(network string, manual bool) (*models.Node, error) {
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,
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
if err != nil {
@@ -187,10 +192,15 @@ func Pull(network string, manual bool) (*models.Node, error) {
if err != nil {
return nil, err
}
var resNode models.Node
if err = json.Unmarshal([]byte(readres.Data), &resNode); err != nil {
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
resNode.OS = runtime.GOOS
if resNode.PullChanges == "yes" || manual {
@@ -211,6 +221,7 @@ func Pull(network string, manual bool) (*models.Node, error) {
if err != nil {
return &resNode, err
}
if resNode.IsServer != "yes" {
req := &nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
@@ -220,6 +231,11 @@ func Pull(network string, manual bool) (*models.Node, error) {
if err != nil {
return &resNode, err
}
} else { // handle server side update
if err = resNode.Update(&resNode); err != nil {
return &resNode, err
}
}
} else {
if err = wireguard.SetWGConfig(network, true); err != nil {
if errors.Is(err, os.ErrNotExist) {
@@ -244,8 +260,10 @@ func Push(network string) error {
postnode := cfg.Node
// always set the OS on client
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
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
@@ -274,7 +292,6 @@ func Push(network string) error {
postnode.PublicKey = privateKeyWG.PublicKey().String()
}
}
postnode.SetLastCheckIn()
nodeData, err := json.Marshal(&postnode)
if err != nil {
return err
@@ -293,6 +310,11 @@ func Push(network string) error {
if err != nil {
return err
}
} else {
if err = postnode.Update(&postnode); err != nil {
return err
}
}
err = config.ModConfig(&postnode)
return err
}

View File

@@ -5,7 +5,6 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"log"
"net"
"os"
@@ -13,6 +12,7 @@ import (
"strings"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/auth"
"github.com/gravitl/netmaker/netclient/config"
@@ -138,7 +138,7 @@ func GetNode(network string) models.Node {
}
func Uninstall() error {
networks, err := GetNetworks()
networks, err := ncutils.GetSystemNetworks()
if err != nil {
ncutils.PrintLog("unable to retrieve networks: "+err.Error(), 1)
ncutils.PrintLog("continuing uninstall without leaving networks", 1)
@@ -163,7 +163,6 @@ func Uninstall() error {
}
func LeaveNetwork(network string) error {
//need to implement checkin on server side
cfg, err := config.ReadConfig(network)
if err != nil {
return err
@@ -171,19 +170,20 @@ func LeaveNetwork(network string) error {
servercfg := cfg.Server
node := cfg.Node
if node.IsServer != "yes" {
var wcclient nodepb.NodeServiceClient
conn, err := grpc.Dial(cfg.Server.GRPCAddress,
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
if err != nil {
log.Printf("Unable to establish client connection to "+servercfg.GRPCAddress+": %v", err)
} else {
}
defer conn.Close()
wcclient = nodepb.NewNodeServiceClient(conn)
ctx, err := auth.SetJWT(wcclient, network)
if err != nil {
log.Printf("Failed to authenticate: %v", err)
} else {
} else { // handle client side
node.SetID()
var header metadata.MD
_, err = wcclient.DeleteNode(
@@ -200,6 +200,13 @@ func LeaveNetwork(network string) error {
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)
}
@@ -244,7 +251,7 @@ func DeleteInterface(ifacename string, postdown string) error {
func List() error {
networks, err := GetNetworks()
networks, err := ncutils.GetSystemNetworks()
if err != nil {
return err
}
@@ -267,34 +274,6 @@ func List() error {
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 {
cfg, err := config.ReadConfig(network)
if err != nil {
@@ -302,7 +281,6 @@ func WipeLocal(network string) error {
}
nodecfg := cfg.Node
ifacename := nodecfg.Interface
if ifacename != "" {
if !ncutils.IsKernel() {
if err = wireguard.RemoveConf(ifacename, true); err == nil {

View File

@@ -8,6 +8,7 @@ import (
"log"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/auth"
"github.com/gravitl/netmaker/netclient/config"
@@ -28,7 +29,6 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
return err
}
ncutils.Log("joining " + cfg.Network + " at " + cfg.Server.GRPCAddress)
err := config.Write(&cfg, cfg.Network)
if err != nil {
return err
@@ -53,7 +53,6 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
cfg.Node.Endpoint = cfg.Node.LocalAddress
} else {
cfg.Node.Endpoint, err = ncutils.GetPublicIP()
}
if err != nil || 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
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)
// differentiate between client/server here
var node models.Node // fill this node with appropriate calls
postnode := &models.Node{
Password: cfg.Node.Password,
MacAddress: cfg.Node.MacAddress,
@@ -112,6 +102,19 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
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 {
return err
}
@@ -133,10 +136,23 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
ncutils.PrintLog("node created on remote server...updating configs", 1)
nodeData := res.Data
var node models.Node
if err = json.Unmarshal([]byte(nodeData), &node); err != nil {
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
node.ListenPort, err = ncutils.GetFreePort(node.ListenPort)
@@ -177,9 +193,8 @@ func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
}
}
ncutils.Log("retrieving remote peers")
peers, hasGateway, gateways, err := server.GetPeers(node.MacAddress, cfg.Network, cfg.Server.GRPCAddress, node.IsDualStack == "yes", node.IsIngressGateway == "yes")
ncutils.Log("retrieving peers")
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) {
ncutils.Log("failed to retrieve peers")
return err

View File

@@ -24,7 +24,7 @@ func main() {
app := cli.NewApp()
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.Version = "v0.8.1"
app.Version = "v0.8.3"
cliFlags := []cli.Flag{
&cli.StringFlag{

View File

@@ -368,3 +368,31 @@ func PrintLog(message string, loglevel int) {
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)]
}

View File

@@ -9,6 +9,7 @@ import (
"time"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/auth"
"github.com/gravitl/netmaker/netclient/config"
@@ -40,6 +41,7 @@ func CheckIn(network string) (*models.Node, error) {
return nil, err
}
node := cfg.Node
if cfg.Node.IsServer != "yes" {
wcclient, err := getGrpcClient(cfg)
if err != nil {
return nil, err
@@ -65,6 +67,7 @@ func CheckIn(network string) (*models.Node, error) {
if err = json.Unmarshal([]byte(response.GetData()), &node); err != nil {
return nil, err
}
}
return &node, err
}
@@ -116,11 +119,11 @@ func RemoveNetwork(network string) error {
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
var gateways []string
var peers []wgtypes.PeerConfig
var wcclient nodepb.NodeServiceClient
cfg, err := config.ReadConfig(network)
if err != nil {
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 {
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,
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
@@ -161,11 +166,17 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
log.Println(err)
return nil, hasGateway, gateways, err
}
var nodes []models.Node
if err := json.Unmarshal([]byte(response.GetData()), &nodes); err != nil {
log.Println("Error unmarshaling data for peers")
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 {
pubkey, err := wgtypes.ParseKey(node.PublicKey)
if err != nil {
@@ -240,7 +251,7 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
}
allowedips = append(allowedips, addr6)
}
if nodecfg.IsServer == "yes" {
if nodecfg.IsServer == "yes" && !(node.IsServer == "yes"){
peer = wgtypes.PeerConfig{
PublicKey: pubkey,
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) {
var peers []wgtypes.PeerConfig
var wcclient nodepb.NodeServiceClient
cfg, err := config.ReadConfig(network)
if err != nil {
log.Fatalf("Issue retrieving config for network: "+network+". Please investigate: %v", err)
}
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,
ncutils.GRPCRequestOpts(cfg.Server.GRPCSSL))
@@ -317,10 +331,26 @@ func GetExtPeers(macaddress string, network string, server string, dualstack boo
log.Println(err)
return nil, err
}
var extPeers []models.Node
if err = json.Unmarshal([]byte(responseObject.Data), &extPeers); err != nil {
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 {
pubkey, err := wgtypes.ParseKey(extPeer.PublicKey)
if err != nil {

View File

@@ -267,7 +267,7 @@ func SetWGConfig(network string, peerupdate bool) error {
servercfg := cfg.Server
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 {
return err
}

37
relay/relay.go Normal file
View 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)
}

View File

@@ -74,7 +74,7 @@ func GetAPIConnString() string {
return conn
}
func GetVersion() string {
version := "0.8.1"
version := "0.8.3"
if config.Config.Server.Version != "" {
version = config.Config.Server.Version
}

View File

@@ -6,11 +6,11 @@ import (
"io"
"log"
"os"
"os/exec"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions"
"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/servercfg"
)
@@ -91,18 +91,8 @@ func copy(src, dst string) (int64, error) {
}
func RemoveNetwork(network string) (bool, error) {
netclientPath := ncutils.GetNetclientPath()
_, 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)
}
err := nccommand.Leave(config.ClientConfig{Network: network})
return true, err
}
func InitServerNetclient() error {
@@ -114,82 +104,89 @@ func InitServerNetclient() error {
log.Println("could not find or create", netclientDir)
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
}
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))
netclientPath := ncutils.GetNetclientPath()
checkinCMD := exec.Command(netclientPath+"/netclient", "checkin", "-n", "all")
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 := SyncNetworks(servernets)
if err != nil && servercfg.GetVerbose() >= 1 {
log.Printf("[server netclient] error syncing networks %s \n", 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 {
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
}
func AddNetwork(network string) (bool, error) {
pubip, err := servercfg.GetPublicIP()
if err != nil {
log.Println("could not get public IP.")
return false, err
}
netclientPath := ncutils.GetNetclientPath()
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
}
err := nccommand.Join(config.ClientConfig{
Network: network,
Daemon: "off",
Node: models.Node{
Network: network,
IsServer: "yes",
Name: models.NODE_SERVER_NAME,
},
}, "")
log.Println("Server added to network " + network)
return true, err
}

View File

@@ -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
}

View File

@@ -191,7 +191,7 @@ func TestAuthenticateUser(t *testing.T) {
password: "xxxxxxx",
code: http.StatusBadRequest,
tokenExpected: false,
errMessage: "Wrong Password",
errMessage: "Incorrect Credentials",
},
AuthorizeTestCase{
testname: "Valid User",