added basic api endpoints

This commit is contained in:
0xdcarns
2022-02-25 16:28:58 -05:00
parent 9668a84cd0
commit aefc8b090b
8 changed files with 153 additions and 45 deletions

View File

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

View File

@@ -11,6 +11,7 @@ import (
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/logic/acls"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mq"
"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(getAccessKeys))).Methods("GET")
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
@@ -231,6 +235,40 @@ func updateNetworkNodeLimit(w http.ResponseWriter, r *http.Request) {
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
// Will stop you if there's any nodes associated
func deleteNetwork(w http.ResponseWriter, r *http.Request) {

View File

@@ -11,6 +11,8 @@ import (
"github.com/gravitl/netmaker/functions"
"github.com/gravitl/netmaker/logger"
"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/mq"
"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/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET")
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) {
@@ -339,6 +343,25 @@ func getNode(w http.ResponseWriter, r *http.Request) {
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.
//TODO: This needs to be refactored
//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)
}
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) {
go func() { // don't block http response
// publish node update if not server

View File

@@ -154,19 +154,17 @@ func TestNodeACLs(t *testing.T) {
t.Run("acls not present", func(t *testing.T) {
currentACL, err := nodeacls.FetchAllACLs(nodeacls.NetworkID(node1.Network))
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))
assert.NotNil(t, err)
assert.Nil(t, node1ACL)
assert.EqualError(t, err, "no node ACL present for node "+node1.ID)
})
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)
assert.Nil(t, err)
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)
assert.Equal(t, acls.Allowed, node1ACL[acls.AclID(node2.ID)])
})
t.Run("node acls exists after creates", func(t *testing.T) {
node1ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID))
assert.Nil(t, err)
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.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)])
})
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.NotNil(t, node1ACL)
node2ACL, err := nodeacls.FetchNodeACL(nodeacls.NetworkID(node2.Network), nodeacls.NodeID(node2.ID))
assert.Nil(t, err)
assert.NotNil(t, node2ACL)
currentACL, err := nodeacls.DisallowNodes(nodeacls.NetworkID(node1.Network), nodeacls.NodeID(node1.ID), nodeacls.NodeID(node2.ID))
assert.Nil(t, err)

View File

@@ -80,3 +80,8 @@ func RemoveNodeACL(networkID NetworkID, nodeID NodeID) (acls.ACLContainer, error
delete(currentNetworkACL, acls.AclID(nodeID))
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))
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/go-playground/validator/v10"
"github.com/gravitl/netmaker/database"
"github.com/gravitl/netmaker/logger"
nodeacls "github.com/gravitl/netmaker/logic/acls/node-acls"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/ncutils"
"github.com/gravitl/netmaker/validation"
@@ -41,6 +42,11 @@ func GetNetworks() ([]models.Network, error) {
// DeleteNetwork - deletes a network
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)
if nodeCount == 0 || database.IsEmptyRecord(err) {
// delete server nodes first then db records

View File

@@ -12,6 +12,8 @@ import (
"github.com/google/uuid"
"github.com/gravitl/netmaker/database"
"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/netclient/ncutils"
"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.")
}
// 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
func IsNodeIDUnique(node *models.Node) (bool, error) {
_, err := database.FetchRecord(database.NODES_TABLE_NAME, node.ID)
@@ -274,6 +311,12 @@ func CreateNode(node *models.Node) error {
if err != nil {
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" {
DecrimentKey(node.Network, node.AccessKey)
}

View File

@@ -17,7 +17,6 @@ import (
"github.com/gravitl/netmaker/logger"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/ncutils"
"github.com/gravitl/netmaker/servercfg"
)
// IsBase64 - checks if a string is in base64 format
@@ -101,34 +100,6 @@ func GenerateCryptoString(n int) (string, error) {
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
func RandomString(length int) string {
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"