netmaker/controllers/nodeGrpcController.go

434 lines
15 KiB
Go
Raw Normal View History

2021-03-26 00:17:52 +08:00
package controller
import (
2021-05-06 23:57:32 +08:00
"context"
2021-03-26 00:17:52 +08:00
"fmt"
2021-07-22 06:55:19 +08:00
2021-05-06 23:57:32 +08:00
"github.com/gravitl/netmaker/functions"
2021-03-26 00:17:52 +08:00
nodepb "github.com/gravitl/netmaker/grpc"
"github.com/gravitl/netmaker/models"
2021-05-06 19:41:11 +08:00
"github.com/gravitl/netmaker/servercfg"
2021-03-26 00:17:52 +08:00
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type NodeServiceServer struct {
nodepb.UnimplementedNodeServiceServer
}
2021-05-06 23:57:32 +08:00
2021-03-26 00:17:52 +08:00
func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.ReadNodeReq) (*nodepb.ReadNodeRes, error) {
// convert string id (from proto) to mongoDB ObjectId
macaddress := req.GetMacaddress()
2021-05-06 23:57:32 +08:00
networkName := req.GetNetwork()
network, _ := functions.GetParentNetwork(networkName)
2021-03-26 00:17:52 +08:00
node, err := GetNode(macaddress, networkName)
2021-03-26 00:17:52 +08:00
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, fmt.Sprintf("Something went wrong: %v", err))
}
/*
2021-05-06 23:57:32 +08:00
if node == nil {
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not find node with Mac Address %s: %v", req.GetMacaddress(), err))
}
2021-03-26 00:17:52 +08:00
*/
// Cast to ReadNodeRes type
2021-03-26 00:17:52 +08:00
response := &nodepb.ReadNodeRes{
Node: &nodepb.Node{
2021-07-22 06:55:19 +08:00
Macaddress: node.MacAddress,
Name: node.Name,
Address: node.Address,
Address6: node.Address6,
Endpoint: node.Endpoint,
Password: node.Password,
Nodenetwork: node.Network,
Interface: node.Interface,
Localaddress: node.LocalAddress,
Postdown: node.PostDown,
Postup: node.PostUp,
Checkininterval: node.CheckInInterval,
Dnsoff: !servercfg.IsDNSMode(),
Ispending: node.IsPending,
Isingressgateway: node.IsIngressGateway,
Ingressgatewayrange: node.IngressGatewayRange,
Publickey: node.PublicKey,
Listenport: node.ListenPort,
Keepalive: node.PersistentKeepalive,
2021-07-24 06:24:34 +08:00
Islocal: network.IsLocal == "yes",
Isdualstack: network.IsDualStack == "yes",
2021-07-22 06:55:19 +08:00
Localrange: network.LocalRange,
2021-03-26 00:17:52 +08:00
},
}
return response, nil
}
2021-07-22 06:55:19 +08:00
2021-06-02 06:40:04 +08:00
/*
2021-05-26 00:48:04 +08:00
func (s *NodeServiceServer) GetConn(ctx context.Context, data *nodepb.Client) (*nodepb.Client, error) {
// Get the protobuf node type from the protobuf request type
// Essentially doing req.Node to access the struct with a nil check
// Now we have to convert this into a NodeItem type to convert into BSON
clientreq := models.IntClient{
2021-05-26 00:48:04 +08:00
// ID: primitive.NilObjectID,
Address: data.GetAddress(),
Address6: data.GetAddress6(),
AccessKey: data.GetAccesskey(),
PublicKey: data.GetPublickey(),
PrivateKey: data.GetPrivatekey(),
ServerPort: data.GetServerport(),
ServerKey: data.GetServerkey(),
2021-06-01 23:14:34 +08:00
ServerWGEndpoint: data.GetServerwgendpoint(),
2021-05-26 00:48:04 +08:00
}
//Check to see if key is valid
//TODO: Triple inefficient!!! This is the third call to the DB we make for networks
if servercfg.IsRegisterKeyRequired() {
validKey := functions.IsKeyValidGlobal(clientreq.AccessKey)
if !validKey {
return nil, status.Errorf(
codes.Internal,
fmt.Sprintf("Invalid key, and server does not allow no-key signups"),
)
}
}
client, err := RegisterIntClient(clientreq)
2021-05-26 00:48:04 +08:00
if err != nil {
// return internal gRPC error to be handled later
return nil, status.Errorf(
codes.Internal,
fmt.Sprintf("Internal error: %v", err),
)
}
// return the node in a CreateNodeRes type
response := &nodepb.Client{
Privatekey: client.PrivateKey,
Publickey: client.PublicKey,
Accesskey: client.AccessKey,
Address: client.Address,
Address6: client.Address6,
2021-06-01 23:14:34 +08:00
Serverwgendpoint: client.ServerWGEndpoint,
2021-05-26 00:48:04 +08:00
Serverport: client.ServerPort,
Serverkey: client.ServerKey,
}
return response, nil
}
2021-06-02 06:40:04 +08:00
*/
2021-03-26 00:17:52 +08:00
func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.CreateNodeReq) (*nodepb.CreateNodeRes, error) {
// Get the protobuf node type from the protobuf request type
// Essentially doing req.Node to access the struct with a nil check
data := req.GetNode()
// Now we have to convert this into a NodeItem type to convert into BSON
node := models.Node{
// ID: primitive.NilObjectID,
2021-05-06 23:57:32 +08:00
MacAddress: data.GetMacaddress(),
LocalAddress: data.GetLocaladdress(),
Name: data.GetName(),
Address: data.GetAddress(),
Address6: data.GetAddress6(),
2021-05-06 23:57:32 +08:00
AccessKey: data.GetAccesskey(),
Endpoint: data.GetEndpoint(),
PersistentKeepalive: data.GetKeepalive(),
Password: data.GetPassword(),
Interface: data.GetInterface(),
Network: data.GetNodenetwork(),
IsPending: data.GetIspending(),
PublicKey: data.GetPublickey(),
ListenPort: data.GetListenport(),
2021-03-26 00:17:52 +08:00
}
2021-05-06 23:57:32 +08:00
err := ValidateNodeCreate(node.Network, node)
2021-03-26 00:17:52 +08:00
2021-05-06 23:57:32 +08:00
if err != nil {
// return internal gRPC error to be handled later
return nil, err
}
2021-03-26 00:17:52 +08:00
2021-05-06 23:57:32 +08:00
//Check to see if key is valid
//TODO: Triple inefficient!!! This is the third call to the DB we make for networks
validKey := functions.IsKeyValid(node.Network, node.AccessKey)
network, err := functions.GetParentNetwork(node.Network)
if err != nil {
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not find network: %v", err))
}
2021-05-06 23:57:32 +08:00
if !validKey {
//Check to see if network will allow manual sign up
//may want to switch this up with the valid key check and avoid a DB call that way.
2021-07-24 06:24:34 +08:00
if network.AllowManualSignUp == "yes" {
2021-05-06 23:57:32 +08:00
node.IsPending = true
} else {
return nil, status.Errorf(
codes.Internal,
fmt.Sprintf("Invalid key, and network does not allow no-key signups"),
2021-03-26 00:17:52 +08:00
)
2021-05-06 23:57:32 +08:00
}
}
2021-03-26 00:17:52 +08:00
node, err = CreateNode(node, node.Network)
2021-03-26 00:17:52 +08:00
if err != nil {
// return internal gRPC error to be handled later
return nil, status.Errorf(
codes.Internal,
fmt.Sprintf("Internal error: %v", err),
)
}
2021-03-26 00:17:52 +08:00
// return the node in a CreateNodeRes type
response := &nodepb.CreateNodeRes{
Node: &nodepb.Node{
2021-05-06 23:57:32 +08:00
Macaddress: node.MacAddress,
Localaddress: node.LocalAddress,
Name: node.Name,
Address: node.Address,
Address6: node.Address6,
2021-05-06 23:57:32 +08:00
Endpoint: node.Endpoint,
Password: node.Password,
Interface: node.Interface,
Nodenetwork: node.Network,
Dnsoff: !servercfg.IsDNSMode(),
2021-05-06 23:57:32 +08:00
Ispending: node.IsPending,
Publickey: node.PublicKey,
Listenport: node.ListenPort,
Keepalive: node.PersistentKeepalive,
2021-07-24 06:24:34 +08:00
Islocal: network.IsLocal == "yes",
Isdualstack: network.IsDualStack == "yes",
2021-05-06 23:57:32 +08:00
Localrange: network.LocalRange,
2021-03-26 00:17:52 +08:00
},
}
2021-05-06 23:57:32 +08:00
err = SetNetworkNodesLastModified(node.Network)
if err != nil {
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not update network last modified date: %v", err))
}
2021-03-26 00:17:52 +08:00
return response, nil
}
func (s *NodeServiceServer) CheckIn(ctx context.Context, req *nodepb.CheckInReq) (*nodepb.CheckInRes, error) {
// Get the protobuf node type from the protobuf request type
2021-05-06 23:57:32 +08:00
// Essentially doing req.Node to access the struct with a nil check
2021-03-26 10:29:36 +08:00
data := req.GetNode()
2021-03-26 00:17:52 +08:00
//postchanges := req.GetPostchanges()
// Now we have to convert this into a NodeItem type to convert into BSON
2021-05-06 23:57:32 +08:00
node := models.Node{
// ID: primitive.NilObjectID,
MacAddress: data.GetMacaddress(),
Address: data.GetAddress(),
Address6: data.GetAddress6(),
2021-05-06 23:57:32 +08:00
Endpoint: data.GetEndpoint(),
Network: data.GetNodenetwork(),
Password: data.GetPassword(),
LocalAddress: data.GetLocaladdress(),
ListenPort: data.GetListenport(),
PersistentKeepalive: data.GetKeepalive(),
PublicKey: data.GetPublickey(),
}
2021-03-26 00:17:52 +08:00
checkinresponse, err := NodeCheckIn(node, node.Network)
2021-03-26 00:17:52 +08:00
2021-05-06 23:57:32 +08:00
if err != nil {
// return internal gRPC error to be handled later
2021-03-26 10:29:36 +08:00
if checkinresponse == (models.CheckInResponse{}) || !checkinresponse.IsPending {
2021-05-06 23:57:32 +08:00
return nil, status.Errorf(
codes.Internal,
fmt.Sprintf("Internal error: %v", err),
)
2021-03-26 10:29:36 +08:00
}
2021-05-06 23:57:32 +08:00
}
// 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
2021-03-26 00:17:52 +08:00
}
func (s *NodeServiceServer) UpdateNode(ctx context.Context, req *nodepb.UpdateNodeReq) (*nodepb.UpdateNodeRes, error) {
// Get the node data from the request
2021-05-06 23:57:32 +08:00
data := req.GetNode()
// Now we have to convert this into a NodeItem type to convert into BSON
2021-05-10 01:31:50 +08:00
nodechange := models.NodeUpdate{
2021-05-06 23:57:32 +08:00
// ID: primitive.NilObjectID,
MacAddress: data.GetMacaddress(),
Name: data.GetName(),
Address: data.GetAddress(),
Address6: data.GetAddress6(),
2021-05-06 23:57:32 +08:00
LocalAddress: data.GetLocaladdress(),
Endpoint: data.GetEndpoint(),
Password: data.GetPassword(),
PersistentKeepalive: data.GetKeepalive(),
Network: data.GetNodenetwork(),
Interface: data.GetInterface(),
PostDown: data.GetPostdown(),
PostUp: data.GetPostup(),
IsPending: data.GetIspending(),
PublicKey: data.GetPublickey(),
ListenPort: data.GetListenport(),
}
2021-03-26 00:17:52 +08:00
// Convert the Id string to a MongoDB ObjectId
macaddress := nodechange.MacAddress
networkName := nodechange.Network
2021-05-06 23:57:32 +08:00
network, _ := functions.GetParentNetwork(networkName)
2021-03-26 00:17:52 +08:00
2021-04-28 10:00:43 +08:00
err := ValidateNodeUpdate(networkName, nodechange)
2021-05-06 23:57:32 +08:00
if err != nil {
return nil, err
2021-03-26 00:17:52 +08:00
}
2021-05-06 23:57:32 +08:00
node, err := functions.GetNodeByMacAddress(networkName, macaddress)
if err != nil {
return nil, status.Errorf(
codes.NotFound,
fmt.Sprintf("Could not find node with supplied Mac Address: %v", err),
)
}
2021-03-26 00:17:52 +08:00
newnode, err := UpdateNode(nodechange, node)
if err != nil {
return nil, status.Errorf(
codes.NotFound,
fmt.Sprintf("Could not find node with supplied Mac Address: %v", err),
)
}
return &nodepb.UpdateNodeRes{
Node: &nodepb.Node{
2021-05-06 23:57:32 +08:00
Macaddress: newnode.MacAddress,
Localaddress: newnode.LocalAddress,
Name: newnode.Name,
Address: newnode.Address,
Address6: newnode.Address6,
2021-05-06 23:57:32 +08:00
Endpoint: newnode.Endpoint,
Password: newnode.Password,
Interface: newnode.Interface,
Postdown: newnode.PostDown,
Postup: newnode.PostUp,
Nodenetwork: newnode.Network,
Ispending: newnode.IsPending,
Publickey: newnode.PublicKey,
Dnsoff: !servercfg.IsDNSMode(),
2021-05-06 23:57:32 +08:00
Listenport: newnode.ListenPort,
Keepalive: newnode.PersistentKeepalive,
2021-07-24 06:24:34 +08:00
Islocal: network.IsLocal == "yes",
Isdualstack: network.IsDualStack == "yes",
2021-05-06 23:57:32 +08:00
Localrange: network.LocalRange,
2021-03-26 00:17:52 +08:00
},
}, nil
}
func (s *NodeServiceServer) DeleteNode(ctx context.Context, req *nodepb.DeleteNodeReq) (*nodepb.DeleteNodeRes, error) {
macaddress := req.GetMacaddress()
network := req.GetNetworkName()
2021-03-26 00:17:52 +08:00
2021-07-22 06:55:19 +08:00
err := DeleteNode(macaddress, network)
2021-03-26 00:17:52 +08:00
2021-07-22 06:55:19 +08:00
if err != nil {
2021-03-26 00:17:52 +08:00
fmt.Println("Error deleting node.")
fmt.Println(err)
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not find/delete node with mac address %s", macaddress))
}
fmt.Println("updating network last modified of " + req.GetNetworkName())
err = SetNetworkNodesLastModified(req.GetNetworkName())
2021-05-06 23:57:32 +08:00
if err != nil {
fmt.Println("Error updating Network")
2021-03-26 00:17:52 +08:00
fmt.Println(err)
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("Could not update network last modified date: %v", err))
2021-05-06 23:57:32 +08:00
}
2021-03-26 00:17:52 +08:00
return &nodepb.DeleteNodeRes{
Success: true,
}, nil
}
func (s *NodeServiceServer) GetPeers(req *nodepb.GetPeersReq, stream nodepb.NodeService_GetPeersServer) error {
// Initiate a NodeItem type to write decoded data to
//data := &models.PeersResponse{}
// collection.Find returns a cursor for our (empty) query
peers, err := GetPeersList(req.GetNetwork())
2021-03-26 00:17:52 +08:00
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
2021-05-06 23:57:32 +08:00
for i := 0; i < len(peers); i++ {
2021-03-26 00:17:52 +08:00
// If no error is found send node over stream
stream.Send(&nodepb.GetPeersRes{
Peers: &nodepb.PeersResponse{
2021-07-22 06:55:19 +08:00
Address: peers[i].Address,
Address6: peers[i].Address6,
Endpoint: peers[i].Endpoint,
2021-05-20 01:59:10 +08:00
Egressgatewayrange: peers[i].EgressGatewayRange,
Isegressgateway: peers[i].IsEgressGateway,
2021-07-22 06:55:19 +08:00
Publickey: peers[i].PublicKey,
Keepalive: peers[i].KeepAlive,
Listenport: peers[i].ListenPort,
Localaddress: peers[i].LocalAddress,
2021-03-26 00:17:52 +08:00
},
})
}
node, err := functions.GetNodeByMacAddress(req.GetNetwork(), req.GetMacaddress())
2021-05-06 23:57:32 +08:00
if err != nil {
return status.Errorf(codes.Internal, fmt.Sprintf("Could not get node: %v", err))
}
2021-03-26 00:17:52 +08:00
err = TimestampNode(node, false, true, false)
2021-05-06 23:57:32 +08:00
if err != nil {
return status.Errorf(codes.Internal, fmt.Sprintf("Internal error occurred: %v", err))
}
2021-03-26 00:17:52 +08:00
return nil
}
2021-05-20 01:59:10 +08:00
func (s *NodeServiceServer) GetExtPeers(req *nodepb.GetExtPeersReq, stream nodepb.NodeService_GetExtPeersServer) error {
2021-07-22 06:55:19 +08:00
// 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())
2021-05-20 01:59:10 +08:00
2021-07-22 06:55:19 +08:00
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++ {
2021-05-20 01:59:10 +08:00
2021-07-22 06:55:19 +08:00
// 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,
},
})
}
2021-05-20 01:59:10 +08:00
2021-07-22 06:55:19 +08:00
node, err := functions.GetNodeByMacAddress(req.GetNetwork(), req.GetMacaddress())
if err != nil {
return status.Errorf(codes.Internal, fmt.Sprintf("Could not get node: %v", err))
}
2021-05-20 01:59:10 +08:00
2021-07-22 06:55:19 +08:00
err = TimestampNode(node, false, true, false)
if err != nil {
return status.Errorf(codes.Internal, fmt.Sprintf("Internal error occurred: %v", err))
}
return nil
2021-05-20 01:59:10 +08:00
}