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" "context"
"encoding/json" "encoding/json"
"errors" "errors"
"github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions" "github.com/gravitl/netmaker/functions"
nodepb "github.com/gravitl/netmaker/grpc" 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. //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) //out := new(LoginResponse)
macaddress := req.GetMacaddress() var reqNode models.Node
network := req.GetNetwork() if err := json.Unmarshal([]byte(req.Data), &reqNode); err != nil {
password := req.GetPassword() return nil, err
}
macaddress := reqNode.MacAddress
network := reqNode.Network
password := reqNode.Password
var result models.NodeAuth var result models.NodeAuth
@@ -148,8 +154,9 @@ func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.LoginRequest)
return nil, err return nil, err
} }
response := &nodepb.LoginResponse{ response := &nodepb.Object{
Accesstoken: tokenString, Data: tokenString,
Type: nodepb.ACCESS_TOKEN,
} }
return response, nil return response, nil
} }

View File

@@ -2,7 +2,6 @@ package controller
import ( import (
"encoding/json" "encoding/json"
"fmt"
"log" "log"
"strconv" "strconv"
"strings" "strings"
@@ -16,9 +15,9 @@ import (
"golang.org/x/crypto/bcrypt" "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) collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
@@ -30,23 +29,19 @@ func GetPeersList(networkName string) ([]models.PeersResponse, error) {
} }
for _, value := range collection { for _, value := range collection {
var node models.Node var node models.Node
var peer models.PeersResponse var peer models.Node
err := json.Unmarshal([]byte(value), &node) err := json.Unmarshal([]byte(value), &node)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
continue continue
} }
err = json.Unmarshal([]byte(value), &peer)
if err != nil {
log.Println(err)
continue
}
if node.IsEgressGateway == "yes" { if node.IsEgressGateway == "yes" {
peer.EgressGatewayRanges = strings.Join(node.EgressGatewayRanges, ",") peer.EgressGatewayRanges = node.EgressGatewayRanges
} }
if node.Network == networkName && node.IsPending != "yes" { if node.Network == networkName && node.IsPending != "yes" {
if node.UDPHolePunch == "yes" && errN == nil && functions.CheckEndpoint(udppeers[peer.PublicKey]) { peer.PublicKey = node.PublicKey
endpointstring := udppeers[peer.PublicKey] if node.UDPHolePunch == "yes" && errN == nil && functions.CheckEndpoint(udppeers[node.PublicKey]) {
endpointstring := udppeers[node.PublicKey]
endpointarr := strings.Split(endpointstring, ":") endpointarr := strings.Split(endpointstring, ":")
log.Println("got values:", endpointstring, endpointarr) log.Println("got values:", endpointstring, endpointarr)
if len(endpointarr) == 2 { if len(endpointarr) == 2 {
@@ -98,21 +93,38 @@ func GetExtPeersList(networkName string, macaddress string) ([]models.ExtPeersRe
return peers, err return peers, err
} }
func DeleteNode(macaddress string, network string) error { /**
* If being deleted by server, create a record in the DELETED_NODES_TABLE for the client to find
key, err := functions.GetRecordKey(macaddress, network) * 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 { if err != nil {
return err return err
} }
if err = database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil { 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 return err
} }
err = SetNetworkNodesLastModified(network)
if servercfg.IsDNSMode() { if servercfg.IsDNSMode() {
err = SetDNS() err = SetDNS()
} }
return err return err
} }
@@ -136,6 +148,10 @@ func GetNode(macaddress string, network string) (models.Node, error) {
} }
data, err := database.FetchRecord(database.NODES_TABLE_NAME, key) data, err := database.FetchRecord(database.NODES_TABLE_NAME, key)
if err != nil { if err != nil {
if data == "" {
data, err = database.FetchRecord(database.DELETED_NODES_TABLE_NAME, key)
err = json.Unmarshal([]byte(data), &node)
}
return node, err return node, err
} }
if err = json.Unmarshal([]byte(data), &node); err != nil { 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 { func SetNetworkNodesLastModified(networkName string) error {
timestamp := time.Now().Unix() timestamp := time.Now().Unix()

View File

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

View File

@@ -2,83 +2,53 @@ package controller
import ( import (
"context" "context"
"fmt" "encoding/json"
"errors"
"log"
"github.com/gravitl/netmaker/functions" "github.com/gravitl/netmaker/functions"
nodepb "github.com/gravitl/netmaker/grpc" nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
) )
type NodeServiceServer struct { type NodeServiceServer struct {
nodepb.UnimplementedNodeServiceServer 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 // convert string id (from proto) to mongoDB ObjectId
macaddress := req.GetMacaddress() var node models.Node
networkName := req.GetNetwork() if err := json.Unmarshal([]byte(req.Data), &node); err != nil {
network, _ := functions.GetParentNetwork(networkName) return nil, err
}
macaddress := node.MacAddress
networkName := node.Network
node, err := GetNode(macaddress, networkName) node, err := GetNode(macaddress, networkName)
if err != nil { 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 // Cast to ReadNodeRes type
nodeData, err := json.Marshal(&node)
response := &nodepb.ReadNodeRes{ if err != nil {
Node: &nodepb.Node{ return nil, err
Macaddress: node.MacAddress, }
Name: node.Name, response := &nodepb.Object{
Address: node.Address, Data: string(nodeData),
Address6: node.Address6, Type: nodepb.NODE_TYPE,
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,
},
} }
return response, nil 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 // Get the protobuf node type from the protobuf request type
// Essentially doing req.Node to access the struct with a nil check // Essentially doing req.Node to access the struct with a nil check
data := req.GetNode() var node models.Node
// Now we have to convert this into a NodeItem type to convert into BSON data := req.GetData()
node := models.Node{ if err := json.Unmarshal([]byte(data), &node); err != nil {
// ID: primitive.NilObjectID, return nil, err
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(),
} }
//Check to see if key is valid //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) validKey := functions.IsKeyValid(node.Network, node.AccessKey)
network, err := functions.GetParentNetwork(node.Network) network, err := functions.GetParentNetwork(node.Network)
if err != nil { if err != nil {
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not find network: %v", err)) return nil, err
} }
if !validKey { if !validKey {
@@ -95,274 +65,125 @@ func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNo
if network.AllowManualSignUp == "yes" { if network.AllowManualSignUp == "yes" {
node.IsPending = "yes" node.IsPending = "yes"
} else { } else {
return nil, status.Errorf( return nil, errors.New("invalid key, and network does not allow no-key signups")
codes.Internal,
fmt.Sprintf("Invalid key, and network does not allow no-key signups"),
)
} }
} }
node, err = CreateNode(node, node.Network) node, err = CreateNode(node, node.Network)
if err != nil { if err != nil {
// return internal gRPC error to be handled later log.Println("could not create node on network " + node.Network + " (gRPC controller)")
return nil, status.Errorf( return nil, err
codes.Internal,
fmt.Sprintf("Internal error: %v", err),
)
} }
nodeData, err := json.Marshal(&node)
// return the node in a CreateNodeRes type // return the node in a CreateNodeRes type
response := &nodepb.CreateNodeRes{ response := &nodepb.Object{
Node: &nodepb.Node{ Data: string(nodeData),
Macaddress: node.MacAddress, Type: nodepb.NODE_TYPE,
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,
},
} }
err = SetNetworkNodesLastModified(node.Network) err = SetNetworkNodesLastModified(node.Network)
if err != nil { 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 return response, nil
} }
func (s *NodeServiceServer) CheckIn(ctx context.Context, req *nodepb.CheckInReq) (*nodepb.CheckInRes, error) { func (s *NodeServiceServer) UpdateNode(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()
//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) {
// Get the node data from the request // Get the node data from the request
data := req.GetNode() var newnode models.Node
// Now we have to convert this into a NodeItem type to convert into BSON if err := json.Unmarshal([]byte(req.GetData()), &newnode); err != nil {
newnode := models.Node{ return nil, err
// 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(),
} }
// Convert the Id string to a MongoDB ObjectId
macaddress := newnode.MacAddress macaddress := newnode.MacAddress
networkName := newnode.Network networkName := newnode.Network
network, _ := functions.GetParentNetwork(networkName)
node, err := functions.GetNodeByMacAddress(networkName, macaddress) node, err := functions.GetNodeByMacAddress(networkName, macaddress)
if err != nil { if err != nil {
return nil, status.Errorf( return nil, err
codes.NotFound,
fmt.Sprintf("Could not find node with supplied Mac Address: %v", err),
)
} }
err = node.Update(&newnode) err = node.Update(&newnode)
if err != nil { if err != nil {
return nil, status.Errorf( return nil, err
codes.NotFound,
fmt.Sprintf("Could not update node: %v", err),
)
} }
return &nodepb.UpdateNodeRes{ nodeData, err := json.Marshal(&node)
Node: &nodepb.Node{
Macaddress: newnode.MacAddress, return &nodepb.Object{
Localaddress: newnode.LocalAddress, Data: string(nodeData),
Name: newnode.Name, Type: nodepb.NODE_TYPE,
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,
},
}, nil }, nil
} }
func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.DeleteNodeReq) (*nodepb.DeleteNodeRes, error) { func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
macaddress := req.GetMacaddress() nodeID := req.GetData()
network := req.GetNetworkName()
err := DeleteNode(macaddress, network)
err := DeleteNode(nodeID, true)
if err != nil { if err != nil {
fmt.Println("Error deleting node.") log.Println("Error deleting node (gRPC controller).")
fmt.Println(err) return nil, err
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not find/delete node with mac address %s", macaddress))
} }
fmt.Println("updating network last modified of " + req.GetNetworkName()) return &nodepb.Object{
err = SetNetworkNodesLastModified(req.GetNetworkName()) Data: "success",
if err != nil { Type: nodepb.STRING_TYPE,
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,
}, nil }, 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 // Initiate a NodeItem type to write decoded data to
//data := &models.PeersResponse{} //data := &models.PeersResponse{}
// collection.Find returns a cursor for our (empty) query // 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 { 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 // 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++ { for i := 0; i < len(peers); i++ {
extPeers = append(extPeers, models.Node{
// If no error is found send node over stream
stream.Send(&nodepb.GetPeersRes{
Peers: &nodepb.PeersResponse{
Address: peers[i].Address, Address: peers[i].Address,
Address6: peers[i].Address6, Address6: peers[i].Address6,
Endpoint: peers[i].Endpoint, Endpoint: peers[i].Endpoint,
Egressgatewayranges: peers[i].EgressGatewayRanges, PublicKey: peers[i].PublicKey,
Isegressgateway: peers[i].IsEgressGateway == "yes", PersistentKeepalive: peers[i].KeepAlive,
Publickey: peers[i].PublicKey, ListenPort: peers[i].ListenPort,
Keepalive: peers[i].KeepAlive, LocalAddress: peers[i].LocalAddress,
Listenport: peers[i].ListenPort,
Localaddress: peers[i].LocalAddress,
},
}) })
} }
node, err := functions.GetNodeByMacAddress(req.GetNetwork(), req.GetMacaddress()) extData, err := json.Marshal(&extPeers)
if err != nil { 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) return &nodepb.Object{
if err != nil { Data: string(extData),
return status.Errorf(codes.Internal, fmt.Sprintf("Internal error occurred: %v", err)) Type: nodepb.EXT_PEER,
} }, nil
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
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -200,9 +200,6 @@ func GetRecordKey(id string, network string) (string, error) {
return id + "###" + network, nil 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 { func UpdateNetworkNodeAddresses(networkName string) error {
collections, err := database.FetchRecords(database.NODES_TABLE_NAME) collections, err := database.FetchRecords(database.NODES_TABLE_NAME)
@@ -235,6 +232,33 @@ func UpdateNetworkNodeAddresses(networkName string) error {
return nil 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 { func UpdateNetworkLocalAddresses(networkName string) error {
collection, err := database.FetchRecords(database.NODES_TABLE_NAME) 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"; option go_package = "google.golang.org/protobuf/types/known/nodepb";
service NodeService { service NodeService {
rpc Login(LoginRequest) returns (LoginResponse); rpc Login(Object) returns (Object);
rpc CreateNode(CreateNodeReq) returns (CreateNodeRes); rpc CreateNode(Object) returns (Object);
rpc ReadNode(ReadNodeReq) returns (ReadNodeRes); rpc ReadNode(Object) returns (Object);
rpc UpdateNode(UpdateNodeReq) returns (UpdateNodeRes); rpc UpdateNode(Object) returns (Object);
rpc DeleteNode(DeleteNodeReq) returns (DeleteNodeRes); rpc DeleteNode(Object) returns (Object);
rpc GetPeers(GetPeersReq) returns (stream GetPeersRes); rpc GetPeers(Object) returns (Object);
rpc GetExtPeers(GetExtPeersReq) returns (stream GetExtPeersRes); rpc GetExtPeers(Object) returns (Object);
rpc CheckIn(CheckInReq) returns (CheckInRes); rpc CheckIn(Object) returns (Object);
} }
message LoginRequest { message Object {
string macaddress = 1; string Data = 1;
string password = 2; string Type = 2;
string network = 3; 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. // 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 { type NodeServiceClient interface {
Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) Login(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
CreateNode(ctx context.Context, in *CreateNodeReq, opts ...grpc.CallOption) (*CreateNodeRes, error) CreateNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
ReadNode(ctx context.Context, in *ReadNodeReq, opts ...grpc.CallOption) (*ReadNodeRes, error) ReadNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
UpdateNode(ctx context.Context, in *UpdateNodeReq, opts ...grpc.CallOption) (*UpdateNodeRes, error) UpdateNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
DeleteNode(ctx context.Context, in *DeleteNodeReq, opts ...grpc.CallOption) (*DeleteNodeRes, error) DeleteNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
GetPeers(ctx context.Context, in *GetPeersReq, opts ...grpc.CallOption) (NodeService_GetPeersClient, error) GetPeers(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
GetExtPeers(ctx context.Context, in *GetExtPeersReq, opts ...grpc.CallOption) (NodeService_GetExtPeersClient, error) GetExtPeers(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
CheckIn(ctx context.Context, in *CheckInReq, opts ...grpc.CallOption) (*CheckInRes, error) CheckIn(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error)
} }
type nodeServiceClient struct { type nodeServiceClient struct {
@@ -36,8 +36,8 @@ func NewNodeServiceClient(cc grpc.ClientConnInterface) NodeServiceClient {
return &nodeServiceClient{cc} return &nodeServiceClient{cc}
} }
func (c *nodeServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) { func (c *nodeServiceClient) Login(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(LoginResponse) out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/Login", in, out, opts...) err := c.cc.Invoke(ctx, "/node.NodeService/Login", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -45,8 +45,8 @@ func (c *nodeServiceClient) Login(ctx context.Context, in *LoginRequest, opts ..
return out, nil return out, nil
} }
func (c *nodeServiceClient) CreateNode(ctx context.Context, in *CreateNodeReq, opts ...grpc.CallOption) (*CreateNodeRes, error) { func (c *nodeServiceClient) CreateNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(CreateNodeRes) out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/CreateNode", in, out, opts...) err := c.cc.Invoke(ctx, "/node.NodeService/CreateNode", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -54,8 +54,8 @@ func (c *nodeServiceClient) CreateNode(ctx context.Context, in *CreateNodeReq, o
return out, nil return out, nil
} }
func (c *nodeServiceClient) ReadNode(ctx context.Context, in *ReadNodeReq, opts ...grpc.CallOption) (*ReadNodeRes, error) { func (c *nodeServiceClient) ReadNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(ReadNodeRes) out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/ReadNode", in, out, opts...) err := c.cc.Invoke(ctx, "/node.NodeService/ReadNode", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -63,8 +63,8 @@ func (c *nodeServiceClient) ReadNode(ctx context.Context, in *ReadNodeReq, opts
return out, nil return out, nil
} }
func (c *nodeServiceClient) UpdateNode(ctx context.Context, in *UpdateNodeReq, opts ...grpc.CallOption) (*UpdateNodeRes, error) { func (c *nodeServiceClient) UpdateNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(UpdateNodeRes) out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/UpdateNode", in, out, opts...) err := c.cc.Invoke(ctx, "/node.NodeService/UpdateNode", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -72,8 +72,8 @@ func (c *nodeServiceClient) UpdateNode(ctx context.Context, in *UpdateNodeReq, o
return out, nil return out, nil
} }
func (c *nodeServiceClient) DeleteNode(ctx context.Context, in *DeleteNodeReq, opts ...grpc.CallOption) (*DeleteNodeRes, error) { func (c *nodeServiceClient) DeleteNode(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
out := new(DeleteNodeRes) out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/DeleteNode", in, out, opts...) err := c.cc.Invoke(ctx, "/node.NodeService/DeleteNode", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -81,72 +81,26 @@ func (c *nodeServiceClient) DeleteNode(ctx context.Context, in *DeleteNodeReq, o
return out, nil return out, nil
} }
func (c *nodeServiceClient) GetPeers(ctx context.Context, in *GetPeersReq, opts ...grpc.CallOption) (NodeService_GetPeersClient, error) { func (c *nodeServiceClient) GetPeers(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
stream, err := c.cc.NewStream(ctx, &NodeService_ServiceDesc.Streams[0], "/node.NodeService/GetPeers", opts...) out := new(Object)
err := c.cc.Invoke(ctx, "/node.NodeService/GetPeers", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
x := &nodeServiceGetPeersClient{stream} return out, nil
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
} }
type NodeService_GetPeersClient interface { func (c *nodeServiceClient) GetExtPeers(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
Recv() (*GetPeersRes, error) out := new(Object)
grpc.ClientStream err := c.cc.Invoke(ctx, "/node.NodeService/GetExtPeers", in, out, opts...)
}
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...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
x := &nodeServiceGetExtPeersClient{stream} return out, nil
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
} }
type NodeService_GetExtPeersClient interface { func (c *nodeServiceClient) CheckIn(ctx context.Context, in *Object, opts ...grpc.CallOption) (*Object, error) {
Recv() (*GetExtPeersRes, error) out := new(Object)
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)
err := c.cc.Invoke(ctx, "/node.NodeService/CheckIn", in, out, opts...) err := c.cc.Invoke(ctx, "/node.NodeService/CheckIn", in, out, opts...)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -158,14 +112,14 @@ func (c *nodeServiceClient) CheckIn(ctx context.Context, in *CheckInReq, opts ..
// All implementations must embed UnimplementedNodeServiceServer // All implementations must embed UnimplementedNodeServiceServer
// for forward compatibility // for forward compatibility
type NodeServiceServer interface { type NodeServiceServer interface {
Login(context.Context, *LoginRequest) (*LoginResponse, error) Login(context.Context, *Object) (*Object, error)
CreateNode(context.Context, *CreateNodeReq) (*CreateNodeRes, error) CreateNode(context.Context, *Object) (*Object, error)
ReadNode(context.Context, *ReadNodeReq) (*ReadNodeRes, error) ReadNode(context.Context, *Object) (*Object, error)
UpdateNode(context.Context, *UpdateNodeReq) (*UpdateNodeRes, error) UpdateNode(context.Context, *Object) (*Object, error)
DeleteNode(context.Context, *DeleteNodeReq) (*DeleteNodeRes, error) DeleteNode(context.Context, *Object) (*Object, error)
GetPeers(*GetPeersReq, NodeService_GetPeersServer) error GetPeers(context.Context, *Object) (*Object, error)
GetExtPeers(*GetExtPeersReq, NodeService_GetExtPeersServer) error GetExtPeers(context.Context, *Object) (*Object, error)
CheckIn(context.Context, *CheckInReq) (*CheckInRes, error) CheckIn(context.Context, *Object) (*Object, error)
mustEmbedUnimplementedNodeServiceServer() mustEmbedUnimplementedNodeServiceServer()
} }
@@ -173,28 +127,28 @@ type NodeServiceServer interface {
type UnimplementedNodeServiceServer struct { 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") 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") 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") 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") 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") return nil, status.Errorf(codes.Unimplemented, "method DeleteNode not implemented")
} }
func (UnimplementedNodeServiceServer) GetPeers(*GetPeersReq, NodeService_GetPeersServer) error { func (UnimplementedNodeServiceServer) GetPeers(context.Context, *Object) (*Object, error) {
return status.Errorf(codes.Unimplemented, "method GetPeers not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetPeers not implemented")
} }
func (UnimplementedNodeServiceServer) GetExtPeers(*GetExtPeersReq, NodeService_GetExtPeersServer) error { func (UnimplementedNodeServiceServer) GetExtPeers(context.Context, *Object) (*Object, error) {
return status.Errorf(codes.Unimplemented, "method GetExtPeers not implemented") 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") return nil, status.Errorf(codes.Unimplemented, "method CheckIn not implemented")
} }
func (UnimplementedNodeServiceServer) mustEmbedUnimplementedNodeServiceServer() {} 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) { 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 { if err := dec(in); err != nil {
return nil, err return nil, err
} }
@@ -223,13 +177,13 @@ func _NodeService_Login_Handler(srv interface{}, ctx context.Context, dec func(i
FullMethod: "/node.NodeService/Login", FullMethod: "/node.NodeService/Login",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { 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) return interceptor(ctx, in, info, handler)
} }
func _NodeService_CreateNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 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 { if err := dec(in); err != nil {
return nil, err return nil, err
} }
@@ -241,13 +195,13 @@ func _NodeService_CreateNode_Handler(srv interface{}, ctx context.Context, dec f
FullMethod: "/node.NodeService/CreateNode", FullMethod: "/node.NodeService/CreateNode",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { 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) return interceptor(ctx, in, info, handler)
} }
func _NodeService_ReadNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 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 { if err := dec(in); err != nil {
return nil, err return nil, err
} }
@@ -259,13 +213,13 @@ func _NodeService_ReadNode_Handler(srv interface{}, ctx context.Context, dec fun
FullMethod: "/node.NodeService/ReadNode", FullMethod: "/node.NodeService/ReadNode",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { 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) return interceptor(ctx, in, info, handler)
} }
func _NodeService_UpdateNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 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 { if err := dec(in); err != nil {
return nil, err return nil, err
} }
@@ -277,13 +231,13 @@ func _NodeService_UpdateNode_Handler(srv interface{}, ctx context.Context, dec f
FullMethod: "/node.NodeService/UpdateNode", FullMethod: "/node.NodeService/UpdateNode",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { 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) return interceptor(ctx, in, info, handler)
} }
func _NodeService_DeleteNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 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 { if err := dec(in); err != nil {
return nil, err return nil, err
} }
@@ -295,55 +249,49 @@ func _NodeService_DeleteNode_Handler(srv interface{}, ctx context.Context, dec f
FullMethod: "/node.NodeService/DeleteNode", FullMethod: "/node.NodeService/DeleteNode",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { 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) return interceptor(ctx, in, info, handler)
} }
func _NodeService_GetPeers_Handler(srv interface{}, stream grpc.ServerStream) error { func _NodeService_GetPeers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
m := new(GetPeersReq) in := new(Object)
if err := stream.RecvMsg(m); err != nil { if err := dec(in); err != nil {
return err return nil, err
} }
return srv.(NodeServiceServer).GetPeers(m, &nodeServiceGetPeersServer{stream}) if interceptor == nil {
return srv.(NodeServiceServer).GetPeers(ctx, in)
}
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_GetPeersServer interface { func _NodeService_GetExtPeers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
Send(*GetPeersRes) error in := new(Object)
grpc.ServerStream if err := dec(in); err != nil {
return nil, err
} }
if interceptor == nil {
type nodeServiceGetPeersServer struct { return srv.(NodeServiceServer).GetExtPeers(ctx, in)
grpc.ServerStream
} }
info := &grpc.UnaryServerInfo{
func (x *nodeServiceGetPeersServer) Send(m *GetPeersRes) error { Server: srv,
return x.ServerStream.SendMsg(m) FullMethod: "/node.NodeService/GetExtPeers",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
func _NodeService_GetExtPeers_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(NodeServiceServer).GetExtPeers(ctx, req.(*Object))
m := new(GetExtPeersReq)
if err := stream.RecvMsg(m); err != nil {
return err
} }
return srv.(NodeServiceServer).GetExtPeers(m, &nodeServiceGetExtPeersServer{stream}) 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_CheckIn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 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 { if err := dec(in); err != nil {
return nil, err return nil, err
} }
@@ -355,7 +303,7 @@ func _NodeService_CheckIn_Handler(srv interface{}, ctx context.Context, dec func
FullMethod: "/node.NodeService/CheckIn", FullMethod: "/node.NodeService/CheckIn",
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { 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) return interceptor(ctx, in, info, handler)
} }
@@ -387,22 +335,19 @@ var NodeService_ServiceDesc = grpc.ServiceDesc{
MethodName: "DeleteNode", MethodName: "DeleteNode",
Handler: _NodeService_DeleteNode_Handler, Handler: _NodeService_DeleteNode_Handler,
}, },
{
MethodName: "GetPeers",
Handler: _NodeService_GetPeers_Handler,
},
{
MethodName: "GetExtPeers",
Handler: _NodeService_GetExtPeers_Handler,
},
{ {
MethodName: "CheckIn", MethodName: "CheckIn",
Handler: _NodeService_CheckIn_Handler, Handler: _NodeService_CheckIn_Handler,
}, },
}, },
Streams: []grpc.StreamDesc{ Streams: []grpc.StreamDesc{},
{
StreamName: "GetPeers",
Handler: _NodeService_GetPeers_Handler,
ServerStreams: true,
},
{
StreamName: "GetExtPeers",
Handler: _NodeService_GetExtPeers_Handler,
ServerStreams: true,
},
},
Metadata: "grpc/node.proto", 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" "log"
"net" "net"
"os" "os"
"os/exec"
"os/signal" "os/signal"
"strconv" "strconv"
"sync" "sync"
@@ -16,6 +15,7 @@ import (
"github.com/gravitl/netmaker/database" "github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/functions" "github.com/gravitl/netmaker/functions"
nodepb "github.com/gravitl/netmaker/grpc" nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/netclient/local"
"github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/servercfg"
"google.golang.org/grpc" "google.golang.org/grpc"
) )
@@ -34,8 +34,7 @@ func initialize() { // Client Mode Prereq Check
log.Fatal(err) log.Fatal(err)
} }
log.Println("database successfully connected.") log.Println("database successfully connected.")
cmd := exec.Command("id", "-u") output, err := local.RunCmd("id -u")
output, err := cmd.Output()
if err != nil { if err != nil {
log.Println("Error running 'id -u' for prereq check. Please investigate or disable client mode.") 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() dbs, err := GetNetworks()
if err != nil { if err != nil && !database.IsEmptyRecord(err) {
return false, err return false, err
} }

View File

@@ -16,48 +16,82 @@ import (
const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" const charset = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
const TEN_YEARS_IN_SECONDS = 300000000 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( var seededRand *rand.Rand = rand.New(
rand.NewSource(time.Now().UnixNano())) rand.NewSource(time.Now().UnixNano()))
//node struct //node struct
type Node struct { type Node struct {
ID string `json:"id,omitempty" bson:"id,omitempty"` ID string `json:"id,omitempty" bson:"id,omitempty"`
Address string `json:"address" bson:"address" validate:"omitempty,ipv4"` Address string `json:"address" bson:"address" yaml:"address" validate:"omitempty,ipv4"`
Address6 string `json:"address6" bson:"address6" validate:"omitempty,ipv6"` Address6 string `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"`
LocalAddress string `json:"localaddress" bson:"localaddress" validate:"omitempty,ip"` LocalAddress string `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"`
Name string `json:"name" bson:"name" validate:"omitempty,max=12,in_charset"` Name string `json:"name" bson:"name" yaml:"name" validate:"omitempty,max=12,in_charset"`
ListenPort int32 `json:"listenport" bson:"listenport" validate:"omitempty,numeric,min=1024,max=65535"` ListenPort int32 `json:"listenport" bson:"listenport" yaml:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
PublicKey string `json:"publickey" bson:"publickey" validate:"required,base64"` PublicKey string `json:"publickey" bson:"publickey" yaml:"publickey" validate:"required,base64"`
Endpoint string `json:"endpoint" bson:"endpoint" validate:"required,ip"` Endpoint string `json:"endpoint" bson:"endpoint" yaml:"endpoint" validate:"required,ip"`
PostUp string `json:"postup" bson:"postup"` PostUp string `json:"postup" bson:"postup" yaml:"postup"`
PostDown string `json:"postdown" bson:"postdown"` PostDown string `json:"postdown" bson:"postdown" yaml:"postdown"`
AllowedIPs []string `json:"allowedips" bson:"allowedips"` AllowedIPs []string `json:"allowedips" bson:"allowedips" yaml:"allowedips"`
PersistentKeepalive int32 `json:"persistentkeepalive" bson:"persistentkeepalive" validate:"omitempty,numeric,max=1000"` PersistentKeepalive int32 `json:"persistentkeepalive" bson:"persistentkeepalive" yaml:"persistentkeepalive" validate:"omitempty,numeric,max=1000"`
SaveConfig string `json:"saveconfig" bson:"saveconfig" validate:"checkyesorno"` SaveConfig string `json:"saveconfig" bson:"saveconfig" yaml:"saveconfig" validate:"checkyesorno"`
AccessKey string `json:"accesskey" bson:"accesskey"` AccessKey string `json:"accesskey" bson:"accesskey" yaml:"accesskey"`
Interface string `json:"interface" bson:"interface"` Interface string `json:"interface" bson:"interface" yaml:"interface"`
LastModified int64 `json:"lastmodified" bson:"lastmodified"` LastModified int64 `json:"lastmodified" bson:"lastmodified" yaml:"lastmodified"`
KeyUpdateTimeStamp int64 `json:"keyupdatetimestamp" bson:"keyupdatetimestamp"` KeyUpdateTimeStamp int64 `json:"keyupdatetimestamp" bson:"keyupdatetimestamp" yaml:"keyupdatetimestamp"`
ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime"` ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime" yaml:"expdatetime"`
LastPeerUpdate int64 `json:"lastpeerupdate" bson:"lastpeerupdate"` LastPeerUpdate int64 `json:"lastpeerupdate" bson:"lastpeerupdate" yaml:"lastpeerupdate"`
LastCheckIn int64 `json:"lastcheckin" bson:"lastcheckin"` LastCheckIn int64 `json:"lastcheckin" bson:"lastcheckin" yaml:"lastcheckin"`
MacAddress string `json:"macaddress" bson:"macaddress" validate:"required,mac,macaddress_unique"` MacAddress string `json:"macaddress" bson:"macaddress" yaml:"macaddress" validate:"required,mac,macaddress_unique"`
CheckInInterval int32 `json:"checkininterval" bson:"checkininterval"` CheckInInterval int32 `json:"checkininterval" bson:"checkininterval" yaml:"checkininterval"`
Password string `json:"password" bson:"password" validate:"required,min=6"` Password string `json:"password" bson:"password" yaml:"password" validate:"required,min=6"`
Network string `json:"network" bson:"network" validate:"network_exists"` Network string `json:"network" bson:"network" yaml:"network" validate:"network_exists"`
IsPending string `json:"ispending" bson:"ispending"` IsPending string `json:"ispending" bson:"ispending" yaml:"ispending"`
IsEgressGateway string `json:"isegressgateway" bson:"isegressgateway"` IsEgressGateway string `json:"isegressgateway" bson:"isegressgateway" yaml:"isegressgateway"`
IsIngressGateway string `json:"isingressgateway" bson:"isingressgateway"` IsIngressGateway string `json:"isingressgateway" bson:"isingressgateway" yaml:"isingressgateway"`
EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges"` EgressGatewayRanges []string `json:"egressgatewayranges" bson:"egressgatewayranges" yaml:"egressgatewayranges"`
IngressGatewayRange string `json:"ingressgatewayrange" bson:"ingressgatewayrange"` IngressGatewayRange string `json:"ingressgatewayrange" bson:"ingressgatewayrange" yaml:"ingressgatewayrange"`
PostChanges string `json:"postchanges" bson:"postchanges"` StaticIP string `json:"staticip" bson:"staticip" yaml:"staticip"`
StaticIP string `json:"staticip" bson:"staticip"` StaticPubKey string `json:"staticpubkey" bson:"staticpubkey" yaml:"staticpubkey"`
StaticPubKey string `json:"staticpubkey" bson:"staticpubkey"` UDPHolePunch string `json:"udpholepunch" bson:"udpholepunch" yaml:"udpholepunch" validate:"checkyesorno"`
UDPHolePunch string `json:"udpholepunch" bson:"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() { func (node *Node) SetLastModified() {
node.LastModified = time.Now().Unix() node.LastModified = time.Now().Unix()
} }
@@ -141,7 +175,10 @@ func (node *Node) SetDefaults() {
} }
} }
node.CheckInInterval = parentNetwork.DefaultCheckInInterval node.CheckInInterval = parentNetwork.DefaultCheckInInterval
node.SetIPForwardingDefault()
node.SetDNSOnDefault()
node.SetIsLocalDefault()
node.SetIsDualStackDefault()
node.SetLastModified() node.SetLastModified()
node.SetDefaultName() node.SetDefaultName()
node.SetLastCheckIn() node.SetLastCheckIn()
@@ -260,8 +297,24 @@ func (newNode *Node) Fill(currentNode *Node) {
if newNode.UDPHolePunch == "" { if newNode.UDPHolePunch == "" {
newNode.UDPHolePunch = currentNode.SaveConfig newNode.UDPHolePunch = currentNode.SaveConfig
} }
if newNode.DNSOn == "" {
newNode.PostChanges = "no" 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 { func (currentNode *Node) Update(newNode *Node) error {

View File

@@ -1,16 +1,20 @@
package auth package auth
import ( import (
"github.com/gravitl/netmaker/netclient/config" "encoding/json"
"fmt" "fmt"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/config"
// "os" // "os"
"context" "context"
"io/ioutil" "io/ioutil"
nodepb "github.com/gravitl/netmaker/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/grpc/codes"
nodepb "github.com/gravitl/netmaker/grpc"
) )
// CreateJWT func will used to create the JWT while signing in and signing out // CreateJWT func will used to create the JWT while signing in and signing out
@@ -45,17 +49,29 @@ func AutoLogin(client nodepb.NodeServiceClient, network string) error {
if err != nil { if err != nil {
return err return err
} }
login := &nodepb.LoginRequest{ pass, err := RetrieveSecret(network)
Password: cfg.Node.Password, if err != nil {
Macaddress: cfg.Node.MacAddress, return err
}
node := models.Node{
Password: pass,
MacAddress: cfg.Node.MacAddress,
Network: network, Network: network,
} }
data, err := json.Marshal(&node)
if err != nil {
return nil
}
login := &nodepb.Object{
Data: string(data),
}
// RPC call // RPC call
res, err := client.Login(context.TODO(), login) res, err := client.Login(context.TODO(), login)
if err != nil { if err != nil {
return err return err
} }
tokenstring := []byte(res.Accesstoken) tokenstring := []byte(res.Data)
err = ioutil.WriteFile(home+"/nettoken-"+network, tokenstring, 0644) err = ioutil.WriteFile(home+"/nettoken-"+network, tokenstring, 0644)
if err != nil { if err != nil {
return err return err
@@ -63,6 +79,17 @@ func AutoLogin(client nodepb.NodeServiceClient, network string) error {
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 { type Configuration struct {
MacAddress string MacAddress string
Password string Password string

View File

@@ -1,14 +1,15 @@
package command package command
import ( import (
"github.com/gravitl/netmaker/netclient/functions" "log"
"github.com/gravitl/netmaker/netclient/config"
"github.com/gravitl/netmaker/netclient/local"
"golang.zx2c4.com/wireguard/wgctrl"
nodepb "github.com/gravitl/netmaker/grpc"
"os" "os"
"strings" "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 ( var (
@@ -19,14 +20,9 @@ var (
wcclient nodepb.NodeServiceClient wcclient nodepb.NodeServiceClient
) )
func Register(cfg config.GlobalConfig) error { func Join(cfg config.ClientConfig, privateKey string) error {
err := functions.Register(cfg)
return err
}
func Join(cfg config.ClientConfig) error { err := functions.JoinNetwork(cfg, privateKey)
err := functions.JoinNetwork(cfg)
if err != nil { if err != nil {
if !strings.Contains(err.Error(), "ALREADY_INSTALLED") { if !strings.Contains(err.Error(), "ALREADY_INSTALLED") {
log.Println("Error installing: ", err) log.Println("Error installing: ", err)
@@ -58,12 +54,8 @@ func CheckIn(cfg config.ClientConfig) error {
log.Println("Required, '-n'. No network provided. Exiting.") log.Println("Required, '-n'. No network provided. Exiting.")
os.Exit(1) os.Exit(1)
} }
err := functions.CheckIn(cfg) err := functions.CheckConfig(cfg)
if err != nil { return err
log.Println("Error checking in: ", err)
os.Exit(1)
}
return nil
} }
func Leave(cfg config.ClientConfig) error { func Leave(cfg config.ClientConfig) error {
@@ -109,7 +101,7 @@ func Pull(cfg config.ClientConfig) error {
return err return err
} }
for _, network := range networks { for _, network := range networks {
err = functions.Pull(network) _, err = functions.Pull(network, true)
if err != nil { if err != nil {
log.Printf("Error pulling network config for "+network+" network: ", err) log.Printf("Error pulling network config for "+network+" network: ", err)
} else { } else {
@@ -118,7 +110,7 @@ func Pull(cfg config.ClientConfig) error {
} }
err = nil err = nil
} else { } else {
err = functions.Pull(cfg.Network) _, err = functions.Pull(cfg.Network, true)
} }
log.Println("Completed pulling network and peer configs.") log.Println("Completed pulling network and peer configs.")
return err return err
@@ -139,4 +131,3 @@ func Unregister(cfg config.GlobalConfig) error {
err := functions.Unregister(cfg) err := functions.Unregister(cfg)
return err return err
} }

View File

@@ -9,7 +9,6 @@ import (
"log" "log"
"os" "os"
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
@@ -22,7 +21,7 @@ type GlobalConfig struct {
type ClientConfig struct { type ClientConfig struct {
Server ServerConfig `yaml:"server"` Server ServerConfig `yaml:"server"`
Node NodeConfig `yaml:"node"` Node models.Node `yaml:"node"`
Network string `yaml:"network"` Network string `yaml:"network"`
Daemon string `yaml:"daemon"` Daemon string `yaml:"daemon"`
OperatingSystem string `yaml:"operatingsystem"` OperatingSystem string `yaml:"operatingsystem"`
@@ -36,45 +35,6 @@ type ServerConfig struct {
GRPCWireGuard string `yaml:"grpcwg"` 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 //reading in the env file
func Write(config *ClientConfig, network string) error { func Write(config *ClientConfig, network string) error {
if network == "" { if network == "" {
@@ -232,6 +192,7 @@ func (config *ClientConfig) ReadConfig() {
fmt.Println(err) fmt.Println(err)
log.Fatal(err) log.Fatal(err)
} else { } else {
config.Node.SetID()
//config = cfg //config = cfg
} }
} }
@@ -289,10 +250,10 @@ func ModGlobalConfig(cfg models.IntClient) error {
return err return err
} }
func ModConfig(node *nodepb.Node) error { func ModConfig(node *models.Node) error {
network := node.Nodenetwork network := node.Network
if network == "" { if network == "" {
return errors.New("No Network Provided") return errors.New("no network provided")
} }
var modconfig ClientConfig var modconfig ClientConfig
var err error var err error
@@ -303,90 +264,23 @@ func ModConfig(node *nodepb.Node) error {
} }
modconfig = *useconfig modconfig = *useconfig
} }
nodecfg := modconfig.Node modconfig.Node.Fill(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
err = Write(&modconfig, network) err = Write(&modconfig, network)
return err return err
} }
func GetCLIConfig(c *cli.Context) (ClientConfig, error) { func GetCLIConfig(c *cli.Context) (ClientConfig, string, error) {
var cfg ClientConfig var cfg ClientConfig
if c.String("token") != "" { if c.String("token") != "" {
tokenbytes, err := base64.StdEncoding.DecodeString(c.String("token")) tokenbytes, err := base64.StdEncoding.DecodeString(c.String("token"))
if err != nil { if err != nil {
log.Println("error decoding token") log.Println("error decoding token")
return cfg, err return cfg, "", err
} }
var accesstoken models.AccessToken var accesstoken models.AccessToken
if err := json.Unmarshal(tokenbytes, &accesstoken); err != nil { if err := json.Unmarshal(tokenbytes, &accesstoken); err != nil {
log.Println("error converting token json to object", tokenbytes) log.Println("error converting token json to object", tokenbytes)
return cfg, err return cfg, "", err
} }
if accesstoken.ServerConfig.APIConnString != "" { if accesstoken.ServerConfig.APIConnString != "" {
@@ -454,87 +348,25 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, error) {
cfg.Node.Password = c.String("password") cfg.Node.Password = c.String("password")
cfg.Node.MacAddress = c.String("macaddress") cfg.Node.MacAddress = c.String("macaddress")
cfg.Node.LocalAddress = c.String("localaddress") cfg.Node.LocalAddress = c.String("localaddress")
cfg.Node.WGAddress = c.String("address") cfg.Node.Address = c.String("address")
cfg.Node.WGAddress6 = c.String("addressIPV6") cfg.Node.Address6 = c.String("addressIPV6")
cfg.Node.Roaming = c.String("roaming") 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.IsLocal = c.String("islocal")
cfg.Node.IsDualStack = c.String("isdualstack") cfg.Node.IsDualStack = c.String("isdualstack")
cfg.Node.PostUp = c.String("postup") cfg.Node.PostUp = c.String("postup")
cfg.Node.PostDown = c.String("postdown") cfg.Node.PostDown = c.String("postdown")
cfg.Node.Port = int32(c.Int("port")) cfg.Node.ListenPort = int32(c.Int("port"))
cfg.Node.KeepAlive = int32(c.Int("keepalive")) cfg.Node.PersistentKeepalive = int32(c.Int("keepalive"))
cfg.Node.PublicKey = c.String("publickey") cfg.Node.PublicKey = c.String("publickey")
cfg.Node.PrivateKey = c.String("privatekey") privateKey := c.String("privatekey")
cfg.Node.Endpoint = c.String("endpoint") cfg.Node.Endpoint = c.String("endpoint")
cfg.Node.IPForwarding = c.String("ipforwarding") cfg.Node.IPForwarding = c.String("ipforwarding")
cfg.OperatingSystem = c.String("operatingsystem") cfg.OperatingSystem = c.String("operatingsystem")
cfg.Daemon = c.String("daemon") cfg.Daemon = c.String("daemon")
cfg.Node.UDPHolePunch = c.String("udpholepunch") cfg.Node.UDPHolePunch = c.String("udpholepunch")
return cfg, nil return cfg, privateKey, 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
} }
func ReadConfig(network string) (*ClientConfig, error) { func ReadConfig(network string) (*ClientConfig, error) {
@@ -596,3 +428,15 @@ func FileExists(f string) bool {
} }
return !info.IsDir() 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,316 +1,180 @@
package functions package functions
import ( import (
"google.golang.org/grpc/credentials"
"crypto/tls" "crypto/tls"
"context" "encoding/json"
"strings" "errors"
"log" "log"
"net"
"os/exec" 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/config"
"github.com/gravitl/netmaker/netclient/local" "github.com/gravitl/netmaker/netclient/local"
"github.com/gravitl/netmaker/netclient/wireguard" "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" "google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
//homedir "github.com/mitchellh/go-homedir" //homedir "github.com/mitchellh/go-homedir"
) )
func CheckIn(cliconf config.ClientConfig) error { func checkIP(node *models.Node, servercfg config.ServerConfig, cliconf config.ClientConfig, network string) bool {
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
ipchange := false ipchange := false
var err error
if nodecfg.DNS == "on" || cliconf.Node.DNS == "on" { if node.Roaming == "yes" {
log.Println("setting dns") if node.IsLocal == "no" {
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.")
}
}
}
}
if nodecfg.Roaming != "off" {
if nodecfg.IsLocal != "yes" {
log.Println("Checking to see if public addresses have changed") log.Println("Checking to see if public addresses have changed")
extIP, err := getPublicIP() extIP, err := getPublicIP()
if err != nil { if err != nil {
log.Println("Error encountered checking ip addresses: %v", err) log.Println("error encountered checking ip addresses:", err)
} }
if nodecfg.Endpoint != extIP && extIP != "" { if node.Endpoint != extIP && extIP != "" {
log.Println("Endpoint has changed from " + log.Println("Endpoint has changed from " +
nodecfg.Endpoint + " to " + extIP) node.Endpoint + " to " + extIP)
log.Println("Updating address") log.Println("Updating address")
nodecfg.Endpoint = extIP
nodecfg.PostChanges = "true"
node.Endpoint = extIP node.Endpoint = extIP
node.Postchanges = "true"
ipchange = true ipchange = true
} }
intIP, err := getPrivateAddr() intIP, err := getPrivateAddr()
if err != nil { if err != nil {
log.Println("Error encountered checking ip addresses: %v", err) log.Println("error encountered checking ip addresses:", err)
} }
if nodecfg.LocalAddress != intIP && intIP != "" { if node.LocalAddress != intIP && intIP != "" {
log.Println("Local Address has changed from " + log.Println("Local Address has changed from " +
nodecfg.LocalAddress + " to " + intIP) node.LocalAddress + " to " + intIP)
log.Println("Updating address") log.Println("Updating address")
nodecfg.LocalAddress = intIP node.LocalAddress = intIP
nodecfg.PostChanges = "true"
node.Localaddress = intIP
node.Postchanges = "true"
ipchange = true ipchange = true
} }
} else { } else {
log.Println("Checking to see if local addresses have changed") log.Println("Checking to see if local addresses have changed")
localIP, err := getLocalIP(nodecfg.LocalRange) localIP, err := getLocalIP(node.LocalRange)
if err != nil { if err != nil {
log.Println("Error encountered checking ip addresses: %v", err) log.Println("error encountered checking ip addresses:", err)
} }
if nodecfg.Endpoint != localIP && localIP != "" { if node.Endpoint != localIP && localIP != "" {
log.Println("Endpoint has changed from " + log.Println("Endpoint has changed from " +
nodecfg.Endpoint + " to " + localIP) node.Endpoint + " to " + localIP)
log.Println("Updating address") log.Println("Updating address")
nodecfg.Endpoint = localIP
nodecfg.LocalAddress = localIP
nodecfg.PostChanges = "true"
node.Endpoint = localIP node.Endpoint = localIP
node.Localaddress = localIP node.LocalAddress = localIP
node.Postchanges = "true"
ipchange = true ipchange = true
} }
} }
if node.Postchanges != "true" {
log.Println("Addresses have not changed.")
}
} }
if ipchange { if ipchange {
err := config.ModConfig(&node) err = config.ModConfig(node)
if err != nil { if err != nil {
return err log.Println("Error:", err)
log.Fatalf("Error: %v", err) return false
} }
err = wireguard.SetWGConfig(network, false) err = wireguard.SetWGConfig(network, false)
if err != nil { if err != nil {
return err log.Println("Error:", err)
log.Fatalf("Error: %v", err) return false
} }
node = server.GetNode(network)
cfg, err := config.ReadConfig(network)
if err != nil {
return err
} }
nodecfg = cfg.Node return ipchange && err == nil
} }
var wcclient nodepb.NodeServiceClient func setDNS(node *models.Node, servercfg config.ServerConfig, nodecfg *models.Node) {
var requestOpts grpc.DialOption if nodecfg.DNSOn == "yes" {
requestOpts = grpc.WithInsecure() log.Println("setting dns")
if servercfg.GRPCSSL == "on" { ifacename := node.Interface
log.Println("using SSL") nameserver := servercfg.CoreDNSAddr
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}}) network := node.Network
requestOpts = grpc.WithTransportCredentials(h2creds) _ = local.UpdateDNS(ifacename, network, nameserver)
} 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)
}
} }
} }
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, func checkNodeActions(node *models.Node, network string, servercfg config.ServerConfig) string {
Network: node.Nodenetwork, if node.Action == models.NODE_UPDATE_KEY {
} err := wireguard.SetWGKeyConfig(network, servercfg.GRPCAddress)
readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
if err != nil { if err != nil {
return err log.Println("Unable to process reset keys request:", err)
log.Fatalf("Error: %v", err) return ""
} }
err = config.ModConfig(readres.Node) node.Action = ""
if err != nil { return ""
return err
log.Fatalf("Error: %v", err)
} }
err = wireguard.SetWGConfig(network, false) if node.Action == models.NODE_DELETE {
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
}
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) err := LeaveNetwork(network)
if err != nil { if err != nil {
return err log.Println("Error:", err)
log.Fatalf("Error: %v", err) return ""
} }
return models.NODE_DELETE
} }
if setupcheck { return ""
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)
}
}
}
//err = Pull(network)
return err
} }
func Pull (network string) error{ /**
node := server.GetNode(network) * 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) cfg, err := config.ReadConfig(network)
if err != nil { if err != nil {
return err 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)
}
return err
}
/**
* 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 nil, err
}
servercfg := cfg.Server servercfg := cfg.Server
var header metadata.MD var header metadata.MD
var wcclient nodepb.NodeServiceClient if cfg.Node.IPForwarding == "yes" {
if err = local.SetIPForwarding(); err != nil {
return nil, err
}
}
var requestOpts grpc.DialOption var requestOpts grpc.DialOption
requestOpts = grpc.WithInsecure() requestOpts = grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" { if cfg.Server.GRPCSSL == "on" {
@@ -319,40 +183,58 @@ func Pull (network string) error{
} }
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts) conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
if err != nil { if err != nil {
log.Println("Cant dial GRPC server: %v", err) log.Println("Cant dial GRPC server:", err)
return err return nil, err
} }
wcclient = nodepb.NewNodeServiceClient(conn) wcclient := nodepb.NewNodeServiceClient(conn)
ctx := context.Background() ctx, err := auth.SetJWT(wcclient, network)
ctx, err = auth.SetJWT(wcclient, network)
if err != nil { if err != nil {
log.Println("Failed to authenticate: %v", err) log.Println("Failed to authenticate:", err)
return err return nil, err
} }
req := &nodepb.ReadNodeReq{ req := &nodepb.Object{
Macaddress: node.Macaddress, Data: node.MacAddress + "###" + node.Network,
Network: node.Nodenetwork, Type: nodepb.STRING_TYPE,
} }
readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header)) readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
if err != nil { if err != nil {
return err return nil, err
} }
err = config.ModConfig(readres.Node) 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 { if err != nil {
return err return &resNode, err
} }
err = wireguard.SetWGConfig(network, false) req := &nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
Metadata: "",
}
_, err = wcclient.UpdateNode(ctx, req, grpc.Header(&header))
if err != nil { if err != nil {
return err return &resNode, err
} }
}
setDNS(&node, servercfg, &cfg.Node)
return err return &node, err
} }
func Push(network string) error { func Push(network string) error {
postnode := server.GetNode(network) postnode := config.GetNode(network)
cfg, err := config.ReadConfig(network) cfg, err := config.ReadConfig(network)
if err != nil { if err != nil {
return err return err
@@ -369,21 +251,34 @@ func Push (network string) error{
} }
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts) conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
if err != nil { if err != nil {
log.Println("Cant dial GRPC server: %v", err) log.Println("Cant dial GRPC server:", err)
return err return err
} }
wcclient = nodepb.NewNodeServiceClient(conn) wcclient = nodepb.NewNodeServiceClient(conn)
ctx := context.Background() ctx, err := auth.SetJWT(wcclient, network)
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 { if err != nil {
log.Println("Failed to authenticate: %v", err)
return err return err
} }
req := &nodepb.UpdateNodeReq{ req := &nodepb.Object{
Node: &postnode, Data: string(nodeData),
Type: nodepb.NODE_TYPE,
Metadata: "",
} }
_, err = wcclient.UpdateNode(ctx, req, grpc.Header(&header)) 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 return err
} }

View File

@@ -1,25 +1,27 @@
package functions package functions
import ( import (
"google.golang.org/grpc/credentials" "context"
"crypto/tls" "crypto/tls"
"fmt"
"encoding/json" "encoding/json"
"errors" "errors"
"context" "fmt"
"net/http"
"io/ioutil" "io/ioutil"
"strings"
"log" "log"
"net" "net"
"net/http"
"os" "os"
"os/exec" "os/exec"
"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/config"
"github.com/gravitl/netmaker/netclient/local" "github.com/gravitl/netmaker/netclient/local"
"github.com/gravitl/netmaker/netclient/auth"
nodepb "github.com/gravitl/netmaker/grpc"
"golang.zx2c4.com/wireguard/wgctrl" "golang.zx2c4.com/wireguard/wgctrl"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
//homedir "github.com/mitchellh/go-homedir" //homedir "github.com/mitchellh/go-homedir"
) )
@@ -60,7 +62,7 @@ func GetFreePort(rangestart int32) (int32, error){
for _, i := range devices { for _, i := range devices {
if int32(i.ListenPort) == x { if int32(i.ListenPort) == x {
conflict = true conflict = true
break; break
} }
} }
if conflict { if conflict {
@@ -205,60 +207,32 @@ func getPrivateAddr() (string, error) {
func needInterfaceUpdate(ctx context.Context, mac string, network string, iface string) (bool, string, error) { func needInterfaceUpdate(ctx context.Context, mac string, network string, iface string) (bool, string, error) {
var header metadata.MD var header metadata.MD
req := &nodepb.ReadNodeReq{ req := &nodepb.Object{
Macaddress: mac, Data: mac + "###" + network,
Network: network, Type: nodepb.STRING_TYPE,
} }
readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header)) readres, err := wcclient.ReadNode(ctx, req, grpc.Header(&header))
if err != nil { if err != nil {
return false, "", err return false, "", err
log.Fatalf("Error: %v", err) log.Fatalf("Error: %v", err)
} }
oldiface := readres.Node.Interface 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) modcfg, err := config.ReadConfig(network)
if err != nil { if err != nil {
log.Fatalf("Error: %v", err) log.Fatalf("Error: %v", err)
} }
nodecfg := modcfg.Node return 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
}
if nodecfg.IsIngressGateway == "yes" {
node.Isingressgateway = true
} else {
node.Isingressgateway = false
}
return node
} }
func Uninstall() error { func Uninstall() error {
@@ -307,9 +281,9 @@ func LeaveNetwork(network string) error {
var header metadata.MD var header metadata.MD
_, err = wcclient.DeleteNode( _, err = wcclient.DeleteNode(
ctx, ctx,
&nodepb.DeleteNodeReq{ &nodepb.Object{
Macaddress: node.MacAddress, Data: node.ID,
NetworkName: node.Network, Type: nodepb.STRING_TYPE,
}, },
grpc.Header(&header), grpc.Header(&header),
) )
@@ -356,7 +330,6 @@ func DeleteInterface(ifacename string, postdown string) error{
return err return err
} }
func List() error { func List() error {
networks, err := GetNetworks() networks, err := GetNetworks()
@@ -366,22 +339,20 @@ func List() error{
for _, network := range networks { for _, network := range networks {
cfg, err := config.ReadConfig(network) cfg, err := config.ReadConfig(network)
if err == nil { if err == nil {
//cfg2 := *cfg jsoncfg, _ := json.Marshal(
listconfig := &config.ListConfig{ map[string]string{
Name: cfg.Node.Name, "Name": cfg.Node.Name,
Interface: cfg.Node.Interface, "Interface": cfg.Node.Interface,
PrivateIPv4: cfg.Node.WGAddress, "PrivateIPv4": cfg.Node.Address,
PrivateIPv6: cfg.Node.WGAddress6, "PrivateIPv6": cfg.Node.Address6,
PublicEndpoint: cfg.Node.Endpoint, "PublicEndpoint": cfg.Node.Endpoint,
} })
jsoncfg, _ := json.Marshal(listconfig)
log.Println(network + ": " + string(jsoncfg)) log.Println(network + ": " + string(jsoncfg))
} else { } else {
log.Println(network + ": Could not retrieve network configuration.") log.Println(network + ": Could not retrieve network configuration.")
} }
} }
return nil return nil
} }
func GetNetworks() ([]string, error) { func GetNetworks() ([]string, error) {

View File

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

View File

@@ -4,6 +4,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"strings" "strings"
//"github.com/davecgh/go-spew/spew" //"github.com/davecgh/go-spew/spew"
"log" "log"
"os/exec" "os/exec"
@@ -30,24 +31,23 @@ func SetDNS(nameserver string) error {
return err return err
} }
func UpdateDNS(ifacename string, network string, nameserver string) error { func UpdateDNS(ifacename string, network string, nameserver string) error {
_, err := exec.LookPath("resolvectl") _, err := exec.LookPath("resolvectl")
if err != nil { if err != nil {
log.Println(err) log.Println(err)
log.Println("WARNING: resolvectl not present. Unable to set dns. Install resolvectl or run manually.") log.Println("WARNING: resolvectl not present. Unable to set dns. Install resolvectl or run manually.")
} else { } else {
_, err = exec.Command("resolvectl", "domain", ifacename, "~"+network).Output() _, err = RunCmd("resolvectl domain " + ifacename + " ~" + network)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
log.Println("WARNING: Error encountered setting domain on dns. Aborted setting dns.") log.Println("WARNING: Error encountered setting domain on dns. Aborted setting dns.")
} else { } else {
_, err = exec.Command("resolvectl", "default-route", ifacename, "false").Output() _, err = RunCmd("resolvectl default-route " + ifacename + " false")
if err != nil { if err != nil {
log.Println(err) log.Println(err)
log.Println("WARNING: Error encountered setting default-route on dns. Aborted setting dns.") log.Println("WARNING: Error encountered setting default-route on dns. Aborted setting dns.")
} else { } else {
_, err = exec.Command("resolvectl", "dns", ifacename, nameserver).Output() _, err = RunCmd("resolvectl dns " + ifacename + " " + nameserver)
if err != nil { if err != nil {
log.Println("WARNING: Error encountered running resolvectl dns " + ifacename + " " + nameserver) log.Println("WARNING: Error encountered running resolvectl dns " + ifacename + " " + nameserver)
log.Println(err) log.Println(err)

View File

@@ -3,16 +3,56 @@ package local
import ( import (
//"github.com/davecgh/go-spew/spew" //"github.com/davecgh/go-spew/spew"
"errors" "errors"
"github.com/gravitl/netmaker/netclient/config"
"log"
"io/ioutil"
"path/filepath"
"io" "io"
"strings" "io/ioutil"
"log"
"os" "os"
"os/exec" "os/exec"
"path/filepath"
"runtime"
"strings"
"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 { func RunCmds(commands []string) error {
var err error var err error
for _, command := range commands { for _, command := range commands {
@@ -77,7 +117,6 @@ func ConfigureSystemD(network string) error {
} }
} }
systemservice := `[Unit] systemservice := `[Unit]
Description=network check for remote peers and local config Description=network check for remote peers and local config
Wants=netclient.timer Wants=netclient.timer
@@ -131,49 +170,23 @@ WantedBy=timers.target
return err return err
} }
} }
//sysExec, err := exec.LookPath("systemctl")
cmdSysEnableService := exec.Command("systemctl", "enable", "netclient@.service")/*&exec.Cmd { _, err = RunCmd("systemctl enable netclient@.service")
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 { if err != nil {
log.Println("Error enabling netclient@.service. Please investigate.") log.Println("Error enabling netclient@.service. Please investigate.")
log.Println(err) log.Println(err)
} }
err = cmdSysDaemonReload.Run() _, err = RunCmd("systemctl daemon-reload")
if err != nil { if err != nil {
log.Println("Error reloading system daemons. Please investigate.") log.Println("Error reloading system daemons. Please investigate.")
log.Println(err) log.Println(err)
} }
err = cmdSysEnableTimer.Run() _, err = RunCmd("systemctl enable netclient-" + network + ".timer")
if err != nil { if err != nil {
log.Println("Error enabling netclient.timer. Please investigate.") log.Println("Error enabling netclient.timer. Please investigate.")
log.Println(err) log.Println(err)
} }
err = cmdSysStartTimer.Run() _, err = RunCmd("systemctl start netclient-" + network + ".timer")
if err != nil { if err != nil {
log.Println("Error starting netclient-" + network + ".timer. Please investigate.") log.Println("Error starting netclient-" + network + ".timer. Please investigate.")
log.Println(err) log.Println(err)
@@ -198,34 +211,24 @@ func isOnlyService(network string) (bool, error) {
func RemoveSystemDServices(network string) error { func RemoveSystemDServices(network string) error {
//sysExec, err := exec.LookPath("systemctl") //sysExec, err := exec.LookPath("systemctl")
fullremove, err := isOnlyService(network) fullremove, err := isOnlyService(network)
if err != nil { if err != nil {
log.Println(err) 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 { if fullremove {
err = cmdSysDisableService.Run() _, err = RunCmd("systemctl disable netclient@.service")
if err != nil { if err != nil {
log.Println("Error disabling netclient@.service. Please investigate.") log.Println("Error disabling netclient@.service. Please investigate.")
log.Println(err) log.Println(err)
} }
} }
err = cmdSysStopTimer.Run() _, err = RunCmd("systemctl daemon-reload")
if err != nil { if err != nil {
log.Println("Error stopping netclient-" + network + ".timer. Please investigate.") log.Println("Error stopping netclient-" + network + ".timer. Please investigate.")
log.Println(err) log.Println(err)
} }
err = cmdSysDisableTimer.Run() _, err = RunCmd("systemctl disable netclient-" + network + ".timer")
if err != nil { if err != nil {
log.Println("Error disabling netclient-" + network + ".timer. Please investigate.") log.Println("Error disabling netclient-" + network + ".timer. Please investigate.")
log.Println(err) log.Println(err)
@@ -242,18 +245,17 @@ func RemoveSystemDServices(network string) error {
log.Println("Error removing file. Please investigate.") log.Println("Error removing file. Please investigate.")
log.Println(err) log.Println(err)
} }
err = cmdSysDaemonReload.Run() _, err = RunCmd("systemctl daemon-reload")
if err != nil { if err != nil {
log.Println("Error reloading system daemons. Please investigate.") log.Println("Error reloading system daemons. Please investigate.")
log.Println(err) log.Println(err)
} }
err = cmdSysResetFailed.Run() _, err = RunCmd("systemctl reset-failed")
if err != nil { if err != nil {
log.Println("Error reseting failed system services. Please investigate.") log.Println("Error reseting failed system services. Please investigate.")
log.Println(err) log.Println(err)
} }
return err return err
} }
func WipeLocal(network string) error { func WipeLocal(network string) error {

View File

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

View File

@@ -1,71 +1,78 @@
package server package server
import ( import (
"google.golang.org/grpc/credentials"
"crypto/tls"
"fmt"
"context" "context"
"crypto/tls"
"encoding/json"
"fmt"
"log" "log"
"strings"
"strconv"
"net" "net"
"strconv"
"time" "time"
"io"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"github.com/gravitl/netmaker/netclient/config"
"github.com/gravitl/netmaker/netclient/auth"
"github.com/gravitl/netmaker/netclient/local"
nodepb "github.com/gravitl/netmaker/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"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
//homedir "github.com/mitchellh/go-homedir" //homedir "github.com/mitchellh/go-homedir"
) )
func GetNode(network string) nodepb.Node { func getGrpcClient(cfg *config.ClientConfig) (nodepb.NodeServiceClient, error) {
servercfg := cfg.Server
modcfg, err := config.ReadConfig(network) 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)
}
conn, err := grpc.Dial(servercfg.GRPCAddress, requestOpts)
if err != nil { if err != nil {
log.Fatalf("Error: %v", err) return nil, err
}
wcclient = nodepb.NewNodeServiceClient(conn)
return wcclient, nil
} }
nodecfg := modcfg.Node func CheckIn(network string) (*models.Node, error) {
var node nodepb.Node cfg, err := config.ReadConfig(network)
if err != nil {
node.Name = nodecfg.Name return nil, err
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
} }
if nodecfg.IsDualStack == "yes" { node := cfg.Node
node.Isdualstack = true wcclient, err := getGrpcClient(cfg)
} else { if err != nil {
node.Isdualstack = false return nil, err
} }
if nodecfg.IsIngressGateway == "yes" { // == run client action ==
node.Isingressgateway= true var header metadata.MD
} else { ctx, err := auth.SetJWT(wcclient, network)
node.Isingressgateway = false nodeData, err := json.Marshal(&node)
if err != nil {
return nil, err
} }
return node 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 { func RemoveNetwork(network string) error {
//need to implement checkin on server side //need to implement checkin on server side
@@ -90,9 +97,7 @@ func RemoveNetwork(network string) error {
//return err //return err
} else { } else {
wcclient = nodepb.NewNodeServiceClient(conn) wcclient = nodepb.NewNodeServiceClient(conn)
ctx, err := auth.SetJWT(wcclient, network)
ctx := context.Background()
ctx, err = auth.SetJWT(wcclient, network)
if err != nil { if err != nil {
//return err //return err
log.Printf("Failed to authenticate: %v", err) log.Printf("Failed to authenticate: %v", err)
@@ -102,9 +107,9 @@ func RemoveNetwork(network string) error {
_, err = wcclient.DeleteNode( _, err = wcclient.DeleteNode(
ctx, ctx,
&nodepb.DeleteNodeReq{ &nodepb.Object{
Macaddress: node.MacAddress, Data: node.MacAddress + "###" + node.Network,
NetworkName: node.Network, Type: nodepb.STRING_TYPE,
}, },
grpc.Header(&header), grpc.Header(&header),
) )
@@ -137,14 +142,13 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
log.Fatalf("Issue retrieving config for network: "+network+". Please investigate: %v", err) log.Fatalf("Issue retrieving config for network: "+network+". Please investigate: %v", err)
} }
nodecfg := cfg.Node nodecfg := cfg.Node
keepalive := nodecfg.KeepAlive keepalive := nodecfg.PersistentKeepalive
keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s") keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s") keepaliveserver, err := time.ParseDuration(strconv.FormatInt(int64(5), 10) + "s")
if err != nil { if err != nil {
log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err) log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)
} }
requestOpts := grpc.WithInsecure() requestOpts := grpc.WithInsecure()
if cfg.Server.GRPCSSL == "on" { if cfg.Server.GRPCSSL == "on" {
h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}}) h2creds := credentials.NewTLS(&tls.Config{NextProtos: []string{"h2"}})
@@ -158,9 +162,9 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
// Instantiate the BlogServiceClient with our client connection to the server // Instantiate the BlogServiceClient with our client connection to the server
wcclient = nodepb.NewNodeServiceClient(conn) wcclient = nodepb.NewNodeServiceClient(conn)
req := &nodepb.GetPeersReq{ req := &nodepb.Object{
Macaddress: macaddress, Data: macaddress + "###" + network,
Network: network, Type: nodepb.STRING_TYPE,
} }
ctx := context.Background() ctx := context.Background()
ctx, err = auth.SetJWT(wcclient, network) ctx, err = auth.SetJWT(wcclient, network)
@@ -170,41 +174,30 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
} }
var header metadata.MD var header metadata.MD
stream, err := wcclient.GetPeers(ctx, req, grpc.Header(&header)) response, err := wcclient.GetPeers(ctx, req, grpc.Header(&header))
if err != nil { if err != nil {
log.Println("Error retrieving peers") log.Println("Error retrieving peers")
log.Println(err) log.Println(err)
return nil, hasGateway, gateways, err return nil, hasGateway, gateways, err
} }
for { var nodes []models.Node
res, err := stream.Recv() if err := json.Unmarshal([]byte(response.GetData()), &nodes); err != nil {
// If end of stream, break the loop log.Println("Error unmarshaling data for peers")
return nil, hasGateway, gateways, err
if err == io.EOF {
break
} }
// if err, return an error for _, node := range nodes {
if err != nil { pubkey, err := wgtypes.ParseKey(node.PublicKey)
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 { if err != nil {
fmt.Println("error parsing key") fmt.Println("error parsing key")
return peers, hasGateway, gateways, err return peers, hasGateway, gateways, err
} }
if nodecfg.PublicKey == res.Peers.Publickey { if nodecfg.PublicKey == node.PublicKey {
continue continue
} }
if nodecfg.Endpoint == res.Peers.Endpoint { if nodecfg.Endpoint == node.Endpoint {
if nodecfg.LocalAddress != res.Peers.Localaddress && res.Peers.Localaddress != "" { if nodecfg.LocalAddress != node.LocalAddress && node.LocalAddress != "" {
res.Peers.Endpoint = res.Peers.Localaddress node.Endpoint = node.LocalAddress
} else { } else {
continue continue
} }
@@ -212,14 +205,14 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
var peer wgtypes.PeerConfig var peer wgtypes.PeerConfig
var peeraddr = net.IPNet{ var peeraddr = net.IPNet{
IP: net.ParseIP(res.Peers.Address), IP: net.ParseIP(node.Address),
Mask: net.CIDRMask(32, 32), Mask: net.CIDRMask(32, 32),
} }
var allowedips []net.IPNet var allowedips []net.IPNet
allowedips = append(allowedips, peeraddr) allowedips = append(allowedips, peeraddr)
if res.Peers.Isegressgateway { if node.IsEgressGateway == "yes" {
hasGateway = true hasGateway = true
ranges := strings.Split(res.Peers.Egressgatewayranges, ",") ranges := node.EgressGatewayRanges
for _, iprange := range ranges { for _, iprange := range ranges {
gateways = append(gateways, iprange) gateways = append(gateways, iprange)
_, ipnet, err := net.ParseCIDR(iprange) _, ipnet, err := net.ParseCIDR(iprange)
@@ -233,9 +226,9 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
} }
} }
} }
if res.Peers.Address6 != "" && dualstack { if node.Address6 != "" && dualstack {
var addr6 = net.IPNet{ var addr6 = net.IPNet{
IP: net.ParseIP(res.Peers.Address6), IP: net.ParseIP(node.Address6),
Mask: net.CIDRMask(128, 128), Mask: net.CIDRMask(128, 128),
} }
allowedips = append(allowedips, addr6) allowedips = append(allowedips, addr6)
@@ -252,8 +245,8 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
PublicKey: pubkey, PublicKey: pubkey,
PersistentKeepaliveInterval: &keepalivedur, PersistentKeepaliveInterval: &keepalivedur,
Endpoint: &net.UDPAddr{ Endpoint: &net.UDPAddr{
IP: net.ParseIP(res.Peers.Endpoint), IP: net.ParseIP(node.Endpoint),
Port: int(res.Peers.Listenport), Port: int(node.ListenPort),
}, },
ReplaceAllowedIPs: true, ReplaceAllowedIPs: true,
AllowedIPs: allowedips, AllowedIPs: allowedips,
@@ -262,8 +255,8 @@ func GetPeers(macaddress string, network string, server string, dualstack bool,
peer = wgtypes.PeerConfig{ peer = wgtypes.PeerConfig{
PublicKey: pubkey, PublicKey: pubkey,
Endpoint: &net.UDPAddr{ Endpoint: &net.UDPAddr{
IP: net.ParseIP(res.Peers.Endpoint), IP: net.ParseIP(node.Endpoint),
Port: int(res.Peers.Listenport), Port: int(node.ListenPort),
}, },
ReplaceAllowedIPs: true, ReplaceAllowedIPs: true,
AllowedIPs: allowedips, AllowedIPs: allowedips,
@@ -301,9 +294,9 @@ func GetExtPeers(macaddress string, network string, server string, dualstack boo
// Instantiate the BlogServiceClient with our client connection to the server // Instantiate the BlogServiceClient with our client connection to the server
wcclient = nodepb.NewNodeServiceClient(conn) wcclient = nodepb.NewNodeServiceClient(conn)
req := &nodepb.GetExtPeersReq{ req := &nodepb.Object{
Macaddress: macaddress, Data: macaddress + "###" + network,
Network: network, Type: nodepb.STRING_TYPE,
} }
ctx := context.Background() ctx := context.Background()
ctx, err = auth.SetJWT(wcclient, network) ctx, err = auth.SetJWT(wcclient, network)
@@ -313,50 +306,38 @@ func GetExtPeers(macaddress string, network string, server string, dualstack boo
} }
var header metadata.MD var header metadata.MD
stream, err := wcclient.GetExtPeers(ctx, req, grpc.Header(&header)) responseObject, err := wcclient.GetExtPeers(ctx, req, grpc.Header(&header))
if err != nil { if err != nil {
fmt.Println("Error retrieving peers") fmt.Println("Error retrieving peers")
fmt.Println(err) fmt.Println(err)
return nil, err return nil, err
} }
for { var extPeers []models.Node
res, err := stream.Recv() if err = json.Unmarshal([]byte(responseObject.Data), extPeers); err != nil {
// If end of stream, break the loop return nil, err
if err == io.EOF {
break
} }
// if err, return an error for _, extPeer := range extPeers {
if err != nil { pubkey, err := wgtypes.ParseKey(extPeer.PublicKey)
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 { if err != nil {
fmt.Println("error parsing key") fmt.Println("error parsing key")
return peers, err return peers, err
} }
if nodecfg.PublicKey == res.Extpeers.Publickey { if nodecfg.PublicKey == extPeer.PublicKey {
continue continue
} }
var peer wgtypes.PeerConfig var peer wgtypes.PeerConfig
var peeraddr = net.IPNet{ var peeraddr = net.IPNet{
IP: net.ParseIP(res.Extpeers.Address), IP: net.ParseIP(extPeer.Address),
Mask: net.CIDRMask(32, 32), Mask: net.CIDRMask(32, 32),
} }
var allowedips []net.IPNet var allowedips []net.IPNet
allowedips = append(allowedips, peeraddr) allowedips = append(allowedips, peeraddr)
if res.Extpeers.Address6 != "" && dualstack { if extPeer.Address6 != "" && dualstack {
var addr6 = net.IPNet{ var addr6 = net.IPNet{
IP: net.ParseIP(res.Extpeers.Address6), IP: net.ParseIP(extPeer.Address6),
Mask: net.CIDRMask(128, 128), Mask: net.CIDRMask(128, 128),
} }
allowedips = append(allowedips, addr6) allowedips = append(allowedips, addr6)

View File

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