diff --git a/database/database.go b/database/database.go index 8d473fdc..bbc40cc4 100644 --- a/database/database.go +++ b/database/database.go @@ -50,6 +50,9 @@ const DATABASE_FILENAME = "netmaker.db" // GENERATED_TABLE_NAME - stores server generated k/v const GENERATED_TABLE_NAME = "generated" +// NODE_ACLS_TABLE_NAME - stores the node ACL rules +const NODE_ACLS_TABLE_NAME = "nodeacls" + // == ERROR CONSTS == // NO_RECORD - no singular result found @@ -127,6 +130,7 @@ func createTables() { createTable(SERVERCONF_TABLE_NAME) createTable(SERVER_UUID_TABLE_NAME) createTable(GENERATED_TABLE_NAME) + createTable(NODE_ACLS_TABLE_NAME) } func createTable(tableName string) error { diff --git a/logic/acls/node-acls/modify.go b/logic/acls/node-acls/modify.go new file mode 100644 index 00000000..090b7e2a --- /dev/null +++ b/logic/acls/node-acls/modify.go @@ -0,0 +1,60 @@ +package nodeacls + +import ( + "encoding/json" + + "github.com/gravitl/netmaker/database" +) + +// UpsertNodeACL - inserts or updates a node ACL on given network +func UpsertNodeACL(networkID NetworkID, nodeID NodeID, defaultVal byte) (NodeACL, error) { + if defaultVal != NotAllowed && defaultVal != Allowed { + defaultVal = NotAllowed + } + var currentNetworkACL, err = FetchCurrentACL(networkID) + if err != nil { + return nil, err + } + var newNodeACL = make(NodeACL) + for existingNode := range currentNetworkACL { + currentNetworkACL[existingNode][nodeID] = defaultVal + newNodeACL[existingNode] = defaultVal + } + currentNetworkACL[nodeID] = newNodeACL + return newNodeACL, nil +} + +// UpsertNetworkACL - Inserts or updates a network ACL given the json string of the ACL and the network name +// if nil, create it +func UpsertNetworkACL(networkID NetworkID, networkACL NetworkACL) (NetworkACL, error) { + if networkACL == nil { + networkACL = make(NetworkACL) + } + return networkACL, database.Insert(string(networkID), string(convertNetworkACLtoACLJson(&networkACL)), database.NODE_ACLS_TABLE_NAME) +} + +// RemoveNodeACL - removes a specific Node's ACL, returns the NetworkACL and error +func RemoveNodeACL(networkID NetworkID, nodeID NodeID) (NetworkACL, error) { + var currentNeworkACL, err = FetchCurrentACL(networkID) + if err != nil { + return nil, err + } + for currentNodeID := range currentNeworkACL { + delete(currentNeworkACL[nodeID], currentNodeID) + } + delete(currentNeworkACL, nodeID) + return UpsertNetworkACL(networkID, currentNeworkACL) +} + +// RemoveNetworkACL - just delete the network ACL +func RemoveNetworkACL(networkID NetworkID) error { + return database.DeleteRecord(database.NODE_ACLS_TABLE_NAME, string(networkID)) +} + +func convertNetworkACLtoACLJson(networkACL *NetworkACL) ACLJson { + data, err := json.Marshal(networkACL) + if err != nil { + return "" + } + return ACLJson(data) +} diff --git a/logic/acls/node-acls/retrieve.go b/logic/acls/node-acls/retrieve.go new file mode 100644 index 00000000..15cc0360 --- /dev/null +++ b/logic/acls/node-acls/retrieve.go @@ -0,0 +1,60 @@ +package nodeacls + +import ( + "encoding/json" + + "github.com/gravitl/netmaker/database" +) + +// AreNodesAllowed - checks if nodes are allowed to communicate in their network ACL +func AreNodesAllowed(networkID NetworkID, node1, node2 NodeID) bool { + var currentNetworkACL, err = FetchCurrentACL(networkID) + if err != nil { + return false + } + return currentNetworkACL[node1][node2] == Allowed && currentNetworkACL[node2][node1] == Allowed +} + +// FetchNodeACL - fetches a specific node's ACL in a given network +func FetchNodeACL(networkID NetworkID, nodeID NodeID) (NodeACL, error) { + currentNetACL, err := FetchCurrentACL(networkID) + if err != nil { + return nil, err + } + return currentNetACL[nodeID], nil +} + +// FetchNodeACLJson - fetches a node's acl in given network except returns the json string +func FetchNodeACLJson(networkID NetworkID, nodeID NodeID) (ACLJson, error) { + currentNodeACL, err := FetchNodeACL(networkID, nodeID) + if err != nil { + return "", err + } + jsonData, err := json.Marshal(¤tNodeACL) + if err != nil { + return "", err + } + return ACLJson(jsonData), nil +} + +// FetchCurrentACL - fetches all current node rules in given network ACL +func FetchCurrentACL(networkID NetworkID) (NetworkACL, error) { + aclJson, err := FetchCurrentACLJson(NetworkID(networkID)) + if err != nil { + return nil, err + } + var currentNetworkACL NetworkACL + if err := json.Unmarshal([]byte(aclJson), ¤tNetworkACL); err != nil { + return nil, err + } + return currentNetworkACL, nil +} + +// FetchCurrentACLJson - fetch the current ACL of given network except in json string +func FetchCurrentACLJson(networkID NetworkID) (ACLJson, error) { + currentACLs, err := database.FetchRecord(database.NODE_ACLS_TABLE_NAME, string(networkID)) + if err != nil { + return ACLJson(""), err + } + return ACLJson(currentACLs), nil +} diff --git a/logic/acls/node-acls/types.go b/logic/acls/node-acls/types.go new file mode 100644 index 00000000..289cb614 --- /dev/null +++ b/logic/acls/node-acls/types.go @@ -0,0 +1,27 @@ +package nodeacls + +var ( + // NotPresent - 0 - not present (default) + NotPresent = byte(0) + // NotAllowed - 1 - not allowed access + NotAllowed = byte(1) // 1 - not allowed + // Allowed - 2 - allowed access + Allowed = byte(2) +) + +type ( + // NodeID - the node id of a given node + NodeID string + + // NetworkID - the networkID of a given network + NetworkID string + + // NodeACL - the ACL of other nodes in a NetworkACL for a single unique node + NodeACL map[NodeID]byte + + // NetworkACL - the total list of all node's ACL in a given network + NetworkACL map[NodeID]NodeACL + + // ACLJson - the string representation in JSON of an ACL Node or Network + ACLJson string +)