began refactoring of client

This commit is contained in:
worker-9
2021-08-02 18:06:26 -04:00
parent a2f27e27ec
commit 44d03f6805
28 changed files with 1801 additions and 4340 deletions

View File

@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"errors"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions"
nodepb "github.com/gravitl/netmaker/grpc"
@@ -97,12 +98,17 @@ func grpcAuthorize(ctx context.Context) error {
}
//Node authenticates using its password and retrieves a JWT for authorization.
func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.LoginRequest) (*nodepb.LoginResponse, error) {
func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
//out := new(LoginResponse)
macaddress := req.GetMacaddress()
network := req.GetNetwork()
password := req.GetPassword()
var reqNode models.Node
if err := json.Unmarshal([]byte(req.Data), &reqNode); err != nil {
return nil, err
}
macaddress := reqNode.MacAddress
network := reqNode.Network
password := reqNode.Password
var result models.NodeAuth
@@ -148,8 +154,9 @@ func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.LoginRequest)
return nil, err
}
response := &nodepb.LoginResponse{
Accesstoken: tokenString,
response := &nodepb.Object{
Data: tokenString,
Type: nodepb.ACCESS_TOKEN,
}
return response, nil
}

View File

@@ -2,7 +2,6 @@ package controller
import (
"encoding/json"
"fmt"
"log"
"strconv"
"strings"
@@ -16,9 +15,9 @@ import (
"golang.org/x/crypto/bcrypt"
)
func GetPeersList(networkName string) ([]models.PeersResponse, error) {
func GetPeersList(networkName string) ([]models.Node, error) {
var peers []models.PeersResponse
var peers []models.Node
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
if err != nil {
log.Println(err)
@@ -30,35 +29,31 @@ func GetPeersList(networkName string) ([]models.PeersResponse, error) {
}
for _, value := range collection {
var node models.Node
var peer models.PeersResponse
var peer models.Node
err := json.Unmarshal([]byte(value), &node)
if err != nil {
log.Println(err)
continue
}
err = json.Unmarshal([]byte(value), &peer)
if err != nil {
log.Println(err)
continue
}
if node.IsEgressGateway == "yes" {
peer.EgressGatewayRanges = strings.Join(node.EgressGatewayRanges, ",")
peer.EgressGatewayRanges = node.EgressGatewayRanges
}
if node.Network == networkName && node.IsPending != "yes" {
if node.UDPHolePunch == "yes" && errN == nil && functions.CheckEndpoint(udppeers[peer.PublicKey]) {
endpointstring := udppeers[peer.PublicKey]
peer.PublicKey = node.PublicKey
if node.UDPHolePunch == "yes" && errN == nil && functions.CheckEndpoint(udppeers[node.PublicKey]) {
endpointstring := udppeers[node.PublicKey]
endpointarr := strings.Split(endpointstring, ":")
log.Println("got values:",endpointstring,endpointarr)
log.Println("got values:", endpointstring, endpointarr)
if len(endpointarr) == 2 {
port, err := strconv.Atoi(endpointarr[1])
if err == nil {
log.Println("overriding:",endpointarr[0],int32(port))
log.Println("overriding:", endpointarr[0], int32(port))
peer.Endpoint = endpointarr[0]
peer.ListenPort = int32(port)
}
}
}
log.Println("setting peer:",peer.PublicKey,peer.Endpoint,peer.ListenPort)
log.Println("setting peer:", peer.PublicKey, peer.Endpoint, peer.ListenPort)
peers = append(peers, peer)
}
}
@@ -98,21 +93,38 @@ func GetExtPeersList(networkName string, macaddress string) ([]models.ExtPeersRe
return peers, err
}
func DeleteNode(macaddress string, network string) error {
key, err := functions.GetRecordKey(macaddress, network)
if err != nil {
/**
* 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
*/
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 {
log.Println(err)
}
}
if err := database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil {
return err
}
if err = database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil {
return err
}
err = SetNetworkNodesLastModified(network)
if servercfg.IsDNSMode() {
err = SetDNS()
}
return err
}
@@ -136,6 +148,10 @@ func GetNode(macaddress string, network string) (models.Node, error) {
}
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 {
@@ -222,84 +238,6 @@ func NotifyNetworkCheck(networkName string) bool {
}
}
func NodeCheckIn(node models.Node, networkName string) (models.CheckInResponse, error) {
var response models.CheckInResponse
parentnetwork, err := functions.GetParentNetwork(networkName)
if err != nil {
err = fmt.Errorf("%w; Couldnt retrieve Network "+networkName+": ", err)
return response, err
}
parentnode, err := GetNode(node.MacAddress, networkName)
if err != nil {
err = fmt.Errorf("%w; Couldnt Get Node "+node.MacAddress, err)
return response, err
}
if parentnode.Name == "netmaker" {
if NotifyNetworkCheck(networkName) {
err := SetNetworkNodesLastModified(networkName)
if err != nil {
log.Println(err, "could not notify network to update peers")
}
}
return models.CheckInResponse{
Success:true,
NeedPeerUpdate:true,
NeedKeyUpdate: false,
NeedConfigUpdate:false,
NeedDelete:false,
NodeMessage:"",
IsPending:false,
}, nil
}
if parentnode.IsPending == "yes" {
err = fmt.Errorf("%w; Node checking in is still pending: "+node.MacAddress, err)
response.IsPending = true
return response, err
}
networklm := parentnetwork.NetworkLastModified
peerslm := parentnetwork.NodesLastModified
gkeyupdate := parentnetwork.KeyUpdateTimeStamp
nkeyupdate := parentnode.KeyUpdateTimeStamp
peerlistlm := parentnode.LastPeerUpdate
parentnodelm := parentnode.LastModified
parentnodelastcheckin := parentnode.LastCheckIn
if parentnodelastcheckin < parentnodelm {
response.NeedConfigUpdate = true
}
if parentnodelm < networklm {
response.NeedConfigUpdate = true
}
if peerlistlm < peerslm {
response.NeedPeerUpdate = true
}
if nkeyupdate < gkeyupdate {
response.NeedKeyUpdate = true
}
if time.Now().Unix() > parentnode.ExpirationDateTime {
response.NeedDelete = true
err = DeleteNode(node.MacAddress, networkName)
} else {
err = TimestampNode(parentnode, true, false, false)
if err != nil {
err = fmt.Errorf("%w; Couldnt Timestamp Node: ", err)
return response, err
}
}
response.Success = true
return response, err
}
func SetNetworkNodesLastModified(networkName string) error {
timestamp := time.Now().Unix()

View File

@@ -4,10 +4,11 @@ import (
"encoding/base64"
"encoding/json"
"errors"
"log"
"net/http"
"strings"
"time"
"log"
"github.com/go-playground/validator/v10"
"github.com/gorilla/mux"
"github.com/gravitl/netmaker/database"
@@ -232,17 +233,11 @@ func keyUpdate(w http.ResponseWriter, r *http.Request) {
}
func KeyUpdate(netname string) (models.Network, error) {
network, err := functions.GetParentNetwork(netname)
err := functions.NetworkNodesUpdateKey(netname)
if err != nil {
return models.Network{}, err
}
network.KeyUpdateTimeStamp = time.Now().Unix()
data, err := json.Marshal(&network)
if err != nil {
return models.Network{}, err
}
database.Insert(netname, string(data), database.NETWORKS_TABLE_NAME)
return network, nil
return models.Network{}, nil
}
//Update a network

View File

@@ -2,83 +2,53 @@ package controller
import (
"context"
"fmt"
"encoding/json"
"errors"
"log"
"github.com/gravitl/netmaker/functions"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type NodeServiceServer struct {
nodepb.UnimplementedNodeServiceServer
}
func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.ReadNodeReq) (*nodepb.ReadNodeRes, error) {
func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
// convert string id (from proto) to mongoDB ObjectId
macaddress := req.GetMacaddress()
networkName := req.GetNetwork()
network, _ := functions.GetParentNetwork(networkName)
var node models.Node
if err := json.Unmarshal([]byte(req.Data), &node); err != nil {
return nil, err
}
macaddress := node.MacAddress
networkName := node.Network
node, err := GetNode(macaddress, networkName)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, fmt.Sprintf("Something went wrong: %v", err))
log.Println("could not get node "+macaddress+" "+networkName, err)
return nil, err
}
// Cast to ReadNodeRes type
response := &nodepb.ReadNodeRes{
Node: &nodepb.Node{
Macaddress: node.MacAddress,
Name: node.Name,
Address: node.Address,
Address6: node.Address6,
Endpoint: node.Endpoint,
Password: node.Password,
Nodenetwork: node.Network,
Interface: node.Interface,
Localaddress: node.LocalAddress,
Postdown: node.PostDown,
Postup: node.PostUp,
Checkininterval: node.CheckInInterval,
Dnsoff: !servercfg.IsDNSMode(),
Ispending: node.IsPending == "yes",
Isingressgateway: node.IsIngressGateway == "yes",
Ingressgatewayrange: node.IngressGatewayRange,
Publickey: node.PublicKey,
Listenport: node.ListenPort,
Keepalive: node.PersistentKeepalive,
Islocal: network.IsLocal == "yes",
Isdualstack: network.IsDualStack == "yes",
Localrange: network.LocalRange,
Udpholepunch: node.UDPHolePunch,
},
nodeData, err := json.Marshal(&node)
if err != nil {
return nil, err
}
response := &nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
}
return response, nil
}
func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNodeReq) (*nodepb.CreateNodeRes, error) {
func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
// Get the protobuf node type from the protobuf request type
// Essentially doing req.Node to access the struct with a nil check
data := req.GetNode()
// Now we have to convert this into a NodeItem type to convert into BSON
node := models.Node{
// ID: primitive.NilObjectID,
MacAddress: data.GetMacaddress(),
LocalAddress: data.GetLocaladdress(),
Name: data.GetName(),
Address: data.GetAddress(),
Address6: data.GetAddress6(),
AccessKey: data.GetAccesskey(),
Endpoint: data.GetEndpoint(),
PersistentKeepalive: data.GetKeepalive(),
Password: data.GetPassword(),
Interface: data.GetInterface(),
Network: data.GetNodenetwork(),
PublicKey: data.GetPublickey(),
ListenPort: data.GetListenport(),
UDPHolePunch: data.GetUdpholepunch(),
var node models.Node
data := req.GetData()
if err := json.Unmarshal([]byte(data), &node); err != nil {
return nil, err
}
//Check to see if key is valid
@@ -86,7 +56,7 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
validKey := functions.IsKeyValid(node.Network, node.AccessKey)
network, err := functions.GetParentNetwork(node.Network)
if err != nil {
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not find network: %v", err))
return nil, err
}
if !validKey {
@@ -95,274 +65,125 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
if network.AllowManualSignUp == "yes" {
node.IsPending = "yes"
} else {
return nil, status.Errorf(
codes.Internal,
fmt.Sprintf("Invalid key, and network does not allow no-key signups"),
)
return nil, errors.New("invalid key, and network does not allow no-key signups")
}
}
node, err = CreateNode(node, node.Network)
if err != nil {
// return internal gRPC error to be handled later
return nil, status.Errorf(
codes.Internal,
fmt.Sprintf("Internal error: %v", err),
)
log.Println("could not create node on network " + node.Network + " (gRPC controller)")
return nil, err
}
nodeData, err := json.Marshal(&node)
// return the node in a CreateNodeRes type
response := &nodepb.CreateNodeRes{
Node: &nodepb.Node{
Macaddress: node.MacAddress,
Localaddress: node.LocalAddress,
Name: node.Name,
Address: node.Address,
Address6: node.Address6,
Endpoint: node.Endpoint,
Password: node.Password,
Interface: node.Interface,
Nodenetwork: node.Network,
Dnsoff: !servercfg.IsDNSMode(),
Ispending: node.IsPending == "yes",
Publickey: node.PublicKey,
Listenport: node.ListenPort,
Keepalive: node.PersistentKeepalive,
Islocal: network.IsLocal == "yes",
Isdualstack: network.IsDualStack == "yes",
Localrange: network.LocalRange,
Udpholepunch: node.UDPHolePunch,
},
response := &nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
}
err = SetNetworkNodesLastModified(node.Network)
if err != nil {
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not update network last modified date: %v", err))
return nil, err
}
return response, nil
}
func (s *NodeServiceServer) CheckIn(ctx context.Context, req *nodepb.CheckInReq) (*nodepb.CheckInRes, error) {
// Get the protobuf node type from the protobuf request type
// Essentially doing req.Node to access the struct with a nil check
data := req.GetNode()
//postchanges := req.GetPostchanges()
// Now we have to convert this into a NodeItem type to convert into BSON
node := models.Node{
// ID: primitive.NilObjectID,
MacAddress: data.GetMacaddress(),
Address: data.GetAddress(),
Address6: data.GetAddress6(),
Endpoint: data.GetEndpoint(),
Network: data.GetNodenetwork(),
Password: data.GetPassword(),
LocalAddress: data.GetLocaladdress(),
ListenPort: data.GetListenport(),
PersistentKeepalive: data.GetKeepalive(),
PublicKey: data.GetPublickey(),
UDPHolePunch: data.GetUdpholepunch(),
SaveConfig: data.GetSaveconfig(),
}
checkinresponse, err := NodeCheckIn(node, node.Network)
if err != nil {
// return internal gRPC error to be handled later
if checkinresponse == (models.CheckInResponse{}) || !checkinresponse.IsPending {
return nil, status.Errorf(
codes.Internal,
fmt.Sprintf("Internal error: %v", err),
)
}
}
// return the node in a CreateNodeRes type
response := &nodepb.CheckInRes{
Checkinresponse: &nodepb.CheckInResponse{
Success: checkinresponse.Success,
Needpeerupdate: checkinresponse.NeedPeerUpdate,
Needdelete: checkinresponse.NeedDelete,
Needconfigupdate: checkinresponse.NeedConfigUpdate,
Needkeyupdate: checkinresponse.NeedKeyUpdate,
Nodemessage: checkinresponse.NodeMessage,
Ispending: checkinresponse.IsPending,
},
}
return response, nil
}
func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNodeReq) (*nodepb.UpdateNodeRes, error) {
func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
// Get the node data from the request
data := req.GetNode()
// Now we have to convert this into a NodeItem type to convert into BSON
newnode := models.Node{
// ID: primitive.NilObjectID,
MacAddress: data.GetMacaddress(),
Name: data.GetName(),
Address: data.GetAddress(),
Address6: data.GetAddress6(),
LocalAddress: data.GetLocaladdress(),
Endpoint: data.GetEndpoint(),
Password: data.GetPassword(),
PersistentKeepalive: data.GetKeepalive(),
Network: data.GetNodenetwork(),
Interface: data.GetInterface(),
PostDown: data.GetPostdown(),
PostUp: data.GetPostup(),
PublicKey: data.GetPublickey(),
ListenPort: data.GetListenport(),
UDPHolePunch: data.GetUdpholepunch(),
SaveConfig: data.GetSaveconfig(),
var newnode models.Node
if err := json.Unmarshal([]byte(req.GetData()), &newnode); err != nil {
return nil, err
}
// Convert the Id string to a MongoDB ObjectId
macaddress := newnode.MacAddress
networkName := newnode.Network
network, _ := functions.GetParentNetwork(networkName)
node, err := functions.GetNodeByMacAddress(networkName, macaddress)
if err != nil {
return nil, status.Errorf(
codes.NotFound,
fmt.Sprintf("Could not find node with supplied Mac Address: %v", err),
)
return nil, err
}
err = node.Update(&newnode)
if err != nil {
return nil, status.Errorf(
codes.NotFound,
fmt.Sprintf("Could not update node: %v", err),
)
return nil, err
}
return &nodepb.UpdateNodeRes{
Node: &nodepb.Node{
Macaddress: newnode.MacAddress,
Localaddress: newnode.LocalAddress,
Name: newnode.Name,
Address: newnode.Address,
Address6: newnode.Address6,
Endpoint: newnode.Endpoint,
Password: newnode.Password,
Interface: newnode.Interface,
Postdown: newnode.PostDown,
Postup: newnode.PostUp,
Nodenetwork: newnode.Network,
Ispending: newnode.IsPending == "yes",
Publickey: newnode.PublicKey,
Dnsoff: !servercfg.IsDNSMode(),
Listenport: newnode.ListenPort,
Keepalive: newnode.PersistentKeepalive,
Islocal: network.IsLocal == "yes",
Isdualstack: network.IsDualStack == "yes",
Localrange: network.LocalRange,
Udpholepunch: newnode.UDPHolePunch,
},
nodeData, err := json.Marshal(&node)
return &nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
}, nil
}
func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.DeleteNodeReq) (*nodepb.DeleteNodeRes, error) {
macaddress := req.GetMacaddress()
network := req.GetNetworkName()
err := DeleteNode(macaddress, network)
func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
nodeID := req.GetData()
err := DeleteNode(nodeID, true)
if err != nil {
fmt.Println("Error deleting node.")
fmt.Println(err)
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not find/delete node with mac address %s", macaddress))
log.Println("Error deleting node (gRPC controller).")
return nil, err
}
fmt.Println("updating network last modified of " + req.GetNetworkName())
err = SetNetworkNodesLastModified(req.GetNetworkName())
if err != nil {
fmt.Println("Error updating Network")
fmt.Println(err)
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not update network last modified date: %v", err))
}
return &nodepb.DeleteNodeRes{
Success: true,
return &nodepb.Object{
Data: "success",
Type: nodepb.STRING_TYPE,
}, nil
}
func (s *NodeServiceServer) GetPeers(req *nodepb.GetPeersReq, stream nodepb.NodeService_GetPeersServer) error {
func (s *NodeServiceServer) GetPeers(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
var node models.Node
if err := json.Unmarshal([]byte(req.GetData()), &node); err != nil {
return nil, err
}
peers, err := GetPeersList(node.Network)
if err != nil {
return nil, err
}
peersData, err := json.Marshal(&peers)
return &nodepb.Object{
Data: string(peersData),
Type: nodepb.NODE_TYPE,
}, nil
}
/**
* Return Ext Peers (clients).NodeCheckIn
* When a gateway node checks in, it pulls these peers to add to peers list in addition to normal network peers.
*/
func (s *NodeServiceServer) GetExtPeers(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
// Initiate a NodeItem type to write decoded data to
//data := &models.PeersResponse{}
// collection.Find returns a cursor for our (empty) query
peers, err := GetPeersList(req.GetNetwork())
var reqNode models.Node
if err := json.Unmarshal([]byte(req.Data), &reqNode); err != nil {
return nil, err
}
peers, err := GetExtPeersList(reqNode.Network, reqNode.MacAddress)
if err != nil {
return status.Errorf(codes.Internal, fmt.Sprintf("Unknown internal error: %v", err))
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++ {
// If no error is found send node over stream
stream.Send(&nodepb.GetPeersRes{
Peers: &nodepb.PeersResponse{
Address: peers[i].Address,
Address6: peers[i].Address6,
Endpoint: peers[i].Endpoint,
Egressgatewayranges: peers[i].EgressGatewayRanges,
Isegressgateway: peers[i].IsEgressGateway == "yes",
Publickey: peers[i].PublicKey,
Keepalive: peers[i].KeepAlive,
Listenport: peers[i].ListenPort,
Localaddress: peers[i].LocalAddress,
},
extPeers = append(extPeers, models.Node{
Address: peers[i].Address,
Address6: peers[i].Address6,
Endpoint: peers[i].Endpoint,
PublicKey: peers[i].PublicKey,
PersistentKeepalive: peers[i].KeepAlive,
ListenPort: peers[i].ListenPort,
LocalAddress: peers[i].LocalAddress,
})
}
node, err := functions.GetNodeByMacAddress(req.GetNetwork(), req.GetMacaddress())
extData, err := json.Marshal(&extPeers)
if err != nil {
return status.Errorf(codes.Internal, fmt.Sprintf("Could not get node: %v", err))
return nil, err
}
err = TimestampNode(node, false, true, false)
if err != nil {
return status.Errorf(codes.Internal, fmt.Sprintf("Internal error occurred: %v", err))
}
return nil
}
func (s *NodeServiceServer) GetExtPeers(req *nodepb.GetExtPeersReq, stream nodepb.NodeService_GetExtPeersServer) error {
// Initiate a NodeItem type to write decoded data to
//data := &models.PeersResponse{}
// collection.Find returns a cursor for our (empty) query
peers, err := GetExtPeersList(req.GetNetwork(), req.GetMacaddress())
if err != nil {
return status.Errorf(codes.Internal, fmt.Sprintf("Unknown internal error: %v", err))
}
// cursor.Next() returns a boolean, if false there are no more items and loop will break
for i := 0; i < len(peers); i++ {
// If no error is found send node over stream
stream.Send(&nodepb.GetExtPeersRes{
Extpeers: &nodepb.ExtPeersResponse{
Address: peers[i].Address,
Address6: peers[i].Address6,
Endpoint: peers[i].Endpoint,
Publickey: peers[i].PublicKey,
Keepalive: peers[i].KeepAlive,
Listenport: peers[i].ListenPort,
Localaddress: peers[i].LocalAddress,
},
})
}
node, err := functions.GetNodeByMacAddress(req.GetNetwork(), req.GetMacaddress())
if err != nil {
return status.Errorf(codes.Internal, fmt.Sprintf("Could not get node: %v", err))
}
err = TimestampNode(node, false, true, false)
if err != nil {
return status.Errorf(codes.Internal, fmt.Sprintf("Internal error occurred: %v", err))
}
return nil
return &nodepb.Object{
Data: string(extData),
Type: nodepb.EXT_PEER,
}, nil
}

View File

@@ -809,7 +809,7 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
// get params
var params = mux.Vars(r)
err := DeleteNode(params["macaddress"], params["network"])
err := DeleteNode(params["macaddress"]+"###"+params["network"], false)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))

View File

@@ -183,7 +183,7 @@ func HasAdmin() (bool, error) {
collection, err := database.FetchRecords(database.USERS_TABLE_NAME)
if err != nil {
return false, err
return true, err
}
for _, value := range collection { // filter for isadmin true

View File

@@ -9,6 +9,7 @@ import (
const NETWORKS_TABLE_NAME = "networks"
const NODES_TABLE_NAME = "nodes"
const DELETED_NODES_TABLE_NAME = "deletednodes"
const USERS_TABLE_NAME = "users"
const DNS_TABLE_NAME = "dns"
const EXT_CLIENT_TABLE_NAME = "extclients"
@@ -16,6 +17,10 @@ const INT_CLIENTS_TABLE_NAME = "intclients"
const PEERS_TABLE_NAME = "peers"
const DATABASE_FILENAME = "netmaker.db"
// == ERROR CONSTS ==
const NO_RECORD = "no result found"
const NO_RECORDS = "could not find any records"
var Database gorqlite.Connection
func InitializeDatabase() error {
@@ -35,6 +40,7 @@ func InitializeDatabase() error {
func createTables() {
createTable(NETWORKS_TABLE_NAME)
createTable(NODES_TABLE_NAME)
createTable(DELETED_NODES_TABLE_NAME)
createTable(USERS_TABLE_NAME)
createTable(DNS_TABLE_NAME)
createTable(EXT_CLIENT_TABLE_NAME)
@@ -104,6 +110,9 @@ func FetchRecord(tableName string, key string) (string, error) {
if err != nil {
return "", err
}
if results[key] == "" {
return "", errors.New(NO_RECORD)
}
return results[key], nil
}
@@ -119,6 +128,9 @@ func FetchRecords(tableName string) (map[string]string, error) {
row.Scan(&key, &value)
records[key] = value
}
if len(records) == 0 {
return nil, errors.New(NO_RECORDS)
}
// log.Println(records)
return records, nil
}

View File

@@ -2,6 +2,7 @@ package database
import (
"encoding/json"
"strings"
)
func SetPeers(newPeers map[string]string, networkName string) bool {
@@ -26,7 +27,6 @@ func GetPeers(networkName string) (map[string]string, error) {
return currentDataMap, err
}
func PeersAreEqual(toCompare map[string]string, networkName string) bool {
currentDataMap, err := GetPeers(networkName)
if err != nil {
@@ -36,9 +36,13 @@ func PeersAreEqual(toCompare map[string]string, networkName string) bool {
return false
}
for k := range currentDataMap {
if currentDataMap[k] != toCompare[k] {
if toCompare[k] != currentDataMap[k] {
return false
}
}
return true
}
func IsEmptyRecord(err error) bool {
return strings.Contains(err.Error(), NO_RECORD) || strings.Contains(err.Error(), NO_RECORDS)
}

View File

@@ -21,7 +21,7 @@ import (
)
func CheckEndpoint(endpoint string) bool {
endpointarr := strings.Split(endpoint,":")
endpointarr := strings.Split(endpoint, ":")
return net.ParseIP(endpointarr[0]) == nil
}
@@ -200,9 +200,6 @@ func GetRecordKey(id string, network string) (string, error) {
return id + "###" + network, nil
}
//TODO: This is very inefficient (N-squared). Need to find a better way.
//Takes a list of nodes in a network and iterates through
//for each node, it gets a unique address. That requires checking against all other nodes once more
func UpdateNetworkNodeAddresses(networkName string) error {
collections, err := database.FetchRecords(database.NODES_TABLE_NAME)
@@ -235,6 +232,33 @@ func UpdateNetworkNodeAddresses(networkName string) error {
return nil
}
func NetworkNodesUpdateKey(networkName string) error {
collections, err := database.FetchRecords(database.NODES_TABLE_NAME)
if err != nil {
return err
}
for _, value := range collections {
var node models.Node
err := json.Unmarshal([]byte(value), &node)
if err != nil {
fmt.Println("error in node address assignment!")
return err
}
node.Action = models.NODE_UPDATE_KEY
data, err := json.Marshal(&node)
if err != nil {
return err
}
database.Insert(node.MacAddress, string(data), database.NODES_TABLE_NAME)
}
return nil
}
func UpdateNetworkLocalAddresses(networkName string) error {
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)

File diff suppressed because it is too large Load Diff

View File

@@ -3,159 +3,18 @@ package node;
option go_package = "google.golang.org/protobuf/types/known/nodepb";
service NodeService {
rpc Login(LoginRequest) returns (LoginResponse);
rpc CreateNode(CreateNodeReq) returns (CreateNodeRes);
rpc ReadNode(ReadNodeReq) returns (ReadNodeRes);
rpc UpdateNode(UpdateNodeReq) returns (UpdateNodeRes);
rpc DeleteNode(DeleteNodeReq) returns (DeleteNodeRes);
rpc GetPeers(GetPeersReq) returns (stream GetPeersRes);
rpc GetExtPeers(GetExtPeersReq) returns (stream GetExtPeersRes);
rpc CheckIn(CheckInReq) returns (CheckInRes);
rpc Login(Object) returns (Object);
rpc CreateNode(Object) returns (Object);
rpc ReadNode(Object) returns (Object);
rpc UpdateNode(Object) returns (Object);
rpc DeleteNode(Object) returns (Object);
rpc GetPeers(Object) returns (Object);
rpc GetExtPeers(Object) returns (Object);
rpc CheckIn(Object) returns (Object);
}
message LoginRequest {
string macaddress = 1;
string password = 2;
string network = 3;
message Object {
string Data = 1;
string Type = 2;
string Metadata = 3;
}
message LoginResponse { string accesstoken = 1; }
message Node {
string id = 1;
string name = 2;
string address = 3;
string address6 = 26;
int32 listenport = 4;
string publickey = 5;
string endpoint = 6;
string macaddress = 7;
string password = 8;
string nodenetwork = 9;
bool ispending = 10;
string postup = 11;
string postdown = 12;
int32 keepalive = 13;
string saveconfig = 14;
string accesskey = 15;
string interface = 16;
string lastcheckin = 17;
string lastmodified = 18;
int32 checkininterval = 19;
string localaddress = 20;
string postchanges = 21;
string allowedips = 22;
bool islocal = 23;
bool isingressgateway = 28;
string ingressgatewayrange = 29;
bool isdualstack = 27;
bool dnsoff = 24;
string localrange = 25;
string udpholepunch = 30;
}
message CheckInResponse {
bool success = 1;
bool needpeerupdate = 2;
bool needconfigupdate = 3;
string nodemessage = 4;
bool ispending = 5;
bool needkeyupdate = 6;
bool needdelete = 7;
}
message PeersResponse {
bool isegressgateway = 1;
string egressgatewayranges = 2;
string ingressgatewayrange = 9;
string publickey = 5;
string endpoint = 6;
string address = 3;
string address6 = 8;
int32 listenport = 4;
string localaddress = 7;
int32 keepalive = 13;
}
message ExtPeersResponse {
string publickey = 5;
string endpoint = 6;
string address = 3;
string address6 = 8;
int32 listenport = 4;
string localaddress = 7;
int32 keepalive = 13;
}
message Client {
string privatekey = 1;
string publickey = 2;
string accesskey = 3;
string address = 4;
string address6 = 5;
string serverwgendpoint = 6;
string serverport = 7;
string serverkey = 8;
}
message CreateNodeReq {
Node node = 1; // Node id blank
}
message CreateNodeRes {
Node node = 1; // Node id filled in
}
message UpdateNodeReq {
Node node = 1;
}
message UpdateNodeRes {
Node node = 1;
}
message ReadNodeReq {
string macaddress = 1;
string network = 2;
}
message ReadNodeRes {
Node node = 1;
}
message DeleteNodeReq {
string macaddress = 1;
string networkName = 2;
}
message DeleteNodeRes {
bool success = 1;
}
message GetPeersReq {
string macaddress = 1;
string network = 2;
}
message GetExtPeersReq {
string macaddress = 1;
string network = 2;
}
message GetPeersRes {
PeersResponse peers = 1;
}
message GetExtPeersRes {
ExtPeersResponse extpeers = 1;
}
message CheckInReq {
Node node = 1;
// bool postchanges = 2;
}
message CheckInRes {
CheckInResponse checkinresponse = 1;
}

View File

@@ -18,14 +18,14 @@ const _ = grpc.SupportPackageIsVersion7
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type NodeServiceClient interface {
Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
CreateNode(ctx context.Context, in *CreateNodeReq, opts ...grpc.CallOption) (*CreateNodeRes, error)
ReadNode(ctx context.Context, in *ReadNodeReq, opts ...grpc.CallOption) (*ReadNodeRes, error)
UpdateNode(ctx context.Context, in *UpdateNodeReq, opts ...grpc.CallOption) (*UpdateNodeRes, error)
DeleteNode(ctx context.Context, in *DeleteNodeReq, opts ...grpc.CallOption) (*DeleteNodeRes, error)
GetPeers(ctx context.Context, in *GetPeersReq, opts ...grpc.CallOption) (NodeService_GetPeersClient, error)
GetExtPeers(ctx context.Context, in *GetExtPeersReq, opts ...grpc.CallOption) (NodeService_GetExtPeersClient, error)
CheckIn(ctx context.Context, in *CheckInReq, opts ...grpc.CallOption) (*CheckInRes, error)
Login(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
CreateNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
ReadNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
UpdateNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
DeleteNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
GetPeers(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
GetExtPeers(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
CheckIn(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
}
type nodeServiceClient struct {
@@ -36,8 +36,8 @@ func NewNodeServiceClient(cc grpc.ClientConnInterface) NodeServiceClient {
return &nodeServiceClient{cc}
}
func (c *nodeServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) {
out := new(LoginResponse)
func (c *nodeServiceClient) Login(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/Login", in, out, opts...)
if err != nil {
return nil, err
@@ -45,8 +45,8 @@ func (c *nodeServiceClient) Login(ctx context.Context, in *LoginRequest, opts ..
return out, nil
}
func (c *nodeServiceClient) CreateNode(ctx context.Context, in *CreateNodeReq, opts ...grpc.CallOption) (*CreateNodeRes, error) {
out := new(CreateNodeRes)
func (c *nodeServiceClient) CreateNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/CreateNode", in, out, opts...)
if err != nil {
return nil, err
@@ -54,8 +54,8 @@ func (c *nodeServiceClient) CreateNode(ctx context.Context, in *CreateNodeReq, o
return out, nil
}
func (c *nodeServiceClient) ReadNode(ctx context.Context, in *ReadNodeReq, opts ...grpc.CallOption) (*ReadNodeRes, error) {
out := new(ReadNodeRes)
func (c *nodeServiceClient) ReadNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/ReadNode", in, out, opts...)
if err != nil {
return nil, err
@@ -63,8 +63,8 @@ func (c *nodeServiceClient) ReadNode(ctx context.Context, in *ReadNodeReq, opts
return out, nil
}
func (c *nodeServiceClient) UpdateNode(ctx context.Context, in *UpdateNodeReq, opts ...grpc.CallOption) (*UpdateNodeRes, error) {
out := new(UpdateNodeRes)
func (c *nodeServiceClient) UpdateNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/UpdateNode", in, out, opts...)
if err != nil {
return nil, err
@@ -72,8 +72,8 @@ func (c *nodeServiceClient) UpdateNode(ctx context.Context, in *UpdateNodeReq, o
return out, nil
}
func (c *nodeServiceClient) DeleteNode(ctx context.Context, in *DeleteNodeReq, opts ...grpc.CallOption) (*DeleteNodeRes, error) {
out := new(DeleteNodeRes)
func (c *nodeServiceClient) DeleteNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/DeleteNode", in, out, opts...)
if err != nil {
return nil, err
@@ -81,72 +81,26 @@ func (c *nodeServiceClient) DeleteNode(ctx context.Context, in *DeleteNodeReq, o
return out, nil
}
func (c *nodeServiceClient) GetPeers(ctx context.Context, in *GetPeersReq, opts ...grpc.CallOption) (NodeService_GetPeersClient, error) {
stream, err := c.cc.NewStream(ctx, &NodeService_ServiceDesc.Streams[0], "/node.NodeService/GetPeers", opts...)
func (c *nodeServiceClient) GetPeers(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/GetPeers", in, out, opts...)
if err != nil {
return nil, err
}
x := &nodeServiceGetPeersClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
return out, nil
}
type NodeService_GetPeersClient interface {
Recv() (*GetPeersRes, error)
grpc.ClientStream
}
type nodeServiceGetPeersClient struct {
grpc.ClientStream
}
func (x *nodeServiceGetPeersClient) Recv() (*GetPeersRes, error) {
m := new(GetPeersRes)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *nodeServiceClient) GetExtPeers(ctx context.Context, in *GetExtPeersReq, opts ...grpc.CallOption) (NodeService_GetExtPeersClient, error) {
stream, err := c.cc.NewStream(ctx, &NodeService_ServiceDesc.Streams[1], "/node.NodeService/GetExtPeers", opts...)
func (c *nodeServiceClient) GetExtPeers(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/GetExtPeers", in, out, opts...)
if err != nil {
return nil, err
}
x := &nodeServiceGetExtPeersClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
return out, nil
}
type NodeService_GetExtPeersClient interface {
Recv() (*GetExtPeersRes, error)
grpc.ClientStream
}
type nodeServiceGetExtPeersClient struct {
grpc.ClientStream
}
func (x *nodeServiceGetExtPeersClient) Recv() (*GetExtPeersRes, error) {
m := new(GetExtPeersRes)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *nodeServiceClient) CheckIn(ctx context.Context, in *CheckInReq, opts ...grpc.CallOption) (*CheckInRes, error) {
out := new(CheckInRes)
func (c *nodeServiceClient) CheckIn(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/CheckIn", in, out, opts...)
if err != nil {
return nil, err
@@ -158,14 +112,14 @@ func (c *nodeServiceClient) CheckIn(ctx context.Context, in *CheckInReq, opts ..
// All implementations must embed UnimplementedNodeServiceServer
// for forward compatibility
type NodeServiceServer interface {
Login(context.Context, *LoginRequest) (*LoginResponse, error)
CreateNode(context.Context, *CreateNodeReq) (*CreateNodeRes, error)
ReadNode(context.Context, *ReadNodeReq) (*ReadNodeRes, error)
UpdateNode(context.Context, *UpdateNodeReq) (*UpdateNodeRes, error)
DeleteNode(context.Context, *DeleteNodeReq) (*DeleteNodeRes, error)
GetPeers(*GetPeersReq, NodeService_GetPeersServer) error
GetExtPeers(*GetExtPeersReq, NodeService_GetExtPeersServer) error
CheckIn(context.Context, *CheckInReq) (*CheckInRes, error)
Login(context.Context, *Object) (*Object, error)
CreateNode(context.Context, *Object) (*Object, error)
ReadNode(context.Context, *Object) (*Object, error)
UpdateNode(context.Context, *Object) (*Object, error)
DeleteNode(context.Context, *Object) (*Object, error)
GetPeers(context.Context, *Object) (*Object, error)
GetExtPeers(context.Context, *Object) (*Object, error)
CheckIn(context.Context, *Object) (*Object, error)
mustEmbedUnimplementedNodeServiceServer()
}
@@ -173,28 +127,28 @@ type NodeServiceServer interface {
type UnimplementedNodeServiceServer struct {
}
func (UnimplementedNodeServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) {
func (UnimplementedNodeServiceServer) Login(context.Context, *Object) (*Object, error) {
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
}
func (UnimplementedNodeServiceServer) CreateNode(context.Context, *CreateNodeReq) (*CreateNodeRes, error) {
func (UnimplementedNodeServiceServer) CreateNode(context.Context, *Object) (*Object, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateNode not implemented")
}
func (UnimplementedNodeServiceServer) ReadNode(context.Context, *ReadNodeReq) (*ReadNodeRes, error) {
func (UnimplementedNodeServiceServer) ReadNode(context.Context, *Object) (*Object, error) {
return nil, status.Errorf(codes.Unimplemented, "method ReadNode not implemented")
}
func (UnimplementedNodeServiceServer) UpdateNode(context.Context, *UpdateNodeReq) (*UpdateNodeRes, error) {
func (UnimplementedNodeServiceServer) UpdateNode(context.Context, *Object) (*Object, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateNode not implemented")
}
func (UnimplementedNodeServiceServer) DeleteNode(context.Context, *DeleteNodeReq) (*DeleteNodeRes, error) {
func (UnimplementedNodeServiceServer) DeleteNode(context.Context, *Object) (*Object, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteNode not implemented")
}
func (UnimplementedNodeServiceServer) GetPeers(*GetPeersReq, NodeService_GetPeersServer) error {
return status.Errorf(codes.Unimplemented, "method GetPeers not implemented")
func (UnimplementedNodeServiceServer) GetPeers(context.Context, *Object) (*Object, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPeers not implemented")
}
func (UnimplementedNodeServiceServer) GetExtPeers(*GetExtPeersReq, NodeService_GetExtPeersServer) error {
return status.Errorf(codes.Unimplemented, "method GetExtPeers not implemented")
func (UnimplementedNodeServiceServer) GetExtPeers(context.Context, *Object) (*Object, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetExtPeers not implemented")
}
func (UnimplementedNodeServiceServer) CheckIn(context.Context, *CheckInReq) (*CheckInRes, error) {
func (UnimplementedNodeServiceServer) CheckIn(context.Context, *Object) (*Object, error) {
return nil, status.Errorf(codes.Unimplemented, "method CheckIn not implemented")
}
func (UnimplementedNodeServiceServer) mustEmbedUnimplementedNodeServiceServer() {}
@@ -211,7 +165,7 @@ func RegisterNodeServiceServer(s grpc.ServiceRegistrar, srv NodeServiceServer) {
}
func _NodeService_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LoginRequest)
in := new(Object)
if err := dec(in); err != nil {
return nil, err
}
@@ -223,13 +177,13 @@ func _NodeService_Login_Handler(srv interface{}, ctx context.Context, dec func(i
FullMethod: "/node.NodeService/Login",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(NodeServiceServer).Login(ctx, req.(*LoginRequest))
return srv.(NodeServiceServer).Login(ctx, req.(*Object))
}
return interceptor(ctx, in, info, handler)
}
func _NodeService_CreateNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateNodeReq)
in := new(Object)
if err := dec(in); err != nil {
return nil, err
}
@@ -241,13 +195,13 @@ func _NodeService_CreateNode_Handler(srv interface{}, ctx context.Context, dec f
FullMethod: "/node.NodeService/CreateNode",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(NodeServiceServer).CreateNode(ctx, req.(*CreateNodeReq))
return srv.(NodeServiceServer).CreateNode(ctx, req.(*Object))
}
return interceptor(ctx, in, info, handler)
}
func _NodeService_ReadNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ReadNodeReq)
in := new(Object)
if err := dec(in); err != nil {
return nil, err
}
@@ -259,13 +213,13 @@ func _NodeService_ReadNode_Handler(srv interface{}, ctx context.Context, dec fun
FullMethod: "/node.NodeService/ReadNode",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(NodeServiceServer).ReadNode(ctx, req.(*ReadNodeReq))
return srv.(NodeServiceServer).ReadNode(ctx, req.(*Object))
}
return interceptor(ctx, in, info, handler)
}
func _NodeService_UpdateNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateNodeReq)
in := new(Object)
if err := dec(in); err != nil {
return nil, err
}
@@ -277,13 +231,13 @@ func _NodeService_UpdateNode_Handler(srv interface{}, ctx context.Context, dec f
FullMethod: "/node.NodeService/UpdateNode",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(NodeServiceServer).UpdateNode(ctx, req.(*UpdateNodeReq))
return srv.(NodeServiceServer).UpdateNode(ctx, req.(*Object))
}
return interceptor(ctx, in, info, handler)
}
func _NodeService_DeleteNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteNodeReq)
in := new(Object)
if err := dec(in); err != nil {
return nil, err
}
@@ -295,55 +249,49 @@ func _NodeService_DeleteNode_Handler(srv interface{}, ctx context.Context, dec f
FullMethod: "/node.NodeService/DeleteNode",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(NodeServiceServer).DeleteNode(ctx, req.(*DeleteNodeReq))
return srv.(NodeServiceServer).DeleteNode(ctx, req.(*Object))
}
return interceptor(ctx, in, info, handler)
}
func _NodeService_GetPeers_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(GetPeersReq)
if err := stream.RecvMsg(m); err != nil {
return err
func _NodeService_GetPeers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Object)
if err := dec(in); err != nil {
return nil, err
}
return srv.(NodeServiceServer).GetPeers(m, &nodeServiceGetPeersServer{stream})
}
type NodeService_GetPeersServer interface {
Send(*GetPeersRes) error
grpc.ServerStream
}
type nodeServiceGetPeersServer struct {
grpc.ServerStream
}
func (x *nodeServiceGetPeersServer) Send(m *GetPeersRes) error {
return x.ServerStream.SendMsg(m)
}
func _NodeService_GetExtPeers_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(GetExtPeersReq)
if err := stream.RecvMsg(m); err != nil {
return err
if interceptor == nil {
return srv.(NodeServiceServer).GetPeers(ctx, in)
}
return srv.(NodeServiceServer).GetExtPeers(m, &nodeServiceGetExtPeersServer{stream})
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/node.NodeService/GetPeers",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(NodeServiceServer).GetPeers(ctx, req.(*Object))
}
return interceptor(ctx, in, info, handler)
}
type NodeService_GetExtPeersServer interface {
Send(*GetExtPeersRes) error
grpc.ServerStream
}
type nodeServiceGetExtPeersServer struct {
grpc.ServerStream
}
func (x *nodeServiceGetExtPeersServer) Send(m *GetExtPeersRes) error {
return x.ServerStream.SendMsg(m)
func _NodeService_GetExtPeers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Object)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(NodeServiceServer).GetExtPeers(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/node.NodeService/GetExtPeers",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(NodeServiceServer).GetExtPeers(ctx, req.(*Object))
}
return interceptor(ctx, in, info, handler)
}
func _NodeService_CheckIn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CheckInReq)
in := new(Object)
if err := dec(in); err != nil {
return nil, err
}
@@ -355,7 +303,7 @@ func _NodeService_CheckIn_Handler(srv interface{}, ctx context.Context, dec func
FullMethod: "/node.NodeService/CheckIn",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(NodeServiceServer).CheckIn(ctx, req.(*CheckInReq))
return srv.(NodeServiceServer).CheckIn(ctx, req.(*Object))
}
return interceptor(ctx, in, info, handler)
}
@@ -387,22 +335,19 @@ var NodeService_ServiceDesc = grpc.ServiceDesc{
MethodName: "DeleteNode",
Handler: _NodeService_DeleteNode_Handler,
},
{
MethodName: "GetPeers",
Handler: _NodeService_GetPeers_Handler,
},
{
MethodName: "GetExtPeers",
Handler: _NodeService_GetExtPeers_Handler,
},
{
MethodName: "CheckIn",
Handler: _NodeService_CheckIn_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "GetPeers",
Handler: _NodeService_GetPeers_Handler,
ServerStreams: true,
},
{
StreamName: "GetExtPeers",
Handler: _NodeService_GetExtPeers_Handler,
ServerStreams: true,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "grpc/node.proto",
}

6
grpc/types.go Normal file
View File

@@ -0,0 +1,6 @@
package nodepb
const STRING_TYPE = "string"
const NODE_TYPE = "node"
const EXT_PEER = "extpeer"
const ACCESS_TOKEN = "accesstoken"

View File

@@ -7,7 +7,6 @@ import (
"log"
"net"
"os"
"os/exec"
"os/signal"
"strconv"
"sync"
@@ -16,6 +15,7 @@ import (
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/netclient/local"
"github.com/gravitl/netmaker/servercfg"
"google.golang.org/grpc"
)
@@ -34,8 +34,7 @@ func initialize() { // Client Mode Prereq Check
log.Fatal(err)
}
log.Println("database successfully connected.")
cmd := exec.Command("id", "-u")
output, err := cmd.Output()
output, err := local.RunCmd("id -u")
if err != nil {
log.Println("Error running 'id -u' for prereq check. Please investigate or disable client mode.")

View File

@@ -157,7 +157,7 @@ func (network *Network) IsNetworkNameUnique() (bool, error) {
dbs, err := GetNetworks()
if err != nil {
if err != nil && !database.IsEmptyRecord(err) {
return false, err
}
@@ -299,29 +299,29 @@ func (currentNetwork *Network) Update(newNetwork *Network) (bool, bool, error) {
func (network *Network) SetNetworkNodesLastModified() error {
timestamp := time.Now().Unix()
timestamp := time.Now().Unix()
network.NodesLastModified = timestamp
data, err := json.Marshal(&network)
if err != nil {
return err
}
err = database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME)
if err != nil {
return err
}
return nil
network.NodesLastModified = timestamp
data, err := json.Marshal(&network)
if err != nil {
return err
}
err = database.Insert(network.NetID, string(data), database.NETWORKS_TABLE_NAME)
if err != nil {
return err
}
return nil
}
func GetNetwork(networkname string) (Network, error) {
var network Network
networkData, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, networkname)
if err != nil {
return network, err
}
if err = json.Unmarshal([]byte(networkData), &network); err != nil {
return Network{}, err
}
return network, nil
var network Network
networkData, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, networkname)
if err != nil {
return network, err
}
if err = json.Unmarshal([]byte(networkData), &network); err != nil {
return Network{}, err
}
return network, nil
}

View File

@@ -16,48 +16,82 @@ import (
const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
const TEN_YEARS_IN_SECONDS = 300000000
// == ACTIONS == (can only be set by GRPC)
const NODE_UPDATE_KEY = "updatekey"
const NODE_DELETE = "delete"
const NODE_IS_PENDING = "pending"
var seededRand *rand.Rand = rand.New(
rand.NewSource(time.Now().UnixNano()))
//node struct
type Node struct {
ID string `json:"id,omitempty" bson:"id,omitempty"`
Address string `json:"address" bson:"address" validate:"omitempty,ipv4"`
Address6 string `json:"address6" bson:"address6" validate:"omitempty,ipv6"`
LocalAddress string `json:"localaddress" bson:"localaddress" validate:"omitempty,ip"`
Name string `json:"name" bson:"name" validate:"omitempty,max=12,in_charset"`
ListenPort int32 `json:"listenport" bson:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
PublicKey string `json:"publickey" bson:"publickey" validate:"required,base64"`
Endpoint string `json:"endpoint" bson:"endpoint" validate:"required,ip"`
PostUp string `json:"postup" bson:"postup"`
PostDown string `json:"postdown" bson:"postdown"`
AllowedIPs []string `json:"allowedips" bson:"allowedips"`
PersistentKeepalive int32 `json:"persistentkeepalive" bson:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
SaveConfig string `json:"saveconfig" bson:"saveconfig" validate:"checkyesorno"`
AccessKey string `json:"accesskey" bson:"accesskey"`
Interface string `json:"interface" bson:"interface"`
LastModified int64 `json:"lastmodified" bson:"lastmodified"`
KeyUpdateTimeStamp int64 `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"`
ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime"`
LastPeerUpdate int64 `json:"lastpeerupdate" bson:"lastpeerupdate"`
LastCheckIn int64 `json:"lastcheckin" bson:"lastcheckin"`
MacAddress string `json:"macaddress" bson:"macaddress" validate:"required,mac,macaddress_unique"`
CheckInInterval int32 `json:"checkininterval" bson:"checkininterval"`
Password string `json:"password" bson:"password" validate:"required,min=6"`
Network string `json:"network" bson:"network" validate:"network_exists"`
IsPending string `json:"ispending" bson:"ispending"`
IsEgressGateway string `json:"isegressgateway" bson:"isegressgateway"`
IsIngressGateway string `json:"isingressgateway" bson:"isingressgateway"`
EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges"`
IngressGatewayRange string `json:"ingressgatewayrange" bson:"ingressgatewayrange"`
PostChanges string `json:"postchanges" bson:"postchanges"`
StaticIP string `json:"staticip" bson:"staticip"`
StaticPubKey string `json:"staticpubkey" bson:"staticpubkey"`
UDPHolePunch string `json:"udpholepunch" bson:"udpholepunch" validate:"checkyesorno"`
Address string `json:"address" bson:"address" yaml:"address" validate:"omitempty,ipv4"`
Address6 string `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"`
LocalAddress string `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"`
Name string `json:"name" bson:"name" yaml:"name" validate:"omitempty,max=12,in_charset"`
ListenPort int32 `json:"listenport" bson:"listenport" yaml:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
PublicKey string `json:"publickey" bson:"publickey" yaml:"publickey" validate:"required,base64"`
Endpoint string `json:"endpoint" bson:"endpoint" yaml:"endpoint" validate:"required,ip"`
PostUp string `json:"postup" bson:"postup" yaml:"postup"`
PostDown string `json:"postdown" bson:"postdown" yaml:"postdown"`
AllowedIPs []string `json:"allowedips" bson:"allowedips" yaml:"allowedips"`
PersistentKeepalive int32 `json:"persistentkeepalive" bson:"persistentkeepalive" yaml:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
SaveConfig string `json:"saveconfig" bson:"saveconfig" yaml:"saveconfig" validate:"checkyesorno"`
AccessKey string `json:"accesskey" bson:"accesskey" yaml:"accesskey"`
Interface string `json:"interface" bson:"interface" yaml:"interface"`
LastModified int64 `json:"lastmodified" bson:"lastmodified" yaml:"lastmodified"`
KeyUpdateTimeStamp int64 `json:"keyupdatetimestamp" bson:"keyupdatetimestamp" yaml:"keyupdatetimestamp"`
ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"`
LastPeerUpdate int64 `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"`
LastCheckIn int64 `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"`
MacAddress string `json:"macaddress" bson:"macaddress" yaml:"macaddress" validate:"required,mac,macaddress_unique"`
CheckInInterval int32 `json:"checkininterval" bson:"checkininterval" yaml:"checkininterval"`
Password string `json:"password" bson:"password" yaml:"password" validate:"required,min=6"`
Network string `json:"network" bson:"network" yaml:"network" validate:"network_exists"`
IsPending string `json:"ispending" bson:"ispending" yaml:"ispending"`
IsEgressGateway string `json:"isegressgateway" bson:"isegressgateway" yaml:"isegressgateway"`
IsIngressGateway string `json:"isingressgateway" bson:"isingressgateway" yaml:"isingressgateway"`
EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"`
IngressGatewayRange string `json:"ingressgatewayrange" bson:"ingressgatewayrange" yaml:"ingressgatewayrange"`
StaticIP string `json:"staticip" bson:"staticip" yaml:"staticip"`
StaticPubKey string `json:"staticpubkey" bson:"staticpubkey" yaml:"staticpubkey"`
UDPHolePunch string `json:"udpholepunch" bson:"udpholepunch" yaml:"udpholepunch" validate:"checkyesorno"`
PullChanges string `json:"pullchanges" bson:"pullchanges" yaml:"pullchanges" validate:"checkyesorno"`
DNSOn string `json:"dnson" bson:"dnson" yaml:"dnson" validate:"checkyesorno"`
IsDualStack string `json:"isdualstack" bson:"isdualstack" yaml:"isdualstack" validate:"checkyesorno"`
Action string `json:"action" bson:"action" yaml:"action"`
IsLocal string `json:"islocal" bson:"islocal" yaml:"islocal" validate:"checkyesorno"`
LocalRange string `json:"localrange" bson:"localrange" yaml:"localrange"`
Roaming string `json:"roaming" bson:"roaming" yaml:"roaming" validate:"checkyesorno"`
IPForwarding string `json:"ipforwarding" bson:"ipforwarding" yaml:"ipforwarding" validate:"checkyesorno"`
}
func (node *Node) SetIPForwardingDefault() {
if node.IPForwarding == "" {
node.IPForwarding = "no"
}
}
func (node *Node) SetIsLocalDefault() {
if node.IsLocal == "" {
node.IsLocal = "no"
}
}
func (node *Node) SetDNSOnDefault() {
if node.DNSOn == "" {
node.DNSOn = "no"
}
}
func (node *Node) SetIsDualStackDefault() {
if node.IsDualStack == "" {
node.IsDualStack = "no"
}
}
//TODO:
//Not sure if below two methods are necessary. May want to revisit
func (node *Node) SetLastModified() {
node.LastModified = time.Now().Unix()
}
@@ -141,7 +175,10 @@ func (node *Node) SetDefaults() {
}
}
node.CheckInInterval = parentNetwork.DefaultCheckInInterval
node.SetIPForwardingDefault()
node.SetDNSOnDefault()
node.SetIsLocalDefault()
node.SetIsDualStackDefault()
node.SetLastModified()
node.SetDefaultName()
node.SetLastCheckIn()
@@ -260,8 +297,24 @@ func (newNode *Node) Fill(currentNode *Node) {
if newNode.UDPHolePunch == "" {
newNode.UDPHolePunch = currentNode.SaveConfig
}
newNode.PostChanges = "no"
if newNode.DNSOn == "" {
newNode.DNSOn = currentNode.DNSOn
}
if newNode.IsDualStack == "" {
newNode.IsDualStack = currentNode.IsDualStack
}
if newNode.IsLocal == "" {
newNode.IsLocal = currentNode.IsLocal
}
if newNode.IPForwarding == "" {
newNode.IPForwarding = currentNode.IPForwarding
}
if newNode.Roaming == "" {
newNode.Roaming = currentNode.Roaming
}
if newNode.Action == "" {
newNode.Action = currentNode.Action
}
}
func (currentNode *Node) Update(newNode *Node) error {

View File

@@ -1,69 +1,96 @@
package auth
import (
"github.com/gravitl/netmaker/netclient/config"
"fmt"
// "os"
"context"
"io/ioutil"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/grpc/codes"
nodepb "github.com/gravitl/netmaker/grpc"
"encoding/json"
"fmt"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/config"
// "os"
"context"
"io/ioutil"
nodepb "github.com/gravitl/netmaker/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
)
// CreateJWT func will used to create the JWT while signing in and signing out
func SetJWT(client nodepb.NodeServiceClient, network string) (context.Context, error) {
//home, err := os.UserHomeDir()
home := "/etc/netclient"
tokentext, err := ioutil.ReadFile(home + "/nettoken-"+network)
if err != nil {
err = AutoLogin(client, network)
if err != nil {
return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong with Auto Login: %v", err))
}
tokentext, err = ioutil.ReadFile(home + "/nettoken-"+network)
if err != nil {
return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong: %v", err))
}
//home, err := os.UserHomeDir()
home := "/etc/netclient"
tokentext, err := ioutil.ReadFile(home + "/nettoken-" + network)
if err != nil {
err = AutoLogin(client, network)
if err != nil {
return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong with Auto Login: %v", err))
}
token := string(tokentext)
tokentext, err = ioutil.ReadFile(home + "/nettoken-" + network)
if err != nil {
return nil, status.Errorf(codes.Unauthenticated, fmt.Sprintf("Something went wrong: %v", err))
}
}
token := string(tokentext)
// Anything linked to this variable will transmit request headers.
md := metadata.New(map[string]string{"authorization": token})
ctx := context.Background()
ctx = metadata.NewOutgoingContext(ctx, md)
return ctx, nil
// Anything linked to this variable will transmit request headers.
md := metadata.New(map[string]string{"authorization": token})
ctx := context.Background()
ctx = metadata.NewOutgoingContext(ctx, md)
return ctx, nil
}
func AutoLogin(client nodepb.NodeServiceClient, network string) error {
//home, err := os.UserHomeDir()
home := "/etc/netclient"
//nodecfg := config.Config.Node
cfg, err := config.ReadConfig(network)
if err != nil {
return err
}
login := &nodepb.LoginRequest{
Password: cfg.Node.Password,
Macaddress: cfg.Node.MacAddress,
Network: network,
}
// RPC call
res, err := client.Login(context.TODO(), login)
if err != nil {
return err
}
tokenstring := []byte(res.Accesstoken)
err = ioutil.WriteFile(home + "/nettoken-"+network, tokenstring, 0644)
if err != nil {
return err
}
return err
//home, err := os.UserHomeDir()
home := "/etc/netclient"
//nodecfg := config.Config.Node
cfg, err := config.ReadConfig(network)
if err != nil {
return err
}
pass, err := RetrieveSecret(network)
if err != nil {
return err
}
node := models.Node{
Password: pass,
MacAddress: cfg.Node.MacAddress,
Network: network,
}
data, err := json.Marshal(&node)
if err != nil {
return nil
}
login := &nodepb.Object{
Data: string(data),
}
// RPC call
res, err := client.Login(context.TODO(), login)
if err != nil {
return err
}
tokenstring := []byte(res.Data)
err = ioutil.WriteFile(home+"/nettoken-"+network, tokenstring, 0644)
if err != nil {
return err
}
return err
}
func StoreSecret(key string, network string) error {
d1 := []byte(key)
err := ioutil.WriteFile("/etc/netclient/secret-"+network, d1, 0644)
return err
}
func RetrieveSecret(network string) (string, error) {
dat, err := ioutil.ReadFile("/etc/netclient/secret-" + network)
return string(dat), err
}
type Configuration struct {
MacAddress string
Password string
Password string
}

View File

@@ -1,32 +1,28 @@
package command
import (
"github.com/gravitl/netmaker/netclient/functions"
"github.com/gravitl/netmaker/netclient/config"
"github.com/gravitl/netmaker/netclient/local"
"golang.zx2c4.com/wireguard/wgctrl"
nodepb "github.com/gravitl/netmaker/grpc"
"log"
"os"
"strings"
"log"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/netclient/config"
"github.com/gravitl/netmaker/netclient/functions"
"github.com/gravitl/netmaker/netclient/local"
"golang.zx2c4.com/wireguard/wgctrl"
)
var (
wgclient *wgctrl.Client
wgclient *wgctrl.Client
)
var (
wcclient nodepb.NodeServiceClient
wcclient nodepb.NodeServiceClient
)
func Register(cfg config.GlobalConfig) error {
err := functions.Register(cfg)
return err
}
func Join(cfg config.ClientConfig, privateKey string) error {
func Join(cfg config.ClientConfig) error {
err := functions.JoinNetwork(cfg)
err := functions.JoinNetwork(cfg, privateKey)
if err != nil {
if !strings.Contains(err.Error(), "ALREADY_INSTALLED") {
log.Println("Error installing: ", err)
@@ -38,15 +34,15 @@ func Join(cfg config.ClientConfig) error {
}
}
if cfg.Daemon != "off" {
err = local.RemoveSystemDServices(cfg.Network)
if err != nil {
log.Println("Error removing services: ", err)
}
err = local.RemoveSystemDServices(cfg.Network)
if err != nil {
log.Println("Error removing services: ", err)
}
}
}
return err
}
log.Println("joined " + cfg.Network)
log.Println("joined " + cfg.Network)
if cfg.Daemon != "off" {
err = functions.InstallDaemon(cfg)
}
@@ -54,74 +50,70 @@ func Join(cfg config.ClientConfig) error {
}
func CheckIn(cfg config.ClientConfig) error {
if cfg.Network == "all" || cfg.Network == "" {
if cfg.Network == "all" || cfg.Network == "" {
log.Println("Required, '-n'. No network provided. Exiting.")
os.Exit(1)
}
err := functions.CheckIn(cfg)
if err != nil {
log.Println("Error checking in: ", err)
os.Exit(1)
}
return nil
err := functions.CheckConfig(cfg)
return err
}
func Leave(cfg config.ClientConfig) error {
err := functions.LeaveNetwork(cfg.Network)
if err != nil {
if err != nil {
log.Println("Error attempting to leave network " + cfg.Network)
}
}
return err
}
func Push(cfg config.ClientConfig) error {
var err error
if cfg.Network == "all" {
log.Println("No network selected. Running Push for all networks.")
networks, err := functions.GetNetworks()
if err != nil {
log.Println("Error retrieving networks. Exiting.")
return err
}
for _, network := range networks {
err = functions.Push(network)
if err != nil {
log.Printf("Error pushing network configs for " + network + " network: ", err)
} else {
log.Println("pushed network config for " + network)
}
}
err = nil
} else {
err = functions.Push(cfg.Network)
}
log.Println("Completed pushing network configs to remote server.")
return err
}
func Pull(cfg config.ClientConfig) error {
var err error
var err error
if cfg.Network == "all" {
log.Println("No network selected. Running Pull for all networks.")
log.Println("No network selected. Running Push for all networks.")
networks, err := functions.GetNetworks()
if err != nil {
log.Println("Error retrieving networks. Exiting.")
return err
}
for _, network := range networks {
err = functions.Pull(network)
err = functions.Push(network)
if err != nil {
log.Printf("Error pulling network config for " + network + " network: ", err)
log.Printf("Error pushing network configs for "+network+" network: ", err)
} else {
log.Println("pushed network config for " + network)
}
}
err = nil
} else {
err = functions.Push(cfg.Network)
}
log.Println("Completed pushing network configs to remote server.")
return err
}
func Pull(cfg config.ClientConfig) error {
var err error
if cfg.Network == "all" {
log.Println("No network selected. Running Pull for all networks.")
networks, err := functions.GetNetworks()
if err != nil {
log.Println("Error retrieving networks. Exiting.")
return err
}
for _, network := range networks {
_, err = functions.Pull(network, true)
if err != nil {
log.Printf("Error pulling network config for "+network+" network: ", err)
} else {
log.Println("pulled network config for " + network)
}
}
err = nil
} else {
err = functions.Pull(cfg.Network)
_, err = functions.Pull(cfg.Network, true)
}
log.Println("Completed pulling network and peer configs.")
return err
return err
}
func List(cfg config.ClientConfig) error {
@@ -133,10 +125,9 @@ func Uninstall(cfg config.GlobalConfig) error {
log.Println("Uninstalling netclient")
err := functions.Uninstall()
err = functions.Unregister(cfg)
return err
return err
}
func Unregister(cfg config.GlobalConfig) error {
err := functions.Unregister(cfg)
return err
err := functions.Unregister(cfg)
return err
}

View File

@@ -9,7 +9,6 @@ import (
"log"
"os"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/models"
"github.com/urfave/cli/v2"
"gopkg.in/yaml.v3"
@@ -22,7 +21,7 @@ type GlobalConfig struct {
type ClientConfig struct {
Server ServerConfig `yaml:"server"`
Node NodeConfig `yaml:"node"`
Node models.Node `yaml:"node"`
Network string `yaml:"network"`
Daemon string `yaml:"daemon"`
OperatingSystem string `yaml:"operatingsystem"`
@@ -36,45 +35,6 @@ type ServerConfig struct {
GRPCWireGuard string `yaml:"grpcwg"`
}
type ListConfig struct {
Name string `yaml:"name"`
Interface string `yaml:"interface"`
PrivateIPv4 string `yaml:"wgaddress"`
PrivateIPv6 string `yaml:"wgaddress6"`
PublicEndpoint string `yaml:"endpoint"`
}
type NodeConfig struct {
Name string `yaml:"name"`
Interface string `yaml:"interface"`
Network string `yaml:"network"`
Password string `yaml:"password"`
MacAddress string `yaml:"macaddress"`
LocalAddress string `yaml:"localaddress"`
WGAddress string `yaml:"wgaddress"`
WGAddress6 string `yaml:"wgaddress6"`
Roaming string `yaml:"roaming"`
DNS string `yaml:"dns"`
IsLocal string `yaml:"islocal"`
IsDualStack string `yaml:"isdualstack"`
IsIngressGateway string `yaml:"isingressgateway"`
LocalRange string `yaml:"localrange"`
PostUp string `yaml:"postup"`
PostDown string `yaml:"postdown"`
Port int32 `yaml:"port"`
KeepAlive int32 `yaml:"keepalive"`
PublicKey string `yaml:"publickey"`
ServerPubKey string `yaml:"serverpubkey"`
PrivateKey string `yaml:"privatekey"`
Endpoint string `yaml:"endpoint"`
PostChanges string `yaml:"postchanges"`
StaticIP string `yaml:"staticip"`
StaticPubKey string `yaml:"staticpubkey"`
IPForwarding string `yaml:"ipforwarding"`
UDPHolePunch string `yaml:"udpholepunch"`
SaveConfig string `yaml:"saveconfig"`
}
//reading in the env file
func Write(config *ClientConfig, network string) error {
if network == "" {
@@ -232,6 +192,7 @@ func (config *ClientConfig) ReadConfig() {
fmt.Println(err)
log.Fatal(err)
} else {
config.Node.SetID()
//config = cfg
}
}
@@ -289,10 +250,10 @@ func ModGlobalConfig(cfg models.IntClient) error {
return err
}
func ModConfig(node *nodepb.Node) error {
network := node.Nodenetwork
func ModConfig(node *models.Node) error {
network := node.Network
if network == "" {
return errors.New("No Network Provided")
return errors.New("no network provided")
}
var modconfig ClientConfig
var err error
@@ -303,90 +264,23 @@ func ModConfig(node *nodepb.Node) error {
}
modconfig = *useconfig
}
nodecfg := modconfig.Node
if node.Name != "" {
nodecfg.Name = node.Name
}
if node.Interface != "" {
nodecfg.Interface = node.Interface
}
if node.Nodenetwork != "" {
nodecfg.Network = node.Nodenetwork
}
if node.Macaddress != "" {
nodecfg.MacAddress = node.Macaddress
}
if node.Localaddress != "" {
nodecfg.LocalAddress = node.Localaddress
}
if node.Postup != "" {
nodecfg.PostUp = node.Postup
}
if node.Postdown != "" {
nodecfg.PostDown = node.Postdown
}
if node.Listenport != 0 {
nodecfg.Port = node.Listenport
}
if node.Keepalive != 0 {
nodecfg.KeepAlive = node.Keepalive
}
if node.Publickey != "" {
nodecfg.PublicKey = node.Publickey
}
if node.Endpoint != "" {
nodecfg.Endpoint = node.Endpoint
}
if node.Password != "" {
nodecfg.Password = node.Password
}
if node.Address != "" {
nodecfg.WGAddress = node.Address
}
if node.Address6 != "" {
nodecfg.WGAddress6 = node.Address6
}
if node.Postchanges != "" {
nodecfg.PostChanges = node.Postchanges
}
if node.Dnsoff == true {
nodecfg.DNS = "off"
}
if node.Isdualstack == true {
nodecfg.IsDualStack = "yes"
}
if node.Udpholepunch != "" {
nodecfg.UDPHolePunch = node.Udpholepunch
}
if node.Saveconfig != "" {
nodecfg.SaveConfig = node.Saveconfig
}
if node.Isingressgateway {
nodecfg.IsIngressGateway = "yes"
} else {
nodecfg.IsIngressGateway = "no"
}
if node.Localrange != "" && node.Islocal {
nodecfg.IsLocal = "yes"
nodecfg.LocalRange = node.Localrange
}
modconfig.Node = nodecfg
modconfig.Node.Fill(node)
err = Write(&modconfig, network)
return err
}
func GetCLIConfig(c *cli.Context) (ClientConfig, error) {
func GetCLIConfig(c *cli.Context) (ClientConfig, string, error) {
var cfg ClientConfig
if c.String("token") != "" {
tokenbytes, err := base64.StdEncoding.DecodeString(c.String("token"))
if err != nil {
log.Println("error decoding token")
return cfg, err
return cfg, "", err
}
var accesstoken models.AccessToken
if err := json.Unmarshal(tokenbytes, &accesstoken); err != nil {
log.Println("error converting token json to object", tokenbytes)
return cfg, err
return cfg, "", err
}
if accesstoken.ServerConfig.APIConnString != "" {
@@ -454,87 +348,25 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, error) {
cfg.Node.Password = c.String("password")
cfg.Node.MacAddress = c.String("macaddress")
cfg.Node.LocalAddress = c.String("localaddress")
cfg.Node.WGAddress = c.String("address")
cfg.Node.WGAddress6 = c.String("addressIPV6")
cfg.Node.Address = c.String("address")
cfg.Node.Address6 = c.String("addressIPV6")
cfg.Node.Roaming = c.String("roaming")
cfg.Node.DNS = c.String("dns")
cfg.Node.DNSOn = c.String("dns")
cfg.Node.IsLocal = c.String("islocal")
cfg.Node.IsDualStack = c.String("isdualstack")
cfg.Node.PostUp = c.String("postup")
cfg.Node.PostDown = c.String("postdown")
cfg.Node.Port = int32(c.Int("port"))
cfg.Node.KeepAlive = int32(c.Int("keepalive"))
cfg.Node.ListenPort = int32(c.Int("port"))
cfg.Node.PersistentKeepalive = int32(c.Int("keepalive"))
cfg.Node.PublicKey = c.String("publickey")
cfg.Node.PrivateKey = c.String("privatekey")
privateKey := c.String("privatekey")
cfg.Node.Endpoint = c.String("endpoint")
cfg.Node.IPForwarding = c.String("ipforwarding")
cfg.OperatingSystem = c.String("operatingsystem")
cfg.Daemon = c.String("daemon")
cfg.Node.UDPHolePunch = c.String("udpholepunch")
return cfg, nil
}
func GetCLIConfigRegister(c *cli.Context) (GlobalConfig, error) {
var cfg GlobalConfig
if c.String("token") != "" {
tokenbytes, err := base64.StdEncoding.DecodeString(c.String("token"))
if err != nil {
log.Println("error decoding token")
return cfg, err
}
var accesstoken models.AccessToken
if err := json.Unmarshal(tokenbytes, &accesstoken); err != nil {
log.Println("error converting token json to object", tokenbytes)
return cfg, err
}
cfg.GRPCWireGuard = accesstoken.WG.GRPCWireGuard
cfg.Client.ServerPrivateAddress = accesstoken.WG.GRPCWGAddress
cfg.Client.ServerGRPCPort = accesstoken.WG.GRPCWGPort
if err != nil {
log.Println("error decoding token grpcserver")
return cfg, err
}
if err != nil {
log.Println("error decoding token apiserver")
return cfg, err
}
if accesstoken.ServerConfig.APIConnString != "" {
cfg.Client.ServerPublicEndpoint = accesstoken.ServerConfig.APIConnString
} else {
cfg.Client.ServerPublicEndpoint = accesstoken.ServerConfig.APIHost
if accesstoken.ServerConfig.APIPort != "" {
cfg.Client.ServerAPIPort = accesstoken.ServerConfig.APIPort
}
}
cfg.Client.ServerWGPort = accesstoken.WG.GRPCWGPort
cfg.Client.ServerKey = accesstoken.ClientConfig.Key
cfg.Client.ServerKey = accesstoken.WG.GRPCWGPubKey
if c.String("grpcserver") != "" {
cfg.Client.ServerPrivateAddress = c.String("grpcserver")
}
if c.String("apiserver") != "" {
cfg.Client.ServerPublicEndpoint = c.String("apiserver")
}
if c.String("pubkey") != "" {
cfg.Client.ServerKey = c.String("pubkey")
}
if c.String("network") != "all" {
cfg.Client.Network = c.String("network")
}
} else {
cfg.Client.ServerPrivateAddress = c.String("grpcserver")
cfg.Client.ServerPublicEndpoint = c.String("apiserver")
cfg.Client.ServerKey = c.String("key")
cfg.Client.Network = c.String("network")
}
cfg.Client.Address = c.String("address")
cfg.Client.Address6 = c.String("addressIPV6")
cfg.Client.PublicKey = c.String("pubkey")
cfg.Client.PrivateKey = c.String("privkey")
return cfg, nil
return cfg, privateKey, nil
}
func ReadConfig(network string) (*ClientConfig, error) {
@@ -596,3 +428,15 @@ func FileExists(f string) bool {
}
return !info.IsDir()
}
func GetNode(network string) models.Node {
modcfg, err := ReadConfig(network)
if err != nil {
log.Fatalf("Error: %v", err)
}
var node models.Node
node.Fill(&modcfg.Node)
return node
}

View File

@@ -1,389 +1,284 @@
package functions
import (
"google.golang.org/grpc/credentials"
"crypto/tls"
"context"
"strings"
"crypto/tls"
"encoding/json"
"errors"
"log"
"net"
"os/exec"
"github.com/gravitl/netmaker/netclient/config"
"github.com/gravitl/netmaker/netclient/local"
"github.com/gravitl/netmaker/netclient/wireguard"
"github.com/gravitl/netmaker/netclient/server"
"github.com/gravitl/netmaker/netclient/auth"
nodepb "github.com/gravitl/netmaker/grpc"
"google.golang.org/grpc"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/auth"
"github.com/gravitl/netmaker/netclient/config"
"github.com/gravitl/netmaker/netclient/local"
"github.com/gravitl/netmaker/netclient/wireguard"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
//homedir "github.com/mitchellh/go-homedir"
)
func CheckIn(cliconf config.ClientConfig) error {
network := cliconf.Network
node := server.GetNode(network)
cfg, err := config.ReadConfig(network)
if err != nil {
return err
}
nodecfg := cfg.Node
servercfg := cfg.Server
log.Println("Checking into server at " + servercfg.GRPCAddress)
setupcheck := true
func checkIP(node *models.Node, servercfg config.ServerConfig, cliconf config.ClientConfig, network string) bool {
ipchange := false
if nodecfg.DNS == "on" || cliconf.Node.DNS == "on" {
log.Println("setting dns")
ifacename := node.Interface
nameserver := servercfg.CoreDNSAddr
network := node.Nodenetwork
_ = local.UpdateDNS(ifacename, network, nameserver)
}
if !(nodecfg.IPForwarding == "off") {
out, err := exec.Command("sysctl", "net.ipv4.ip_forward").Output()
if err != nil {
log.Println(err)
log.Println("WARNING: Error encountered setting ip forwarding. This can break functionality.")
} else {
s := strings.Fields(string(out))
if s[2] != "1" {
_, err = exec.Command("sysctl", "-w", "net.ipv4.ip_forward=1").Output()
if err != nil {
log.Println(err)
log.Println("WARNING: Error encountered setting ip forwarding. You may want to investigate this.")
}
var err error
if node.Roaming == "yes" {
if node.IsLocal == "no" {
log.Println("Checking to see if public addresses have changed")
extIP, err := getPublicIP()
if err != nil {
log.Println("error encountered checking ip addresses:", err)
}
if node.Endpoint != extIP && extIP != "" {
log.Println("Endpoint has changed from " +
node.Endpoint + " to " + extIP)
log.Println("Updating address")
node.Endpoint = extIP
ipchange = true
}
intIP, err := getPrivateAddr()
if err != nil {
log.Println("error encountered checking ip addresses:", err)
}
if node.LocalAddress != intIP && intIP != "" {
log.Println("Local Address has changed from " +
node.LocalAddress + " to " + intIP)
log.Println("Updating address")
node.LocalAddress = intIP
ipchange = true
}
} else {
log.Println("Checking to see if local addresses have changed")
localIP, err := getLocalIP(node.LocalRange)
if err != nil {
log.Println("error encountered checking ip addresses:", err)
}
if node.Endpoint != localIP && localIP != "" {
log.Println("Endpoint has changed from " +
node.Endpoint + " to " + localIP)
log.Println("Updating address")
node.Endpoint = localIP
node.LocalAddress = localIP
ipchange = true
}
}
}
if nodecfg.Roaming != "off" {
if nodecfg.IsLocal != "yes" {
log.Println("Checking to see if public addresses have changed")
extIP, err := getPublicIP()
if err != nil {
log.Println("Error encountered checking ip addresses: %v", err)
}
if nodecfg.Endpoint != extIP && extIP != "" {
log.Println("Endpoint has changed from " +
nodecfg.Endpoint + " to " + extIP)
log.Println("Updating address")
nodecfg.Endpoint = extIP
nodecfg.PostChanges = "true"
node.Endpoint = extIP
node.Postchanges = "true"
ipchange = true
}
intIP, err := getPrivateAddr()
if err != nil {
log.Println("Error encountered checking ip addresses: %v", err)
}
if nodecfg.LocalAddress != intIP && intIP != "" {
log.Println("Local Address has changed from " +
nodecfg.LocalAddress + " to " + intIP)
log.Println("Updating address")
nodecfg.LocalAddress = intIP
nodecfg.PostChanges = "true"
node.Localaddress = intIP
node.Postchanges = "true"
ipchange = true
}
} else {
log.Println("Checking to see if local addresses have changed")
localIP, err := getLocalIP(nodecfg.LocalRange)
if err != nil {
log.Println("Error encountered checking ip addresses: %v", err)
}
if nodecfg.Endpoint != localIP && localIP != "" {
log.Println("Endpoint has changed from " +
nodecfg.Endpoint + " to " + localIP)
log.Println("Updating address")
nodecfg.Endpoint = localIP
nodecfg.LocalAddress = localIP
nodecfg.PostChanges = "true"
node.Endpoint = localIP
node.Localaddress = localIP
node.Postchanges = "true"
ipchange = true
}
}
if node.Postchanges != "true" {
log.Println("Addresses have not changed.")
}
}
if ipchange {
err := config.ModConfig(&node)
if err != nil {
return err
log.Fatalf("Error: %v", err)
}
err = wireguard.SetWGConfig(network, false)
if err != nil {
return err
log.Fatalf("Error: %v", err)
}
node = server.GetNode(network)
cfg, err := config.ReadConfig(network)
err = config.ModConfig(node)
if err != nil {
return err
}
nodecfg = cfg.Node
}
var wcclient nodepb.NodeServiceClient
var requestOpts grpc.DialOption
requestOpts = grpc.WithInsecure()
if servercfg.GRPCSSL == "on" {
log.Println("using SSL")
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
requestOpts = grpc.WithTransportCredentials(h2creds)
} else {
log.Println("using insecure GRPC connection")
}
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
if err != nil {
log.Println("Cant dial GRPC server: %v", err)
return err
}
wcclient = nodepb.NewNodeServiceClient(conn)
ctx := context.Background()
log.Println("Authenticating with GRPC Server")
ctx, err = auth.SetJWT(wcclient, network)
if err != nil {
log.Println("Failed to authenticate: %v", err)
return err
}
log.Println("Authenticated")
log.Println("Checking In.")
var header metadata.MD
node.Nodenetwork = network
checkinres, err := wcclient.CheckIn(
ctx,
&nodepb.CheckInReq{
Node: &node,
},
grpc.Header(&header),
)
if err != nil {
if checkinres != nil && checkinres.Checkinresponse.Ispending {
log.Println("Node is in pending status. Waiting for Admin approval of node before making further updates.")
return nil
}
log.Println("Unable to process Check In request: %v", err)
return err
}
log.Println("Checked in.")
if checkinres.Checkinresponse.Ispending {
log.Println("Node is in pending status. Waiting for Admin approval of node before making further updates.")
return err
}
newinterface := server.GetNode(network).Interface
readreq := &nodepb.ReadNodeReq{
Macaddress: node.Macaddress,
Network: node.Nodenetwork,
}
readres, err := wcclient.ReadNode(ctx, readreq, grpc.Header(&header))
if err != nil {
log.Println("Error: %v", err)
} else {
currentiface := readres.Node.Interface
ifaceupdate := newinterface != currentiface
if err != nil {
log.Println("Error retrieving interface: %v", err)
}
if ifaceupdate {
log.Println("Interface update: " + currentiface +
" >>>> " + newinterface)
err := DeleteInterface(currentiface, nodecfg.PostDown)
if err != nil {
log.Println("ERROR DELETING INTERFACE: " + currentiface)
}
err = wireguard.SetWGConfig(network, false)
if err != nil {
log.Println("Error updating interface: %v", err)
}
log.Println("Error:", err)
return false
}
err = wireguard.SetWGConfig(network, false)
if err != nil {
log.Println("Error:", err)
return false
}
}
return ipchange && err == nil
}
if checkinres.Checkinresponse.Needconfigupdate {
log.Println("Server has requested that node update config.")
log.Println("Updating config from remote server.")
req := &nodepb.ReadNodeReq{
Macaddress: node.Macaddress,
Network: node.Nodenetwork,
}
readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
if err != nil {
return err
log.Fatalf("Error: %v", err)
}
err = config.ModConfig(readres.Node)
if err != nil {
return err
log.Fatalf("Error: %v", err)
}
err = wireguard.SetWGConfig(network, false)
if err != nil {
return err
log.Fatalf("Error: %v", err)
}
setupcheck = false
} else if nodecfg.PostChanges == "true" {
log.Println("Node has requested to update remote config.")
log.Println("Posting local config to remote server.")
postnode := server.GetNode(network)
log.Println("POSTING NODE: ",postnode.Macaddress,postnode.Saveconfig)
req := &nodepb.UpdateNodeReq{
Node: &postnode,
}
res, err := wcclient.UpdateNode(ctx, req, grpc.Header(&header))
if err != nil {
return err
log.Fatalf("Error: %v", err)
}
res.Node.Postchanges = "false"
err = config.ModConfig(res.Node)
if err != nil {
return err
log.Fatalf("Error: %v", err)
}
if err != nil {
return err
log.Fatalf("Error: %v", err)
}
setupcheck = false
func setDNS(node *models.Node, servercfg config.ServerConfig, nodecfg *models.Node) {
if nodecfg.DNSOn == "yes" {
log.Println("setting dns")
ifacename := node.Interface
nameserver := servercfg.CoreDNSAddr
network := node.Network
_ = local.UpdateDNS(ifacename, network, nameserver)
}
if checkinres.Checkinresponse.Needkeyupdate {
log.Println("Server has requested that node update key pairs.")
log.Println("Proceeding to re-generate key pairs for Wiregard.")
err = wireguard.SetWGKeyConfig(network, servercfg.GRPCAddress)
if err != nil {
return err
log.Fatalf("Unable to process reset keys request: %v", err)
}
setupcheck = false
}
if checkinres.Checkinresponse.Needpeerupdate {
log.Println("Server has requested that node update peer list.")
log.Println("Updating peer list from remote server.")
err = wireguard.SetWGConfig(network, true)
if err != nil {
return err
log.Fatalf("Unable to process Set Peers request: %v", err)
}
setupcheck = false
}
if checkinres.Checkinresponse.Needdelete {
log.Println("This machine got the delete signal. Deleting.")
err := LeaveNetwork(network)
if err != nil {
return err
log.Fatalf("Error: %v", err)
}
}
/**
*
*
*/
func checkNodeActions(node *models.Node, network string, servercfg config.ServerConfig) string {
if node.Action == models.NODE_UPDATE_KEY {
err := wireguard.SetWGKeyConfig(network, servercfg.GRPCAddress)
if err != nil {
log.Println("Unable to process reset keys request:", err)
return ""
}
node.Action = ""
return ""
}
if setupcheck {
iface := nodecfg.Interface
_, err := net.InterfaceByName(iface)
if err != nil {
log.Println("interface " + iface + " does not currently exist. Setting up WireGuard.")
err = wireguard.SetWGKeyConfig(network, servercfg.GRPCAddress)
if err != nil {
return err
log.Fatalf("Error: %v", err)
}
if node.Action == models.NODE_DELETE {
err := LeaveNetwork(network)
if err != nil {
log.Println("Error:", err)
return ""
}
return models.NODE_DELETE
}
return ""
}
/**
* Pull changes if any (interface refresh)
* - Save it
* Check local changes for (ipAddress, publickey, configfile changes) (interface refresh)
* - Save it
* - Push it
* Pull Peers (sync)
*/
func CheckConfig(cliconf config.ClientConfig) error {
network := cliconf.Network
// node := server.GetNode(network)
cfg, err := config.ReadConfig(network)
if err != nil {
return err
}
// nodecfg := cfg.Node
servercfg := cfg.Server
newNode, err := Pull(network, false)
if err != nil {
return err
}
if newNode.IsPending == "yes" {
return errors.New("node is pending")
}
// check for interface change
if cfg.Node.Interface != newNode.Interface {
if err = DeleteInterface(cfg.Node.Interface, cfg.Node.PostDown); err != nil {
log.Println("could not delete old interface", cfg.Node.Interface)
}
}
actionCompleted := checkNodeActions(newNode, network, servercfg)
if actionCompleted == models.NODE_DELETE {
return errors.New("node has been removed")
}
// Check if ip changed and push if so
if checkIP(newNode, servercfg, cliconf, network) {
err = Push(network)
}
//err = Pull(network)
return err
}
func Pull (network string) error{
node := server.GetNode(network)
/**
* Pull the latest node from server
* Perform action if necessary
*/
func Pull(network string, manual bool) (*models.Node, error) {
node := config.GetNode(network)
cfg, err := config.ReadConfig(network)
if err != nil {
return err
}
servercfg := cfg.Server
var header metadata.MD
if err != nil {
return nil, err
}
servercfg := cfg.Server
var header metadata.MD
if cfg.Node.IPForwarding == "yes" {
if err = local.SetIPForwarding(); err != nil {
return nil, err
}
}
var requestOpts grpc.DialOption
requestOpts = grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" {
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
requestOpts = grpc.WithTransportCredentials(h2creds)
}
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
if err != nil {
log.Println("Cant dial GRPC server:", err)
return nil, err
}
wcclient := nodepb.NewNodeServiceClient(conn)
ctx, err := auth.SetJWT(wcclient, network)
if err != nil {
log.Println("Failed to authenticate:", err)
return nil, err
}
req := &nodepb.Object{
Data: node.MacAddress + "###" + node.Network,
Type: nodepb.STRING_TYPE,
}
readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
if err != nil {
return nil, err
}
var resNode models.Node
if err = json.Unmarshal([]byte(readres.Data), &resNode); err != nil {
return nil, err
}
if resNode.PullChanges == "yes" || manual {
if err = config.ModConfig(&resNode); err != nil {
return nil, err
}
if err = wireguard.SetWGConfig(network, false); err != nil {
return nil, err
}
resNode.PullChanges = "no"
nodeData, err := json.Marshal(&resNode)
if err != nil {
return &resNode, err
}
req := &nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
Metadata: "",
}
_, err = wcclient.UpdateNode(ctx, req, grpc.Header(&header))
if err != nil {
return &resNode, err
}
}
setDNS(&node, servercfg, &cfg.Node)
return &node, err
}
func Push(network string) error {
postnode := config.GetNode(network)
cfg, err := config.ReadConfig(network)
if err != nil {
return err
}
servercfg := cfg.Server
var header metadata.MD
var wcclient nodepb.NodeServiceClient
var requestOpts grpc.DialOption
requestOpts = grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" {
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
requestOpts = grpc.WithTransportCredentials(h2creds)
}
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
if err != nil {
log.Println("Cant dial GRPC server: %v", err)
return err
}
wcclient = nodepb.NewNodeServiceClient(conn)
var requestOpts grpc.DialOption
requestOpts = grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" {
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
requestOpts = grpc.WithTransportCredentials(h2creds)
}
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
if err != nil {
log.Println("Cant dial GRPC server:", err)
return err
}
wcclient = nodepb.NewNodeServiceClient(conn)
ctx := context.Background()
ctx, err = auth.SetJWT(wcclient, network)
if err != nil {
log.Println("Failed to authenticate: %v", err)
return err
}
req := &nodepb.ReadNodeReq{
Macaddress: node.Macaddress,
Network: node.Nodenetwork,
}
readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
if err != nil {
return err
}
err = config.ModConfig(readres.Node)
if err != nil {
return err
}
err = wireguard.SetWGConfig(network, false)
if err != nil {
return err
}
ctx, err := auth.SetJWT(wcclient, network)
if err != nil {
log.Println("Failed to authenticate:", err)
return err
}
nodeData, err := json.Marshal(&postnode)
if err != nil {
return err
}
req := &nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
Metadata: "",
}
data, err := wcclient.UpdateNode(ctx, req, grpc.Header(&header))
if err != nil {
return err
}
err = json.Unmarshal([]byte(data.Data), &postnode)
if err != nil {
return err
}
err = config.ModConfig(&postnode)
return err
}
func Push (network string) error{
postnode := server.GetNode(network)
cfg, err := config.ReadConfig(network)
if err != nil {
return err
}
servercfg := cfg.Server
var header metadata.MD
var wcclient nodepb.NodeServiceClient
var requestOpts grpc.DialOption
requestOpts = grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" {
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
requestOpts = grpc.WithTransportCredentials(h2creds)
}
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
if err != nil {
log.Println("Cant dial GRPC server: %v", err)
return err
}
wcclient = nodepb.NewNodeServiceClient(conn)
ctx := context.Background()
ctx, err = auth.SetJWT(wcclient, network)
if err != nil {
log.Println("Failed to authenticate: %v", err)
return err
}
req := &nodepb.UpdateNodeReq{
Node: &postnode,
}
_, err = wcclient.UpdateNode(ctx, req, grpc.Header(&header))
return err
}

View File

@@ -1,66 +1,68 @@
package functions
import (
"google.golang.org/grpc/credentials"
"crypto/tls"
"fmt"
"context"
"crypto/tls"
"encoding/json"
"errors"
"context"
"net/http"
"io/ioutil"
"strings"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"os/exec"
"github.com/gravitl/netmaker/netclient/config"
"github.com/gravitl/netmaker/netclient/local"
"github.com/gravitl/netmaker/netclient/auth"
nodepb "github.com/gravitl/netmaker/grpc"
"strings"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/auth"
"github.com/gravitl/netmaker/netclient/config"
"github.com/gravitl/netmaker/netclient/local"
"golang.zx2c4.com/wireguard/wgctrl"
"google.golang.org/grpc"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
//homedir "github.com/mitchellh/go-homedir"
)
var (
wcclient nodepb.NodeServiceClient
wcclient nodepb.NodeServiceClient
)
func ListPorts() error{
func ListPorts() error {
wgclient, err := wgctrl.New()
if err != nil {
if err != nil {
return err
}
devices, err := wgclient.Devices()
if err != nil {
return err
}
if err != nil {
return err
}
fmt.Println("Here are your ports:")
for _, i := range devices {
for _, i := range devices {
fmt.Println(i.ListenPort)
}
return err
}
func GetFreePort(rangestart int32) (int32, error){
wgclient, err := wgctrl.New()
if err != nil {
return 0, err
}
devices, err := wgclient.Devices()
if err != nil {
return 0, err
}
func GetFreePort(rangestart int32) (int32, error) {
wgclient, err := wgctrl.New()
if err != nil {
return 0, err
}
devices, err := wgclient.Devices()
if err != nil {
return 0, err
}
var portno int32
portno = 0
for x := rangestart; x <= 60000; x++ {
for x := rangestart; x <= 60000; x++ {
conflict := false
for _, i := range devices {
if int32(i.ListenPort) == x {
conflict = true
break;
break
}
}
if conflict {
@@ -69,49 +71,49 @@ func GetFreePort(rangestart int32) (int32, error){
portno = x
break
}
return portno, err
return portno, err
}
func getLocalIP(localrange string) (string, error) {
_, localRange, err := net.ParseCIDR(localrange)
if err != nil {
return "", err
}
ifaces, err := net.Interfaces()
if err != nil {
if err != nil {
return "", err
}
var local string
found := false
for _, i := range ifaces {
if i.Flags&net.FlagUp == 0 {
continue // interface down
}
if i.Flags&net.FlagLoopback != 0 {
continue // loopback interface
}
addrs, err := i.Addrs()
if err != nil {
return "", err
}
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
if !found {
ip = v.IP
local = ip.String()
found = localRange.Contains(ip)
}
case *net.IPAddr:
if !found {
ip = v.IP
local = ip.String()
found = localRange.Contains(ip)
}
}
}
}
}
ifaces, err := net.Interfaces()
if err != nil {
return "", err
}
var local string
found := false
for _, i := range ifaces {
if i.Flags&net.FlagUp == 0 {
continue // interface down
}
if i.Flags&net.FlagLoopback != 0 {
continue // loopback interface
}
addrs, err := i.Addrs()
if err != nil {
return "", err
}
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
if !found {
ip = v.IP
local = ip.String()
found = localRange.Contains(ip)
}
case *net.IPAddr:
if !found {
ip = v.IP
local = ip.String()
found = localRange.Contains(ip)
}
}
}
}
if !found || local == "" {
return "", errors.New("Failed to find local IP in range " + localrange)
}
@@ -120,10 +122,10 @@ func getLocalIP(localrange string) (string, error) {
func getPublicIP() (string, error) {
iplist := []string{"http://ip.client.gravitl.com","https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
iplist := []string{"http://ip.client.gravitl.com", "https://ifconfig.me", "http://api.ipify.org", "http://ipinfo.io/ip"}
endpoint := ""
var err error
for _, ipserver := range iplist {
for _, ipserver := range iplist {
resp, err := http.Get(ipserver)
if err != nil {
continue
@@ -140,125 +142,97 @@ func getPublicIP() (string, error) {
}
if err == nil && endpoint == "" {
err = errors.New("Public Address Not Found.")
err = errors.New("Public Address Not Found.")
}
return endpoint, err
}
func getMacAddr() ([]string, error) {
ifas, err := net.Interfaces()
if err != nil {
return nil, err
}
var as []string
for _, ifa := range ifas {
a := ifa.HardwareAddr.String()
if a != "" {
as = append(as, a)
}
}
return as, nil
ifas, err := net.Interfaces()
if err != nil {
return nil, err
}
var as []string
for _, ifa := range ifas {
a := ifa.HardwareAddr.String()
if a != "" {
as = append(as, a)
}
}
return as, nil
}
func getPrivateAddr() (string, error) {
ifaces, err := net.Interfaces()
if err != nil {
return "", err
}
var local string
found := false
for _, i := range ifaces {
if i.Flags&net.FlagUp == 0 {
continue // interface down
}
if i.Flags&net.FlagLoopback != 0 {
continue // loopback interface
}
addrs, err := i.Addrs()
if err != nil {
return "", err
}
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
if !found {
ip = v.IP
local = ip.String()
found = true
}
case *net.IPAddr:
if !found {
ip = v.IP
local = ip.String()
found = true
}
}
}
}
if !found {
err := errors.New("Local Address Not Found.")
ifaces, err := net.Interfaces()
if err != nil {
return "", err
}
var local string
found := false
for _, i := range ifaces {
if i.Flags&net.FlagUp == 0 {
continue // interface down
}
if i.Flags&net.FlagLoopback != 0 {
continue // loopback interface
}
addrs, err := i.Addrs()
if err != nil {
return "", err
}
return local, err
for _, addr := range addrs {
var ip net.IP
switch v := addr.(type) {
case *net.IPNet:
if !found {
ip = v.IP
local = ip.String()
found = true
}
case *net.IPAddr:
if !found {
ip = v.IP
local = ip.String()
found = true
}
}
}
}
if !found {
err := errors.New("Local Address Not Found.")
return "", err
}
return local, err
}
func needInterfaceUpdate(ctx context.Context, mac string, network string, iface string) (bool, string, error) {
var header metadata.MD
req := &nodepb.ReadNodeReq{
Macaddress: mac,
Network: network,
}
readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
if err != nil {
return false, "", err
log.Fatalf("Error: %v", err)
}
oldiface := readres.Node.Interface
var header metadata.MD
req := &nodepb.Object{
Data: mac + "###" + network,
Type: nodepb.STRING_TYPE,
}
readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
if err != nil {
return false, "", err
log.Fatalf("Error: %v", err)
}
var resNode models.Node
if err := json.Unmarshal([]byte(readres.Data), &resNode); err != nil {
return false, iface, err
}
oldiface := resNode.Interface
return iface != oldiface, oldiface, err
return iface != oldiface, oldiface, err
}
func GetNode(network string) nodepb.Node {
func GetNode(network string) models.Node {
modcfg, err := config.ReadConfig(network)
if err != nil {
log.Fatalf("Error: %v", err)
}
nodecfg := modcfg.Node
var node nodepb.Node
node.Name = nodecfg.Name
node.Interface = nodecfg.Interface
node.Nodenetwork = nodecfg.Network
node.Localaddress = nodecfg.LocalAddress
node.Address = nodecfg.WGAddress
node.Address6 = nodecfg.WGAddress6
node.Listenport = nodecfg.Port
node.Keepalive = nodecfg.KeepAlive
node.Postup = nodecfg.PostUp
node.Postdown = nodecfg.PostDown
node.Publickey = nodecfg.PublicKey
node.Macaddress = nodecfg.MacAddress
node.Endpoint = nodecfg.Endpoint
node.Password = nodecfg.Password
if nodecfg.DNS == "on" {
node.Dnsoff = true
} else {
node.Dnsoff = false
}
if nodecfg.IsDualStack == "yes" {
node.Isdualstack = true
} else {
node.Isdualstack = false
modcfg, err := config.ReadConfig(network)
if err != nil {
log.Fatalf("Error: %v", err)
}
if nodecfg.IsIngressGateway == "yes" {
node.Isingressgateway = true
} else {
node.Isingressgateway = false
}
return node
return modcfg.Node
}
func Uninstall() error {
@@ -270,7 +244,7 @@ func Uninstall() error {
for _, network := range networks {
err = LeaveNetwork(network)
if err != nil {
log.Println("Encounter issue leaving network " + network + ": ", err)
log.Println("Encounter issue leaving network "+network+": ", err)
}
}
}
@@ -278,40 +252,40 @@ 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
}
servercfg := cfg.Server
node := cfg.Node
var wcclient nodepb.NodeServiceClient
var requestOpts grpc.DialOption
requestOpts = grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" {
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
requestOpts = grpc.WithTransportCredentials(h2creds)
}
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
//need to implement checkin on server side
cfg, err := config.ReadConfig(network)
if err != nil {
log.Printf("Unable to establish client connection to " + servercfg.GRPCAddress + ": %v", err)
}else {
return err
}
servercfg := cfg.Server
node := cfg.Node
var wcclient nodepb.NodeServiceClient
var requestOpts grpc.DialOption
requestOpts = grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" {
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
requestOpts = grpc.WithTransportCredentials(h2creds)
}
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
if err != nil {
log.Printf("Unable to establish client connection to "+servercfg.GRPCAddress+": %v", err)
} else {
wcclient = nodepb.NewNodeServiceClient(conn)
ctx := context.Background()
ctx, err = auth.SetJWT(wcclient, network)
if err != nil {
log.Printf("Failed to authenticate: %v", err)
log.Printf("Failed to authenticate: %v", err)
} else {
var header metadata.MD
_, err = wcclient.DeleteNode(
ctx,
&nodepb.DeleteNodeReq{
Macaddress: node.MacAddress,
NetworkName: node.Network,
},
grpc.Header(&header),
ctx,
&nodepb.Object{
Data: node.ID,
Type: nodepb.STRING_TYPE,
},
grpc.Header(&header),
)
if err != nil {
log.Printf("Encountered error deleting node: %v", err)
@@ -323,41 +297,40 @@ func LeaveNetwork(network string) error {
}
err = local.WipeLocal(network)
if err != nil {
log.Printf("Unable to wipe local config: %v", err)
log.Printf("Unable to wipe local config: %v", err)
} else {
log.Println("Removed " + node.Network + " network locally")
}
if cfg.Daemon != "off" {
err = local.RemoveSystemDServices(network)
err = local.RemoveSystemDServices(network)
}
return err
}
func DeleteInterface(ifacename string, postdown string) error{
ipExec, err := exec.LookPath("ip")
func DeleteInterface(ifacename string, postdown string) error {
ipExec, err := exec.LookPath("ip")
cmdIPLinkDel := &exec.Cmd {
Path: ipExec,
Args: []string{ ipExec, "link", "del", ifacename },
Stdout: os.Stdout,
Stderr: os.Stdout,
}
err = cmdIPLinkDel.Run()
if err != nil {
log.Println(err)
}
if postdown != "" {
runcmds := strings.Split(postdown, "; ")
err = local.RunCmds(runcmds)
if err != nil {
log.Println("Error encountered running PostDown: " + err.Error())
}
}
return err
cmdIPLinkDel := &exec.Cmd{
Path: ipExec,
Args: []string{ipExec, "link", "del", ifacename},
Stdout: os.Stdout,
Stderr: os.Stdout,
}
err = cmdIPLinkDel.Run()
if err != nil {
log.Println(err)
}
if postdown != "" {
runcmds := strings.Split(postdown, "; ")
err = local.RunCmds(runcmds)
if err != nil {
log.Println("Error encountered running PostDown: " + err.Error())
}
}
return err
}
func List() error{
func List() error {
networks, err := GetNetworks()
if err != nil {
@@ -366,36 +339,34 @@ func List() error{
for _, network := range networks {
cfg, err := config.ReadConfig(network)
if err == nil {
//cfg2 := *cfg
listconfig := &config.ListConfig{
Name: cfg.Node.Name,
Interface: cfg.Node.Interface,
PrivateIPv4: cfg.Node.WGAddress,
PrivateIPv6: cfg.Node.WGAddress6,
PublicEndpoint: cfg.Node.Endpoint,
}
jsoncfg, _ := json.Marshal(listconfig)
jsoncfg, _ := json.Marshal(
map[string]string{
"Name": cfg.Node.Name,
"Interface": cfg.Node.Interface,
"PrivateIPv4": cfg.Node.Address,
"PrivateIPv6": cfg.Node.Address6,
"PublicEndpoint": cfg.Node.Endpoint,
})
log.Println(network + ": " + string(jsoncfg))
} else {
log.Println(network + ": Could not retrieve network configuration.")
}
}
return nil
}
func GetNetworks() ([]string, error) {
var networks []string
files, err := ioutil.ReadDir("/etc/netclient")
if err != nil {
return networks, err
}
for _, f := range files {
if strings.Contains(f.Name(), "netconfig-") && !strings.Contains(f.Name(), "global-001"){
networkname := stringAfter(f.Name(), "netconfig-")
networks = append(networks, networkname)
}
}
var networks []string
files, err := ioutil.ReadDir("/etc/netclient")
if err != nil {
return networks, err
}
for _, f := range files {
if strings.Contains(f.Name(), "netconfig-") && !strings.Contains(f.Name(), "global-001") {
networkname := stringAfter(f.Name(), "netconfig-")
networks = append(networks, networkname)
}
}
return networks, err
}

View File

@@ -3,6 +3,7 @@ package functions
import (
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"log"
@@ -11,6 +12,8 @@ import (
"time"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/auth"
"github.com/gravitl/netmaker/netclient/config"
"github.com/gravitl/netmaker/netclient/local"
"github.com/gravitl/netmaker/netclient/server"
@@ -22,7 +25,7 @@ import (
//homedir "github.com/mitchellh/go-homedir"
)
func JoinNetwork(cfg config.ClientConfig) error {
func JoinNetwork(cfg config.ClientConfig, privateKey string) error {
hasnet := local.HasNetwork(cfg.Network)
if hasnet {
@@ -100,12 +103,12 @@ func JoinNetwork(cfg config.ClientConfig) error {
}
if cfg.Node.Password == "" {
cfg.Node.Password = GenPass()
auth.StoreSecret(cfg.Node.Password, cfg.Node.Network)
}
if cfg.Node.Endpoint == "" {
if cfg.Node.IsLocal == "yes" && cfg.Node.LocalAddress != "" {
cfg.Node.Endpoint = cfg.Node.LocalAddress
} else {
cfg.Node.Endpoint, err = getPublicIP()
if err != nil {
fmt.Println("Error setting cfg.Node.Endpoint.")
@@ -115,13 +118,13 @@ func JoinNetwork(cfg config.ClientConfig) error {
} else {
cfg.Node.Endpoint = cfg.Node.Endpoint
}
if cfg.Node.PrivateKey == "" {
privatekey, err := wgtypes.GeneratePrivateKey()
if privateKey == "" {
wgPrivatekey, err := wgtypes.GeneratePrivateKey()
if err != nil {
log.Fatal(err)
}
cfg.Node.PrivateKey = privatekey.String()
cfg.Node.PublicKey = privatekey.PublicKey().String()
privateKey = wgPrivatekey.String()
cfg.Node.PublicKey = wgPrivatekey.PublicKey().String()
}
if cfg.Node.MacAddress == "" {
@@ -134,8 +137,8 @@ func JoinNetwork(cfg config.ClientConfig) error {
cfg.Node.MacAddress = macs[0]
}
}
if cfg.Node.Port == 0 {
cfg.Node.Port, err = GetFreePort(51821)
if cfg.Node.ListenPort == 0 {
cfg.Node.ListenPort, err = GetFreePort(51821)
if err != nil {
fmt.Printf("Error retrieving port: %v", err)
}
@@ -155,59 +158,65 @@ func JoinNetwork(cfg config.ClientConfig) error {
wcclient = nodepb.NewNodeServiceClient(conn)
postnode := &nodepb.Node{
Password: cfg.Node.Password,
Macaddress: cfg.Node.MacAddress,
Accesskey: cfg.Server.AccessKey,
Nodenetwork: cfg.Network,
Listenport: cfg.Node.Port,
Postup: cfg.Node.PostUp,
Postdown: cfg.Node.PostDown,
Keepalive: cfg.Node.KeepAlive,
Localaddress: cfg.Node.LocalAddress,
Interface: cfg.Node.Interface,
Publickey: cfg.Node.PublicKey,
Name: cfg.Node.Name,
Endpoint: cfg.Node.Endpoint,
Saveconfig: cfg.Node.SaveConfig,
Udpholepunch: cfg.Node.UDPHolePunch,
postnode := &models.Node{
Password: cfg.Node.Password,
MacAddress: cfg.Node.MacAddress,
AccessKey: cfg.Server.AccessKey,
Network: cfg.Network,
ListenPort: cfg.Node.ListenPort,
PostUp: cfg.Node.PostUp,
PostDown: cfg.Node.PostDown,
PersistentKeepalive: cfg.Node.PersistentKeepalive,
LocalAddress: cfg.Node.LocalAddress,
Interface: cfg.Node.Interface,
PublicKey: cfg.Node.PublicKey,
Name: cfg.Node.Name,
Endpoint: cfg.Node.Endpoint,
SaveConfig: cfg.Node.SaveConfig,
UDPHolePunch: cfg.Node.UDPHolePunch,
}
err = config.ModConfig(postnode)
if err = config.ModConfig(postnode); err != nil {
return err
}
data, err := json.Marshal(&postnode)
if err != nil {
return err
}
res, err := wcclient.CreateNode(
context.TODO(),
&nodepb.CreateNodeReq{
Node: postnode,
&nodepb.Object{
Data: string(data),
Type: nodepb.NODE_TYPE,
},
)
if err != nil {
return err
}
log.Println("node created on remote server...updating configs")
node := res.Node
if err != nil {
nodeData := res.Data
var node models.Node
if err = json.Unmarshal([]byte(nodeData), &node); err != nil {
return err
}
if node.Dnsoff == true {
cfg.Node.DNS = "yes"
if node.DNSOn == "yes" {
cfg.Node.DNSOn = "yes"
}
if !(cfg.Node.IsLocal == "yes") && node.Islocal && node.Localrange != "" {
node.Localaddress, err = getLocalIP(node.Localrange)
if !(cfg.Node.IsLocal == "yes") && node.IsLocal == "yes" && node.LocalRange != "" {
node.LocalAddress, err = getLocalIP(node.LocalRange)
if err != nil {
return err
}
node.Endpoint = node.Localaddress
node.Endpoint = node.LocalAddress
}
err = config.ModConfig(node)
err = config.ModConfig(&node)
if err != nil {
return err
}
if node.Ispending {
if node.IsPending == "yes" {
fmt.Println("Node is marked as PENDING.")
fmt.Println("Awaiting approval from Admin before configuring WireGuard.")
if cfg.Daemon != "off" {
@@ -216,18 +225,18 @@ func JoinNetwork(cfg config.ClientConfig) error {
}
}
log.Println("retrieving remote peers")
peers, hasGateway, gateways, err := server.GetPeers(node.Macaddress, cfg.Network, cfg.Server.GRPCAddress, node.Isdualstack, node.Isingressgateway)
peers, hasGateway, gateways, err := server.GetPeers(node.MacAddress, cfg.Network, cfg.Server.GRPCAddress, node.IsDualStack == "yes", node.IsIngressGateway == "yes")
if err != nil {
log.Println("failed to retrieve peers")
return err
}
err = wireguard.StorePrivKey(cfg.Node.PrivateKey, cfg.Network)
err = wireguard.StorePrivKey(privateKey, cfg.Network)
if err != nil {
return err
}
log.Println("starting wireguard")
err = wireguard.InitWireguard(node, cfg.Node.PrivateKey, peers, hasGateway, gateways)
err = wireguard.InitWireguard(&node, privateKey, peers, hasGateway, gateways)
if err != nil {
return err
}

View File

@@ -4,56 +4,56 @@ import (
"io/ioutil"
"os"
"strings"
//"github.com/davecgh/go-spew/spew"
"log"
"os/exec"
"log"
"os/exec"
)
func SetDNS(nameserver string) error {
bytes, err := ioutil.ReadFile("/etc/resolv.conf")
if err != nil {
return err
}
resolvstring := string(bytes)
// //check whether s contains substring text
hasdns := strings.Contains(resolvstring, nameserver)
if hasdns {
return nil
}
resolv, err := os.OpenFile("/etc/resolv.conf",os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer resolv.Close()
_, err = resolv.WriteString("nameserver " + nameserver + "\n")
bytes, err := ioutil.ReadFile("/etc/resolv.conf")
if err != nil {
return err
}
resolvstring := string(bytes)
// //check whether s contains substring text
hasdns := strings.Contains(resolvstring, nameserver)
if hasdns {
return nil
}
resolv, err := os.OpenFile("/etc/resolv.conf", os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer resolv.Close()
_, err = resolv.WriteString("nameserver " + nameserver + "\n")
return err
return err
}
func UpdateDNS(ifacename string, network string, nameserver string) error {
_, err := exec.LookPath("resolvectl")
if err != nil {
log.Println(err)
log.Println("WARNING: resolvectl not present. Unable to set dns. Install resolvectl or run manually.")
} else {
_, err = exec.Command("resolvectl", "domain", ifacename, "~"+network).Output()
if err != nil {
log.Println(err)
log.Println("WARNING: Error encountered setting domain on dns. Aborted setting dns.")
} else {
_, err = exec.Command("resolvectl", "default-route", ifacename, "false").Output()
if err != nil {
log.Println(err)
log.Println("WARNING: Error encountered setting default-route on dns. Aborted setting dns.")
} else {
_, err = exec.Command("resolvectl", "dns", ifacename, nameserver).Output()
if err!= nil {
log.Println("WARNING: Error encountered running resolvectl dns " + ifacename + " " + nameserver)
log.Println(err)
}
}
}
}
return err
_, err := exec.LookPath("resolvectl")
if err != nil {
log.Println(err)
log.Println("WARNING: resolvectl not present. Unable to set dns. Install resolvectl or run manually.")
} else {
_, err = RunCmd("resolvectl domain " + ifacename + " ~" + network)
if err != nil {
log.Println(err)
log.Println("WARNING: Error encountered setting domain on dns. Aborted setting dns.")
} else {
_, err = RunCmd("resolvectl default-route " + ifacename + " false")
if err != nil {
log.Println(err)
log.Println("WARNING: Error encountered setting default-route on dns. Aborted setting dns.")
} else {
_, err = RunCmd("resolvectl dns " + ifacename + " " + nameserver)
if err != nil {
log.Println("WARNING: Error encountered running resolvectl dns " + ifacename + " " + nameserver)
log.Println(err)
}
}
}
}
return err
}

View File

@@ -1,82 +1,121 @@
package local
import (
//"github.com/davecgh/go-spew/spew"
//"github.com/davecgh/go-spew/spew"
"errors"
"github.com/gravitl/netmaker/netclient/config"
"io"
"io/ioutil"
"log"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"io"
"runtime"
"strings"
"os"
"os/exec"
"github.com/gravitl/netmaker/netclient/config"
)
func SetIPForwarding() error {
os := runtime.GOOS
var err error
switch os {
case "linux":
err = SetIPForwardingLinux()
default:
err = errors.New("This OS is not supported")
}
return err
}
func SetIPForwardingLinux() error {
out, err := RunCmd("sysctl net.ipv4.ip_forward")
if err != nil {
log.Println(err)
log.Println("WARNING: Error encountered setting ip forwarding. This can break functionality.")
return err
} else {
s := strings.Fields(string(out))
if s[2] != "1" {
_, err = RunCmd("sysctl -w net.ipv4.ip_forward=1")
if err != nil {
log.Println(err)
log.Println("WARNING: Error encountered setting ip forwarding. You may want to investigate this.")
return err
}
}
}
return nil
}
func RunCmd(command string) (string, error) {
args := strings.Fields(command)
out, err := exec.Command(args[0], args[1:]...).Output()
return string(out), err
}
func RunCmds(commands []string) error {
var err error
for _, command := range commands {
args := strings.Fields(command)
out, err := exec.Command(args[0], args[1:]...).Output()
if string(out) != "" {
var err error
for _, command := range commands {
args := strings.Fields(command)
out, err := exec.Command(args[0], args[1:]...).Output()
if string(out) != "" {
log.Println(string(out))
}
if err != nil {
return err
}
}
return err
if err != nil {
return err
}
}
return err
}
func FileExists(f string) bool {
info, err := os.Stat(f)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
info, err := os.Stat(f)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}
func ConfigureSystemD(network string) error {
/*
path, err := os.Getwd()
if err != nil {
log.Println(err)
return err
}
path, err := os.Getwd()
if err != nil {
log.Println(err)
return err
}
*/
//binarypath := path + "/netclient"
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
return err
}
binarypath := dir + "/netclient"
_, err = os.Stat("/etc/netclient")
if os.IsNotExist(err) {
os.Mkdir("/etc/netclient", 744)
} else if err != nil {
log.Println("couldnt find or create /etc/netclient")
return err
}
if !FileExists("/usr/local/bin/netclient") {
os.Symlink("/etc/netclient/netclient","/usr/local/bin/netclient")
/*
_, err = copy(binarypath, "/usr/local/bin/netclient")
if err != nil {
log.Println(err)
return err
}
*/
}
if !FileExists("/etc/netclient/netclient") {
_, err = copy(binarypath, "/etc/netclient/netclient")
if err != nil {
log.Println(err)
return err
}
binarypath := dir + "/netclient"
_, err = os.Stat("/etc/netclient")
if os.IsNotExist(err) {
os.Mkdir("/etc/netclient", 744)
} else if err != nil {
log.Println("couldnt find or create /etc/netclient")
return err
}
if !FileExists("/usr/local/bin/netclient") {
os.Symlink("/etc/netclient/netclient", "/usr/local/bin/netclient")
/*
_, err = copy(binarypath, "/usr/local/bin/netclient")
if err != nil {
log.Println(err)
return err
}
*/
}
if !FileExists("/etc/netclient/netclient") {
_, err = copy(binarypath, "/etc/netclient/netclient")
if err != nil {
log.Println(err)
return err
}
}
systemservice := `[Unit]
Description=network check for remote peers and local config
@@ -94,18 +133,18 @@ WantedBy=multi-user.target
Description=Calls the Netmaker Mesh Client Service
`
systemtimer = systemtimer + "Requires=netclient@"+network+".service"
systemtimer = systemtimer + "Requires=netclient@" + network + ".service"
systemtimer = systemtimer +
`
systemtimer = systemtimer +
`
[Timer]
`
systemtimer = systemtimer + "Unit=netclient@"+network+".service"
systemtimer = systemtimer + "Unit=netclient@" + network + ".service"
systemtimer = systemtimer +
`
systemtimer = systemtimer +
`
OnCalendar=*:*:0/30
@@ -117,67 +156,41 @@ WantedBy=timers.target
timerbytes := []byte(systemtimer)
if !FileExists("/etc/systemd/system/netclient@.service") {
err = ioutil.WriteFile("/etc/systemd/system/netclient@.service", servicebytes, 0644)
if err != nil {
log.Println(err)
return err
}
err = ioutil.WriteFile("/etc/systemd/system/netclient@.service", servicebytes, 0644)
if err != nil {
log.Println(err)
return err
}
}
if !FileExists("/etc/systemd/system/netclient-"+network+".timer") {
err = ioutil.WriteFile("/etc/systemd/system/netclient-"+network+".timer", timerbytes, 0644)
if err != nil {
log.Println(err)
return err
}
if !FileExists("/etc/systemd/system/netclient-" + network + ".timer") {
err = ioutil.WriteFile("/etc/systemd/system/netclient-"+network+".timer", timerbytes, 0644)
if err != nil {
log.Println(err)
return err
}
}
//sysExec, err := exec.LookPath("systemctl")
cmdSysEnableService := exec.Command("systemctl", "enable", "netclient@.service")/*&exec.Cmd {
Path: sysExec,
Args: []string{ sysExec, "enable", "netclient@.service" },
Stdout: os.Stdout,
Stderr: os.Stdout,
}*/
cmdSysDaemonReload := exec.Command("systemctl", "daemon-reload")/*&exec.Cmd {
Path: sysExec,
Args: []string{ sysExec, "daemon-reload"},
Stdout: os.Stdout,
Stderr: os.Stdout,
}*/
cmdSysEnableTimer := exec.Command("systemctl", "enable", "netclient-"+network+".timer")/*&exec.Cmd {
Path: sysExec,
Args: []string{ sysExec, "enable", "netclient-"+network+".timer" },
Stdout: os.Stdout,
Stderr: os.Stdout,
}*/
cmdSysStartTimer := exec.Command("systemctl", "start", "netclient-"+network+".timer")/*&exec.Cmd {
Path: sysExec,
Args: []string{ sysExec, "start", "netclient-"+network+".timer"},
Stdout: os.Stdout,
Stderr: os.Stdout,
}*/
err = cmdSysEnableService.Run()
if err != nil {
log.Println("Error enabling netclient@.service. Please investigate.")
log.Println(err)
}
err = cmdSysDaemonReload.Run()
if err != nil {
log.Println("Error reloading system daemons. Please investigate.")
log.Println(err)
}
err = cmdSysEnableTimer.Run()
if err != nil {
log.Println("Error enabling netclient.timer. Please investigate.")
log.Println(err)
}
err = cmdSysStartTimer.Run()
if err != nil {
log.Println("Error starting netclient-"+network+".timer. Please investigate.")
log.Println(err)
}
_, err = RunCmd("systemctl enable netclient@.service")
if err != nil {
log.Println("Error enabling netclient@.service. Please investigate.")
log.Println(err)
}
_, err = RunCmd("systemctl daemon-reload")
if err != nil {
log.Println("Error reloading system daemons. Please investigate.")
log.Println(err)
}
_, err = RunCmd("systemctl enable netclient-" + network + ".timer")
if err != nil {
log.Println("Error enabling netclient.timer. Please investigate.")
log.Println(err)
}
_, err = RunCmd("systemctl start netclient-" + network + ".timer")
if err != nil {
log.Println("Error starting netclient-" + network + ".timer. Please investigate.")
log.Println(err)
}
return nil
}
@@ -188,7 +201,7 @@ func isOnlyService(network string) (bool, error) {
return isonly, err
}
count := len(files)
if count == 0 {
if count == 0 {
isonly = true
}
return isonly, err
@@ -196,78 +209,67 @@ func isOnlyService(network string) (bool, error) {
}
func RemoveSystemDServices(network string) error {
//sysExec, err := exec.LookPath("systemctl")
//sysExec, err := exec.LookPath("systemctl")
fullremove, err := isOnlyService(network)
if err != nil {
log.Println(err)
}
cmdSysDisableService := exec.Command("systemctl","disable","netclient@.service")
cmdSysDaemonReload := exec.Command("systemctl","daemon-reload")
cmdSysResetFailed := exec.Command("systemctl","reset-failed")
cmdSysStopTimer := exec.Command("systemctl", "stop", "netclient-"+network+".timer")
cmdSysDisableTimer := exec.Command("systemctl", "disable", "netclient-"+network+".timer")
if err != nil {
log.Println("Error stopping netclient@.service. Please investigate.")
log.Println(err)
}
if fullremove {
err = cmdSysDisableService.Run()
if err != nil {
log.Println("Error disabling netclient@.service. Please investigate.")
log.Println(err)
}
_, err = RunCmd("systemctl disable netclient@.service")
if err != nil {
log.Println("Error disabling netclient@.service. Please investigate.")
log.Println(err)
}
}
_, err = RunCmd("systemctl daemon-reload")
if err != nil {
log.Println("Error stopping netclient-" + network + ".timer. Please investigate.")
log.Println(err)
}
_, err = RunCmd("systemctl disable netclient-" + network + ".timer")
if err != nil {
log.Println("Error disabling netclient-" + network + ".timer. Please investigate.")
log.Println(err)
}
err = cmdSysStopTimer.Run()
if err != nil {
log.Println("Error stopping netclient-"+network+".timer. Please investigate.")
log.Println(err)
}
err = cmdSysDisableTimer.Run()
if err != nil {
log.Println("Error disabling netclient-"+network+".timer. Please investigate.")
log.Println(err)
}
if fullremove {
if FileExists("/etc/systemd/system/netclient@.service") {
err = os.Remove("/etc/systemd/system/netclient@.service")
}
}
if FileExists("/etc/systemd/system/netclient-"+network+".timer") {
err = os.Remove("/etc/systemd/system/netclient-"+network+".timer")
if FileExists("/etc/systemd/system/netclient-" + network + ".timer") {
err = os.Remove("/etc/systemd/system/netclient-" + network + ".timer")
}
if err != nil {
log.Println("Error removing file. Please investigate.")
log.Println(err)
log.Println("Error removing file. Please investigate.")
log.Println(err)
}
_, err = RunCmd("systemctl daemon-reload")
if err != nil {
log.Println("Error reloading system daemons. Please investigate.")
log.Println(err)
}
_, err = RunCmd("systemctl reset-failed")
if err != nil {
log.Println("Error reseting failed system services. Please investigate.")
log.Println(err)
}
err = cmdSysDaemonReload.Run()
if err != nil {
log.Println("Error reloading system daemons. Please investigate.")
log.Println(err)
}
err = cmdSysResetFailed.Run()
if err != nil {
log.Println("Error reseting failed system services. Please investigate.")
log.Println(err)
}
return err
}
func WipeLocal(network string) error{
cfg, err := config.ReadConfig(network)
if err != nil {
return err
}
nodecfg := cfg.Node
ifacename := nodecfg.Interface
func WipeLocal(network string) error {
cfg, err := config.ReadConfig(network)
if err != nil {
return err
}
nodecfg := cfg.Node
ifacename := nodecfg.Interface
//home, err := homedir.Dir()
home := "/etc/netclient"
//home, err := homedir.Dir()
home := "/etc/netclient"
if FileExists(home + "/netconfig-" + network) {
_ = os.Remove(home + "/netconfig-" + network)
_ = os.Remove(home + "/netconfig-" + network)
}
if FileExists(home + "/nettoken-" + network) {
_ = os.Remove(home + "/nettoken-" + network)
@@ -276,79 +278,79 @@ func WipeLocal(network string) error{
_ = os.Remove(home + "/wgkey-" + network)
}
ipExec, err := exec.LookPath("ip")
ipExec, err := exec.LookPath("ip")
if ifacename != "" {
cmdIPLinkDel := &exec.Cmd {
Path: ipExec,
Args: []string{ ipExec, "link", "del", ifacename },
Stdout: os.Stdout,
Stderr: os.Stdout,
}
err = cmdIPLinkDel.Run()
if err != nil {
log.Println(err)
}
if nodecfg.PostDown != "" {
runcmds := strings.Split(nodecfg.PostDown, "; ")
err = RunCmds(runcmds)
if err != nil {
log.Println("Error encountered running PostDown: " + err.Error())
}
}
}
return err
if ifacename != "" {
cmdIPLinkDel := &exec.Cmd{
Path: ipExec,
Args: []string{ipExec, "link", "del", ifacename},
Stdout: os.Stdout,
Stderr: os.Stdout,
}
err = cmdIPLinkDel.Run()
if err != nil {
log.Println(err)
}
if nodecfg.PostDown != "" {
runcmds := strings.Split(nodecfg.PostDown, "; ")
err = RunCmds(runcmds)
if err != nil {
log.Println("Error encountered running PostDown: " + err.Error())
}
}
}
return err
}
func WipeGRPCClient() error{
home := "/etc/netclient"
_ = os.Remove(home + "/netconfig-global-001")
func WipeGRPCClient() error {
home := "/etc/netclient"
_ = os.Remove(home + "/netconfig-global-001")
ipExec, err := exec.LookPath("ip")
cmdIPLinkDel := &exec.Cmd {
Path: ipExec,
Args: []string{ ipExec, "link", "del", "grpc-wg-001" },
Stdout: os.Stdout,
Stderr: os.Stdout,
}
err = cmdIPLinkDel.Run()
return err
cmdIPLinkDel := &exec.Cmd{
Path: ipExec,
Args: []string{ipExec, "link", "del", "grpc-wg-001"},
Stdout: os.Stdout,
Stderr: os.Stdout,
}
err = cmdIPLinkDel.Run()
return err
}
func HasNetwork(network string) bool{
func HasNetwork(network string) bool {
return FileExists("/etc/systemd/system/netclient-"+network+".timer") ||
FileExists("/etc/netclient/netconfig-"+network)
return FileExists("/etc/systemd/system/netclient-"+network+".timer") ||
FileExists("/etc/netclient/netconfig-"+network)
}
func copy(src, dst string) (int64, error) {
sourceFileStat, err := os.Stat(src)
if err != nil {
return 0, err
}
sourceFileStat, err := os.Stat(src)
if err != nil {
return 0, err
}
if !sourceFileStat.Mode().IsRegular() {
return 0, errors.New(src + " is not a regular file")
}
if !sourceFileStat.Mode().IsRegular() {
return 0, errors.New(src + " is not a regular file")
}
source, err := os.Open(src)
if err != nil {
return 0, err
}
defer source.Close()
source, err := os.Open(src)
if err != nil {
return 0, err
}
defer source.Close()
destination, err := os.Create(dst)
if err != nil {
return 0, err
}
defer destination.Close()
nBytes, err := io.Copy(destination, source)
destination, err := os.Create(dst)
if err != nil {
return 0, err
}
defer destination.Close()
nBytes, err := io.Copy(destination, source)
err = os.Chmod(dst, 0755)
if err != nil {
log.Println(err)
}
return nBytes, err
return nBytes, err
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/gravitl/netmaker/netclient/command"
"github.com/gravitl/netmaker/netclient/config"
"github.com/gravitl/netmaker/netclient/local"
"github.com/urfave/cli/v2"
)
@@ -202,33 +203,12 @@ func main() {
}
app.Commands = []*cli.Command{
{
Name: "register",
Usage: "Register with Netmaker Server for secure GRPC communications.",
Flags: cliFlags,
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfigRegister(c)
if err != nil {
return err
}
if cfg.GRPCWireGuard == "off" {
log.Println("Server is not using WireGuard to secure GRPC. Skipping.")
return err
}
if cfg.Client.ServerPrivateAddress == "" {
err = errors.New("No server address provided.")
return err
}
err = command.Register(cfg)
return err
},
},
{
Name: "join",
Usage: "Join a Netmaker network.",
Flags: cliFlags,
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
cfg, pvtKey, err := config.GetCLIConfig(c)
if err != nil {
return err
}
@@ -240,7 +220,7 @@ func main() {
err = errors.New("No server address provided.")
return err
}
err = command.Join(cfg)
err = command.Join(cfg, pvtKey)
return err
},
},
@@ -251,7 +231,7 @@ func main() {
// the action, or code that will be executed when
// we execute our `ns` command
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
cfg, _, err := config.GetCLIConfig(c)
if err != nil {
return err
}
@@ -266,7 +246,7 @@ func main() {
// the action, or code that will be executed when
// we execute our `ns` command
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
cfg, _, err := config.GetCLIConfig(c)
if err != nil {
return err
}
@@ -281,7 +261,7 @@ func main() {
// the action, or code that will be executed when
// we execute our `ns` command
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
cfg, _, err := config.GetCLIConfig(c)
if err != nil {
return err
}
@@ -296,7 +276,7 @@ func main() {
// the action, or code that will be executed when
// we execute our `ns` command
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
cfg, _, err := config.GetCLIConfig(c)
if err != nil {
return err
}
@@ -311,7 +291,7 @@ func main() {
// the action, or code that will be executed when
// we execute our `ns` command
Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c)
cfg, _, err := config.GetCLIConfig(c)
if err != nil {
return err
}
@@ -356,8 +336,7 @@ func main() {
}
// start our application
getID := exec.Command("id", "-u")
out, err := getID.Output()
out, err := local.RunCmd("id -u")
if err != nil {
log.Fatal(err)

View File

@@ -1,373 +1,354 @@
package server
import (
"google.golang.org/grpc/credentials"
"crypto/tls"
"fmt"
"context"
"crypto/tls"
"encoding/json"
"fmt"
"log"
"strings"
"strconv"
"net"
"strconv"
"time"
"io"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/auth"
"github.com/gravitl/netmaker/netclient/config"
"github.com/gravitl/netmaker/netclient/auth"
"github.com/gravitl/netmaker/netclient/local"
nodepb "github.com/gravitl/netmaker/grpc"
"google.golang.org/grpc"
"github.com/gravitl/netmaker/netclient/local"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
//homedir "github.com/mitchellh/go-homedir"
)
func GetNode(network string) nodepb.Node {
modcfg, err := config.ReadConfig(network)
if err != nil {
log.Fatalf("Error: %v", err)
}
nodecfg := modcfg.Node
var node nodepb.Node
node.Name = nodecfg.Name
node.Interface = nodecfg.Interface
node.Nodenetwork = nodecfg.Network
node.Localaddress = nodecfg.LocalAddress
node.Address = nodecfg.WGAddress
node.Address6 = nodecfg.WGAddress6
node.Listenport = nodecfg.Port
node.Keepalive = nodecfg.KeepAlive
node.Postup = nodecfg.PostUp
node.Postdown = nodecfg.PostDown
node.Publickey = nodecfg.PublicKey
node.Macaddress = nodecfg.MacAddress
node.Endpoint = nodecfg.Endpoint
node.Password = nodecfg.Password
node.Saveconfig = nodecfg.SaveConfig
node.Udpholepunch = nodecfg.UDPHolePunch
if nodecfg.DNS == "on" {
node.Dnsoff = false
} else {
node.Dnsoff = true
func getGrpcClient(cfg *config.ClientConfig) (nodepb.NodeServiceClient, error) {
servercfg := cfg.Server
var wcclient nodepb.NodeServiceClient
// == GRPC SETUP ==
var requestOpts grpc.DialOption
requestOpts = grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" {
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
requestOpts = grpc.WithTransportCredentials(h2creds)
}
if nodecfg.IsDualStack == "yes" {
node.Isdualstack = true
} else {
node.Isdualstack = false
}
if nodecfg.IsIngressGateway == "yes" {
node.Isingressgateway= true
} else {
node.Isingressgateway = false
}
return node
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
if err != nil {
return nil, err
}
wcclient = nodepb.NewNodeServiceClient(conn)
return wcclient, nil
}
func CheckIn(network string) (*models.Node, error) {
cfg, err := config.ReadConfig(network)
if err != nil {
return nil, err
}
node := cfg.Node
wcclient, err := getGrpcClient(cfg)
if err != nil {
return nil, err
}
// == run client action ==
var header metadata.MD
ctx, err := auth.SetJWT(wcclient, network)
nodeData, err := json.Marshal(&node)
if err != nil {
return nil, err
}
response, err := wcclient.ReadNode(
ctx,
&nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
},
grpc.Header(&header),
)
if err != nil {
log.Printf("Encountered error checking in node: %v", err)
}
if err = json.Unmarshal([]byte(response.GetData()), &node); err != nil {
return nil, err
}
return &node, err
}
func RemoveNetwork(network string) error {
//need to implement checkin on server side
cfg, err := config.ReadConfig(network)
if err != nil {
return err
}
//need to implement checkin on server side
cfg, err := config.ReadConfig(network)
if err != nil {
return err
}
servercfg := cfg.Server
node := cfg.Node
node := cfg.Node
fmt.Println("Deleting remote node with MAC: " + node.MacAddress)
var wcclient nodepb.NodeServiceClient
var requestOpts grpc.DialOption
requestOpts = grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" {
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
requestOpts = grpc.WithTransportCredentials(h2creds)
}
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
var wcclient nodepb.NodeServiceClient
var requestOpts grpc.DialOption
requestOpts = grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" {
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
requestOpts = grpc.WithTransportCredentials(h2creds)
}
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
if err != nil {
log.Printf("Unable to establish client connection to " + servercfg.GRPCAddress + ": %v", err)
log.Printf("Unable to establish client connection to "+servercfg.GRPCAddress+": %v", err)
//return err
}else {
wcclient = nodepb.NewNodeServiceClient(conn)
} else {
wcclient = nodepb.NewNodeServiceClient(conn)
ctx, err := auth.SetJWT(wcclient, network)
if err != nil {
//return err
log.Printf("Failed to authenticate: %v", err)
} else {
ctx := context.Background()
ctx, err = auth.SetJWT(wcclient, network)
if err != nil {
//return err
log.Printf("Failed to authenticate: %v", err)
} else {
var header metadata.MD
var header metadata.MD
_, err = wcclient.DeleteNode(
ctx,
&nodepb.DeleteNodeReq{
Macaddress: node.MacAddress,
NetworkName: node.Network,
},
grpc.Header(&header),
)
if err != nil {
log.Printf("Encountered error deleting node: %v", err)
fmt.Println(err)
} else {
fmt.Println("Deleted node " + node.MacAddress)
}
}
_, err = wcclient.DeleteNode(
ctx,
&nodepb.Object{
Data: node.MacAddress + "###" + node.Network,
Type: nodepb.STRING_TYPE,
},
grpc.Header(&header),
)
if err != nil {
log.Printf("Encountered error deleting node: %v", err)
fmt.Println(err)
} else {
fmt.Println("Deleted node " + node.MacAddress)
}
}
}
err = local.WipeLocal(network)
if err != nil {
log.Printf("Unable to wipe local config: %v", err)
log.Printf("Unable to wipe local config: %v", err)
}
if cfg.Daemon != "off" {
err = local.RemoveSystemDServices(network)
err = local.RemoveSystemDServices(network)
}
return err
}
func GetPeers(macaddress string, network string, server string, dualstack bool, isIngressGateway bool) ([]wgtypes.PeerConfig, bool, []string, error) {
//need to implement checkin on server side
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)
}
nodecfg := cfg.Node
keepalive := nodecfg.KeepAlive
keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s")
if err != nil {
log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)
}
//need to implement checkin on server side
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)
}
nodecfg := cfg.Node
keepalive := nodecfg.PersistentKeepalive
keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s")
if err != nil {
log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)
}
requestOpts := grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" {
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
requestOpts = grpc.WithTransportCredentials(h2creds)
}
requestOpts := grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" {
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
requestOpts = grpc.WithTransportCredentials(h2creds)
}
conn, err := grpc.Dial(server, requestOpts)
if err != nil {
log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
}
// Instantiate the BlogServiceClient with our client connection to the server
wcclient = nodepb.NewNodeServiceClient(conn)
if err != nil {
log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
}
// Instantiate the BlogServiceClient with our client connection to the server
wcclient = nodepb.NewNodeServiceClient(conn)
req := &nodepb.GetPeersReq{
Macaddress: macaddress,
Network: network,
}
ctx := context.Background()
ctx, err = auth.SetJWT(wcclient, network)
if err != nil {
log.Println("Failed to authenticate.")
return peers, hasGateway, gateways, err
}
var header metadata.MD
req := &nodepb.Object{
Data: macaddress + "###" + network,
Type: nodepb.STRING_TYPE,
}
ctx := context.Background()
ctx, err = auth.SetJWT(wcclient, network)
if err != nil {
log.Println("Failed to authenticate.")
return peers, hasGateway, gateways, err
}
var header metadata.MD
stream, err := wcclient.GetPeers(ctx, req, grpc.Header(&header))
if err != nil {
log.Println("Error retrieving peers")
log.Println(err)
return nil, hasGateway, gateways, err
}
for {
res, err := stream.Recv()
// If end of stream, break the loop
response, err := wcclient.GetPeers(ctx, req, grpc.Header(&header))
if err != nil {
log.Println("Error retrieving peers")
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
}
for _, node := range nodes {
pubkey, err := wgtypes.ParseKey(node.PublicKey)
if err != nil {
fmt.Println("error parsing key")
return peers, hasGateway, gateways, err
}
if err == io.EOF {
break
}
// if err, return an error
if err != nil {
if strings.Contains(err.Error(), "mongo: no documents in result") {
continue
} else {
fmt.Println("ERROR ENCOUNTERED WITH RESPONSE")
fmt.Println(res)
return peers, hasGateway, gateways, err
}
}
pubkey, err := wgtypes.ParseKey(res.Peers.Publickey)
if err != nil {
fmt.Println("error parsing key")
return peers, hasGateway, gateways, err
}
if nodecfg.PublicKey == res.Peers.Publickey {
continue
}
if nodecfg.Endpoint == res.Peers.Endpoint {
if nodecfg.LocalAddress != res.Peers.Localaddress && res.Peers.Localaddress != "" {
res.Peers.Endpoint = res.Peers.Localaddress
if nodecfg.PublicKey == node.PublicKey {
continue
}
if nodecfg.Endpoint == node.Endpoint {
if nodecfg.LocalAddress != node.LocalAddress && node.LocalAddress != "" {
node.Endpoint = node.LocalAddress
} else {
continue
}
}
}
var peer wgtypes.PeerConfig
var peeraddr = net.IPNet{
IP: net.ParseIP(res.Peers.Address),
Mask: net.CIDRMask(32, 32),
}
var allowedips []net.IPNet
allowedips = append(allowedips, peeraddr)
if res.Peers.Isegressgateway {
hasGateway = true
ranges := strings.Split(res.Peers.Egressgatewayranges, ",")
var peer wgtypes.PeerConfig
var peeraddr = net.IPNet{
IP: net.ParseIP(node.Address),
Mask: net.CIDRMask(32, 32),
}
var allowedips []net.IPNet
allowedips = append(allowedips, peeraddr)
if node.IsEgressGateway == "yes" {
hasGateway = true
ranges := node.EgressGatewayRanges
for _, iprange := range ranges {
gateways = append(gateways,iprange)
_, ipnet, err := net.ParseCIDR(iprange)
if err != nil {
fmt.Println("ERROR ENCOUNTERED SETTING GATEWAY")
fmt.Println("NOT SETTING GATEWAY")
fmt.Println(err)
} else {
fmt.Println(" Gateway Range: " + iprange)
allowedips = append(allowedips, *ipnet)
}
gateways = append(gateways, iprange)
_, ipnet, err := net.ParseCIDR(iprange)
if err != nil {
fmt.Println("ERROR ENCOUNTERED SETTING GATEWAY")
fmt.Println("NOT SETTING GATEWAY")
fmt.Println(err)
} else {
fmt.Println(" Gateway Range: " + iprange)
allowedips = append(allowedips, *ipnet)
}
}
}
if node.Address6 != "" && dualstack {
var addr6 = net.IPNet{
IP: net.ParseIP(node.Address6),
Mask: net.CIDRMask(128, 128),
}
allowedips = append(allowedips, addr6)
}
if nodecfg.Name == "netmaker" {
peer = wgtypes.PeerConfig{
PublicKey: pubkey,
PersistentKeepaliveInterval: &keepaliveserver,
ReplaceAllowedIPs: true,
AllowedIPs: allowedips,
}
}
if res.Peers.Address6 != "" && dualstack {
var addr6 = net.IPNet{
IP: net.ParseIP(res.Peers.Address6),
Mask: net.CIDRMask(128, 128),
}
allowedips = append(allowedips, addr6)
}
if nodecfg.Name == "netmaker" {
peer = wgtypes.PeerConfig{
PublicKey: pubkey,
PersistentKeepaliveInterval: &keepaliveserver,
ReplaceAllowedIPs: true,
AllowedIPs: allowedips,
}
} else if keepalive != 0 {
peer = wgtypes.PeerConfig{
PublicKey: pubkey,
PersistentKeepaliveInterval: &keepalivedur,
Endpoint: &net.UDPAddr{
IP: net.ParseIP(res.Peers.Endpoint),
Port: int(res.Peers.Listenport),
},
ReplaceAllowedIPs: true,
AllowedIPs: allowedips,
}
} else {
peer = wgtypes.PeerConfig{
PublicKey: pubkey,
Endpoint: &net.UDPAddr{
IP: net.ParseIP(res.Peers.Endpoint),
Port: int(res.Peers.Listenport),
},
ReplaceAllowedIPs: true,
AllowedIPs: allowedips,
}
}
peers = append(peers, peer)
peer = wgtypes.PeerConfig{
PublicKey: pubkey,
PersistentKeepaliveInterval: &keepalivedur,
Endpoint: &net.UDPAddr{
IP: net.ParseIP(node.Endpoint),
Port: int(node.ListenPort),
},
ReplaceAllowedIPs: true,
AllowedIPs: allowedips,
}
} else {
peer = wgtypes.PeerConfig{
PublicKey: pubkey,
Endpoint: &net.UDPAddr{
IP: net.ParseIP(node.Endpoint),
Port: int(node.ListenPort),
},
ReplaceAllowedIPs: true,
AllowedIPs: allowedips,
}
}
peers = append(peers, peer)
}
if isIngressGateway {
extPeers, err := GetExtPeers(macaddress, network, server, dualstack)
if err == nil {
peers = append(peers, extPeers...)
} else {
fmt.Println("ERROR RETRIEVING EXTERNAL PEERS")
fmt.Println(err)
}
}
return peers, hasGateway, gateways, err
}
if isIngressGateway {
extPeers, err := GetExtPeers(macaddress, network, server, dualstack)
if err == nil {
peers = append(peers, extPeers...)
} else {
fmt.Println("ERROR RETRIEVING EXTERNAL PEERS")
fmt.Println(err)
}
}
return peers, hasGateway, gateways, err
}
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 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
requestOpts := grpc.WithInsecure()
conn, err := grpc.Dial(server, requestOpts)
if err != nil {
log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
}
// Instantiate the BlogServiceClient with our client connection to the server
wcclient = nodepb.NewNodeServiceClient(conn)
requestOpts := grpc.WithInsecure()
conn, err := grpc.Dial(server, requestOpts)
if err != nil {
log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
}
// Instantiate the BlogServiceClient with our client connection to the server
wcclient = nodepb.NewNodeServiceClient(conn)
req := &nodepb.GetExtPeersReq{
Macaddress: macaddress,
Network: network,
}
ctx := context.Background()
ctx, err = auth.SetJWT(wcclient, network)
if err != nil {
fmt.Println("Failed to authenticate.")
return peers, err
}
var header metadata.MD
req := &nodepb.Object{
Data: macaddress + "###" + network,
Type: nodepb.STRING_TYPE,
}
ctx := context.Background()
ctx, err = auth.SetJWT(wcclient, network)
if err != nil {
fmt.Println("Failed to authenticate.")
return peers, err
}
var header metadata.MD
stream, err := wcclient.GetExtPeers(ctx, req, grpc.Header(&header))
if err != nil {
fmt.Println("Error retrieving peers")
fmt.Println(err)
return nil, err
}
for {
res, err := stream.Recv()
// If end of stream, break the loop
responseObject, err := wcclient.GetExtPeers(ctx, req, grpc.Header(&header))
if err != nil {
fmt.Println("Error retrieving peers")
fmt.Println(err)
return nil, err
}
var extPeers []models.Node
if err = json.Unmarshal([]byte(responseObject.Data), extPeers); err != nil {
return nil, err
}
for _, extPeer := range extPeers {
pubkey, err := wgtypes.ParseKey(extPeer.PublicKey)
if err != nil {
fmt.Println("error parsing key")
return peers, err
}
if err == io.EOF {
break
}
// if err, return an error
if err != nil {
if strings.Contains(err.Error(), "mongo: no documents in result") {
continue
} else {
fmt.Println("ERROR ENCOUNTERED WITH RESPONSE")
fmt.Println(res)
return peers, err
}
}
pubkey, err := wgtypes.ParseKey(res.Extpeers.Publickey)
if err != nil {
fmt.Println("error parsing key")
return peers, err
}
if nodecfg.PublicKey == extPeer.PublicKey {
continue
}
if nodecfg.PublicKey == res.Extpeers.Publickey {
continue
}
var peer wgtypes.PeerConfig
var peeraddr = net.IPNet{
IP: net.ParseIP(extPeer.Address),
Mask: net.CIDRMask(32, 32),
}
var allowedips []net.IPNet
allowedips = append(allowedips, peeraddr)
var peer wgtypes.PeerConfig
var peeraddr = net.IPNet{
IP: net.ParseIP(res.Extpeers.Address),
Mask: net.CIDRMask(32, 32),
}
var allowedips []net.IPNet
allowedips = append(allowedips, peeraddr)
if extPeer.Address6 != "" && dualstack {
var addr6 = net.IPNet{
IP: net.ParseIP(extPeer.Address6),
Mask: net.CIDRMask(128, 128),
}
allowedips = append(allowedips, addr6)
}
peer = wgtypes.PeerConfig{
PublicKey: pubkey,
ReplaceAllowedIPs: true,
AllowedIPs: allowedips,
}
peers = append(peers, peer)
if res.Extpeers.Address6 != "" && dualstack {
var addr6 = net.IPNet{
IP: net.ParseIP(res.Extpeers.Address6),
Mask: net.CIDRMask(128, 128),
}
allowedips = append(allowedips, addr6)
}
peer = wgtypes.PeerConfig{
PublicKey: pubkey,
ReplaceAllowedIPs: true,
AllowedIPs: allowedips,
}
peers = append(peers, peer)
}
return peers, err
}
return peers, err
}

View File

@@ -3,6 +3,7 @@ package wireguard
import (
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
@@ -13,7 +14,6 @@ import (
"strconv"
"strings"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/auth"
@@ -53,12 +53,9 @@ func InitGRPCWireguard(client models.IntClient) error {
if client.Address6 == "" && client.Address == "" {
return errors.New("no address to configure")
}
cmdIPDevLinkAdd := exec.Command("ip", "link", "add", "dev", ifacename, "type", "wireguard")
cmdIPAddrAdd := exec.Command("ip", "address", "add", "dev", ifacename, client.Address+"/24")
cmdIPAddr6Add := exec.Command("ip", "address", "add", "dev", ifacename, client.Address6+"/64")
currentiface, err := net.InterfaceByName(ifacename)
if err != nil {
err = cmdIPDevLinkAdd.Run()
_, err = local.RunCmd("ip link add dev " + ifacename + " type wireguard")
if err != nil && !strings.Contains(err.Error(), "exists") {
log.Println("Error creating interface")
}
@@ -77,14 +74,14 @@ func InitGRPCWireguard(client models.IntClient) error {
}
}
if !match && client.Address != "" {
err = cmdIPAddrAdd.Run()
_, err = local.RunCmd("ip address add dev " + ifacename + " " + client.Address + "/24")
if err != nil {
log.Println("Error adding ipv4 address")
fmt.Println(err)
}
}
if !match6 && client.Address6 != "" {
err = cmdIPAddr6Add.Run()
_, err = local.RunCmd("ip address add dev" + ifacename + " " + client.Address6 + "/64")
if err != nil {
log.Println("Error adding ipv6 address")
fmt.Println(err)
@@ -133,10 +130,8 @@ func InitGRPCWireguard(client models.IntClient) error {
}
}
cmdIPLinkUp := exec.Command("ip", "link", "set", "up", "dev", ifacename)
cmdIPLinkDown := exec.Command("ip", "link", "set", "down", "dev", ifacename)
err = cmdIPLinkDown.Run()
err = cmdIPLinkUp.Run()
_, err = local.RunCmd("ip link set up dev " + ifacename)
_, err = local.RunCmd("ip link set down dev " + ifacename)
if err != nil {
return err
}
@@ -144,7 +139,7 @@ func InitGRPCWireguard(client models.IntClient) error {
return err
}
func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string) error {
func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig, hasGateway bool, gateways []string) error {
ipExec, err := exec.LookPath("ip")
if err != nil {
@@ -159,7 +154,7 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
if err != nil {
return err
}
modcfg, err := config.ReadConfig(node.Nodenetwork)
modcfg, err := config.ReadConfig(node.Network)
if err != nil {
return err
}
@@ -183,29 +178,16 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
log.Fatal("no address to configure")
}
nameserver := servercfg.CoreDNSAddr
network := node.Nodenetwork
network := node.Network
if nodecfg.Network != "" {
network = nodecfg.Network
} else if node.Nodenetwork != "" {
network = node.Nodenetwork
} else if node.Network != "" {
network = node.Network
}
cmdIPDevLinkAdd := &exec.Cmd{
Path: ipExec,
Args: []string{ipExec, "link", "add", "dev", ifacename, "type", "wireguard"},
Stdout: os.Stdout,
Stderr: os.Stdout,
}
cmdIPAddrAdd := &exec.Cmd{
Path: ipExec,
Args: []string{ipExec, "address", "add", "dev", ifacename, node.Address + "/24"},
Stdout: os.Stdout,
Stderr: os.Stdout,
}
cmdIPLinkDelete := exec.Command("ip", "link", "delete", "dev", ifacename)
delErr := cmdIPLinkDelete.Run()
addLinkErr := cmdIPDevLinkAdd.Run()
addErr := cmdIPAddrAdd.Run()
_, delErr := local.RunCmd("ip link delete dev " + ifacename)
_, addLinkErr := local.RunCmd(ipExec + " link add dev " + ifacename + " type wireguard")
_, addErr := local.RunCmd(ipExec + " address add dev " + ifacename + " " + node.Address + "/24")
if delErr != nil {
log.Println(delErr)
}
@@ -216,7 +198,7 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
log.Println(addErr)
}
var nodeport int
nodeport = int(node.Listenport)
nodeport = int(node.ListenPort)
conf := wgtypes.Config{}
if nodecfg.UDPHolePunch == "yes" && nodecfg.Name != "netmaker" {
@@ -254,7 +236,7 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
}
}
//=========DNS Setup==========\\
if nodecfg.DNS == "on" {
if nodecfg.DNSOn == "yes" {
_ = local.UpdateDNS(ifacename, network, nameserver)
}
//=========End DNS Setup=======\\
@@ -295,16 +277,16 @@ func InitWireguard(node *nodepb.Node, privkey string, peers []wgtypes.PeerConfig
}
if hasGateway {
for _, gateway := range gateways {
out, err := exec.Command(ipExec, "-4", "route", "add", gateway, "dev", ifacename).Output()
out, err := local.RunCmd(ipExec + " -4 route add " + gateway + " dev " + ifacename)
fmt.Println(string(out))
if err != nil {
fmt.Println("Error encountered adding gateway: " + err.Error())
}
}
}
if node.Address6 != "" && node.Isdualstack {
if node.Address6 != "" && node.IsDualStack == "yes" {
fmt.Println("Adding address: " + node.Address6)
out, err := exec.Command(ipExec, "address", "add", "dev", ifacename, node.Address6+"/64").Output()
out, err := local.RunCmd(ipExec + " address add dev " + ifacename + " " + node.Address6 + "/64")
if err != nil {
fmt.Println(out)
fmt.Println("Error encountered adding ipv6: " + err.Error())
@@ -345,7 +327,7 @@ func SetWGKeyConfig(network string, serveraddr string) error {
return err
}
node := server.GetNode(network)
node := config.GetNode(network)
privatekey, err := wgtypes.GeneratePrivateKey()
if err != nil {
@@ -354,7 +336,7 @@ func SetWGKeyConfig(network string, serveraddr string) error {
privkeystring := privatekey.String()
publickey := privatekey.PublicKey()
node.Publickey = publickey.String()
node.PublicKey = publickey.String()
err = StorePrivKey(privkeystring, network)
if err != nil {
@@ -365,10 +347,15 @@ func SetWGKeyConfig(network string, serveraddr string) error {
return err
}
postnode := server.GetNode(network)
postnode := config.GetNode(network)
req := &nodepb.UpdateNodeReq{
Node: &postnode,
nodeData, err := json.Marshal(&postnode)
if err != nil {
return err
}
req := &nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
}
_, err = wcclient.UpdateNode(ctx, req, grpc.Header(&header))
@@ -392,9 +379,9 @@ func SetWGConfig(network string, peerupdate bool) error {
}
servercfg := cfg.Server
nodecfg := cfg.Node
node := server.GetNode(network)
node := config.GetNode(network)
peers, hasGateway, gateways, err := server.GetPeers(node.Macaddress, nodecfg.Network, servercfg.GRPCAddress, node.Isdualstack, node.Isingressgateway)
peers, hasGateway, gateways, err := server.GetPeers(node.MacAddress, nodecfg.Network, servercfg.GRPCAddress, node.IsDualStack == "yes", node.IsIngressGateway == "yes")
if err != nil {
return err
}
@@ -403,7 +390,7 @@ func SetWGConfig(network string, peerupdate bool) error {
return err
}
if peerupdate {
SetPeers(node.Interface, node.Keepalive, peers)
SetPeers(node.Interface, node.PersistentKeepalive, peers)
} else {
err = InitWireguard(&node, privkey, peers, hasGateway, gateways)
}
@@ -426,29 +413,30 @@ func SetPeers(iface string, keepalive int32, peers []wgtypes.PeerConfig) {
return
}
for _, peer := range peers {
for _, currentPeer := range device.Peers {
if currentPeer.AllowedIPs[0].String() == peer.AllowedIPs[0].String() &&
currentPeer.PublicKey.String() == peer.PublicKey.String() {
err := exec.Command("wg","set",iface,"peer",currentPeer.PublicKey.String(),"delete").Run()
if err != nil {
log.Println("error setting peer",peer.Endpoint.String(),)
}
if currentPeer.AllowedIPs[0].String() == peer.AllowedIPs[0].String() &&
currentPeer.PublicKey.String() == peer.PublicKey.String() {
_, err := local.RunCmd("wg set " + iface + " peer " + currentPeer.PublicKey.String() + " delete")
if err != nil {
log.Println("error setting peer", peer.Endpoint.String())
}
}
}
udpendpoint := peer.Endpoint.IP.String()+":"+peer.Endpoint.IP.String()
}
udpendpoint := peer.Endpoint.IP.String() + ":" + peer.Endpoint.IP.String()
var allowedips string
var iparr []string
for _, ipaddr := range peer.AllowedIPs {
iparr = append(iparr,ipaddr.String())
iparr = append(iparr, ipaddr.String())
}
allowedips = strings.Join(iparr,",")
err := exec.Command("wg","set",iface,"peer",peer.PublicKey.String(),
"endpoint",udpendpoint,
"persistent-keepalive",string(keepalive),
"allowed-ips",allowedips)
allowedips = strings.Join(iparr, ",")
_, err = local.RunCmd("wg set " + iface + " peer " + peer.PublicKey.String() +
" endpoint " + udpendpoint +
" persistent-keepalive " + string(keepalive) +
" allowed-ips " + allowedips)
if err != nil {
log.Println("error setting peer",peer.Endpoint.String(),)
log.Println("error setting peer", peer.Endpoint.String())
}
}
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/local"
"github.com/gravitl/netmaker/servercfg"
)
@@ -121,7 +122,7 @@ func RemoveNetwork(network string) (bool, error) {
log.Println("could not find /etc/netclient")
return false, err
}
cmdoutput, err := exec.Command("/etc/netclient/netclient", "leave", "-n", network).Output()
cmdoutput, err := local.RunCmd("/etc/netclient/netclient leave -n " + network)
if err != nil {
log.Println(string(cmdoutput))
return false, err