optimize further

This commit is contained in:
0xdcarns 2021-12-10 21:09:42 -05:00
parent e45a485bce
commit 548997f9ef
18 changed files with 61 additions and 100 deletions

View file

@ -103,7 +103,7 @@ func grpcAuthorize(ctx context.Context) error {
return nil
}
//Node authenticates using its password and retrieves a JWT for authorization.
// Login - node authenticates using its password and retrieves a JWT for authorization.
func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
//out := new(LoginResponse)
@ -117,15 +117,15 @@ func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.Object) (*nod
password := reqNode.Password
var result models.NodeAuth
err := errors.New("Generic server error.")
var err error
// err := errors.New("generic server error")
if macaddress == "" {
//TODO: Set Error response
err = errors.New("Missing Mac Address.")
err = errors.New("missing mac address")
return nil, err
} else if password == "" {
err = errors.New("Missing Password.")
err = errors.New("missing password")
return nil, err
} else {
//Search DB for node with Mac Address. Ignore pending nodes (they should not be able to authenticate with API until approved).
@ -156,7 +156,7 @@ func (s *NodeServiceServer) Login(ctx context.Context, req *nodepb.Object) (*nod
return nil, err
}
if tokenString == "" {
err = errors.New("Something went wrong. Could not retrieve token.")
err = errors.New("something went wrong, could not retrieve token")
return nil, err
}

View file

@ -55,7 +55,7 @@ func TestGetNodeDNS(t *testing.T) {
})
t.Run("MultipleNodes", func(t *testing.T) {
createnode := &models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.100.100.3", MacAddress: "01:02:03:04:05:07", Password: "password", Network: "skynet"}
_, err := logic.CreateNode(createnode, "skynet")
err := logic.CreateNode(createnode)
assert.Nil(t, err)
dns, err := logic.GetNodeDNS("skynet")
assert.Nil(t, err)

View file

@ -232,8 +232,7 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
err = logic.CreateExtClient(extclient)
err = logic.CreateExtClient(&extclient)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
@ -264,7 +263,7 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
newclient, err := logic.UpdateExtClient(newExtClient.ClientID, params["network"], oldExtClient)
newclient, err := logic.UpdateExtClient(newExtClient.ClientID, params["network"], &oldExtClient)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return

View file

@ -350,8 +350,3 @@ func createNet() {
logic.CreateNetwork(network)
}
}
func getNet() models.Network {
network, _ := logic.GetNetwork("skynet")
return network
}

View file

@ -35,20 +35,17 @@ func nodeHandlers(r *mux.Router) {
}
//Node authenticates using its password and retrieves a JWT for authorization.
func authenticate(response http.ResponseWriter, request *http.Request) {
var params = mux.Vars(request)
networkname := params["network"]
//Auth request consists of Mac Address and Password (from node that is authorizing
//in case of Master, auth is ignored and mac is set to "mastermac"
var authRequest models.AuthParams
var result models.Node
var errorResponse = models.ErrorResponse{
Code: http.StatusInternalServerError, Message: "W1R3: It's not you it's me.",
}
//Get password fnd mac rom request
decoder := json.NewDecoder(request.Body)
decoderErr := decoder.Decode(&authRequest)
defer request.Body.Close()
@ -70,7 +67,6 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
return
} else {
//Search DB for node with Mac Address. Ignore pending nodes (they should not be able to authenticate with API until approved).
collection, err := database.FetchRecords(database.NODES_TABLE_NAME)
if err != nil {
errorResponse.Code = http.StatusBadRequest
@ -94,9 +90,6 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
return
}
//compare password from request to stored password in database
//might be able to have a common hash (certificates?) and compare those so that a password isn't passed in in plain text...
//TODO: Consider a way of hashing the password client side before sending, or using certificates
err = bcrypt.CompareHashAndPassword([]byte(result.Password), []byte(authRequest.Password))
if err != nil {
errorResponse.Code = http.StatusBadRequest
@ -104,7 +97,6 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
returnErrorResponse(response, request, errorResponse)
return
} else {
//Create a new JWT for the node
tokenString, _ := logic.CreateJWT(authRequest.MacAddress, result.Network)
if tokenString == "" {
@ -122,7 +114,6 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
MacAddress: authRequest.MacAddress,
},
}
//Send back the JWT
successJSONResponse, jsonError := json.Marshal(successResponse)
if jsonError != nil {
@ -185,10 +176,6 @@ func authorize(networkCheck bool, authNetwork string, next http.Handler) http.Ha
return
}
//This checks if
//A: the token is the master password
//B: the token corresponds to a mac address, and if so, which one
//TODO: There's probably a better way of dealing with the "master token"/master password. Plz Help.
var isAuthorized = false
var macaddress = ""
username, networks, isadmin, errN := logic.VerifyUserToken(authToken)
@ -379,10 +366,10 @@ func createNode(w http.ResponseWriter, r *http.Request) {
return
}
var node = &models.Node{}
var node = models.Node{}
//get node from body of request
err = json.NewDecoder(r.Body).Decode(node)
err = json.NewDecoder(r.Body).Decode(&node)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
@ -390,14 +377,12 @@ func createNode(w http.ResponseWriter, r *http.Request) {
node.Network = networkName
network, err := logic.GetNetworkByNode(node)
network, err := logic.GetNetworkByNode(&node)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
}
//Check to see if key is valid
//TODO: Triple inefficient!!! This is the third call to the DB we make for networks
validKey := logic.IsKeyValid(networkName, node.AccessKey)
if !validKey {
@ -414,7 +399,7 @@ func createNode(w http.ResponseWriter, r *http.Request) {
}
}
node, err = logic.CreateNode(node, networkName)
err = logic.CreateNode(&node)
if err != nil {
returnErrorResponse(w, r, formatError(err, "internal"))
return
@ -476,6 +461,7 @@ func deleteEgressGateway(w http.ResponseWriter, r *http.Request) {
}
// == INGRESS ==
func createIngressGateway(w http.ResponseWriter, r *http.Request) {
var params = mux.Vars(r)
w.Header().Set("Content-Type", "application/json")
@ -562,8 +548,6 @@ func updateNode(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(newNode)
}
//Delete a node
//Pretty straightforward
func deleteNode(w http.ResponseWriter, r *http.Request) {
// Set header
w.Header().Set("Content-Type", "application/json")

View file

@ -49,49 +49,42 @@ func (s *NodeServiceServer) ReadNode(ctx context.Context, req *nodepb.Object) (*
// NodeServiceServer.CreateNode - creates a node and responds over gRPC
func (s *NodeServiceServer) CreateNode(ctx context.Context, req *nodepb.Object) (*nodepb.Object, error) {
// Get the protobuf node type from the protobuf request type
// Essentially doing req.Node to access the struct with a nil check
var node = &models.Node{}
var node = models.Node{}
var err error
data := req.GetData()
if err := json.Unmarshal([]byte(data), node); err != nil {
if err := json.Unmarshal([]byte(data), &node); err != nil {
return nil, err
}
//Check to see if key is valid
//TODO: Triple inefficient!!! This is the third call to the DB we make for networks
validKey := logic.IsKeyValid(node.Network, node.AccessKey)
network, err := logic.GetParentNetwork(node.Network)
node.NetworkSettings, err = logic.GetNetworkSettings(node.Network)
if err != nil {
return nil, err
}
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.
if network.AllowManualSignUp == "yes" {
if node.NetworkSettings.AllowManualSignUp == "yes" {
node.IsPending = "yes"
} else {
return nil, errors.New("invalid key, and network does not allow no-key signups")
}
}
node, err = logic.CreateNode(node, node.Network)
if err != nil {
return nil, err
}
node.NetworkSettings, err = logic.GetNetworkSettings(node.Network)
err = logic.CreateNode(&node)
if err != nil {
return nil, err
}
nodeData, errN := json.Marshal(&node)
if errN != nil {
return nil, err
}
// return the node in a CreateNodeRes type
response := &nodepb.Object{
Data: string(nodeData),
Type: nodepb.NODE_TYPE,
}
err = logic.SetNetworkNodesLastModified(node.Network)
if err != nil {
return nil, err

View file

@ -152,7 +152,7 @@ func deleteAllNodes() {
}
func createTestNode() *models.Node {
createnode := &models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Name: "testnode", Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"}
node, _ := logic.CreateNode(createnode, "skynet")
return node
createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Name: "testnode", Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"}
logic.CreateNode(&createnode)
return &createnode
}

View file

@ -60,10 +60,7 @@ func securityCheckServer(adminonly bool, next http.Handler) http.HandlerFunc {
//Consider a more secure way of setting master key
func authenticateMasterServer(tokenString string) bool {
if tokenString == servercfg.GetMasterKey() {
return true
}
return false
return tokenString == servercfg.GetMasterKey()
}
func removeNetwork(w http.ResponseWriter, r *http.Request) {

View file

@ -196,6 +196,7 @@ func IsKeyValid(networkname string, keyvalue string) bool {
return isvalid
}
// RemoveKeySensitiveInfo - remove sensitive key info
func RemoveKeySensitiveInfo(keys []models.AccessKey) []models.AccessKey {
var returnKeys []models.AccessKey
for _, key := range keys {

View file

@ -114,7 +114,7 @@ func GetExtClient(clientid string, network string) (models.ExtClient, error) {
}
// CreateExtClient - creates an extclient
func CreateExtClient(extclient models.ExtClient) error {
func CreateExtClient(extclient *models.ExtClient) error {
if extclient.PrivateKey == "" {
privateKey, err := wgtypes.GeneratePrivateKey()
if err != nil {
@ -155,7 +155,7 @@ func CreateExtClient(extclient models.ExtClient) error {
}
// UpdateExtClient - only supports name changes right now
func UpdateExtClient(newclientid string, network string, client models.ExtClient) (models.ExtClient, error) {
func UpdateExtClient(newclientid string, network string, client *models.ExtClient) (*models.ExtClient, error) {
err := DeleteExtClient(network, client.ClientID)
if err != nil {

View file

@ -155,15 +155,15 @@ func GetParentNetwork(networkname string) (models.Network, error) {
}
// GetParentNetwork - get parent network
func GetNetworkSettings(networkname string) (*models.Network, error) {
func GetNetworkSettings(networkname string) (models.Network, error) {
var network *models.Network
var network models.Network
networkData, err := database.FetchRecord(database.NETWORKS_TABLE_NAME, networkname)
if err != nil {
return network, err
}
if err = json.Unmarshal([]byte(networkData), network); err != nil {
return &models.Network{}, err
if err = json.Unmarshal([]byte(networkData), &network); err != nil {
return models.Network{}, err
}
network.AccessKeys = []models.AccessKey{}
return network, nil

View file

@ -79,7 +79,7 @@ func ServerJoin(network string, serverID string, privateKey string) error {
node.Network = network
logger.Log(2, "adding a server instance on network", node.Network)
node, err = CreateNode(node, network)
err = CreateNode(node)
if err != nil {
return err
}
@ -283,7 +283,7 @@ func GetServerPeers(serverNode *models.Node) ([]wgtypes.PeerConfig, bool, []stri
// handle egress gateway peers
if node.IsEgressGateway == "yes" {
hasGateway = true
ranges := node.EgressGatewayRanges[:]
ranges := node.EgressGatewayRanges
for _, iprange := range ranges { // go through each cidr for egress gateway
_, ipnet, err := net.ParseCIDR(iprange) // confirming it's valid cidr
if err != nil {

View file

@ -76,18 +76,15 @@ func DeleteNode(node *models.Node, exterminate bool) error {
}
// CreateNode - creates a node in database
func CreateNode(node *models.Node, networkName string) (*models.Node, error) {
func CreateNode(node *models.Node) error {
//encrypt that password so we never see it
hash, err := bcrypt.GenerateFromPassword([]byte(node.Password), 5)
if err != nil {
return node, err
return err
}
//set password to encrypted password
node.Password = string(hash)
node.Network = networkName
if node.Name == models.NODE_SERVER_NAME {
node.IsServer = "yes"
}
@ -99,35 +96,35 @@ func CreateNode(node *models.Node, networkName string) (*models.Node, error) {
}
}
SetNodeDefaults(node)
node.Address, err = UniqueAddress(networkName)
node.Address, err = UniqueAddress(node.Network)
if err != nil {
return node, err
return err
}
node.Address6, err = UniqueAddress6(networkName)
node.Address6, err = UniqueAddress6(node.Network)
if err != nil {
return node, err
return err
}
//Create a JWT for the node
tokenString, _ := CreateJWT(node.MacAddress, networkName)
tokenString, _ := CreateJWT(node.MacAddress, node.Network)
if tokenString == "" {
//returnErrorResponse(w, r, errorResponse)
return node, err
return err
}
err = ValidateNode(node, false)
if err != nil {
return node, err
return err
}
key, err := GetRecordKey(node.MacAddress, node.Network)
if err != nil {
return node, err
return err
}
nodebytes, err := json.Marshal(&node)
if err != nil {
return node, err
return err
}
err = database.Insert(key, string(nodebytes), database.NODES_TABLE_NAME)
if err != nil {
return node, err
return err
}
if node.IsPending != "yes" {
DecrimentKey(node.Network, node.AccessKey)
@ -136,7 +133,7 @@ func CreateNode(node *models.Node, networkName string) (*models.Node, error) {
if servercfg.IsDNSMode() {
err = SetDNS()
}
return node, err
return err
}
// SetNetworkNodesLastModified - sets the network nodes last modified

View file

@ -300,6 +300,7 @@ func setWGConfig(node *models.Node, peerupdate bool) error {
err = initWireguard(node, privkey, peers[:], hasGateway, gateways[:])
logger.Log(3, "finished setting wg config on server", node.Name)
}
peers = nil
return err
}

12
main.go
View file

@ -2,7 +2,6 @@ package main
import (
"fmt"
"log"
"net"
"os"
"os/signal"
@ -38,8 +37,7 @@ func initialize() { // Client Mode Prereq Check
var err error
if err = database.InitializeDatabase(); err != nil {
logger.Log(0, "Error connecting to database")
log.Fatal(err)
logger.FatalLog("Error connecting to database")
}
logger.Log(0, "database successfully connected")
@ -134,16 +132,12 @@ func runGRPC(wg *sync.WaitGroup) {
defer wg.Done()
// Configure 'log' package to give file name and line number on eg. log.Fatal
// Pipe flags to one another (log.LstdFLags = log.Ldate | log.Ltime)
log.SetFlags(log.LstdFlags | log.Lshortfile)
grpcport := servercfg.GetGRPCPort()
listener, err := net.Listen("tcp", ":"+grpcport)
// Handle errors if any
if err != nil {
log.Fatalf("[netmaker] Unable to listen on port "+grpcport+", error: %v", err)
logger.FatalLog("[netmaker] Unable to listen on port", grpcport, ": error:", err.Error())
}
s := grpc.NewServer(
@ -158,7 +152,7 @@ func runGRPC(wg *sync.WaitGroup) {
// Start the server in a child routine
go func() {
if err := s.Serve(listener); err != nil {
log.Fatalf("Failed to serve: %v", err)
logger.FatalLog("Failed to serve:", err.Error())
}
}()
logger.Log(0, "Agent Server successfully started on port ", grpcport, "(gRPC)")

View file

@ -31,7 +31,7 @@ type Node struct {
Address6 string `json:"address6" bson:"address6" yaml:"address6" validate:"omitempty,ipv6"`
LocalAddress string `json:"localaddress" bson:"localaddress" yaml:"localaddress" validate:"omitempty,ip"`
Name string `json:"name" bson:"name" yaml:"name" validate:"omitempty,max=62,in_charset"`
NetworkSettings *Network `json:"networksettings" bson:"networksettings" yaml:"networksettings" validate:"-"`
NetworkSettings Network `json:"networksettings" bson:"networksettings" yaml:"networksettings" validate:"-"`
ListenPort int32 `json:"listenport" bson:"listenport" yaml:"listenport" validate:"omitempty,numeric,min=1024,max=65535"`
PublicKey string `json:"publickey" bson:"publickey" yaml:"publickey" validate:"required,base64"`
Endpoint string `json:"endpoint" bson:"endpoint" yaml:"endpoint" validate:"required,ip"`
@ -239,7 +239,7 @@ func (newNode *Node) Fill(currentNode *Node) {
newNode.PostDown = currentNode.PostDown
}
if newNode.AllowedIPs == nil {
newNode.AllowedIPs = currentNode.AllowedIPs[:]
newNode.AllowedIPs = currentNode.AllowedIPs
}
if newNode.PersistentKeepalive == 0 {
newNode.PersistentKeepalive = currentNode.PersistentKeepalive
@ -298,10 +298,10 @@ func (newNode *Node) Fill(currentNode *Node) {
newNode.IsIngressGateway = currentNode.IsIngressGateway
}
if newNode.EgressGatewayRanges == nil {
newNode.EgressGatewayRanges = currentNode.EgressGatewayRanges[:]
newNode.EgressGatewayRanges = currentNode.EgressGatewayRanges
}
if newNode.IngressGatewayRange == "" {
newNode.IngressGatewayRange = currentNode.IngressGatewayRange[:]
newNode.IngressGatewayRange = currentNode.IngressGatewayRange
}
if newNode.IsStatic == "" {
newNode.IsStatic = currentNode.IsStatic
@ -343,7 +343,7 @@ func (newNode *Node) Fill(currentNode *Node) {
newNode.OS = currentNode.OS
}
if newNode.RelayAddrs == nil {
newNode.RelayAddrs = currentNode.RelayAddrs[:]
newNode.RelayAddrs = currentNode.RelayAddrs
}
if newNode.IsRelay == "" {
newNode.IsRelay = currentNode.IsRelay

View file

@ -85,7 +85,7 @@ type AccessKey struct {
Name string `json:"name" bson:"name" validate:"omitempty,max=20"`
Value string `json:"value" bson:"value" validate:"omitempty,alphanum,max=16"`
AccessString string `json:"accessstring" bson:"accessstring"`
Uses int `json:"uses" bson:"uses"`
Uses int `json:"uses" bson:"uses" validate:"numeric,min=0"`
}
// DisplayKey - what is displayed for key

View file

@ -122,7 +122,7 @@ func ModConfig(node *models.Node) error {
}
modconfig.Node = (*node)
modconfig.NetworkSettings = (*node.NetworkSettings)
modconfig.NetworkSettings = node.NetworkSettings
err = Write(&modconfig, network)
return err
}