Began converting to rqlite

This commit is contained in:
afeiszli
2021-07-20 17:18:45 -04:00
parent 0775520f73
commit d22ad13cfe
9 changed files with 626 additions and 914 deletions

View File

@@ -2,11 +2,13 @@ package controller
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"log" "log"
"time" "time"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions" "github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mongoconn" "github.com/gravitl/netmaker/mongoconn"
@@ -59,64 +61,41 @@ func GetPeersList(networkName string) ([]models.PeersResponse, error) {
return peers, err return peers, err
} }
func GetExtPeersList(networkName string, macaddress string) ([]models.ExtPeersResponse, error) { func GetExtPeersList(networkName string, macaddress string) ([]models.ExtPeersResponse, error) {
var peers []models.ExtPeersResponse var peers []models.ExtPeersResponse
records, err := database.FetchRecords(database.EXT_CLIENT_TABLE_NAME)
//Connection mongoDB with mongoconn class if err != nil {
collection := mongoconn.Client.Database("netmaker").Collection("extclients") return peers, err
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) for _, value := range records {
var peer models.ExtPeersResponse
//Get all nodes in the relevant network which are NOT in pending state err = json.Unmarshal([]byte(value), &peer)
filter := bson.M{"network": networkName, "ingressgatewayid": macaddress} if err != nil {
cur, err := collection.Find(ctx, filter) functions.PrintUserLog("netmaker", "failed to unmarshal ext client", 2)
continue
if err != nil { }
return peers, err peers = append(peers, peer)
} }
return peers, err
// Close the cursor once finished and cancel if it takes too long
defer cancel()
for cur.Next(context.TODO()) {
var peer models.ExtPeersResponse
err := cur.Decode(&peer)
if err != nil {
log.Fatal(err)
}
// add the node to our node array
//maybe better to just return this? But then that's just GetNodes...
peers = append(peers, peer)
}
//Uh oh, fatal error! This needs some better error handling
//TODO: needs appropriate error handling so the server doesnt shut down.
if err := cur.Err(); err != nil {
log.Fatal(err)
}
return peers, err
} }
func ValidateNodeCreate(networkName string, node models.Node) error { func ValidateNodeCreate(networkName string, node models.Node) error {
v := validator.New() v := validator.New()
_ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool { _ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool {
var isFieldUnique bool = functions.IsFieldUnique(networkName, "macaddress", node.MacAddress) isFieldUnique, _ := functions.IsMacAddressUnique(node.MacAddress, networkName)
return isFieldUnique return isFieldUnique
}) })
_ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool { _ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
_, err := node.GetNetwork() _, err := node.GetNetwork()
return err == nil return err == nil
}) })
_ = v.RegisterValidation("in_charset", func(fl validator.FieldLevel) bool { _ = v.RegisterValidation("in_charset", func(fl validator.FieldLevel) bool {
isgood := functions.NameInNodeCharSet(node.Name) isgood := functions.NameInNodeCharSet(node.Name)
return isgood return isgood
}) })
err := v.Struct(node) err := v.Struct(node)
if err != nil { if err != nil {
@@ -133,10 +112,10 @@ func ValidateNodeUpdate(networkName string, node models.NodeUpdate) error {
_, err := node.GetNetwork() _, err := node.GetNetwork()
return err == nil return err == nil
}) })
_ = v.RegisterValidation("in_charset", func(fl validator.FieldLevel) bool { _ = v.RegisterValidation("in_charset", func(fl validator.FieldLevel) bool {
isgood := functions.NameInNodeCharSet(node.Name) isgood := functions.NameInNodeCharSet(node.Name)
return isgood return isgood
}) })
err := v.Struct(node) err := v.Struct(node)
if err != nil { if err != nil {
for _, e := range err.(validator.ValidationErrors) { for _, e := range err.(validator.ValidationErrors) {
@@ -302,27 +281,27 @@ func DeleteNode(macaddress string, network string) (bool, error) {
func DeleteIntClient(clientid string) (bool, error) { func DeleteIntClient(clientid string) (bool, error) {
deleted := false deleted := false
collection := mongoconn.Client.Database("netmaker").Collection("intclients") collection := mongoconn.Client.Database("netmaker").Collection("intclients")
filter := bson.M{"clientid": clientid} filter := bson.M{"clientid": clientid}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
result, err := collection.DeleteOne(ctx, filter) result, err := collection.DeleteOne(ctx, filter)
deletecount := result.DeletedCount deletecount := result.DeletedCount
if deletecount > 0 { if deletecount > 0 {
deleted = true deleted = true
} }
defer cancel() defer cancel()
err = serverctl.ReconfigureServerWireGuard() err = serverctl.ReconfigureServerWireGuard()
return deleted, err return deleted, err
} }
func GetNode(macaddress string, network string) (models.Node, error) { func GetNode(macaddress string, network string) (models.Node, error) {
@@ -343,18 +322,18 @@ func GetNode(macaddress string, network string) (models.Node, error) {
func GetIntClient(clientid string) (models.IntClient, error) { func GetIntClient(clientid string) (models.IntClient, error) {
var client models.IntClient var client models.IntClient
collection := mongoconn.Client.Database("netmaker").Collection("intclients") collection := mongoconn.Client.Database("netmaker").Collection("intclients")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"clientid": clientid} filter := bson.M{"clientid": clientid}
err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&clientid) err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&clientid)
defer cancel() defer cancel()
return client, err return client, err
} }
func CreateNode(node models.Node, networkName string) (models.Node, error) { func CreateNode(node models.Node, networkName string) (models.Node, error) {

View File

@@ -545,7 +545,7 @@ func UpdateNetwork(networkChange models.NetworkUpdate, network models.Network) (
} }
} }
if haslocalrangeupdate { if haslocalrangeupdate {
err = functions.UpdateNetworkPrivateAddresses(network.NetID) err = functions.UpdateNetworkLocalAddresses(network.NetID)
if err != nil { if err != nil {
return models.Network{}, err return models.Network{}, err
} }
@@ -734,14 +734,14 @@ func CreateAccessKey(accesskey models.AccessKey, network models.Network) (models
s := servercfg.GetServerConfig() s := servercfg.GetServerConfig()
w := servercfg.GetWGConfig() w := servercfg.GetWGConfig()
servervals := models.ServerConfig{ servervals := models.ServerConfig{
CoreDNSAddr: s.CoreDNSAddr, CoreDNSAddr: s.CoreDNSAddr,
APIConnString: s.APIConnString, APIConnString: s.APIConnString,
APIHost: s.APIHost, APIHost: s.APIHost,
APIPort: s.APIPort, APIPort: s.APIPort,
GRPCConnString: s.GRPCConnString, GRPCConnString: s.GRPCConnString,
GRPCHost: s.GRPCHost, GRPCHost: s.GRPCHost,
GRPCPort: s.GRPCPort, GRPCPort: s.GRPCPort,
GRPCSSL: s.GRPCSSL, GRPCSSL: s.GRPCSSL,
} }
wgvals := models.WG{ wgvals := models.WG{
GRPCWireGuard: w.GRPCWireGuard, GRPCWireGuard: w.GRPCWireGuard,

100
database/database.go Normal file
View File

@@ -0,0 +1,100 @@
package database
import (
"log"
"github.com/rqlite/gorqlite"
)
const NETWORKS_TABLE_NAME = "networks"
const NODES_TABLE_NAME = "nodes"
const USERS_TABLE_NAME = "users"
const DNS_TABLE_NAME = "dns"
const EXT_CLIENT_TABLE_NAME = "extclients"
const INT_CLIENTS_TABLE_NAME = "intclients"
const DATABASE_FILENAME = "netmaker.db"
var Database gorqlite.Connection
func InitializeDatabase() error {
conn, err := gorqlite.Open("http://")
if err != nil {
return err
}
// sqliteDatabase, _ := sql.Open("sqlite3", "./database/"+dbFilename)
Database = conn
Database.SetConsistencyLevel("strong")
createTables()
return nil
}
func createTables() {
createTable(NETWORKS_TABLE_NAME)
createTable(NODES_TABLE_NAME)
createTable(USERS_TABLE_NAME)
createTable(DNS_TABLE_NAME)
createTable(EXT_CLIENT_TABLE_NAME)
createTable(INT_CLIENTS_TABLE_NAME)
}
func createTable(tableName string) error {
_, err := Database.WriteOne("CREATE TABLE IF NOT EXISTS " + tableName + " (key TEXT NOT NULL UNIQUE PRIMARY KEY, value TEXT)")
if err != nil {
return err
}
return nil
}
func Insert(key string, value string, tableName string) error {
_, err := Database.WriteOne("INSERT OR REPLACE INTO " + tableName + " (key, value) VALUES ('" + key + "', '" + value + "')")
if err != nil {
return err
}
return nil
}
func DeleteRecord(tableName string, key string) error {
_, err := Database.WriteOne("DELETE FROM " + tableName + " WHERE key = \"" + key + "\"")
if err != nil {
return err
}
return nil
}
func DeleteAllRecords(tableName string) error {
_, err := Database.WriteOne("DELETE TABLE " + tableName)
if err != nil {
return err
}
err = createTable(tableName)
if err != nil {
return err
}
return nil
}
func FetchRecord(tableName string, key string) (string, error) {
results, err := FetchRecords(tableName)
if err != nil {
return "", err
}
return results[key], nil
}
func FetchRecords(tableName string) (map[string]string, error) {
row, err := Database.QueryOne("SELECT * FROM " + tableName + " ORDER BY key")
if err != nil {
return nil, err
}
records := make(map[string]string)
for row.Next() { // Iterate and fetch the records from result cursor
var key string
var value string
row.Scan(&key, &value)
records[key] = value
}
log.Println(tableName, records)
return records, nil
}

View File

@@ -5,7 +5,6 @@
package functions package functions
import ( import (
"context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors" "errors"
@@ -16,13 +15,9 @@ import (
"strings" "strings"
"time" "time"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mongoconn"
"github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/servercfg"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
) )
func PrintUserLog(username string, message string, loglevel int) { func PrintUserLog(username string, message string, loglevel int) {
@@ -76,179 +71,85 @@ func CreateServerToken(netID string) (string, error) {
accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(tokenjson)) accesskey.AccessString = base64.StdEncoding.EncodeToString([]byte(tokenjson))
network.AccessKeys = append(network.AccessKeys, accesskey) network.AccessKeys = append(network.AccessKeys, accesskey)
if data, err := json.Marshal(network); err != nil {
collection := mongoconn.Client.Database("netmaker").Collection("networks") return "", err
} else {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) database.Insert(netID, string(data), database.NETWORKS_TABLE_NAME)
// Create filter
filter := bson.M{"netid": netID}
// prepare update model.
update := bson.D{
{"$set", bson.D{
{"accesskeys", network.AccessKeys},
}},
} }
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
defer cancel()
if errN != nil {
return "", errN
}
return accesskey.AccessString, nil return accesskey.AccessString, nil
} }
func GetPeersList(networkName string) ([]models.PeersResponse, error) { func GetPeersList(networkName string) ([]models.PeersResponse, error) {
var peers []models.PeersResponse var peers []models.PeersResponse
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
//Connection mongoDB with mongoconn class
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
//Get all nodes in the relevant network which are NOT in pending state
filter := bson.M{"network": networkName, "ispending": false}
cur, err := collection.Find(ctx, filter)
if err != nil { if err != nil {
return peers, err return peers, err
} }
// Close the cursor once finished and cancel if it takes too long for _, value := range collection {
defer cancel()
for cur.Next(context.TODO()) {
var peer models.PeersResponse var peer models.PeersResponse
err := cur.Decode(&peer) err := json.Unmarshal([]byte(value), &peer)
if err != nil { if err != nil {
log.Fatal(err) continue // try the rest
} }
// add the node to our node array
//maybe better to just return this? But then that's just GetNodes...
peers = append(peers, peer) peers = append(peers, peer)
} }
//Uh oh, fatal error! This needs some better error handling
//TODO: needs appropriate error handling so the server doesnt shut down.
if err := cur.Err(); err != nil {
log.Fatal(err)
}
return peers, err return peers, err
} }
func GetIntPeersList() ([]models.PeersResponse, error) { func GetIntPeersList() ([]models.PeersResponse, error) {
var peers []models.PeersResponse var peers []models.PeersResponse
records, err := database.FetchRecords(database.INT_CLIENTS_TABLE_NAME)
collection := mongoconn.Client.Database("netmaker").Collection("intclients")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"isserver": ""}
cur, err := collection.Find(ctx, filter)
if err != nil { if err != nil {
return peers, err return peers, err
} }
// parse the peers
// Close the cursor once finished and cancel if it takes too long for _, value := range records {
defer cancel()
for cur.Next(context.TODO()) {
var peer models.PeersResponse var peer models.PeersResponse
err := cur.Decode(&peer) err := json.Unmarshal([]byte(value), &peer)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
// add the node to our node array // add the node to our node array
//maybe better to just return this? But then that's just GetNodes... //maybe better to just return this? But then that's just GetNodes...
peers = append(peers, peer) peers = append(peers, peer)
} }
//Uh oh, fatal error! This needs some better error handling
//TODO: needs appropriate error handling so the server doesnt shut down.
if err := cur.Err(); err != nil {
log.Fatal(err)
}
return peers, err return peers, err
} }
func IsFieldUnique(network string, field string, value string) bool { func GetServerIntClient() (*models.IntClient, error) {
var node models.Node intClients, err := database.FetchRecords(database.INT_CLIENTS_TABLE_NAME)
isunique := true for _, value := range intClients {
var intClient models.IntClient
collection := mongoconn.Client.Database("netmaker").Collection("nodes") err = json.Unmarshal([]byte(value), &intClient)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) if err != nil {
return nil, err
filter := bson.M{field: value, "network": network} }
if intClient.IsServer == "yes" && intClient.Network == "comms" {
err := collection.FindOne(ctx, filter).Decode(&node) return &intClient, nil
defer cancel()
if err != nil {
return isunique
}
if node.Name != "" {
isunique = false
}
return isunique
}
func ServerIntClientExists() (bool, error) {
collection := mongoconn.Client.Database("netmaker").Collection("intclients")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"isserver": "yes"}
var result bson.M
err := collection.FindOne(ctx, filter).Decode(&result)
defer cancel()
if err != nil {
if err == mongo.ErrNoDocuments {
return false, nil
} }
} }
return true, err return nil, err
} }
func NetworkExists(name string) (bool, error) { func NetworkExists(name string) (bool, error) {
collection := mongoconn.Client.Database("netmaker").Collection("networks") var network string
var err error
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) if network, err = database.FetchRecord(database.NETWORKS_TABLE_NAME, name); err != nil {
return false, err
filter := bson.M{"netid": name}
var result bson.M
err := collection.FindOne(ctx, filter).Decode(&result)
defer cancel()
if err != nil {
if err == mongo.ErrNoDocuments {
return false, nil
}
} }
return true, err return len(network) > 0, nil
} }
//TODO: This is very inefficient (N-squared). Need to find a better way. //TODO: This is very inefficient (N-squared). Need to find a better way.
@@ -256,25 +157,15 @@ func NetworkExists(name string) (bool, error) {
//for each node, it gets a unique address. That requires checking against all other nodes once more //for each node, it gets a unique address. That requires checking against all other nodes once more
func UpdateNetworkNodeAddresses(networkName string) error { func UpdateNetworkNodeAddresses(networkName string) error {
//Connection mongoDB with mongoconn class collections, err := database.FetchRecords(database.NODES_TABLE_NAME)
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"network": networkName}
cur, err := collection.Find(ctx, filter)
if err != nil { if err != nil {
return err return err
} }
defer cancel() for _, value := range collections {
for cur.Next(context.TODO()) {
var node models.Node var node models.Node
err := json.Unmarshal([]byte(value), &node)
err := cur.Decode(&node)
if err != nil { if err != nil {
fmt.Println("error in node address assignment!") fmt.Println("error in node address assignment!")
return err return err
@@ -285,42 +176,30 @@ func UpdateNetworkNodeAddresses(networkName string) error {
return iperr return iperr
} }
filter := bson.M{"macaddress": node.MacAddress} node.Address = ipaddr
update := bson.D{{"$set", bson.D{{"address", ipaddr}}}} data, err := json.Marshal(&node)
if err != nil {
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&node) return err
defer cancel()
if errN != nil {
return errN
} }
database.Insert(node.MacAddress, string(data), database.NODES_TABLE_NAME)
} }
return err return nil
} }
//TODO TODO TODO!!!!! func UpdateNetworkLocalAddresses(networkName string) error {
func UpdateNetworkPrivateAddresses(networkName string) error {
//Connection mongoDB with mongoconn class collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"network": networkName}
cur, err := collection.Find(ctx, filter)
if err != nil { if err != nil {
return err return err
} }
defer cancel() for _, value := range collection {
for cur.Next(context.TODO()) {
var node models.Node var node models.Node
err := cur.Decode(&node) err := json.Unmarshal([]byte(value), &node)
if err != nil { if err != nil {
fmt.Println("error in node address assignment!") fmt.Println("error in node address assignment!")
return err return err
@@ -331,18 +210,16 @@ func UpdateNetworkPrivateAddresses(networkName string) error {
return iperr return iperr
} }
filter := bson.M{"macaddress": node.MacAddress} node.Address = ipaddr
update := bson.D{{"$set", bson.D{{"address", ipaddr}}}} newNodeData, err := json.Marshal(&node)
if err != nil {
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&node) fmt.Println("error in node address assignment!")
return err
defer cancel()
if errN != nil {
return errN
} }
database.Insert(node.MacAddress, string(newNodeData), database.NODES_TABLE_NAME)
} }
return err return nil
} }
//Checks to see if any other networks have the same name (id) //Checks to see if any other networks have the same name (id)
@@ -385,60 +262,68 @@ func IsNetworkDisplayNameUnique(name string) (bool, error) {
return isunique, nil return isunique, nil
} }
func GetNetworkNodeNumber(networkName string) (int, error) { func IsMacAddressUnique(macaddress string, networkName string) (bool, error) {
collection := mongoconn.Client.Database("netmaker").Collection("nodes") collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"network": networkName}
count, err := collection.CountDocuments(ctx, filter)
returncount := int(count)
//not sure if this is the right way of handling this error...
if err != nil { if err != nil {
return 9999, err return false, err
}
for _, value := range collection {
var node models.Node
if err = json.Unmarshal([]byte(value), &node); err != nil {
return false, err
} else {
if node.MacAddress == macaddress && node.Network == networkName {
return false, nil
}
}
} }
defer cancel() return true, nil
return returncount, err
} }
//Kind of a weird name. Should just be GetNetworks I think. Consider changing. func GetNetworkNodeNumber(networkName string) (int, error) {
//Anyway, returns all the networks
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
count := 0
if err != nil {
return count, err
}
for _, value := range collection {
var node models.Node
if err = json.Unmarshal([]byte(value), &node); err != nil {
return count, err
} else {
if node.Network == networkName {
count++
}
}
}
return count, nil
}
// Anyway, returns all the networks
func ListNetworks() ([]models.Network, error) { func ListNetworks() ([]models.Network, error) {
var networks []models.Network var networks []models.Network
collection := mongoconn.Client.Database("netmaker").Collection("networks") collection, err := database.FetchRecords(database.NETWORKS_TABLE_NAME)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
if err != nil { if err != nil {
return networks, err return networks, err
} }
defer cancel() for _, value := range collection {
for cur.Next(context.TODO()) {
var network models.Network var network models.Network
err := cur.Decode(&network) if err := json.Unmarshal([]byte(value), &network); err != nil {
if err != nil {
return networks, err return networks, err
} }
// add network our array // add network our array
networks = append(networks, network) networks = append(networks, network)
} }
if err := cur.Err(); err != nil {
return networks, err
}
return networks, err return networks, err
} }
@@ -502,20 +387,13 @@ func IsKeyValidGlobal(keyvalue string) bool {
func GetParentNetwork(networkname string) (models.Network, error) { func GetParentNetwork(networkname string) (models.Network, error) {
var network models.Network var network models.Network
networkData, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, networkname)
collection := mongoconn.Client.Database("netmaker").Collection("networks")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"netid": networkname}
err := collection.FindOne(ctx, filter).Decode(&network)
defer cancel()
if err != nil { if err != nil {
return network, err return network, err
} }
if err = json.Unmarshal([]byte(networkData), network); err != nil {
return network, err
}
return network, nil return network, nil
} }
@@ -545,31 +423,6 @@ func IsBase64(s string) bool {
return err == nil return err == nil
} }
//This should probably just be called GetNode
//It returns a node based on the ID of the node.
//Why do we need this?
//TODO: Check references. This seems unnecessary.
func GetNodeObj(id primitive.ObjectID) models.Node {
var node models.Node
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"_id": id}
err := collection.FindOne(ctx, filter).Decode(&node)
defer cancel()
if err != nil {
fmt.Println(err)
fmt.Println("Did not get the node...")
return node
}
fmt.Println("Got node " + node.Name)
return node
}
//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 {
@@ -616,47 +469,41 @@ func GetNodeByMacAddress(network string, macaddress string) (models.Node, error)
var node models.Node var node models.Node
filter := bson.M{"macaddress": macaddress, "network": network} records, err := database.FetchRecords(database.NODES_TABLE_NAME)
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
err := collection.FindOne(ctx, filter).Decode(&node)
defer cancel()
if err != nil { if err != nil {
return node, err return node, err
} }
return node, nil
for _, value := range records {
json.Unmarshal([]byte(value), &node)
if node.MacAddress == macaddress && node.Network == network {
return node, nil
}
}
return models.Node{}, nil
} }
func DeleteAllIntClients() error { func DeleteAllIntClients() error {
collection := mongoconn.Client.Database("netmaker").Collection("intclients") err := database.DeleteAllRecords(database.INT_CLIENTS_TABLE_NAME)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// Filter out them ID's again
err := collection.Drop(ctx)
if err != nil { if err != nil {
return err return err
} }
defer cancel()
return nil return nil
} }
func GetAllIntClients() ([]models.IntClient, error) { func GetAllIntClients() ([]models.IntClient, error) {
var client models.IntClient
var clients []models.IntClient var clients []models.IntClient
collection := mongoconn.Client.Database("netmaker").Collection("intclients") collection, err := database.FetchRecords(database.INT_CLIENTS_TABLE_NAME)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// Filter out them ID's again
cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
if err != nil { if err != nil {
return []models.IntClient{}, err return clients, err
} }
defer cancel()
for cur.Next(context.TODO()) { for _, value := range collection {
err := cur.Decode(&client) var client models.IntClient
err := json.Unmarshal([]byte(value), &client)
if err != nil { if err != nil {
return []models.IntClient{}, err return []models.IntClient{}, err
} }
@@ -664,26 +511,20 @@ func GetAllIntClients() ([]models.IntClient, error) {
clients = append(clients, client) clients = append(clients, client)
} }
//TODO: Fatal error
if err := cur.Err(); err != nil {
return []models.IntClient{}, err
}
return clients, nil return clients, nil
} }
func GetAllExtClients() ([]models.ExtClient, error) { func GetAllExtClients() ([]models.ExtClient, error) {
var extclient models.ExtClient
var extclients []models.ExtClient var extclients []models.ExtClient
collection := mongoconn.Client.Database("netmaker").Collection("extclients") collection, err := database.FetchRecords(database.EXT_CLIENT_TABLE_NAME)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// Filter out them ID's again
cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
if err != nil { if err != nil {
return []models.ExtClient{}, err return extclients, err
} }
defer cancel()
for cur.Next(context.TODO()) { for _, value := range collection {
err := cur.Decode(&extclient) var extclient models.ExtClient
err := json.Unmarshal([]byte(value), &extclient)
if err != nil { if err != nil {
return []models.ExtClient{}, err return []models.ExtClient{}, err
} }
@@ -691,10 +532,6 @@ func GetAllExtClients() ([]models.ExtClient, error) {
extclients = append(extclients, extclient) extclients = append(extclients, extclient)
} }
//TODO: Fatal error
if err := cur.Err(); err != nil {
return []models.ExtClient{}, err
}
return extclients, nil return extclients, nil
} }
@@ -724,11 +561,11 @@ func UniqueAddress(networkName string) (string, error) {
continue continue
} }
if networkName == "comms" { if networkName == "comms" {
if IsIPUniqueClients(networkName, ip.String()) { if IsIPUnique(networkName, ip.String(), database.INT_CLIENTS_TABLE_NAME, false) {
return ip.String(), err return ip.String(), err
} }
} else { } else {
if IsIPUnique(networkName, ip.String()) && IsIPUniqueExtClients(networkName, ip.String()) { if IsIPUnique(networkName, ip.String(), database.NODES_TABLE_NAME, false) && IsIPUnique(networkName, ip.String(), database.EXT_CLIENT_TABLE_NAME, false) {
return ip.String(), err return ip.String(), err
} }
} }
@@ -765,11 +602,11 @@ func UniqueAddress6(networkName string) (string, error) {
continue continue
} }
if networkName == "comms" { if networkName == "comms" {
if IsIP6UniqueClients(networkName, ip.String()) { if IsIPUnique(networkName, ip.String(), database.INT_CLIENTS_TABLE_NAME, true) {
return ip.String(), err return ip.String(), err
} }
} else { } else {
if IsIP6Unique(networkName, ip.String()) { if IsIPUnique(networkName, ip.String(), database.NODES_TABLE_NAME, true) {
return ip.String(), err return ip.String(), err
} }
} }
@@ -814,136 +651,31 @@ func GenKeyName() string {
return "key" + string(b) return "key" + string(b)
} }
func IsIPUniqueExtClients(network string, ip string) bool { func IsIPUnique(network string, ip string, tableName string, isIpv6 bool) bool {
var extclient models.ExtClient
isunique := true isunique := true
collection, err := database.FetchRecords(tableName)
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"address": ip, "network": network}
err := collection.FindOne(ctx, filter).Decode(&extclient)
defer cancel()
if err != nil { if err != nil {
return isunique return isunique
} }
if extclient.Address == ip { for _, value := range collection { // filter
isunique = false var node models.Node
} if err = json.Unmarshal([]byte(value), &node); err != nil {
return isunique continue
} }
if isIpv6 {
//checks if IP is unique in the address range if node.Address6 == ip && node.Network == network {
//used by UniqueAddress return false
func IsIPUnique(network string, ip string) bool { }
} else {
var node models.Node if node.Address == ip && node.Network == network {
return false
isunique := true }
}
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"address": ip, "network": network}
err := collection.FindOne(ctx, filter).Decode(&node)
defer cancel()
if err != nil {
return isunique
} }
if node.Address == ip {
isunique = false
}
return isunique
}
//checks if IP is unique in the address range
//used by UniqueAddress
func IsIP6Unique(network string, ip string) bool {
var node models.Node
isunique := true
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"address6": ip, "network": network}
err := collection.FindOne(ctx, filter).Decode(&node)
defer cancel()
if err != nil {
return isunique
}
if node.Address6 == ip {
isunique = false
}
return isunique
}
//checks if IP is unique in the address range
//used by UniqueAddress
func IsIP6UniqueClients(network string, ip string) bool {
var client models.IntClient
isunique := true
collection := mongoconn.Client.Database("netmaker").Collection("intclients")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"address6": ip, "network": network}
err := collection.FindOne(ctx, filter).Decode(&client)
defer cancel()
if err != nil {
return isunique
}
if client.Address6 == ip {
isunique = false
}
return isunique
}
//checks if IP is unique in the address range
//used by UniqueAddress
func IsIPUniqueClients(network string, ip string) bool {
var client models.IntClient
isunique := true
collection := mongoconn.Client.Database("netmaker").Collection("intclients")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"address": ip, "network": network}
err := collection.FindOne(ctx, filter).Decode(&client)
defer cancel()
if err != nil {
return isunique
}
if client.Address == ip {
isunique = false
}
return isunique return isunique
} }
@@ -964,31 +696,18 @@ func DecrimentKey(networkName string, keyvalue string) {
if currentkey.Value == keyvalue { if currentkey.Value == keyvalue {
network.AccessKeys[i].Uses-- network.AccessKeys[i].Uses--
if network.AccessKeys[i].Uses < 1 { if network.AccessKeys[i].Uses < 1 {
//this is the part where it will call the delete network.AccessKeys = append(network.AccessKeys[:i],
//not sure if there's edge cases I'm missing network.AccessKeys[i+1:]...)
DeleteKey(network, i) break
return
} }
} }
} }
collection := mongoconn.Client.Database("netmaker").Collection("networks") if newNetworkData, err := json.Marshal(&network); err != nil {
PrintUserLog("netmaker", "failed to decrement key", 2)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"netid": network.NetID}
update := bson.D{
{"$set", bson.D{
{"accesskeys", network.AccessKeys},
}},
}
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
defer cancel()
if errN != nil {
return return
} else {
database.Insert(network.NetID, string(newNetworkData), database.NETWORKS_TABLE_NAME)
} }
} }
@@ -998,26 +717,10 @@ func DeleteKey(network models.Network, i int) {
network.AccessKeys = append(network.AccessKeys[:i], network.AccessKeys = append(network.AccessKeys[:i],
network.AccessKeys[i+1:]...) network.AccessKeys[i+1:]...)
collection := mongoconn.Client.Database("netmaker").Collection("networks") if networkData, err := json.Marshal(&network); err != nil {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// Create filter
filter := bson.M{"netid": network.NetID}
// prepare update model.
update := bson.D{
{"$set", bson.D{
{"accesskeys", network.AccessKeys},
}},
}
errN := collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
defer cancel()
if errN != nil {
return return
} else {
database.Insert(network.NetID, string(networkData), database.NETWORKS_TABLE_NAME)
} }
} }
@@ -1032,28 +735,21 @@ func Inc(ip net.IP) {
} }
func GetAllNodes() ([]models.Node, error) { func GetAllNodes() ([]models.Node, error) {
var node models.Node
var nodes []models.Node var nodes []models.Node
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
// Filter out them ID's again
cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
if err != nil { if err != nil {
return []models.Node{}, err return []models.Node{}, err
} }
defer cancel()
for cur.Next(context.TODO()) { for _, value := range collection {
err := cur.Decode(&node) var node models.Node
if err != nil { if err := json.Unmarshal([]byte(value), &node); err != nil {
return []models.Node{}, err return []models.Node{}, err
} }
// add node to our array // add node to our array
nodes = append(nodes, node) nodes = append(nodes, node)
} }
//TODO: Fatal error
if err := cur.Err(); err != nil {
return []models.Node{}, err
}
return nodes, nil return nodes, nil
} }

3
go.mod
View File

@@ -6,10 +6,13 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/go-playground/validator/v10 v10.5.0 github.com/go-playground/validator/v10 v10.5.0
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 github.com/golang/protobuf v1.5.2
github.com/gorilla/handlers v1.5.1 github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/jinzhu/copier v0.3.2 // indirect github.com/jinzhu/copier v0.3.2 // indirect
github.com/mattn/go-sqlite3 v1.14.8
github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.6.1 github.com/stretchr/testify v1.6.1
github.com/txn2/txeh v1.3.0 github.com/txn2/txeh v1.3.0

6
go.sum
View File

@@ -34,6 +34,8 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+
github.com/go-playground/validator/v10 v10.5.0 h1:X9rflw/KmpACwT8zdrm1upefpvdy6ur8d1kWyq6sg3E= github.com/go-playground/validator/v10 v10.5.0 h1:X9rflw/KmpACwT8zdrm1upefpvdy6ur8d1kWyq6sg3E=
github.com/go-playground/validator/v10 v10.5.0/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk= github.com/go-playground/validator/v10 v10.5.0/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
@@ -119,6 +121,8 @@ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgx
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0= github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0=
github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc= github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc=
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
@@ -142,6 +146,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f h1:BSnJgAfHzEp7o8PYJ7YfwAVHhqu7BYUTggcn/LGlUWY=
github.com/rqlite/gorqlite v0.0.0-20210514125552-08ff1e76b22f/go.mod h1:UW/gxgQwSePTvL1KA8QEHsXeYHP4xkoXgbDdN781p34=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=

250
main.go
View File

@@ -4,80 +4,75 @@
package main package main
import ( import (
"log" "context"
"github.com/gravitl/netmaker/controllers" "log"
"github.com/gravitl/netmaker/servercfg" "net"
"github.com/gravitl/netmaker/serverctl" "os"
"github.com/gravitl/netmaker/mongoconn" "os/exec"
"github.com/gravitl/netmaker/functions" "os/signal"
"os" "strconv"
"os/exec" "sync"
"net"
"context" controller "github.com/gravitl/netmaker/controllers"
"strconv" "github.com/gravitl/netmaker/database"
"sync" "github.com/gravitl/netmaker/functions"
"os/signal" nodepb "github.com/gravitl/netmaker/grpc"
service "github.com/gravitl/netmaker/controllers" "github.com/gravitl/netmaker/mongoconn"
nodepb "github.com/gravitl/netmaker/grpc" "github.com/gravitl/netmaker/servercfg"
"google.golang.org/grpc" "github.com/gravitl/netmaker/serverctl"
"google.golang.org/grpc"
) )
//Start MongoDB Connection and start API Request Handler //Start MongoDB Connection and start API Request Handler
func main() { func main() {
checkModes() // check which flags are set and if root or not
initialize() // initial db and grpc server
defer database.Database.Close()
startControllers() // start the grpc or rest endpoints
}
func checkModes() { // Client Mode Prereq Check
var err error
cmd := exec.Command("id", "-u")
output, err := cmd.Output()
//Client Mode Prereq Check
if servercfg.IsClientMode() {
cmd := exec.Command("id", "-u")
output, err := cmd.Output()
if err != nil {
log.Println("Error running 'id -u' for prereq check. Please investigate or disable client mode.")
log.Fatal(err)
}
i, err := strconv.Atoi(string(output[:len(output)-1]))
if err != nil {
log.Println("Error retrieving uid from 'id -u' for prereq check. Please investigate or disable client mode.")
log.Fatal(err)
}
if i != 0 {
log.Fatal("To run in client mode requires root privileges. Either disable client mode or run with sudo.")
}
}
if servercfg.IsDNSMode() {
err := functions.SetDNSDir()
if err != nil {
log.Fatal(err)
}
}
//Start Mongodb
mongoconn.ConnectDatabase()
installserver := false
//Create the default network (default: 10.10.10.0/24)
created, err := serverctl.CreateDefaultNetwork()
if err != nil { if err != nil {
log.Printf("Error creating default network: %v", err) log.Println("Error running 'id -u' for prereq check. Please investigate or disable client mode.")
log.Fatal(err)
}
uid, err := strconv.Atoi(string(output[:len(output)-1]))
if err != nil {
log.Println("Error retrieving uid from 'id -u' for prereq check. Please investigate or disable client mode.")
log.Fatal(err)
}
if uid != 0 {
log.Fatal("To run in client mode requires root privileges. Either disable client mode or run with sudo.")
} }
if created && servercfg.IsClientMode() { if servercfg.IsDNSMode() {
installserver = true err := functions.SetDNSDir()
} if err != nil {
if servercfg.IsGRPCWireGuard() { log.Fatal(err)
err = serverctl.InitServerWireGuard()
//err = serverctl.ReconfigureServerWireGuard()
if err != nil {
log.Fatal(err)
} }
} }
var waitnetwork sync.WaitGroup }
func initialize() {
database.InitializeDatabase()
if servercfg.IsGRPCWireGuard() {
if err := serverctl.InitServerWireGuard(); err != nil {
log.Fatal(err)
}
}
functions.PrintUserLog("netmaker", "successfully created db tables if not present", 1)
}
func startControllers() {
var waitnetwork sync.WaitGroup
//Run Agent Server //Run Agent Server
if servercfg.IsAgentBackend() { if servercfg.IsAgentBackend() {
if !(servercfg.DisableRemoteIPCheck()) && servercfg.GetGRPCHost() == "127.0.0.1" { if !(servercfg.DisableRemoteIPCheck()) && servercfg.GetGRPCHost() == "127.0.0.1" {
err := servercfg.SetHost() err := servercfg.SetHost()
if err != nil { if err != nil {
log.Println("Unable to Set host. Exiting...") log.Println("Unable to Set host. Exiting...")
@@ -85,23 +80,23 @@ func main() {
} }
} }
waitnetwork.Add(1) waitnetwork.Add(1)
go runGRPC(&waitnetwork, installserver) go runGRPC(&waitnetwork)
} }
if servercfg.IsDNSMode() { if servercfg.IsDNSMode() {
err := controller.SetDNS() err := controller.SetDNS()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
//Run Rest Server //Run Rest Server
if servercfg.IsRestBackend() { if servercfg.IsRestBackend() {
if !servercfg.DisableRemoteIPCheck() && servercfg.GetAPIHost() == "127.0.0.1" { if !servercfg.DisableRemoteIPCheck() && servercfg.GetAPIHost() == "127.0.0.1" {
err := servercfg.SetHost() err := servercfg.SetHost()
if err != nil { if err != nil {
log.Println("Unable to Set host. Exiting...") log.Println("Unable to Set host. Exiting...")
log.Fatal(err) log.Fatal(err)
} }
} }
waitnetwork.Add(1) waitnetwork.Add(1)
controller.HandleRESTRequests(&waitnetwork) controller.HandleRESTRequests(&waitnetwork)
} }
@@ -112,88 +107,67 @@ func main() {
log.Println("exiting") log.Println("exiting")
} }
func runGRPC(wg *sync.WaitGroup) {
func runGRPC(wg *sync.WaitGroup, installserver bool) {
defer wg.Done() defer wg.Done()
// Configure 'log' package to give file name and line number on eg. log.Fatal // Configure 'log' package to give file name and line number on eg. log.Fatal
// Pipe flags to one another (log.LstdFLags = log.Ldate | log.Ltime) // Pipe flags to one another (log.LstdFLags = log.Ldate | log.Ltime)
log.SetFlags(log.LstdFlags | log.Lshortfile) log.SetFlags(log.LstdFlags | log.Lshortfile)
grpcport := servercfg.GetGRPCPort() grpcport := servercfg.GetGRPCPort()
listener, err := net.Listen("tcp", ":"+grpcport) listener, err := net.Listen("tcp", ":"+grpcport)
// Handle errors if any // Handle errors if any
if err != nil { if err != nil {
log.Fatalf("Unable to listen on port " + grpcport + ", error: %v", err) log.Fatalf("Unable to listen on port "+grpcport+", error: %v", err)
}
s := grpc.NewServer(
authServerUnaryInterceptor(),
authServerStreamInterceptor(),
)
// Create NodeService type
srv := &service.NodeServiceServer{}
// Register the service with the server
nodepb.RegisterNodeServiceServer(s, srv)
srv.NodeDB = mongoconn.NodeDB
// Start the server in a child routine
go func() {
if err := s.Serve(listener); err != nil {
log.Fatalf("Failed to serve: %v", err)
}
}()
log.Println("Agent Server succesfully started on port " + grpcport + " (gRPC)")
if installserver {
success := true
if !servercfg.DisableDefaultNet() {
log.Println("Adding server to default network")
success, err = serverctl.AddNetwork("default")
}
if err != nil {
log.Printf("Error adding to default network: %v", err)
log.Println("Unable to add server to network. Continuing.")
log.Println("Please investigate client installation on server.")
} else if !success {
log.Println("Unable to add server to network. Continuing.")
log.Println("Please investigate client installation on server.")
} else{
log.Println("Server successfully added to default network.")
}
} }
log.Println("Setup complete. You are ready to begin using netmaker.")
// Right way to stop the server using a SHUTDOWN HOOK s := grpc.NewServer(
// Create a channel to receive OS signals authServerUnaryInterceptor(),
c := make(chan os.Signal) authServerStreamInterceptor(),
)
// Create NodeService type
srv := &controller.NodeServiceServer{}
// Relay os.Interrupt to our channel (os.Interrupt = CTRL+C) // Register the service with the server
// Ignore other incoming signals nodepb.RegisterNodeServiceServer(s, srv)
signal.Notify(c, os.Interrupt)
// Block main routine until a signal is received srv.NodeDB = mongoconn.NodeDB
// As long as user doesn't press CTRL+C a message is not passed and our main routine keeps running
<-c
// After receiving CTRL+C Properly stop the server // Start the server in a child routine
log.Println("Stopping the Agent server...") go func() {
s.Stop() if err := s.Serve(listener); err != nil {
listener.Close() log.Fatalf("Failed to serve: %v", err)
log.Println("Agent server closed..") }
log.Println("Closing MongoDB connection") }()
mongoconn.Client.Disconnect(context.TODO()) log.Println("Agent Server succesfully started on port " + grpcport + " (gRPC)")
log.Println("MongoDB connection closed.")
// Right way to stop the server using a SHUTDOWN HOOK
// Create a channel to receive OS signals
c := make(chan os.Signal)
// Relay os.Interrupt to our channel (os.Interrupt = CTRL+C)
// Ignore other incoming signals
signal.Notify(c, os.Interrupt)
// Block main routine until a signal is received
// As long as user doesn't press CTRL+C a message is not passed and our main routine keeps running
<-c
// After receiving CTRL+C Properly stop the server
log.Println("Stopping the Agent server...")
s.Stop()
listener.Close()
log.Println("Agent server closed..")
log.Println("Closing MongoDB connection")
mongoconn.Client.Disconnect(context.TODO())
log.Println("MongoDB connection closed.")
} }
func authServerUnaryInterceptor() grpc.ServerOption { func authServerUnaryInterceptor() grpc.ServerOption {
return grpc.UnaryInterceptor(controller.AuthServerUnaryInterceptor) return grpc.UnaryInterceptor(controller.AuthServerUnaryInterceptor)
} }
func authServerStreamInterceptor() grpc.ServerOption { func authServerStreamInterceptor() grpc.ServerOption {
return grpc.StreamInterceptor(controller.AuthServerStreamInterceptor) return grpc.StreamInterceptor(controller.AuthServerStreamInterceptor)
} }

View File

@@ -1,137 +1,92 @@
package serverctl package serverctl
import ( import (
"log" "context"
"encoding/json"
"errors"
"io"
"log"
"os"
"os/exec"
"time"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions" "github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mongoconn" "github.com/gravitl/netmaker/mongoconn"
"github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/servercfg"
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/options"
"io"
"time"
"context"
"errors"
"os"
"os/exec"
) )
func CreateDefaultNetwork() (bool, error) {
log.Println("Creating default network...")
iscreated := false
exists, err := functions.NetworkExists("default")
if exists || err != nil {
log.Println("Default network already exists. Skipping...")
return iscreated, err
} else {
var network models.Network
network.NetID = "default"
network.AddressRange = "10.10.10.0/24"
network.DisplayName = "default"
network.SetDefaults()
network.SetNodesLastModified()
network.SetNetworkLastModified()
network.KeyUpdateTimeStamp = time.Now().Unix()
priv := false
network.IsLocal = &priv
network.KeyUpdateTimeStamp = time.Now().Unix()
allow := true
network.AllowManualSignUp = &allow
collection := mongoconn.Client.Database("netmaker").Collection("networks")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// insert our network into the network table
_, err = collection.InsertOne(ctx, network)
defer cancel()
}
if err == nil {
iscreated = true
}
return iscreated, err
}
func GetServerWGConf() (models.IntClient, error) { func GetServerWGConf() (models.IntClient, error) {
var server models.IntClient var server models.IntClient
collection := mongoconn.Client.Database("netmaker").Collection("intclients") collection := mongoconn.Client.Database("netmaker").Collection("intclients")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"network": "comms", "isserver": "yes"} filter := bson.M{"network": "comms", "isserver": "yes"}
err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&server) err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&server)
defer cancel() defer cancel()
return server, err return server, err
} }
func CreateCommsNetwork() (bool, error) { func CreateCommsNetwork() (bool, error) {
iscreated := false iscreated := false
exists, err := functions.NetworkExists("comms") exists, err := functions.NetworkExists("comms")
if exists || err != nil { if exists || err != nil {
log.Println("comms network already exists. Skipping...") log.Println("comms network already exists. Skipping...")
return true, nil return true, err
} else { } else {
var network models.Network
var network models.Network network.NetID = "comms"
network.IsIPv6 = "no"
network.IsIPv4 = "yes"
network.IsGRPCHub = "yes"
network.AddressRange = servercfg.GetGRPCWGAddressRange()
network.DisplayName = "comms"
network.SetDefaults()
network.SetNodesLastModified()
network.SetNetworkLastModified()
network.KeyUpdateTimeStamp = time.Now().Unix()
priv := false
network.IsLocal = &priv
network.KeyUpdateTimeStamp = time.Now().Unix()
network.NetID = "comms" log.Println("Creating comms network...")
network.IsIPv6 = "no" value, err := json.Marshal(network)
network.IsIPv4 = "yes" if err != nil {
network.IsGRPCHub = "yes" return false, err
network.AddressRange = servercfg.GetGRPCWGAddressRange() }
network.DisplayName = "comms" database.Insert(network.NetID, string(value), database.NETWORKS_TABLE_NAME)
network.SetDefaults() }
network.SetNodesLastModified() if err == nil {
network.SetNetworkLastModified() iscreated = true
network.KeyUpdateTimeStamp = time.Now().Unix() }
priv := false return iscreated, err
network.IsLocal = &priv
network.KeyUpdateTimeStamp = time.Now().Unix()
log.Println("Creating comms network...")
collection := mongoconn.Client.Database("netmaker").Collection("networks")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// insert our network into the network table
_, err = collection.InsertOne(ctx, network)
defer cancel()
}
if err == nil {
iscreated = true
}
return iscreated, err
} }
func DownloadNetclient() error { func DownloadNetclient() error {
/* /*
// Get the data // Get the data
resp, err := http.Get("https://github.com/gravitl/netmaker/releases/download/latest/netclient") resp, err := http.Get("https://github.com/gravitl/netmaker/releases/download/latest/netclient")
if err != nil { if err != nil {
log.Println("could not download netclient") log.Println("could not download netclient")
return err return err
} }
defer resp.Body.Close() defer resp.Body.Close()
// Create the file // Create the file
out, err := os.Create("/etc/netclient/netclient") out, err := os.Create("/etc/netclient/netclient")
*/ */
if !FileExists("/etc/netclient/netclient") { if !FileExists("/etc/netclient/netclient") {
_, err := copy("./netclient/netclient", "/etc/netclient/netclient") _, err := copy("./netclient/netclient", "/etc/netclient/netclient")
if err != nil { if err != nil {
log.Println("could not create /etc/netclient") log.Println("could not create /etc/netclient")
return err return err
} }
} }
//defer out.Close() //defer out.Close()
@@ -141,98 +96,97 @@ func DownloadNetclient() error {
} }
func FileExists(f string) bool { func FileExists(f string) bool {
info, err := os.Stat(f) info, err := os.Stat(f)
if os.IsNotExist(err) { if os.IsNotExist(err) {
return false return false
} }
return !info.IsDir() return !info.IsDir()
} }
func copy(src, dst string) (int64, error) { func copy(src, dst string) (int64, error) {
sourceFileStat, err := os.Stat(src) sourceFileStat, err := os.Stat(src)
if err != nil { if err != nil {
return 0, err return 0, err
} }
if !sourceFileStat.Mode().IsRegular() { if !sourceFileStat.Mode().IsRegular() {
return 0, errors.New(src + " is not a regular file") return 0, errors.New(src + " is not a regular file")
} }
source, err := os.Open(src) source, err := os.Open(src)
if err != nil { if err != nil {
return 0, err return 0, err
} }
defer source.Close() defer source.Close()
destination, err := os.Create(dst) destination, err := os.Create(dst)
if err != nil { if err != nil {
return 0, err return 0, err
} }
defer destination.Close() defer destination.Close()
nBytes, err := io.Copy(destination, source) nBytes, err := io.Copy(destination, source)
err = os.Chmod(dst, 0755) err = os.Chmod(dst, 0755)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
} }
return nBytes, err return nBytes, err
} }
func RemoveNetwork(network string) (bool, error) { func RemoveNetwork(network string) (bool, error) {
_, err := os.Stat("/etc/netclient/netclient") _, err := os.Stat("/etc/netclient/netclient")
if err != nil { if err != nil {
log.Println("could not find /etc/netclient") log.Println("could not find /etc/netclient")
return false, err return false, err
} }
cmdoutput, err := exec.Command("/etc/netclient/netclient","leave","-n",network).Output() cmdoutput, err := exec.Command("/etc/netclient/netclient", "leave", "-n", network).Output()
if err != nil { if err != nil {
log.Println(string(cmdoutput)) log.Println(string(cmdoutput))
return false, err return false, err
} }
log.Println("Server removed from network " + network) log.Println("Server removed from network " + network)
return true, err return true, err
} }
func AddNetwork(network string) (bool, error) { func AddNetwork(network string) (bool, error) {
pubip, err := servercfg.GetPublicIP() pubip, err := servercfg.GetPublicIP()
if err != nil { if err != nil {
log.Println("could not get public IP.") log.Println("could not get public IP.")
return false, err return false, err
} }
_, err = os.Stat("/etc/netclient") _, err = os.Stat("/etc/netclient")
if os.IsNotExist(err) { if os.IsNotExist(err) {
os.Mkdir("/etc/netclient", 744) os.Mkdir("/etc/netclient", 744)
} else if err != nil { } else if err != nil {
log.Println("could not find or create /etc/netclient") log.Println("could not find or create /etc/netclient")
return false, err return false, err
} }
token, err := functions.CreateServerToken(network) token, err := functions.CreateServerToken(network)
if err != nil { if err != nil {
log.Println("could not create server token for " + network) log.Println("could not create server token for " + network)
return false, err return false, err
} }
_, err = os.Stat("/etc/netclient/netclient") _, err = os.Stat("/etc/netclient/netclient")
if os.IsNotExist(err) { if os.IsNotExist(err) {
err = DownloadNetclient() err = DownloadNetclient()
if err != nil { if err != nil {
return false, err return false, err
} }
} }
err = os.Chmod("/etc/netclient/netclient", 0755) err = os.Chmod("/etc/netclient/netclient", 0755)
if err != nil { if err != nil {
log.Println("could not change netclient directory permissions") log.Println("could not change netclient directory permissions")
return false, err return false, err
} }
log.Println("executing network join: " + "/etc/netclient/netclient "+"join "+"-t "+token+" -name "+"netmaker"+" -endpoint "+pubip) log.Println("executing network join: " + "/etc/netclient/netclient " + "join " + "-t " + token + " -name " + "netmaker" + " -endpoint " + pubip)
out, err := exec.Command("/etc/netclient/netclient","join","-t",token,"-name","netmaker","-endpoint",pubip).Output() out, err := exec.Command("/etc/netclient/netclient", "join", "-t", token, "-name", "netmaker", "-endpoint", pubip).Output()
if string(out) != "" { if string(out) != "" {
log.Println(string(out)) log.Println(string(out))
} }
if err != nil { if err != nil {
return false, errors.New(string(out) + err.Error()) return false, errors.New(string(out) + err.Error())
} }
log.Println("Server added to network " + network) log.Println("Server added to network " + network)
return true, err return true, err
} }

View File

@@ -1,21 +1,22 @@
package serverctl package serverctl
import ( import (
//"github.com/davecgh/go-spew/spew" //"github.com/davecgh/go-spew/spew"
"os"
"log" "encoding/json"
"context"
"time"
"net"
"strconv"
"errors" "errors"
"log"
"net"
"os"
"strconv"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
"github.com/vishvananda/netlink" "github.com/vishvananda/netlink"
"golang.zx2c4.com/wireguard/wgctrl" "golang.zx2c4.com/wireguard/wgctrl"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes" "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"github.com/gravitl/netmaker/servercfg"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mongoconn"
) )
func InitServerWireGuard() error { func InitServerWireGuard() error {
@@ -50,9 +51,9 @@ func InitServerWireGuard() error {
} }
err = netlink.AddrAdd(wglink, address) err = netlink.AddrAdd(wglink, address)
if err != nil && !os.IsExist(err){ if err != nil && !os.IsExist(err) {
return err return err
} }
err = netlink.LinkSetUp(wglink) err = netlink.LinkSetUp(wglink)
if err != nil { if err != nil {
log.Println("could not bring up wireguard interface") log.Println("could not bring up wireguard interface")
@@ -69,105 +70,104 @@ func InitServerWireGuard() error {
client.Address = servercfg.GetGRPCWGAddress() client.Address = servercfg.GetGRPCWGAddress()
client.IsServer = "yes" client.IsServer = "yes"
client.Network = "comms" client.Network = "comms"
exists, _ := functions.ServerIntClientExists() exists, _ := functions.GetServerIntClient()
if exists { if exists != nil {
err = RegisterServer(client)
} }
err = RegisterServer(client) return err
return err
} }
func DeleteServerClient() error { func DeleteServerClient() error {
return nil return nil
} }
func RegisterServer(client models.IntClient) error { func RegisterServer(client models.IntClient) error {
if client.PrivateKey == "" { if client.PrivateKey == "" {
privateKey, err := wgtypes.GeneratePrivateKey() privateKey, err := wgtypes.GeneratePrivateKey()
if err != nil { if err != nil {
return err return err
} }
client.PrivateKey = privateKey.String() client.PrivateKey = privateKey.String()
client.PublicKey = privateKey.PublicKey().String() client.PublicKey = privateKey.PublicKey().String()
} }
if client.Address == "" { if client.Address == "" {
newAddress, err := functions.UniqueAddress(client.Network) newAddress, err := functions.UniqueAddress(client.Network)
if err != nil { if err != nil {
return err return err
} }
if newAddress == "" { if newAddress == "" {
return errors.New("Could not retrieve address") return errors.New("Could not retrieve address")
} }
client.Address = newAddress client.Address = newAddress
} }
if client.Network == "" { client.Network = "comms" } if client.Network == "" {
client.ServerKey = client.PublicKey client.Network = "comms"
}
client.ServerKey = client.PublicKey
value, err := json.Marshal(client)
if err != nil {
return err
}
database.Insert(client.PublicKey, string(value), database.INT_CLIENTS_TABLE_NAME)
collection := mongoconn.Client.Database("netmaker").Collection("intclients") ReconfigureServerWireGuard()
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// insert our network into the network table
_, err := collection.InsertOne(ctx, client)
defer cancel()
ReconfigureServerWireGuard() return err
return err
} }
func ReconfigureServerWireGuard() error { func ReconfigureServerWireGuard() error {
server, err := GetServerWGConf() server, err := functions.GetServerIntClient()
if err != nil { if err != nil {
return err return err
} }
serverkey, err := wgtypes.ParseKey(server.PrivateKey) serverkey, err := wgtypes.ParseKey(server.PrivateKey)
if err != nil { if err != nil {
return err return err
} }
serverport, err := strconv.Atoi(servercfg.GetGRPCWGPort()) serverport, err := strconv.Atoi(servercfg.GetGRPCWGPort())
if err != nil { if err != nil {
return err return err
} }
peers, err := functions.GetIntPeersList() peers, err := functions.GetIntPeersList()
if err != nil { if err != nil {
return err return err
} }
wgserver, err := wgctrl.New() wgserver, err := wgctrl.New()
if err != nil { if err != nil {
return err return err
} }
var serverpeers []wgtypes.PeerConfig var serverpeers []wgtypes.PeerConfig
for _, peer := range peers { for _, peer := range peers {
pubkey, err := wgtypes.ParseKey(peer.PublicKey) pubkey, err := wgtypes.ParseKey(peer.PublicKey)
if err != nil { if err != nil {
return err return err
} }
var peercfg wgtypes.PeerConfig var peercfg wgtypes.PeerConfig
var allowedips []net.IPNet var allowedips []net.IPNet
if peer.Address != "" { if peer.Address != "" {
var peeraddr = net.IPNet{ var peeraddr = net.IPNet{
IP: net.ParseIP(peer.Address), IP: net.ParseIP(peer.Address),
Mask: net.CIDRMask(32, 32), Mask: net.CIDRMask(32, 32),
} }
allowedips = append(allowedips, peeraddr) allowedips = append(allowedips, peeraddr)
} }
if peer.Address6 != "" { if peer.Address6 != "" {
var addr6 = net.IPNet{ var addr6 = net.IPNet{
IP: net.ParseIP(peer.Address6), IP: net.ParseIP(peer.Address6),
Mask: net.CIDRMask(128, 128), Mask: net.CIDRMask(128, 128),
} }
allowedips = append(allowedips, addr6) allowedips = append(allowedips, addr6)
} }
peercfg = wgtypes.PeerConfig{ peercfg = wgtypes.PeerConfig{
PublicKey: pubkey, PublicKey: pubkey,
ReplaceAllowedIPs: true, ReplaceAllowedIPs: true,
AllowedIPs: allowedips, AllowedIPs: allowedips,
} }
serverpeers = append(serverpeers, peercfg) serverpeers = append(serverpeers, peercfg)
} }
wgconf := wgtypes.Config{ wgconf := wgtypes.Config{