128 lines
3.9 KiB
Python
128 lines
3.9 KiB
Python
from primaite.common.enums import NodeHardwareAction, NodePOLType, NodeSoftwareAction
|
|
|
|
|
|
def transform_action_node_readable(action):
|
|
"""
|
|
Convert a node action from enumerated format to readable format.
|
|
|
|
example:
|
|
[1, 3, 1, 0] -> [1, 'SERVICE', 'PATCHING', 0]
|
|
"""
|
|
action_node_property = NodePOLType(action[1]).name
|
|
|
|
if action_node_property == "OPERATING":
|
|
property_action = NodeHardwareAction(action[2]).name
|
|
elif (action_node_property == "OS" or action_node_property == "SERVICE") and action[
|
|
2
|
|
] <= 1:
|
|
property_action = NodeSoftwareAction(action[2]).name
|
|
else:
|
|
property_action = "NONE"
|
|
|
|
new_action = [action[0], action_node_property, property_action, action[3]]
|
|
return new_action
|
|
|
|
|
|
def transform_action_acl_readable(action):
|
|
"""
|
|
Transform an ACL action to a more readable format.
|
|
|
|
example:
|
|
[0, 1, 2, 5, 0, 1] -> ['NONE', 'ALLOW', 2, 5, 'ANY', 1]
|
|
"""
|
|
action_decisions = {0: "NONE", 1: "CREATE", 2: "DELETE"}
|
|
action_permissions = {0: "DENY", 1: "ALLOW"}
|
|
|
|
action_decision = action_decisions[action[0]]
|
|
action_permission = action_permissions[action[1]]
|
|
|
|
# For IPs, Ports and Protocols, 0 means any, otherwise its just an index
|
|
new_action = [action_decision, action_permission] + list(action[2:6])
|
|
for n, val in enumerate(list(action[2:6])):
|
|
if val == 0:
|
|
new_action[n + 2] = "ANY"
|
|
|
|
return new_action
|
|
|
|
|
|
def is_valid_node_action(action):
|
|
"""Is the node action an actual valid action.
|
|
|
|
Only uses information about the action to determine if the action has an effect
|
|
|
|
Does NOT consider:
|
|
- Node ID not valid to perform an operation - e.g. selected node has no service so cannot patch
|
|
- Node already being in that state (turning an ON node ON)
|
|
"""
|
|
action_r = transform_action_node_readable(action)
|
|
|
|
node_property = action_r[1]
|
|
node_action = action_r[2]
|
|
|
|
# print("node property", node_property, "\nnode action", node_action)
|
|
|
|
if node_property == "NONE":
|
|
return False
|
|
if node_action == "NONE":
|
|
return False
|
|
if node_property == "OPERATING" and node_action == "PATCHING":
|
|
# Operating State cannot PATCH
|
|
return False
|
|
if node_property != "OPERATING" and node_action not in ["NONE", "PATCHING"]:
|
|
# Software States can only do Nothing or Patch
|
|
return False
|
|
return True
|
|
|
|
|
|
def is_valid_acl_action(action):
|
|
"""
|
|
Is the ACL action an actual valid action.
|
|
|
|
Only uses information about the action to determine if the action has an effect.
|
|
|
|
Does NOT consider:
|
|
- Trying to create identical rules
|
|
- Trying to create a rule which is a subset of another rule (caused by "ANY")
|
|
"""
|
|
action_r = transform_action_acl_readable(action)
|
|
|
|
action_decision = action_r[0]
|
|
action_permission = action_r[1]
|
|
action_source_id = action_r[2]
|
|
action_destination_id = action_r[3]
|
|
|
|
if action_decision == "NONE":
|
|
return False
|
|
if (
|
|
action_source_id == action_destination_id
|
|
and action_source_id != "ANY"
|
|
and action_destination_id != "ANY"
|
|
):
|
|
# ACL rule towards itself
|
|
return False
|
|
if action_permission == "DENY":
|
|
# DENY is unnecessary, we can create and delete allow rules instead
|
|
# No allow rule = blocked/DENY by feault. ALLOW overrides existing DENY.
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def is_valid_acl_action_extra(action):
|
|
"""Harsher version of valid acl actions, does not allow action."""
|
|
if is_valid_acl_action(action) is False:
|
|
return False
|
|
|
|
action_r = transform_action_acl_readable(action)
|
|
action_protocol = action_r[4]
|
|
action_port = action_r[5]
|
|
|
|
# Don't allow protocols or ports to be ANY
|
|
# in the future we might want to do the opposite, and only have ANY option for ports and service
|
|
if action_protocol == "ANY":
|
|
return False
|
|
if action_port == "ANY":
|
|
return False
|
|
|
|
return True
|