Browse Source

added basic api endpoints

0xdcarns 3 years ago
parent
commit
aefc8b090b

+ 1 - 2
controllers/config/dnsconfig/netmaker.hosts

@@ -1,2 +1 @@
-10.0.0.1         testnode.skynet
-10.0.0.2         myhost.skynet
+10.0.0.2         testnode.skynet myhost.skynet

+ 38 - 0
controllers/network.go

@@ -11,6 +11,7 @@ import (
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
+	"github.com/gravitl/netmaker/logic/acls"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/mq"
 	"github.com/gravitl/netmaker/mq"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
@@ -34,6 +35,9 @@ func networkHandlers(r *mux.Router) {
 	r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(false, http.HandlerFunc(createAccessKey))).Methods("POST")
 	r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(false, http.HandlerFunc(createAccessKey))).Methods("POST")
 	r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(false, http.HandlerFunc(getAccessKeys))).Methods("GET")
 	r.HandleFunc("/api/networks/{networkname}/keys", securityCheck(false, http.HandlerFunc(getAccessKeys))).Methods("GET")
 	r.HandleFunc("/api/networks/{networkname}/keys/{name}", securityCheck(false, http.HandlerFunc(deleteAccessKey))).Methods("DELETE")
 	r.HandleFunc("/api/networks/{networkname}/keys/{name}", securityCheck(false, http.HandlerFunc(deleteAccessKey))).Methods("DELETE")
+	r.HandleFunc("/api/networks/{networkname}/acls", securityCheck(true, http.HandlerFunc(updateNetworkACL))).Methods("PUT")
+	r.HandleFunc("/api/networks/{networkname}/acls", securityCheck(true, http.HandlerFunc(getNetworkACL))).Methods("GET")
+
 }
 }
 
 
 //simple get all networks function
 //simple get all networks function
@@ -231,6 +235,40 @@ func updateNetworkNodeLimit(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(network)
 	json.NewEncoder(w).Encode(network)
 }
 }
 
 
+func updateNetworkACL(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+	var params = mux.Vars(r)
+	netname := params["networkname"]
+	var networkACLChange acls.ACLContainer
+	networkACLChange, err := networkACLChange.Get(acls.ContainerID(netname))
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+	_ = json.NewDecoder(r.Body).Decode(&networkACLChange)
+	newNetACL, err := networkACLChange.Save(acls.ContainerID(netname))
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "badrequest"))
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(newNetACL)
+}
+
+func getNetworkACL(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+	var params = mux.Vars(r)
+	netname := params["networkname"]
+	var networkACL acls.ACLContainer
+	networkACL, err := networkACL.Get(acls.ContainerID(netname))
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(networkACL)
+}
+
 // Delete a network
 // Delete a network
 // Will stop you if  there's any nodes associated
 // Will stop you if  there's any nodes associated
 func deleteNetwork(w http.ResponseWriter, r *http.Request) {
 func deleteNetwork(w http.ResponseWriter, r *http.Request) {

+ 49 - 1
controllers/node.go

@@ -11,6 +11,8 @@ import (
 	"github.com/gravitl/netmaker/functions"
 	"github.com/gravitl/netmaker/functions"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
+	"github.com/gravitl/netmaker/logic/acls"
+	nodeacls "github.com/gravitl/netmaker/logic/acls/node-acls"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/mq"
 	"github.com/gravitl/netmaker/mq"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
@@ -34,7 +36,9 @@ func nodeHandlers(r *mux.Router) {
 	r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST")
 	r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST")
 	r.HandleFunc("/api/nodes/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET")
 	r.HandleFunc("/api/nodes/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET")
 	r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods("POST")
 	r.HandleFunc("/api/nodes/adm/{network}/authenticate", authenticate).Methods("POST")
-
+	// ACLs
+	r.HandleFunc("/api/nodes/{network}/{nodeid}/acls", authorize(true, "node", http.HandlerFunc(getNodeACL))).Methods("GET")
+	r.HandleFunc("/api/nodes/{network}/{nodeid}/acls", authorize(true, "node", http.HandlerFunc(updateNodeACL))).Methods("PUT")
 }
 }
 
 
 func authenticate(response http.ResponseWriter, request *http.Request) {
 func authenticate(response http.ResponseWriter, request *http.Request) {
@@ -339,6 +343,25 @@ func getNode(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(node)
 	json.NewEncoder(w).Encode(node)
 }
 }
 
 
+// Get an individual node. Nothin fancy here folks.
+func getNodeACL(w http.ResponseWriter, r *http.Request) {
+	// set header.
+	w.Header().Set("Content-Type", "application/json")
+
+	var params = mux.Vars(r)
+	var nodeID = params["nodeid"]
+	var networkID = params["network"]
+
+	nodeACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(networkID), nodeacls.NodeID(nodeID))
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "notfound"))
+		return
+	}
+	logger.Log(2, r.Header.Get("user"), "fetched node ACL", params["nodeid"])
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(nodeACL)
+}
+
 //Get the time that a network of nodes was last modified.
 //Get the time that a network of nodes was last modified.
 //TODO: This needs to be refactored
 //TODO: This needs to be refactored
 //Potential way to do this: On UpdateNode, set a new field for "LastModified"
 //Potential way to do this: On UpdateNode, set a new field for "LastModified"
@@ -623,6 +646,31 @@ func deleteNode(w http.ResponseWriter, r *http.Request) {
 	runForceServerUpdate(&node)
 	runForceServerUpdate(&node)
 }
 }
 
 
+func updateNodeACL(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+
+	var params = mux.Vars(r)
+	var nodeID = params["nodeid"]
+	var networkID = params["network"]
+	var newNodeACL acls.ACL
+	// we decode our body request params
+	err := json.NewDecoder(r.Body).Decode(&newNodeACL)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "badrequest"))
+		return
+	}
+
+	newNodeACL, err = nodeacls.UpdateNodeACL(nodeacls.NetworkID(networkID), nodeacls.NodeID(nodeID), newNodeACL)
+	if err != nil {
+		returnErrorResponse(w, r, formatError(err, "internal"))
+		return
+	}
+
+	logger.Log(1, r.Header.Get("user"), "updated node ACL for", nodeID, "on network", networkID)
+	w.WriteHeader(http.StatusOK)
+	json.NewEncoder(w).Encode(newNodeACL)
+}
+
 func runUpdates(node *models.Node, ifaceDelta bool) {
 func runUpdates(node *models.Node, ifaceDelta bool) {
 	go func() { // don't block http response
 	go func() { // don't block http response
 		// publish node update if not server
 		// publish node update if not server

+ 9 - 11
controllers/node_test.go

@@ -154,19 +154,17 @@ func TestNodeACLs(t *testing.T) {
 	t.Run("acls not present", func(t *testing.T) {
 	t.Run("acls not present", func(t *testing.T) {
 		currentACL, err := nodeacls.FetchAllACLs(nodeacls.NetworkID(node1.Network))
 		currentACL, err := nodeacls.FetchAllACLs(nodeacls.NetworkID(node1.Network))
 		assert.Nil(t, err)
 		assert.Nil(t, err)
-		assert.Nil(t, currentACL[acls.AclID(node1.ID)])
-		assert.Nil(t, currentACL[acls.AclID(node2.ID)])
+		assert.NotNil(t, currentACL)
 		node1ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID))
 		node1ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID))
-		assert.NotNil(t, err)
-		assert.Nil(t, node1ACL)
-		assert.EqualError(t, err, "no node ACL present for node "+node1.ID)
+		assert.Nil(t, err)
+		assert.NotNil(t, node1ACL)
+		assert.Equal(t, acls.Allowed, node1ACL[acls.AclID(node2.ID)])
 	})
 	})
 	t.Run("node acls exists after creates", func(t *testing.T) {
 	t.Run("node acls exists after creates", func(t *testing.T) {
-		node1ACL, err := nodeacls.CreateNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID), acls.Allowed)
+		node1ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID))
 		assert.Nil(t, err)
 		assert.Nil(t, err)
 		assert.NotNil(t, node1ACL)
 		assert.NotNil(t, node1ACL)
-		assert.Equal(t, node1ACL[acls.AclID(node2.ID)], acls.NotPresent)
-		node2ACL, err := nodeacls.CreateNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node2.ID), acls.Allowed)
+		node2ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node2.Network), nodeacls.NodeID(node2.ID))
 		assert.Nil(t, err)
 		assert.Nil(t, err)
 		assert.NotNil(t, node2ACL)
 		assert.NotNil(t, node2ACL)
 		assert.Equal(t, acls.Allowed, node2ACL[acls.AclID(node1.ID)])
 		assert.Equal(t, acls.Allowed, node2ACL[acls.AclID(node1.ID)])
@@ -177,11 +175,11 @@ func TestNodeACLs(t *testing.T) {
 		assert.Equal(t, acls.Allowed, node1ACL[acls.AclID(node2.ID)])
 		assert.Equal(t, acls.Allowed, node1ACL[acls.AclID(node2.ID)])
 	})
 	})
 	t.Run("node acls correct after modify", func(t *testing.T) {
 	t.Run("node acls correct after modify", func(t *testing.T) {
-		node1ACL, err := nodeacls.CreateNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID), acls.Allowed)
-		assert.Nil(t, err)
-		node2ACL, err := nodeacls.CreateNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node2.ID), acls.Allowed)
+		node1ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID))
 		assert.Nil(t, err)
 		assert.Nil(t, err)
 		assert.NotNil(t, node1ACL)
 		assert.NotNil(t, node1ACL)
+		node2ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node2.Network), nodeacls.NodeID(node2.ID))
+		assert.Nil(t, err)
 		assert.NotNil(t, node2ACL)
 		assert.NotNil(t, node2ACL)
 		currentACL, err := nodeacls.DisallowNodes(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID), nodeacls.NodeID(node2.ID))
 		currentACL, err := nodeacls.DisallowNodes(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID), nodeacls.NodeID(node2.ID))
 		assert.Nil(t, err)
 		assert.Nil(t, err)

+ 5 - 0
logic/acls/node-acls/modify.go

@@ -80,3 +80,8 @@ func RemoveNodeACL(networkID NetworkID, nodeID NodeID) (acls.ACLContainer, error
 	delete(currentNetworkACL, acls.AclID(nodeID))
 	delete(currentNetworkACL, acls.AclID(nodeID))
 	return currentNetworkACL.Save(acls.ContainerID(networkID))
 	return currentNetworkACL.Save(acls.ContainerID(networkID))
 }
 }
+
+// DeleteACLContainer - removes an ACLContainer state from db
+func DeleteACLContainer(network NetworkID) error {
+	return database.DeleteRecord(database.NODE_ACLS_TABLE_NAME, string(network))
+}

+ 6 - 0
logic/networks.go

@@ -12,6 +12,7 @@ import (
 	"github.com/go-playground/validator/v10"
 	"github.com/go-playground/validator/v10"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
+	nodeacls "github.com/gravitl/netmaker/logic/acls/node-acls"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/validation"
 	"github.com/gravitl/netmaker/validation"
@@ -41,6 +42,11 @@ func GetNetworks() ([]models.Network, error) {
 
 
 // DeleteNetwork - deletes a network
 // DeleteNetwork - deletes a network
 func DeleteNetwork(network string) error {
 func DeleteNetwork(network string) error {
+	// remove ACL for network
+	err := nodeacls.DeleteACLContainer(nodeacls.NetworkID(network))
+	if err != nil {
+		logger.Log(1, "failed to remove the node acls during network delete for network,", network)
+	}
 	nodeCount, err := GetNetworkNonServerNodeCount(network)
 	nodeCount, err := GetNetworkNonServerNodeCount(network)
 	if nodeCount == 0 || database.IsEmptyRecord(err) {
 	if nodeCount == 0 || database.IsEmptyRecord(err) {
 		// delete server nodes first then db records
 		// delete server nodes first then db records

+ 43 - 0
logic/nodes.go

@@ -12,6 +12,8 @@ import (
 	"github.com/google/uuid"
 	"github.com/google/uuid"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
+	"github.com/gravitl/netmaker/logic/acls"
+	nodeacls "github.com/gravitl/netmaker/logic/acls/node-acls"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
@@ -174,6 +176,41 @@ func UpdateNode(currentNode *models.Node, newNode *models.Node) error {
 	return fmt.Errorf("failed to update node " + currentNode.ID + ", cannot change ID.")
 	return fmt.Errorf("failed to update node " + currentNode.ID + ", cannot change ID.")
 }
 }
 
 
+// DeleteNodeByID - deletes a node from database or moves into delete nodes table
+func DeleteNodeByID(node *models.Node, exterminate bool) error {
+	var err error
+	var key = node.ID
+	if !exterminate {
+		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 {
+			logger.Log(2, err.Error())
+		}
+	}
+	if err = database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil {
+		return err
+	}
+	if servercfg.IsDNSMode() {
+		SetDNS()
+	}
+
+	_, err = nodeacls.RemoveNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID))
+	if err != nil {
+		// ignoring for now, could hit a nil pointer if delete called twice
+		logger.Log(2, "attempted to remove node ACL for node", node.Name, node.ID)
+	}
+
+	return removeLocalServer(node)
+}
+
 // IsNodeIDUnique - checks if node id is unique
 // IsNodeIDUnique - checks if node id is unique
 func IsNodeIDUnique(node *models.Node) (bool, error) {
 func IsNodeIDUnique(node *models.Node) (bool, error) {
 	_, err := database.FetchRecord(database.NODES_TABLE_NAME, node.ID)
 	_, err := database.FetchRecord(database.NODES_TABLE_NAME, node.ID)
@@ -274,6 +311,12 @@ func CreateNode(node *models.Node) error {
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
+	// TODO get template logic to decide initial ACL value
+	_, err = nodeacls.CreateNodeACL(nodeacls.NetworkID(node.Network), nodeacls.NodeID(node.ID), acls.Allowed)
+	if err != nil {
+		return err
+	}
+
 	if node.IsPending != "yes" {
 	if node.IsPending != "yes" {
 		DecrimentKey(node.Network, node.AccessKey)
 		DecrimentKey(node.Network, node.AccessKey)
 	}
 	}

+ 0 - 29
logic/util.go

@@ -17,7 +17,6 @@ import (
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/netclient/ncutils"
 	"github.com/gravitl/netmaker/netclient/ncutils"
-	"github.com/gravitl/netmaker/servercfg"
 )
 )
 
 
 // IsBase64 - checks if a string is in base64 format
 // IsBase64 - checks if a string is in base64 format
@@ -101,34 +100,6 @@ func GenerateCryptoString(n int) (string, error) {
 	return string(ret), nil
 	return string(ret), nil
 }
 }
 
 
-// DeleteNodeByID - deletes a node from database or moves into delete nodes table
-func DeleteNodeByID(node *models.Node, exterminate bool) error {
-	var err error
-	var key = node.ID
-	if !exterminate {
-		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 {
-			logger.Log(2, err.Error())
-		}
-	}
-	if err = database.DeleteRecord(database.NODES_TABLE_NAME, key); err != nil {
-		return err
-	}
-	if servercfg.IsDNSMode() {
-		SetDNS()
-	}
-	return removeLocalServer(node)
-}
-
 // RandomString - returns a random string in a charset
 // RandomString - returns a random string in a charset
 func RandomString(length int) string {
 func RandomString(length int) string {
 	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
 	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"