diff --git a/src/primaite/config/_package_data/data_manipulation.yaml b/src/primaite/config/_package_data/data_manipulation.yaml index d810e58a..b6899b79 100644 --- a/src/primaite/config/_package_data/data_manipulation.yaml +++ b/src/primaite/config/_package_data/data_manipulation.yaml @@ -265,14 +265,10 @@ agents: - type: NODE_SHUTDOWN - type: NODE_STARTUP - type: NODE_RESET - - type: NETWORK_ACL_ADDRULE - options: - target_router_hostname: router_1 - - type: NETWORK_ACL_REMOVERULE - options: - target_router_hostname: router_1 - - type: NETWORK_NIC_ENABLE - - type: NETWORK_NIC_DISABLE + - type: ROUTER_ACL_ADDRULE + - type: ROUTER_ACL_REMOVERULE + - type: HOST_NIC_ENABLE + - type: HOST_NIC_DISABLE action_map: 0: @@ -484,8 +480,9 @@ agents: node_id: 6 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -494,8 +491,9 @@ agents: dest_port_id: 1 protocol_id: 1 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -504,8 +502,9 @@ agents: dest_port_id: 1 protocol_id: 1 48: # old action num: 24 # block tcp traffic from client 1 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -514,8 +513,9 @@ agents: dest_port_id: 1 protocol_id: 3 49: # old action num: 25 # block tcp traffic from client 2 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -524,8 +524,9 @@ agents: dest_port_id: 1 protocol_id: 3 50: # old action num: 26 - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -534,8 +535,9 @@ agents: dest_port_id: 1 protocol_id: 3 51: # old action num: 27 - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -544,122 +546,132 @@ agents: dest_port_id: 1 protocol_id: 3 52: # old action num: 28 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 0 53: # old action num: 29 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 1 54: # old action num: 30 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 2 55: # old action num: 31 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 3 56: # old action num: 32 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 4 57: # old action num: 33 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 5 58: # old action num: 34 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 6 59: # old action num: 35 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 7 60: # old action num: 36 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 8 61: # old action num: 37 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 9 62: # old action num: 38 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 0 nic_id: 0 63: # old action num: 39 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 0 nic_id: 0 64: # old action num: 40 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 1 nic_id: 0 65: # old action num: 41 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 1 nic_id: 0 66: # old action num: 42 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 2 nic_id: 0 67: # old action num: 43 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 2 nic_id: 0 68: # old action num: 44 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 3 nic_id: 0 69: # old action num: 45 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 3 nic_id: 0 70: # old action num: 46 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 0 71: # old action num: 47 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 0 72: # old action num: 48 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 1 73: # old action num: 49 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 1 74: # old action num: 50 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 5 nic_id: 0 75: # old action num: 51 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 5 nic_id: 0 76: # old action num: 52 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 6 nic_id: 0 77: # old action num: 53 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 6 nic_id: 0 diff --git a/src/primaite/config/_package_data/data_manipulation_marl.yaml b/src/primaite/config/_package_data/data_manipulation_marl.yaml index 3e95a6ee..86759b2d 100644 --- a/src/primaite/config/_package_data/data_manipulation_marl.yaml +++ b/src/primaite/config/_package_data/data_manipulation_marl.yaml @@ -267,14 +267,10 @@ agents: - type: NODE_SHUTDOWN - type: NODE_STARTUP - type: NODE_RESET - - type: NETWORK_ACL_ADDRULE - options: - target_router_hostname: router_1 - - type: NETWORK_ACL_REMOVERULE - options: - target_router_hostname: router_1 - - type: NETWORK_NIC_ENABLE - - type: NETWORK_NIC_DISABLE + - type: ROUTER_ACL_ADDRULE + - type: ROUTER_ACL_REMOVERULE + - type: HOST_NIC_ENABLE + - type: HOST_NIC_DISABLE action_map: 0: @@ -486,8 +482,9 @@ agents: node_id: 6 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -496,8 +493,9 @@ agents: dest_port_id: 1 protocol_id: 1 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -506,8 +504,9 @@ agents: dest_port_id: 1 protocol_id: 1 48: # old action num: 24 # block tcp traffic from client 1 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -516,8 +515,9 @@ agents: dest_port_id: 1 protocol_id: 3 49: # old action num: 25 # block tcp traffic from client 2 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -526,8 +526,9 @@ agents: dest_port_id: 1 protocol_id: 3 50: # old action num: 26 - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -536,8 +537,9 @@ agents: dest_port_id: 1 protocol_id: 3 51: # old action num: 27 - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -546,122 +548,132 @@ agents: dest_port_id: 1 protocol_id: 3 52: # old action num: 28 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 0 53: # old action num: 29 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 1 54: # old action num: 30 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 2 55: # old action num: 31 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 3 56: # old action num: 32 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 4 57: # old action num: 33 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 5 58: # old action num: 34 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 6 59: # old action num: 35 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 7 60: # old action num: 36 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 8 61: # old action num: 37 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 9 62: # old action num: 38 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 0 nic_id: 0 63: # old action num: 39 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 0 nic_id: 0 64: # old action num: 40 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 1 nic_id: 0 65: # old action num: 41 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 1 nic_id: 0 66: # old action num: 42 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 2 nic_id: 0 67: # old action num: 43 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 2 nic_id: 0 68: # old action num: 44 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 3 nic_id: 0 69: # old action num: 45 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 3 nic_id: 0 70: # old action num: 46 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 0 71: # old action num: 47 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 0 72: # old action num: 48 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 1 73: # old action num: 49 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 1 74: # old action num: 50 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 5 nic_id: 0 75: # old action num: 51 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 5 nic_id: 0 76: # old action num: 52 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 6 nic_id: 0 77: # old action num: 53 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 6 nic_id: 0 @@ -830,14 +842,14 @@ agents: - type: NODE_SHUTDOWN - type: NODE_STARTUP - type: NODE_RESET - - type: NETWORK_ACL_ADDRULE + - type: ROUTER_ACL_ADDRULE options: - target_router_hostname: router_1 - - type: NETWORK_ACL_REMOVERULE + target_router_nodename: router_1 + - type: ROUTER_ACL_REMOVERULE options: - target_router_hostname: router_1 - - type: NETWORK_NIC_ENABLE - - type: NETWORK_NIC_DISABLE + target_router_nodename: router_1 + - type: HOST_NIC_ENABLE + - type: HOST_NIC_DISABLE action_map: 0: @@ -1049,8 +1061,9 @@ agents: node_id: 6 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -1059,8 +1072,9 @@ agents: dest_port_id: 1 protocol_id: 1 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -1069,8 +1083,9 @@ agents: dest_port_id: 1 protocol_id: 1 48: # old action num: 24 # block tcp traffic from client 1 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -1079,8 +1094,9 @@ agents: dest_port_id: 1 protocol_id: 3 49: # old action num: 25 # block tcp traffic from client 2 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -1089,8 +1105,9 @@ agents: dest_port_id: 1 protocol_id: 3 50: # old action num: 26 - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -1099,8 +1116,9 @@ agents: dest_port_id: 1 protocol_id: 3 51: # old action num: 27 - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -1109,122 +1127,132 @@ agents: dest_port_id: 1 protocol_id: 3 52: # old action num: 28 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 0 53: # old action num: 29 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 1 54: # old action num: 30 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 2 55: # old action num: 31 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 3 56: # old action num: 32 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 4 57: # old action num: 33 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 5 58: # old action num: 34 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 6 59: # old action num: 35 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 7 60: # old action num: 36 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 8 61: # old action num: 37 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 9 62: # old action num: 38 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 0 nic_id: 0 63: # old action num: 39 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 0 nic_id: 0 64: # old action num: 40 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 1 nic_id: 0 65: # old action num: 41 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 1 nic_id: 0 66: # old action num: 42 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 2 nic_id: 0 67: # old action num: 43 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 2 nic_id: 0 68: # old action num: 44 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 3 nic_id: 0 69: # old action num: 45 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 3 nic_id: 0 70: # old action num: 46 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 0 71: # old action num: 47 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 0 72: # old action num: 48 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 1 73: # old action num: 49 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 1 74: # old action num: 50 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 5 nic_id: 0 75: # old action num: 51 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 5 nic_id: 0 76: # old action num: 52 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 6 nic_id: 0 77: # old action num: 53 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 6 nic_id: 0 diff --git a/src/primaite/game/agent/actions.py b/src/primaite/game/agent/actions.py index b79fc985..9e967f91 100644 --- a/src/primaite/game/agent/actions.py +++ b/src/primaite/game/agent/actions.py @@ -219,6 +219,45 @@ class NodeApplicationFixAction(NodeApplicationAbstractAction): self.verb: str = "fix" +class NodeApplicationInstallAction(AbstractAction): + """Action which installs an application.""" + + def __init__(self, manager: "ActionManager", num_nodes: int, **kwargs) -> None: + super().__init__(manager=manager) + self.shape: Dict[str, int] = {"node_id": num_nodes} + + def form_request(self, node_id: int, application_name: str, ip_address: str) -> List[str]: + """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" + node_name = self.manager.get_node_name_by_idx(node_id) + if node_name is None: + return ["do_nothing"] + return [ + "network", + "node", + node_name, + "software_manager", + "application", + "install", + application_name, + ip_address, + ] + + +class NodeApplicationRemoveAction(AbstractAction): + """Action which removes/uninstalls an application.""" + + def __init__(self, manager: "ActionManager", num_nodes: int, **kwargs) -> None: + super().__init__(manager=manager) + self.shape: Dict[str, int] = {"node_id": num_nodes} + + def form_request(self, node_id: int, application_name: str) -> List[str]: + """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" + node_name = self.manager.get_node_name_by_idx(node_id) + if node_name is None: + return ["do_nothing"] + return ["network", "node", node_name, "software_manager", "application", "uninstall", application_name] + + class NodeFolderAbstractAction(AbstractAction): """ Base class for folder actions. @@ -405,25 +444,22 @@ class NodeResetAction(NodeAbstractAction): self.verb: str = "reset" -class NetworkACLAddRuleAction(AbstractAction): +class RouterACLAddRuleAction(AbstractAction): """Action which adds a rule to a router's ACL.""" def __init__( self, manager: "ActionManager", - target_router_hostname: str, max_acl_rules: int, num_ips: int, num_ports: int, num_protocols: int, **kwargs, ) -> None: - """Init method for NetworkACLAddRuleAction. + """Init method for RouterACLAddRuleAction. :param manager: Reference to the ActionManager which created this action. :type manager: ActionManager - :param target_router_hostname: hostname of the router to which the ACL rule should be added. - :type target_router_hostname: str :param max_acl_rules: Maximum number of ACL rules that can be added to the router. :type max_acl_rules: int :param num_ips: Number of IP addresses in the simulation. @@ -444,10 +480,10 @@ class NetworkACLAddRuleAction(AbstractAction): "dest_port_id": num_ports, "protocol_id": num_protocols, } - self.target_router_name: str = target_router_hostname def form_request( self, + target_router_nodename: str, position: int, permission: int, source_ip_id: int, @@ -461,7 +497,7 @@ class NetworkACLAddRuleAction(AbstractAction): permission_str = "UNUSED" return ["do_nothing"] # NOT SUPPORTED, JUST DO NOTHING IF WE COME ACROSS THIS elif permission == 1: - permission_str = "ALLOW" + permission_str = "PERMIT" elif permission == 2: permission_str = "DENY" else: @@ -511,7 +547,7 @@ class NetworkACLAddRuleAction(AbstractAction): return [ "network", "node", - self.target_router_name, + target_router_nodename, "acl", "add_rule", permission_str, @@ -524,29 +560,176 @@ class NetworkACLAddRuleAction(AbstractAction): ] -class NetworkACLRemoveRuleAction(AbstractAction): +class RouterACLRemoveRuleAction(AbstractAction): """Action which removes a rule from a router's ACL.""" - def __init__(self, manager: "ActionManager", target_router_hostname: str, max_acl_rules: int, **kwargs) -> None: - """Init method for NetworkACLRemoveRuleAction. + def __init__(self, manager: "ActionManager", max_acl_rules: int, **kwargs) -> None: + """Init method for RouterACLRemoveRuleAction. :param manager: Reference to the ActionManager which created this action. :type manager: ActionManager - :param target_router_hostname: Hostname of the router from which the ACL rule should be removed. - :type target_router_hostname: str :param max_acl_rules: Maximum number of ACL rules that can be added to the router. :type max_acl_rules: int """ super().__init__(manager=manager) self.shape: Dict[str, int] = {"position": max_acl_rules} - self.target_router_name: str = target_router_hostname - def form_request(self, position: int) -> List[str]: + def form_request(self, target_router_nodename: str, position: int) -> List[str]: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" - return ["network", "node", self.target_router_name, "acl", "remove_rule", position] + return ["network", "node", target_router_nodename, "acl", "remove_rule", position] -class NetworkNICAbstractAction(AbstractAction): +class FirewallACLAddRuleAction(AbstractAction): + """Action which adds a rule to a firewall port's ACL.""" + + def __init__( + self, + manager: "ActionManager", + max_acl_rules: int, + num_ips: int, + num_ports: int, + num_protocols: int, + **kwargs, + ) -> None: + """Init method for FirewallACLAddRuleAction. + + :param manager: Reference to the ActionManager which created this action. + :type manager: ActionManager + :param max_acl_rules: Maximum number of ACL rules that can be added to the router. + :type max_acl_rules: int + :param num_ips: Number of IP addresses in the simulation. + :type num_ips: int + :param num_ports: Number of ports in the simulation. + :type num_ports: int + :param num_protocols: Number of protocols in the simulation. + :type num_protocols: int + """ + super().__init__(manager=manager) + num_permissions = 3 + self.shape: Dict[str, int] = { + "position": max_acl_rules, + "permission": num_permissions, + "source_ip_id": num_ips, + "dest_ip_id": num_ips, + "source_port_id": num_ports, + "dest_port_id": num_ports, + "protocol_id": num_protocols, + } + + def form_request( + self, + target_firewall_nodename: str, + firewall_port_name: str, + firewall_port_direction: str, + position: int, + permission: int, + source_ip_id: int, + dest_ip_id: int, + source_port_id: int, + dest_port_id: int, + protocol_id: int, + ) -> List[str]: + """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" + if permission == 0: + permission_str = "UNUSED" + return ["do_nothing"] # NOT SUPPORTED, JUST DO NOTHING IF WE COME ACROSS THIS + elif permission == 1: + permission_str = "PERMIT" + elif permission == 2: + permission_str = "DENY" + else: + _LOGGER.warning(f"{self.__class__} received permission {permission}, expected 0 or 1.") + + if protocol_id == 0: + return ["do_nothing"] # NOT SUPPORTED, JUST DO NOTHING IF WE COME ACROSS THIS + + if protocol_id == 1: + protocol = "ALL" + else: + protocol = self.manager.get_internet_protocol_by_idx(protocol_id - 2) + # subtract 2 to account for UNUSED=0 and ALL=1. + + if source_ip_id == 0: + return ["do_nothing"] # invalid formulation + elif source_ip_id == 1: + src_ip = "ALL" + else: + src_ip = self.manager.get_ip_address_by_idx(source_ip_id - 2) + # subtract 2 to account for UNUSED=0, and ALL=1 + + if source_port_id == 0: + return ["do_nothing"] # invalid formulation + elif source_port_id == 1: + src_port = "ALL" + else: + src_port = self.manager.get_port_by_idx(source_port_id - 2) + # subtract 2 to account for UNUSED=0, and ALL=1 + + if source_ip_id == 0: + return ["do_nothing"] # invalid formulation + elif dest_ip_id == 1: + dst_ip = "ALL" + else: + dst_ip = self.manager.get_ip_address_by_idx(dest_ip_id - 2) + # subtract 2 to account for UNUSED=0, and ALL=1 + + if dest_port_id == 0: + return ["do_nothing"] # invalid formulation + elif dest_port_id == 1: + dst_port = "ALL" + else: + dst_port = self.manager.get_port_by_idx(dest_port_id - 2) + # subtract 2 to account for UNUSED=0, and ALL=1 + + return [ + "network", + "node", + target_firewall_nodename, + firewall_port_name, + firewall_port_direction, + "acl", + "add_rule", + permission_str, + protocol, + str(src_ip), + src_port, + str(dst_ip), + dst_port, + position, + ] + + +class FirewallACLRemoveRuleAction(AbstractAction): + """Action which removes a rule from a firewall port's ACL.""" + + def __init__(self, manager: "ActionManager", max_acl_rules: int, **kwargs) -> None: + """Init method for RouterACLRemoveRuleAction. + + :param manager: Reference to the ActionManager which created this action. + :type manager: ActionManager + :param max_acl_rules: Maximum number of ACL rules that can be added to the router. + :type max_acl_rules: int + """ + super().__init__(manager=manager) + self.shape: Dict[str, int] = {"position": max_acl_rules} + + def form_request( + self, target_firewall_nodename: str, firewall_port_name: str, firewall_port_direction: str, position: int + ) -> List[str]: + """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" + return [ + "network", + "node", + target_firewall_nodename, + firewall_port_name, + firewall_port_direction, + "acl", + "remove_rule", + position, + ] + + +class HostNICAbstractAction(AbstractAction): """ Abstract base class for NIC actions. @@ -555,7 +738,7 @@ class NetworkNICAbstractAction(AbstractAction): """ def __init__(self, manager: "ActionManager", num_nodes: int, max_nics_per_node: int, **kwargs) -> None: - """Init method for NetworkNICAbstractAction. + """Init method for HostNICAbstractAction. :param manager: Reference to the ActionManager which created this action. :type manager: ActionManager @@ -577,7 +760,7 @@ class NetworkNICAbstractAction(AbstractAction): return ["network", "node", node_name, "network_interface", nic_num, self.verb] -class NetworkNICEnableAction(NetworkNICAbstractAction): +class HostNICEnableAction(HostNICAbstractAction): """Action which enables a NIC.""" def __init__(self, manager: "ActionManager", num_nodes: int, max_nics_per_node: int, **kwargs) -> None: @@ -585,7 +768,7 @@ class NetworkNICEnableAction(NetworkNICAbstractAction): self.verb: str = "enable" -class NetworkNICDisableAction(NetworkNICAbstractAction): +class HostNICDisableAction(HostNICAbstractAction): """Action which disables a NIC.""" def __init__(self, manager: "ActionManager", num_nodes: int, max_nics_per_node: int, **kwargs) -> None: @@ -593,51 +776,42 @@ class NetworkNICDisableAction(NetworkNICAbstractAction): self.verb: str = "disable" -class NetworkPortAbstractAction(AbstractAction): - """ - Abstract base class for Port actions. +class NetworkPortEnableAction(AbstractAction): + """Action which enables are port on a router or a firewall.""" - Any action which applies to a Router/Firewall and uses node_id and port_id as its only two parameters - can inherit from this base class. - """ + def __init__(self, manager: "ActionManager", max_nics_per_node: int, **kwargs) -> None: + """Init method for NetworkPortEnableAction. - def __init__(self, manager: "ActionManager", num_nodes: int, max_nics_per_node: int, **kwargs) -> None: - """Init method for NetworkNICAbstractAction. - - :param manager: Reference to the ActionManager which created this action. - :type manager: ActionManager - :param num_nodes: Number of nodes in the simulation. - :type num_nodes: int :param max_nics_per_node: Maximum number of NICs per node. :type max_nics_per_node: int """ super().__init__(manager=manager) - self.shape: Dict[str, int] = {"node_id": num_nodes, "port_id": max_nics_per_node} - self.verb: str # define but don't initialise: defends against children classes not defining this + self.shape: Dict[str, int] = {"port_id": max_nics_per_node} - def form_request(self, node_id: int, port_id: int) -> List[str]: + def form_request(self, target_nodename: str, port_id: int) -> List[str]: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" - node_name = self.manager.get_node_name_by_idx(node_idx=node_id) - port_num = self.manager.get_nic_num_by_idx(node_idx=node_id, nic_idx=port_id) - if node_name is None or port_num is None: + if target_nodename is None or port_id is None: return ["do_nothing"] - return ["network", "node", node_name, "network_interface", port_num, self.verb] + return ["network", "node", target_nodename, "network_interface", port_id, "enable"] -class NetworkPortEnableAction(NetworkPortAbstractAction): - """Action which enables a PORT.""" +class NetworkPortDisableAction(AbstractAction): + """Action which disables are port on a router or a firewall.""" - def __init__(self, manager: "ActionManager", num_nodes: int, max_nics_per_node: int, **kwargs) -> None: - super().__init__(manager=manager, num_nodes=num_nodes, max_nics_per_node=max_nics_per_node, **kwargs) - self.verb: str = "enable" + def __init__(self, manager: "ActionManager", max_nics_per_node: int, **kwargs) -> None: + """Init method for NetworkPortDisableAction. + :param max_nics_per_node: Maximum number of NICs per node. + :type max_nics_per_node: int + """ + super().__init__(manager=manager) + self.shape: Dict[str, int] = {"port_id": max_nics_per_node} -class NetworkPortDisableAction(NetworkPortAbstractAction): - """Action which disables a PORT.""" - - def __init__(self, manager: "ActionManager", num_nodes: int, max_nics_per_node: int, **kwargs) -> None: - super().__init__(manager=manager, num_nodes=num_nodes, max_nics_per_node=max_nics_per_node, **kwargs) - self.verb: str = "disable" + def form_request(self, target_nodename: str, port_id: int) -> List[str]: + """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" + if target_nodename is None or port_id is None: + return ["do_nothing"] + return ["network", "node", target_nodename, "network_interface", port_id, "disable"] class ActionManager: @@ -658,6 +832,8 @@ class ActionManager: "NODE_APPLICATION_SCAN": NodeApplicationScanAction, "NODE_APPLICATION_CLOSE": NodeApplicationCloseAction, "NODE_APPLICATION_FIX": NodeApplicationFixAction, + "NODE_APPLICATION_INSTALL": NodeApplicationInstallAction, + "NODE_APPLICATION_REMOVE": NodeApplicationRemoveAction, "NODE_FILE_SCAN": NodeFileScanAction, "NODE_FILE_CHECKHASH": NodeFileCheckhashAction, "NODE_FILE_DELETE": NodeFileDeleteAction, @@ -672,10 +848,12 @@ class ActionManager: "NODE_SHUTDOWN": NodeShutdownAction, "NODE_STARTUP": NodeStartupAction, "NODE_RESET": NodeResetAction, - "NETWORK_ACL_ADDRULE": NetworkACLAddRuleAction, - "NETWORK_ACL_REMOVERULE": NetworkACLRemoveRuleAction, - "NETWORK_NIC_ENABLE": NetworkNICEnableAction, - "NETWORK_NIC_DISABLE": NetworkNICDisableAction, + "ROUTER_ACL_ADDRULE": RouterACLAddRuleAction, + "ROUTER_ACL_REMOVERULE": RouterACLRemoveRuleAction, + "FIREWALL_ACL_ADDRULE": FirewallACLAddRuleAction, + "FIREWALL_ACL_REMOVERULE": FirewallACLRemoveRuleAction, + "HOST_NIC_ENABLE": HostNICEnableAction, + "HOST_NIC_DISABLE": HostNICDisableAction, "NETWORK_PORT_ENABLE": NetworkPortEnableAction, "NETWORK_PORT_DISABLE": NetworkPortDisableAction, } @@ -819,7 +997,8 @@ class ActionManager: {0: ("NODE_SERVICE_SCAN", {node_id:0, service_id:2})} """ if act_map is None: - self.action_map = self._enumerate_actions() + # raise RuntimeError("Action map must be specified in the config file.") + pass else: self.action_map = {i: (a["action"], a["options"]) for i, a in act_map.items()} # make sure all numbers between 0 and N are represented as dict keys in action map diff --git a/src/primaite/game/game.py b/src/primaite/game/game.py index 05b76679..6ba7e63c 100644 --- a/src/primaite/game/game.py +++ b/src/primaite/game/game.py @@ -15,10 +15,11 @@ from primaite.game.science import graph_has_cycle, topological_sort from primaite.simulator.network.hardware.base import NodeOperatingState from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.host_node import NIC -from primaite.simulator.network.hardware.nodes.host.server import Server +from primaite.simulator.network.hardware.nodes.host.server import Printer, Server from primaite.simulator.network.hardware.nodes.network.firewall import Firewall from primaite.simulator.network.hardware.nodes.network.router import Router from primaite.simulator.network.hardware.nodes.network.switch import Switch +from primaite.simulator.network.hardware.nodes.network.wireless_router import WirelessRouter from primaite.simulator.network.nmne import set_nmne_config from primaite.simulator.network.transmission.transport_layer import Port from primaite.simulator.sim_container import Simulation @@ -273,8 +274,18 @@ class PrimaiteGame: new_node = Router.from_config(node_cfg) elif n_type == "firewall": new_node = Firewall.from_config(node_cfg) + elif n_type == "wireless_router": + new_node = WirelessRouter.from_config(node_cfg) + elif n_type == "printer": + new_node = Printer( + hostname=node_cfg["hostname"], + ip_address=node_cfg["ip_address"], + subnet_mask=node_cfg["subnet_mask"], + ) else: - _LOGGER.warning(f"invalid node type {n_type} in config") + msg = f"invalid node type {n_type} in config" + _LOGGER.error(msg) + raise ValueError(msg) if "services" in node_cfg: for service_cfg in node_cfg["services"]: new_service = None diff --git a/src/primaite/simulator/network/container.py b/src/primaite/simulator/network/container.py index 0e970c3d..a4079fb8 100644 --- a/src/primaite/simulator/network/container.py +++ b/src/primaite/simulator/network/container.py @@ -8,6 +8,7 @@ from prettytable import MARKDOWN, PrettyTable from primaite import getLogger from primaite.simulator.core import RequestManager, RequestType, SimComponent from primaite.simulator.network.hardware.base import Link, Node, WiredNetworkInterface +from primaite.simulator.network.hardware.nodes.host.server import Printer from primaite.simulator.system.applications.application import Application from primaite.simulator.system.services.service import Service @@ -110,6 +111,16 @@ class Network(SimComponent): """The Firewalls in the Network.""" return [node for node in self.nodes.values() if node.__class__.__name__ == "Firewall"] + @property + def printer_nodes(self) -> List[Node]: + """The printers on the network.""" + return [node for node in self.nodes.values() if isinstance(node, Printer)] + + @property + def wireless_router_nodes(self) -> List[Node]: + """The Routers in the Network.""" + return [node for node in self.nodes.values() if node.__class__.__name__ == "WirelessRouter"] + def show(self, nodes: bool = True, ip_addresses: bool = True, links: bool = True, markdown: bool = False): """ Print tables describing the Network. @@ -128,6 +139,8 @@ class Network(SimComponent): "Switch": self.switch_nodes, "Server": self.server_nodes, "Computer": self.computer_nodes, + "Printer": self.printer_nodes, + "Wireless Router": self.wireless_router_nodes, } if nodes: table = PrettyTable(["Node", "Type", "Operating State"]) diff --git a/src/primaite/simulator/network/hardware/base.py b/src/primaite/simulator/network/hardware/base.py index 38d20e1f..bfa547d2 100644 --- a/src/primaite/simulator/network/hardware/base.py +++ b/src/primaite/simulator/network/hardware/base.py @@ -5,7 +5,7 @@ import secrets from abc import ABC, abstractmethod from ipaddress import IPv4Address, IPv4Network from pathlib import Path -from typing import Any, Dict, Optional, Union +from typing import Any, Dict, Optional, Type, TypeVar, Union from prettytable import MARKDOWN, PrettyTable from pydantic import BaseModel, Field @@ -35,8 +35,11 @@ from primaite.simulator.system.core.software_manager import SoftwareManager from primaite.simulator.system.core.sys_log import SysLog from primaite.simulator.system.processes.process import Process from primaite.simulator.system.services.service import Service +from primaite.simulator.system.software import IOSoftware from primaite.utils.validators import IPV4Address +IOSoftwareClass = TypeVar("IOSoftwareClass", bound=IOSoftware) + _LOGGER = getLogger(__name__) @@ -843,12 +846,58 @@ class Node(SimComponent): ) rm.add_request("os", RequestType(func=self._os_request_manager, validator=_node_is_on)) + self._software_request_manager = RequestManager() + rm.add_request("software_manager", RequestType(func=self._software_request_manager, validator=_node_is_on)) + self._application_manager = RequestManager() + self._software_request_manager.add_request( + name="application", request_type=RequestType(func=self._application_manager) + ) + + self._application_manager.add_request( + name="install", + request_type=RequestType( + func=lambda request, context: RequestResponse.from_bool( + self.application_install_action( + application=self._read_application_type(request[0]), ip_address=request[1] + ) + ) + ), + ) + + self._application_manager.add_request( + name="uninstall", + request_type=RequestType( + func=lambda request, context: RequestResponse.from_bool( + self.application_uninstall_action(application=self._read_application_type(request[0])) + ) + ), + ) + return rm def _install_system_software(self): """Install System Software - software that is usually provided with the OS.""" pass + def _read_application_type(self, application_class_str: str) -> Type[IOSoftwareClass]: + """Wrapper that converts the string from the request manager into the appropriate class for the application.""" + if application_class_str == "DoSBot": + from primaite.simulator.system.applications.red_applications.dos_bot import DoSBot + + return DoSBot + elif application_class_str == "DataManipulationBot": + from primaite.simulator.system.applications.red_applications.data_manipulation_bot import ( + DataManipulationBot, + ) + + return DataManipulationBot + elif application_class_str == "WebBrowser": + from primaite.simulator.system.applications.web_browser import WebBrowser + + return WebBrowser + else: + return 0 + def describe_state(self) -> Dict: """ Produce a dictionary describing the current state of this object. @@ -1257,6 +1306,75 @@ class Node(SimComponent): _LOGGER.info(f"Removed application {application.name} from node {self.hostname}") self._application_request_manager.remove_request(application.name) + def application_install_action(self, application: Application, ip_address: Optional[str] = None) -> bool: + """ + Install an application on this node and configure it. + + This method is useful for allowing agents to take this action. + + :param application: Application object that has not been installed on any node yet. + :type application: Application + :param ip_address: IP address used to configure the application + (target IP for the DoSBot or server IP for the DataManipulationBot) + :type ip_address: str + :return: True if the application is installed successfully, otherwise False. + """ + if application in self: + _LOGGER.warning( + f"Can't add application {application.__name__}" + f"to node {self.hostname}. It's already installed." + ) + return True + + self.software_manager.install(application) + application_instance = self.software_manager.software.get(str(application.__name__)) + self.applications[application_instance.uuid] = application_instance + self.sys_log.info(f"Installed application {application_instance.name}") + _LOGGER.debug(f"Added application {application_instance.name} to node {self.hostname}") + self._application_request_manager.add_request( + application_instance.name, RequestType(func=application_instance._request_manager) + ) + + # Configure application if additional parameters are given + if ip_address: + if application_instance.name == "DoSBot": + application_instance.configure(target_ip_address=IPv4Address(ip_address)) + elif application_instance.name == "DataManipulationBot": + application_instance.configure(server_ip_address=IPv4Address(ip_address)) + else: + pass + + if application_instance.name in self.software_manager.software: + return True + else: + return False + + def application_uninstall_action(self, application: Application) -> bool: + """ + Uninstall and completely remove application from this node. + + This method is useful for allowing agents to take this action. + + :param application: Application object that is currently associated with this node. + :type application: Application + :return: True if the application is uninstalled successfully, otherwise False. + """ + if application.__name__ not in self.software_manager.software: + _LOGGER.warning( + f"Can't remove application {application.__name__}" + f"from node {self.hostname}. It's not installed." + ) + return True + + application_instance = self.software_manager.software.get( + str(application.__name__) + ) # This works because we can't have two applications with the same name on the same node + # self.uninstall_application(application_instance) + self.software_manager.uninstall(application_instance.name) + + if application_instance.name not in self.software_manager.software: + return True + else: + return False + def _shut_down_actions(self): """Actions to perform when the node is shut down.""" # Turn off all the services in the node @@ -1288,4 +1406,6 @@ class Node(SimComponent): def __contains__(self, item: Any) -> bool: if isinstance(item, Service): return item.uuid in self.services + elif isinstance(item, Application): + return item.uuid in self.applications return None diff --git a/src/primaite/simulator/network/hardware/nodes/host/server.py b/src/primaite/simulator/network/hardware/nodes/host/server.py index 9f5157ad..593cd0dd 100644 --- a/src/primaite/simulator/network/hardware/nodes/host/server.py +++ b/src/primaite/simulator/network/hardware/nodes/host/server.py @@ -28,3 +28,9 @@ class Server(HostNode): * Applications: * Web Browser """ + + +class Printer(HostNode): + """Printer? I don't even know her!.""" + + # TODO: Implement printer-specific behaviour diff --git a/src/primaite/simulator/network/hardware/nodes/network/firewall.py b/src/primaite/simulator/network/hardware/nodes/network/firewall.py index d7b1dfd9..08735b3b 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/firewall.py +++ b/src/primaite/simulator/network/hardware/nodes/network/firewall.py @@ -1,9 +1,10 @@ from ipaddress import IPv4Address -from typing import Dict, Final, Optional, Union +from typing import Dict, Final, Union from prettytable import MARKDOWN, PrettyTable -from pydantic import validate_call +from pydantic import Field, validate_call +from primaite.simulator.core import RequestManager, RequestType from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState from primaite.simulator.network.hardware.nodes.network.router import ( AccessControlList, @@ -67,22 +68,34 @@ class Firewall(Router): :ivar str hostname: The Firewall hostname. """ - internal_inbound_acl: Optional[AccessControlList] = None + internal_inbound_acl: AccessControlList = Field( + default_factory=lambda: AccessControlList(name="Internal Inbound", implicit_action=ACLAction.DENY) + ) """Access Control List for managing entering the internal network.""" - internal_outbound_acl: Optional[AccessControlList] = None + internal_outbound_acl: AccessControlList = Field( + default_factory=lambda: AccessControlList(name="Internal Outbound", implicit_action=ACLAction.DENY) + ) """Access Control List for managing traffic leaving the internal network.""" - dmz_inbound_acl: Optional[AccessControlList] = None + dmz_inbound_acl: AccessControlList = Field( + default_factory=lambda: AccessControlList(name="DMZ Inbound", implicit_action=ACLAction.DENY) + ) """Access Control List for managing traffic entering the DMZ.""" - dmz_outbound_acl: Optional[AccessControlList] = None + dmz_outbound_acl: AccessControlList = Field( + default_factory=lambda: AccessControlList(name="DMZ Outbound", implicit_action=ACLAction.DENY) + ) """Access Control List for managing traffic leaving the DMZ.""" - external_inbound_acl: Optional[AccessControlList] = None + external_inbound_acl: AccessControlList = Field( + default_factory=lambda: AccessControlList(name="External Inbound", implicit_action=ACLAction.PERMIT) + ) """Access Control List for managing traffic entering from an external network.""" - external_outbound_acl: Optional[AccessControlList] = None + external_outbound_acl: AccessControlList = Field( + default_factory=lambda: AccessControlList(name="External Outbound", implicit_action=ACLAction.PERMIT) + ) """Access Control List for managing traffic leaving towards an external network.""" def __init__(self, hostname: str, **kwargs): @@ -100,29 +113,85 @@ class Firewall(Router): self.connect_nic( RouterInterface(ip_address="127.0.0.1", subnet_mask="255.0.0.0", gateway="0.0.0.0", port_name="dmz") ) + # Update ACL objects with firewall's hostname and syslog to allow accurate logging + self.internal_inbound_acl.sys_log = kwargs["sys_log"] + self.internal_inbound_acl.name = f"{hostname} - Internal Inbound" - # Initialise ACLs for internal and dmz interfaces with a default DENY policy - self.internal_inbound_acl = AccessControlList( - sys_log=kwargs["sys_log"], implicit_action=ACLAction.DENY, name=f"{hostname} - Internal Inbound" + self.internal_outbound_acl.sys_log = kwargs["sys_log"] + self.internal_outbound_acl.name = f"{hostname} - Internal Outbound" + + self.dmz_inbound_acl.sys_log = kwargs["sys_log"] + self.dmz_inbound_acl.name = f"{hostname} - DMZ Inbound" + + self.dmz_outbound_acl.sys_log = kwargs["sys_log"] + self.dmz_outbound_acl.name = f"{hostname} - DMZ Outbound" + + self.external_inbound_acl.sys_log = kwargs["sys_log"] + self.external_inbound_acl.name = f"{hostname} - External Inbound" + + self.external_outbound_acl.sys_log = kwargs["sys_log"] + self.external_outbound_acl.name = f"{hostname} - External Outbound" + + def _init_request_manager(self) -> RequestManager: + """ + Initialise the request manager. + + More information in user guide and docstring for SimComponent._init_request_manager. + """ + rm = super()._init_request_manager() + self._internal_acl_request_manager = RequestManager() + rm.add_request("internal", RequestType(func=self._internal_acl_request_manager)) + + self._dmz_acl_request_manager = RequestManager() + rm.add_request("dmz", RequestType(func=self._dmz_acl_request_manager)) + + self._external_acl_request_manager = RequestManager() + rm.add_request("external", RequestType(func=self._external_acl_request_manager)) + + self._internal_inbound_acl_request_manager = RequestManager() + self._internal_outbound_acl_request_manager = RequestManager() + self._internal_acl_request_manager.add_request( + "inbound", RequestType(func=self._internal_inbound_acl_request_manager) ) - self.internal_outbound_acl = AccessControlList( - sys_log=kwargs["sys_log"], implicit_action=ACLAction.DENY, name=f"{hostname} - Internal Outbound" - ) - self.dmz_inbound_acl = AccessControlList( - sys_log=kwargs["sys_log"], implicit_action=ACLAction.DENY, name=f"{hostname} - DMZ Inbound" - ) - self.dmz_outbound_acl = AccessControlList( - sys_log=kwargs["sys_log"], implicit_action=ACLAction.DENY, name=f"{hostname} - DMZ Outbound" + self._internal_acl_request_manager.add_request( + "outbound", RequestType(func=self._internal_outbound_acl_request_manager) ) - # external ACLs should have a default PERMIT policy - self.external_inbound_acl = AccessControlList( - sys_log=kwargs["sys_log"], implicit_action=ACLAction.PERMIT, name=f"{hostname} - External Inbound" + self.dmz_inbound_acl_request_manager = RequestManager() + self.dmz_outbound_acl_request_manager = RequestManager() + self._dmz_acl_request_manager.add_request("inbound", RequestType(func=self.dmz_inbound_acl_request_manager)) + self._dmz_acl_request_manager.add_request("outbound", RequestType(func=self.dmz_outbound_acl_request_manager)) + + self.external_inbound_acl_request_manager = RequestManager() + self.external_outbound_acl_request_manager = RequestManager() + self._external_acl_request_manager.add_request( + "inbound", RequestType(func=self.external_inbound_acl_request_manager) ) - self.external_outbound_acl = AccessControlList( - sys_log=kwargs["sys_log"], implicit_action=ACLAction.PERMIT, name=f"{hostname} - External Outbound" + self._external_acl_request_manager.add_request( + "outbound", RequestType(func=self.external_outbound_acl_request_manager) ) + self._internal_inbound_acl_request_manager.add_request( + "acl", RequestType(func=self.internal_inbound_acl._request_manager) + ) + self._internal_outbound_acl_request_manager.add_request( + "acl", RequestType(func=self.internal_outbound_acl._request_manager) + ) + + self.dmz_inbound_acl_request_manager.add_request("acl", RequestType(func=self.dmz_inbound_acl._request_manager)) + self.dmz_outbound_acl_request_manager.add_request( + "acl", RequestType(func=self.dmz_outbound_acl._request_manager) + ) + + self.external_inbound_acl_request_manager.add_request( + "acl", RequestType(func=self.external_inbound_acl._request_manager) + ) + self.external_outbound_acl_request_manager.add_request( + "acl", RequestType(func=self.external_outbound_acl._request_manager) + ) + + return rm + def describe_state(self) -> Dict: """ Describes the current state of the Firewall. diff --git a/src/primaite/simulator/network/hardware/nodes/network/router.py b/src/primaite/simulator/network/hardware/nodes/network/router.py index 69ab6a82..9e6ba6ac 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/router.py +++ b/src/primaite/simulator/network/hardware/nodes/network/router.py @@ -277,7 +277,7 @@ class AccessControlList(SimComponent): :ivar int max_acl_rules: The maximum number of ACL rules that can be added to the list. Defaults to 25. """ - sys_log: SysLog + sys_log: Optional[SysLog] = None implicit_action: ACLAction implicit_rule: ACLRule max_acl_rules: int = 25 @@ -1420,7 +1420,7 @@ class Router(NetworkNode): :return: Configured router. :rtype: Router """ - router = Router( + router = cls( hostname=cfg["hostname"], num_ports=int(cfg.get("num_ports", "5")), operating_state=NodeOperatingState.ON @@ -1443,6 +1443,8 @@ class Router(NetworkNode): protocol=None if not (p := r_cfg.get("protocol")) else IPProtocol[p], src_ip_address=r_cfg.get("src_ip"), dst_ip_address=r_cfg.get("dst_ip"), + src_wildcard_mask=r_cfg.get("src_wildcard_mask"), + dst_wildcard_mask=r_cfg.get("dst_wildcard_mask"), position=r_num, ) if "routes" in cfg: diff --git a/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py b/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py index 3e8d715f..62332269 100644 --- a/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py +++ b/src/primaite/simulator/network/hardware/nodes/network/wireless_router.py @@ -1,10 +1,14 @@ +from ipaddress import IPv4Address from typing import Any, Dict, Union from pydantic import validate_call from primaite.simulator.network.airspace import AirSpaceFrequency, IPWirelessNetworkInterface -from primaite.simulator.network.hardware.nodes.network.router import Router, RouterInterface +from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState +from primaite.simulator.network.hardware.nodes.network.router import ACLAction, Router, RouterInterface from primaite.simulator.network.transmission.data_link_layer import Frame +from primaite.simulator.network.transmission.network_layer import IPProtocol +from primaite.simulator.network.transmission.transport_layer import Port from primaite.utils.validators import IPV4Address @@ -209,3 +213,68 @@ class WirelessRouter(Router): raise NotImplementedError( "Please use the 'configure_wireless_access_point' and 'configure_router_interface' functions." ) + + @classmethod + def from_config(cls, cfg: Dict) -> "WirelessRouter": + """Generate the wireless router from config. + + Schema: + - hostname (str): unique name for this router. + - router_interface (dict): The values should be another dict specifying + - ip_address (str) + - subnet_mask (str) + - wireless_access_point (dict): Dict with + - ip address, + - subnet mask, + - frequency, (string: either WIFI_2_4 or WIFI_5) + - acl (dict): Dict with integers from 1 - max_acl_rules as keys. The key defines the position within the ACL + where the rule will be added (lower number is resolved first). The values should describe valid ACL + Rules as: + - action (str): either PERMIT or DENY + - src_port (str, optional): the named port such as HTTP, HTTPS, or POSTGRES_SERVER + - dst_port (str, optional): the named port such as HTTP, HTTPS, or POSTGRES_SERVER + - protocol (str, optional): the named IP protocol such as ICMP, TCP, or UDP + - src_ip_address (str, optional): IP address octet written in base 10 + - dst_ip_address (str, optional): IP address octet written in base 10 + + :param cfg: Config dictionary + :type cfg: Dict + :return: WirelessRouter instance. + :rtype: WirelessRouter + """ + operating_state = ( + NodeOperatingState.ON if not (p := cfg.get("operating_state")) else NodeOperatingState[p.upper()] + ) + router = cls(hostname=cfg["hostname"], operating_state=operating_state) + if "router_interface" in cfg: + ip_address = cfg["router_interface"]["ip_address"] + subnet_mask = cfg["router_interface"]["subnet_mask"] + router.configure_router_interface(ip_address=ip_address, subnet_mask=subnet_mask) + if "wireless_access_point" in cfg: + ip_address = cfg["wireless_access_point"]["ip_address"] + subnet_mask = cfg["wireless_access_point"]["subnet_mask"] + frequency = AirSpaceFrequency[cfg["wireless_access_point"]["frequency"]] + router.configure_wireless_access_point(ip_address=ip_address, subnet_mask=subnet_mask, frequency=frequency) + + if "acl" in cfg: + for r_num, r_cfg in cfg["acl"].items(): + router.acl.add_rule( + action=ACLAction[r_cfg["action"]], + src_port=None if not (p := r_cfg.get("src_port")) else Port[p], + dst_port=None if not (p := r_cfg.get("dst_port")) else Port[p], + protocol=None if not (p := r_cfg.get("protocol")) else IPProtocol[p], + src_ip_address=r_cfg.get("src_ip"), + dst_ip_address=r_cfg.get("dst_ip"), + src_wildcard_mask=r_cfg.get("src_wildcard_mask"), + dst_wildcard_mask=r_cfg.get("dst_wildcard_mask"), + position=r_num, + ) + if "routes" in cfg: + for route in cfg.get("routes"): + router.route_table.add_route( + address=IPv4Address(route.get("address")), + subnet_mask=IPv4Address(route.get("subnet_mask", "255.255.255.0")), + next_hop_ip_address=IPv4Address(route.get("next_hop_ip_address")), + metric=float(route.get("metric", 0)), + ) + return router diff --git a/src/primaite/simulator/system/software.py b/src/primaite/simulator/system/software.py index ab60adde..3ab32bc6 100644 --- a/src/primaite/simulator/system/software.py +++ b/src/primaite/simulator/system/software.py @@ -88,7 +88,7 @@ class Software(SimComponent): "The count of times the software has been scanned, defaults to 0." revealed_to_red: bool = False "Indicates if the software has been revealed to red agent, defaults is False." - software_manager: "SoftwareManager" = None + software_manager: Optional["SoftwareManager"] = None "An instance of Software Manager that is used by the parent node." sys_log: SysLog = None "An instance of SysLog that is used by the parent node." diff --git a/tests/assets/configs/bad_primaite_session.yaml b/tests/assets/configs/bad_primaite_session.yaml index c613008e..d07a0376 100644 --- a/tests/assets/configs/bad_primaite_session.yaml +++ b/tests/assets/configs/bad_primaite_session.yaml @@ -175,14 +175,10 @@ agents: - type: NODE_SHUTDOWN - type: NODE_STARTUP - type: NODE_RESET - - type: NETWORK_ACL_ADDRULE - options: - target_router_hostname: router_1 - - type: NETWORK_ACL_REMOVERULE - options: - target_router_hostname: router_1 - - type: NETWORK_NIC_ENABLE - - type: NETWORK_NIC_DISABLE + - type: ROUTER_ACL_ADDRULE + - type: ROUTER_ACL_REMOVERULE + - type: HOST_NIC_ENABLE + - type: HOST_NIC_DISABLE action_map: 0: @@ -297,8 +293,9 @@ agents: options: node_id: 5 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -307,8 +304,9 @@ agents: dest_port_id: 1 protocol_id: 1 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -317,8 +315,9 @@ agents: dest_port_id: 1 protocol_id: 1 24: # block tcp traffic from client 1 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -327,8 +326,9 @@ agents: dest_port_id: 1 protocol_id: 3 25: # block tcp traffic from client 2 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -337,8 +337,9 @@ agents: dest_port_id: 1 protocol_id: 3 26: - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -347,8 +348,9 @@ agents: dest_port_id: 1 protocol_id: 3 27: - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -357,122 +359,132 @@ agents: dest_port_id: 1 protocol_id: 3 28: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 0 29: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 1 30: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 2 31: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 3 32: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 4 33: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 5 34: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 6 35: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 7 36: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 8 37: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 9 38: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 0 nic_id: 0 39: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 0 nic_id: 0 40: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 1 nic_id: 0 41: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 1 nic_id: 0 42: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 2 nic_id: 0 43: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 2 nic_id: 0 44: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 3 nic_id: 0 45: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 3 nic_id: 0 46: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 0 47: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 0 48: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 1 49: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 1 50: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 5 nic_id: 0 51: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 5 nic_id: 0 52: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 6 nic_id: 0 53: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 6 nic_id: 0 diff --git a/tests/assets/configs/basic_firewall.yaml b/tests/assets/configs/basic_firewall.yaml index 5de704dc..da293167 100644 --- a/tests/assets/configs/basic_firewall.yaml +++ b/tests/assets/configs/basic_firewall.yaml @@ -46,6 +46,15 @@ agents: action_list: - type: DONOTHING - type: NODE_APPLICATION_EXECUTE + action_map: + 0: + action: DONOTHING + options: {} + 1: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 0 options: nodes: - node_name: client_2 diff --git a/tests/assets/configs/basic_switched_network.yaml b/tests/assets/configs/basic_switched_network.yaml index aab6b780..9dfeae06 100644 --- a/tests/assets/configs/basic_switched_network.yaml +++ b/tests/assets/configs/basic_switched_network.yaml @@ -46,6 +46,15 @@ agents: action_list: - type: DONOTHING - type: NODE_APPLICATION_EXECUTE + action_map: + 0: + action: DONOTHING + options: {} + 1: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 0 options: nodes: - node_name: client_2 diff --git a/tests/assets/configs/dmz_network.yaml b/tests/assets/configs/dmz_network.yaml index 076c174a..acac301a 100644 --- a/tests/assets/configs/dmz_network.yaml +++ b/tests/assets/configs/dmz_network.yaml @@ -71,6 +71,15 @@ agents: action_list: - type: DONOTHING - type: NODE_APPLICATION_EXECUTE + action_map: + 0: + action: DONOTHING + options: {} + 1: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 0 options: nodes: - node_name: client_1 diff --git a/tests/assets/configs/eval_only_primaite_session.yaml b/tests/assets/configs/eval_only_primaite_session.yaml index a4450264..8723ae38 100644 --- a/tests/assets/configs/eval_only_primaite_session.yaml +++ b/tests/assets/configs/eval_only_primaite_session.yaml @@ -30,7 +30,10 @@ agents: action_space: action_list: - type: DONOTHING - + action_map: + 0: + action: DONOTHING + options: {} options: nodes: - node_name: client_2 @@ -63,6 +66,15 @@ agents: - type: NODE_FILE_DELETE - type: NODE_FILE_CORRUPT - type: NODE_OS_SCAN + action_map: + 0: + action: DONOTHING + options: {} + 1: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 0 options: nodes: - node_name: client_1 @@ -179,14 +191,10 @@ agents: - type: NODE_SHUTDOWN - type: NODE_STARTUP - type: NODE_RESET - - type: NETWORK_ACL_ADDRULE - options: - target_router_hostname: router_1 - - type: NETWORK_ACL_REMOVERULE - options: - target_router_hostname: router_1 - - type: NETWORK_NIC_ENABLE - - type: NETWORK_NIC_DISABLE + - type: ROUTER_ACL_ADDRULE + - type: ROUTER_ACL_REMOVERULE + - type: HOST_NIC_ENABLE + - type: HOST_NIC_DISABLE action_map: 0: @@ -301,8 +309,9 @@ agents: options: node_id: 5 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -311,8 +320,9 @@ agents: dest_port_id: 1 protocol_id: 1 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -321,8 +331,9 @@ agents: dest_port_id: 1 protocol_id: 1 24: # block tcp traffic from client 1 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -331,8 +342,9 @@ agents: dest_port_id: 1 protocol_id: 3 25: # block tcp traffic from client 2 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -341,8 +353,9 @@ agents: dest_port_id: 1 protocol_id: 3 26: - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -351,8 +364,9 @@ agents: dest_port_id: 1 protocol_id: 3 27: - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -361,122 +375,132 @@ agents: dest_port_id: 1 protocol_id: 3 28: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 0 29: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 1 30: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 2 31: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 3 32: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 4 33: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 5 34: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 6 35: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 7 36: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 8 37: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 9 38: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 0 nic_id: 0 39: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 0 nic_id: 0 40: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 1 nic_id: 0 41: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 1 nic_id: 0 42: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 2 nic_id: 0 43: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 2 nic_id: 0 44: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 3 nic_id: 0 45: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 3 nic_id: 0 46: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 0 47: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 0 48: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 1 49: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 1 50: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 5 nic_id: 0 51: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 5 nic_id: 0 52: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 6 nic_id: 0 53: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 6 nic_id: 0 diff --git a/tests/assets/configs/firewall_actions_network.yaml b/tests/assets/configs/firewall_actions_network.yaml new file mode 100644 index 00000000..b7848c53 --- /dev/null +++ b/tests/assets/configs/firewall_actions_network.yaml @@ -0,0 +1,460 @@ +# Network with DMZ +# +# An example network configuration with an internal network, a DMZ network and a couple of external networks. +# +# ............................................................................ +# . . +# . Internal Network . +# . . +# . -------------- -------------- -------------- . +# . | client_1 |------| switch_1 |--------| router_1 | . +# . -------------- -------------- -------------- . +# . (Computer) | . +# ........................................................|................... +# | +# | +# ........................................................|................... +# . | . +# . DMZ Network | . +# . | . +# . ---------------- -------------- -------------- . +# . | dmz_server |------| switch_2 |------| firewall | . +# . ---------------- -------------- -------------- . +# . (Server) | . +# ........................................................|................... +# | +# External Network | +# | +# | +# ----------------------- -------------- --------------------- +# | external_computer |------| switch_3 |------| external_server | +# ----------------------- -------------- --------------------- +# +training_config: + rl_framework: SB3 + rl_algorithm: PPO + seed: 333 + n_learn_episodes: 1 + n_eval_episodes: 5 + max_steps_per_episode: 128 + deterministic_eval: false + n_agents: 1 + agent_references: + - defender + +io_settings: + save_step_metadata: false + save_pcap_logs: true + save_sys_logs: true + + +game: + max_episode_length: 256 + ports: + - ARP + - DNS + - HTTP + - POSTGRES_SERVER + protocols: + - ICMP + - TCP + - UDP + +agents: + - ref: defender + team: BLUE + type: ProxyAgent + observation_space: + type: UC2BlueObservation + options: + num_services_per_node: 1 + num_folders_per_node: 1 + num_files_per_folder: 1 + num_nics_per_node: 2 + nodes: + - node_hostname: client_1 + links: + - link_ref: client_1___switch_1 + acl: + options: + max_acl_rules: 10 + router_hostname: router_1 + ip_address_order: + - node_hostname: client_1 + nic_num: 1 + ics: null + action_space: + action_list: + - type: DONOTHING + - type: FIREWALL_ACL_ADDRULE + - type: FIREWALL_ACL_REMOVERULE + - type: NETWORK_PORT_DISABLE + - type: NETWORK_PORT_ENABLE + action_map: + 0: + action: DONOTHING + options: {} + 1: + action: FIREWALL_ACL_ADDRULE + options: + target_firewall_nodename: firewall + firewall_port_name: internal + firewall_port_direction: inbound + position: 1 + permission: 1 + source_ip_id: 2 # client 1 + dest_ip_id: 1 # ALL + source_port_id: 1 + dest_port_id: 1 + protocol_id: 1 + 2: + action: FIREWALL_ACL_REMOVERULE + options: + target_firewall_nodename: firewall + firewall_port_name: internal + firewall_port_direction: inbound + position: 1 + 3: + action: FIREWALL_ACL_ADDRULE + options: + target_firewall_nodename: firewall + firewall_port_name: internal + firewall_port_direction: outbound + position: 1 + permission: 2 + source_ip_id: 2 # client 1 + dest_ip_id: 1 # ALL + source_port_id: 2 + dest_port_id: 3 + protocol_id: 2 + 4: + action: FIREWALL_ACL_REMOVERULE + options: + target_firewall_nodename: firewall + firewall_port_name: internal + firewall_port_direction: outbound + position: 1 + 5: + action: FIREWALL_ACL_ADDRULE + options: + target_firewall_nodename: firewall + firewall_port_name: dmz + firewall_port_direction: inbound + position: 1 + permission: 2 + source_ip_id: 3 # dmz_server + dest_ip_id: 2 # client_1 + source_port_id: 4 + dest_port_id: 4 + protocol_id: 4 + 6: + action: FIREWALL_ACL_REMOVERULE + options: + target_firewall_nodename: firewall + firewall_port_name: dmz + firewall_port_direction: inbound + position: 1 + 7: + action: FIREWALL_ACL_ADDRULE + options: + target_firewall_nodename: firewall + firewall_port_name: dmz + firewall_port_direction: outbound + position: 2 + permission: 2 + source_ip_id: 3 # dmz_server + dest_ip_id: 2 # client_1 + source_port_id: 4 + dest_port_id: 4 + protocol_id: 3 + 8: + action: FIREWALL_ACL_REMOVERULE + options: + target_firewall_nodename: firewall + firewall_port_name: dmz + firewall_port_direction: outbound + position: 2 + 9: + action: FIREWALL_ACL_ADDRULE + options: + target_firewall_nodename: firewall + firewall_port_name: external + firewall_port_direction: inbound + position: 10 + permission: 2 + source_ip_id: 4 # external_computer + dest_ip_id: 3 # dmz + source_port_id: 5 + dest_port_id: 5 + protocol_id: 2 + 10: + action: FIREWALL_ACL_REMOVERULE + options: + target_firewall_nodename: firewall + firewall_port_name: external + firewall_port_direction: inbound + position: 10 + 11: + action: FIREWALL_ACL_ADDRULE + options: + target_firewall_nodename: firewall + firewall_port_name: external + firewall_port_direction: outbound + position: 1 + permission: 2 + source_ip_id: 4 # external_computer + dest_ip_id: 2 # client_1 + source_port_id: 1 + dest_port_id: 1 + protocol_id: 1 + 12: + action: FIREWALL_ACL_REMOVERULE + options: + target_firewall_nodename: firewall + firewall_port_name: external + firewall_port_direction: outbound + position: 1 + 13: + action: NETWORK_PORT_DISABLE + options: + target_nodename: firewall + port_id: 3 + 14: + action: NETWORK_PORT_ENABLE + options: + target_nodename: firewall + port_id: 3 + options: + nodes: + - node_name: client_1 + - node_name: dmz_server + - node_name: external_computer + ip_address_order: + - node_name: client_1 + nic_num: 1 + - node_name: dmz_server + nic_num: 1 + - node_name: external_computer + nic_num: 1 + max_folders_per_node: 2 + max_files_per_folder: 2 + max_services_per_node: 2 + max_nics_per_node: 8 + max_acl_rules: 10 + reward_function: + reward_components: + - type: DUMMY + + agent_settings: + start_settings: + start_step: 5 + frequency: 4 + variance: 3 + + + +simulation: + network: + nodes: + - ref: client_1 + type: computer + hostname: client_1 + ip_address: 192.168.0.10 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.0.1 + dns_server: 192.168.20.11 + start_up_duration: 0 + shut_down_duration: 0 + + - ref: switch_1 + type: switch + hostname: switch_1 + num_ports: 8 + start_up_duration: 0 + shut_down_duration: 0 + + - ref: router_1 + type: router + hostname: router_1 + num_ports: 5 + start_up_duration: 0 + shut_down_duration: 0 + ports: + 1: + ip_address: 192.168.0.1 + subnet_mask: 255.255.255.0 + 2: + ip_address: 192.168.1.1 + subnet_mask: 255.255.255.0 + acl: + 22: + action: PERMIT + src_port: ARP + dst_port: ARP + 23: + action: PERMIT + protocol: ICMP + routes: + - address: 192.168.10.10 # route to dmz_server + subnet_mask: 255.255.255.0 + next_hop_ip_address: 192.168.1.2 + metric: 0 + - address: 192.168.20.10 # route to external_computer + subnet_mask: 255.255.255.0 + next_hop_ip_address: 192.168.1.2 + metric: 0 + - address: 192.168.20.11 # route to external_server + subnet_mask: 255.255.255.0 + next_hop_ip_address: 192.168.1.2 + metric: 0 + + - ref: dmz_server + type: server + hostname: dmz_server + ip_address: 192.168.10.10 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.10.1 + dns_server: 192.168.20.11 + start_up_duration: 0 + shut_down_duration: 0 + + - ref: switch_2 + type: switch + hostname: switch_2 + num_ports: 8 + start_up_duration: 0 + shut_down_duration: 0 + + - ref: firewall + type: firewall + hostname: firewall + start_up_duration: 0 + shut_down_duration: 0 + ports: + external_port: # port 1 + ip_address: 192.168.20.1 + subnet_mask: 255.255.255.0 + internal_port: # port 2 + ip_address: 192.168.1.2 + subnet_mask: 255.255.255.0 + dmz_port: # port 3 + ip_address: 192.168.10.1 + subnet_mask: 255.255.255.0 + acl: + internal_inbound_acl: + 22: + action: PERMIT + src_port: ARP + dst_port: ARP + 23: + action: PERMIT + protocol: ICMP + internal_outbound_acl: + 22: + action: PERMIT + src_port: ARP + dst_port: ARP + 23: + action: PERMIT + protocol: ICMP + dmz_inbound_acl: + 22: + action: PERMIT + src_port: ARP + dst_port: ARP + 23: + action: PERMIT + protocol: ICMP + dmz_outbound_acl: + 22: + action: PERMIT + src_port: ARP + dst_port: ARP + 23: + action: PERMIT + protocol: ICMP + external_inbound_acl: + 22: + action: PERMIT + src_port: ARP + dst_port: ARP + external_outbound_acl: + 22: + action: PERMIT + src_port: ARP + dst_port: ARP + routes: + - address: 192.168.0.10 # route to client_1 + subnet_mask: 255.255.255.0 + next_hop_ip_address: 192.168.1.1 + metric: 0 + + - ref: switch_3 + type: switch + hostname: switch_3 + num_ports: 8 + start_up_duration: 0 + shut_down_duration: 0 + + - ref: external_computer + type: computer + hostname: external_computer + ip_address: 192.168.20.10 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.20.1 + dns_server: 192.168.20.11 + start_up_duration: 0 + shut_down_duration: 0 + + - ref: external_server + type: server + hostname: external_server + ip_address: 192.168.20.11 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.20.1 + start_up_duration: 0 + shut_down_duration: 0 + services: + - ref: domain_controller_dns_server + type: DNSServer + links: + - ref: client_1___switch_1 + endpoint_a_ref: client_1 + endpoint_a_port: 1 + endpoint_b_ref: switch_1 + endpoint_b_port: 1 + - ref: router_1___switch_1 + endpoint_a_ref: router_1 + endpoint_a_port: 1 + endpoint_b_ref: switch_1 + endpoint_b_port: 8 + - ref: router_1___firewall + endpoint_a_ref: firewall + endpoint_a_port: 2 # internal firewall port + endpoint_b_ref: router_1 + endpoint_b_port: 2 + - ref: firewall___switch_2 + endpoint_a_ref: firewall + endpoint_a_port: 3 # dmz firewall port + endpoint_b_ref: switch_2 + endpoint_b_port: 8 + - ref: dmz_server___switch_2 + endpoint_a_ref: dmz_server + endpoint_a_port: 1 + endpoint_b_ref: switch_2 + endpoint_b_port: 1 + - ref: firewall___switch_3 + endpoint_a_ref: firewall + endpoint_a_port: 1 # external firewall port + endpoint_b_ref: switch_3 + endpoint_b_port: 8 + - ref: external_computer___switch_3 + endpoint_a_ref: external_computer + endpoint_a_port: 1 + endpoint_b_ref: switch_3 + endpoint_b_port: 1 + - ref: external_server___switch_3 + endpoint_a_ref: external_server + endpoint_a_port: 1 + endpoint_b_ref: switch_3 + endpoint_b_port: 2 diff --git a/tests/assets/configs/multi_agent_session.yaml b/tests/assets/configs/multi_agent_session.yaml index 8723e71a..dd416523 100644 --- a/tests/assets/configs/multi_agent_session.yaml +++ b/tests/assets/configs/multi_agent_session.yaml @@ -186,14 +186,10 @@ agents: - type: NODE_SHUTDOWN - type: NODE_STARTUP - type: NODE_RESET - - type: NETWORK_ACL_ADDRULE - options: - target_router_hostname: router_1 - - type: NETWORK_ACL_REMOVERULE - options: - target_router_hostname: router_1 - - type: NETWORK_NIC_ENABLE - - type: NETWORK_NIC_DISABLE + - type: ROUTER_ACL_ADDRULE + - type: ROUTER_ACL_REMOVERULE + - type: HOST_NIC_ENABLE + - type: HOST_NIC_DISABLE action_map: 0: @@ -308,8 +304,9 @@ agents: options: node_id: 5 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -318,8 +315,9 @@ agents: dest_port_id: 1 protocol_id: 1 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -328,8 +326,9 @@ agents: dest_port_id: 1 protocol_id: 1 24: # block tcp traffic from client 1 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -338,8 +337,9 @@ agents: dest_port_id: 1 protocol_id: 3 25: # block tcp traffic from client 2 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -348,8 +348,9 @@ agents: dest_port_id: 1 protocol_id: 3 26: - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -358,8 +359,9 @@ agents: dest_port_id: 1 protocol_id: 3 27: - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -368,122 +370,132 @@ agents: dest_port_id: 1 protocol_id: 3 28: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 0 29: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 1 30: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 2 31: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 3 32: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 4 33: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 5 34: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 6 35: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 7 36: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 8 37: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 9 38: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 0 nic_id: 0 39: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 0 nic_id: 0 40: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 1 nic_id: 0 41: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 1 nic_id: 0 42: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 2 nic_id: 0 43: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 2 nic_id: 0 44: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 3 nic_id: 0 45: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 3 nic_id: 0 46: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 0 47: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 0 48: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 1 49: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 1 50: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 5 nic_id: 0 51: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 5 nic_id: 0 52: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 6 nic_id: 0 53: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 6 nic_id: 0 @@ -640,14 +652,10 @@ agents: - type: NODE_SHUTDOWN - type: NODE_STARTUP - type: NODE_RESET - - type: NETWORK_ACL_ADDRULE - options: - target_router_hostname: router_1 - - type: NETWORK_ACL_REMOVERULE - options: - target_router_hostname: router_1 - - type: NETWORK_NIC_ENABLE - - type: NETWORK_NIC_DISABLE + - type: ROUTER_ACL_ADDRULE + - type: ROUTER_ACL_REMOVERULE + - type: HOST_NIC_ENABLE + - type: HOST_NIC_DISABLE action_map: 0: @@ -762,8 +770,9 @@ agents: options: node_id: 5 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -772,8 +781,9 @@ agents: dest_port_id: 1 protocol_id: 1 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -782,8 +792,9 @@ agents: dest_port_id: 1 protocol_id: 1 24: # block tcp traffic from client 1 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -792,8 +803,9 @@ agents: dest_port_id: 1 protocol_id: 3 25: # block tcp traffic from client 2 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -802,8 +814,9 @@ agents: dest_port_id: 1 protocol_id: 3 26: - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -812,8 +825,9 @@ agents: dest_port_id: 1 protocol_id: 3 27: - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -822,122 +836,132 @@ agents: dest_port_id: 1 protocol_id: 3 28: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 0 29: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 1 30: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 2 31: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 3 32: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 4 33: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 5 34: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 6 35: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 7 36: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 8 37: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 9 38: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 0 nic_id: 0 39: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 0 nic_id: 0 40: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 1 nic_id: 0 41: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 1 nic_id: 0 42: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 2 nic_id: 0 43: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 2 nic_id: 0 44: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 3 nic_id: 0 45: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 3 nic_id: 0 46: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 0 47: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 0 48: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 1 49: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 1 50: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 5 nic_id: 0 51: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 5 nic_id: 0 52: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 6 nic_id: 0 53: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 6 nic_id: 0 diff --git a/tests/assets/configs/shared_rewards.yaml b/tests/assets/configs/shared_rewards.yaml index 9acf3ad5..4b925844 100644 --- a/tests/assets/configs/shared_rewards.yaml +++ b/tests/assets/configs/shared_rewards.yaml @@ -265,14 +265,10 @@ agents: - type: NODE_SHUTDOWN - type: NODE_STARTUP - type: NODE_RESET - - type: NETWORK_ACL_ADDRULE - options: - target_router_hostname: router_1 - - type: NETWORK_ACL_REMOVERULE - options: - target_router_hostname: router_1 - - type: NETWORK_NIC_ENABLE - - type: NETWORK_NIC_DISABLE + - type: ROUTER_ACL_ADDRULE + - type: ROUTER_ACL_REMOVERULE + - type: HOST_NIC_ENABLE + - type: HOST_NIC_DISABLE action_map: 0: @@ -484,8 +480,9 @@ agents: node_id: 6 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -494,8 +491,9 @@ agents: dest_port_id: 1 protocol_id: 1 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -504,8 +502,9 @@ agents: dest_port_id: 1 protocol_id: 1 48: # old action num: 24 # block tcp traffic from client 1 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -514,8 +513,9 @@ agents: dest_port_id: 1 protocol_id: 3 49: # old action num: 25 # block tcp traffic from client 2 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -524,8 +524,9 @@ agents: dest_port_id: 1 protocol_id: 3 50: # old action num: 26 - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -534,8 +535,9 @@ agents: dest_port_id: 1 protocol_id: 3 51: # old action num: 27 - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -544,122 +546,132 @@ agents: dest_port_id: 1 protocol_id: 3 52: # old action num: 28 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 0 53: # old action num: 29 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 1 54: # old action num: 30 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 2 55: # old action num: 31 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 3 56: # old action num: 32 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 4 57: # old action num: 33 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 5 58: # old action num: 34 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 6 59: # old action num: 35 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 7 60: # old action num: 36 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 8 61: # old action num: 37 - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 9 62: # old action num: 38 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 0 nic_id: 0 63: # old action num: 39 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 0 nic_id: 0 64: # old action num: 40 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 1 nic_id: 0 65: # old action num: 41 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 1 nic_id: 0 66: # old action num: 42 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 2 nic_id: 0 67: # old action num: 43 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 2 nic_id: 0 68: # old action num: 44 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 3 nic_id: 0 69: # old action num: 45 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 3 nic_id: 0 70: # old action num: 46 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 0 71: # old action num: 47 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 0 72: # old action num: 48 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 1 73: # old action num: 49 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 1 74: # old action num: 50 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 5 nic_id: 0 75: # old action num: 51 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 5 nic_id: 0 76: # old action num: 52 - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 6 nic_id: 0 77: # old action num: 53 - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 6 nic_id: 0 diff --git a/tests/assets/configs/test_application_install.yaml b/tests/assets/configs/test_application_install.yaml new file mode 100644 index 00000000..b3fca4bc --- /dev/null +++ b/tests/assets/configs/test_application_install.yaml @@ -0,0 +1,998 @@ +training_config: + rl_framework: SB3 + rl_algorithm: PPO + seed: 333 + n_learn_episodes: 1 + n_eval_episodes: 5 + max_steps_per_episode: 128 + deterministic_eval: false + n_agents: 1 + agent_references: + - defender + +io_settings: + save_agent_actions: true + save_step_metadata: false + save_pcap_logs: false + save_sys_logs: false + + +game: + max_episode_length: 128 + ports: + - HTTP + - POSTGRES_SERVER + protocols: + - ICMP + - TCP + - UDP + thresholds: + nmne: + high: 10 + medium: 5 + low: 0 + +agents: + - ref: client_2_green_user + team: GREEN + type: ProbabilisticAgent + agent_settings: + action_probabilities: + 0: 0.3 + 1: 0.6 + 2: 0.1 + observation_space: + type: UC2GreenObservation + action_space: + action_list: + - type: DONOTHING + - type: NODE_APPLICATION_EXECUTE + options: + nodes: + - node_name: client_2 + applications: + - application_name: WebBrowser + - application_name: DatabaseClient + max_folders_per_node: 1 + max_files_per_folder: 1 + max_services_per_node: 1 + max_applications_per_node: 2 + action_map: + 0: + action: DONOTHING + options: {} + 1: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 0 + 2: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 1 + + reward_function: + reward_components: + - type: WEBPAGE_UNAVAILABLE_PENALTY + weight: 0.25 + options: + node_hostname: client_2 + - type: GREEN_ADMIN_DATABASE_UNREACHABLE_PENALTY + weight: 0.05 + options: + node_hostname: client_2 + + - ref: client_1_green_user + team: GREEN + type: ProbabilisticAgent + agent_settings: + action_probabilities: + 0: 0.3 + 1: 0.6 + 2: 0.1 + observation_space: + type: UC2GreenObservation + action_space: + action_list: + - type: DONOTHING + - type: NODE_APPLICATION_EXECUTE + options: + nodes: + - node_name: client_1 + applications: + - application_name: WebBrowser + - application_name: DatabaseClient + max_folders_per_node: 1 + max_files_per_folder: 1 + max_services_per_node: 1 + max_applications_per_node: 2 + action_map: + 0: + action: DONOTHING + options: {} + 1: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 0 + 2: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 1 + + reward_function: + reward_components: + - type: WEBPAGE_UNAVAILABLE_PENALTY + weight: 0.25 + options: + node_hostname: client_1 + - type: GREEN_ADMIN_DATABASE_UNREACHABLE_PENALTY + weight: 0.05 + options: + node_hostname: client_1 + + + + + + - ref: data_manipulation_attacker + team: RED + type: RedDatabaseCorruptingAgent + + observation_space: + type: UC2RedObservation + options: + nodes: {} + + action_space: + action_list: + - type: DONOTHING + - type: NODE_APPLICATION_EXECUTE + options: + nodes: + - node_name: client_1 + applications: + - application_name: DataManipulationBot + - node_name: client_2 + applications: + - application_name: DataManipulationBot + max_folders_per_node: 1 + max_files_per_folder: 1 + max_services_per_node: 1 + + reward_function: + reward_components: + - type: DUMMY + + agent_settings: # options specific to this particular agent type, basically args of __init__(self) + start_settings: + start_step: 25 + frequency: 20 + variance: 5 + + - ref: defender + team: BLUE + type: ProxyAgent + + observation_space: + type: UC2BlueObservation + options: + num_services_per_node: 1 + num_folders_per_node: 1 + num_files_per_folder: 1 + num_nics_per_node: 2 + nodes: + - node_hostname: domain_controller + services: + - service_name: DNSServer + - node_hostname: web_server + services: + - service_name: WebServer + - node_hostname: database_server + folders: + - folder_name: database + files: + - file_name: database.db + - node_hostname: backup_server + - node_hostname: security_suite + - node_hostname: client_1 + - node_hostname: client_2 + links: + - link_ref: router_1___switch_1 + - link_ref: router_1___switch_2 + - link_ref: switch_1___domain_controller + - link_ref: switch_1___web_server + - link_ref: switch_1___database_server + - link_ref: switch_1___backup_server + - link_ref: switch_1___security_suite + - link_ref: switch_2___client_1 + - link_ref: switch_2___client_2 + - link_ref: switch_2___security_suite + acl: + options: + max_acl_rules: 10 + router_hostname: router_1 + ip_address_order: + - node_hostname: domain_controller + nic_num: 1 + - node_hostname: web_server + nic_num: 1 + - node_hostname: database_server + nic_num: 1 + - node_hostname: backup_server + nic_num: 1 + - node_hostname: security_suite + nic_num: 1 + - node_hostname: client_1 + nic_num: 1 + - node_hostname: client_2 + nic_num: 1 + - node_hostname: security_suite + nic_num: 2 + ics: null + + action_space: + action_list: + - type: DONOTHING + - type: NODE_SERVICE_SCAN + - type: NODE_SERVICE_STOP + - type: NODE_SERVICE_START + - type: NODE_SERVICE_PAUSE + - type: NODE_SERVICE_RESUME + - type: NODE_SERVICE_RESTART + - type: NODE_SERVICE_DISABLE + - type: NODE_SERVICE_ENABLE + - type: NODE_SERVICE_FIX + - type: NODE_FILE_SCAN + - type: NODE_FILE_CHECKHASH + - type: NODE_FILE_DELETE + - type: NODE_FILE_REPAIR + - type: NODE_FILE_RESTORE + - type: NODE_FOLDER_SCAN + - type: NODE_FOLDER_CHECKHASH + - type: NODE_FOLDER_REPAIR + - type: NODE_FOLDER_RESTORE + - type: NODE_OS_SCAN + - type: NODE_SHUTDOWN + - type: NODE_STARTUP + - type: NODE_RESET + - type: ROUTER_ACL_ADDRULE + - type: ROUTER_ACL_REMOVERULE + - type: HOST_NIC_ENABLE + - type: HOST_NIC_DISABLE + - type: NODE_APPLICATION_INSTALL + - type: NODE_APPLICATION_REMOVE + - type: NODE_APPLICATION_EXECUTE + + action_map: + 0: + action: DONOTHING + options: {} + # scan webapp service + 1: + action: NODE_SERVICE_SCAN + options: + node_id: 1 + service_id: 0 + # stop webapp service + 2: + action: NODE_SERVICE_STOP + options: + node_id: 1 + service_id: 0 + # start webapp service + 3: + action: "NODE_SERVICE_START" + options: + node_id: 1 + service_id: 0 + 4: + action: "NODE_SERVICE_PAUSE" + options: + node_id: 1 + service_id: 0 + 5: + action: "NODE_SERVICE_RESUME" + options: + node_id: 1 + service_id: 0 + 6: + action: "NODE_SERVICE_RESTART" + options: + node_id: 1 + service_id: 0 + 7: + action: "NODE_SERVICE_DISABLE" + options: + node_id: 1 + service_id: 0 + 8: + action: "NODE_SERVICE_ENABLE" + options: + node_id: 1 + service_id: 0 + 9: # check database.db file + action: "NODE_FILE_SCAN" + options: + node_id: 2 + folder_id: 0 + file_id: 0 + 10: + action: "NODE_FILE_SCAN" # CHECKHASH replaced by SCAN - but the behaviour is the same in this context. + options: + node_id: 2 + folder_id: 0 + file_id: 0 + 11: + action: "NODE_FILE_DELETE" + options: + node_id: 2 + folder_id: 0 + file_id: 0 + 12: + action: "NODE_FILE_REPAIR" + options: + node_id: 2 + folder_id: 0 + file_id: 0 + 13: + action: "NODE_SERVICE_FIX" + options: + node_id: 2 + service_id: 0 + 14: + action: "NODE_FOLDER_SCAN" + options: + node_id: 2 + folder_id: 0 + 15: + action: "NODE_FOLDER_SCAN" # CHECKHASH replaced by SCAN - but the behaviour is the same in this context. + options: + node_id: 2 + folder_id: 0 + 16: + action: "NODE_FOLDER_REPAIR" + options: + node_id: 2 + folder_id: 0 + 17: + action: "NODE_FOLDER_RESTORE" + options: + node_id: 2 + folder_id: 0 + 18: + action: "NODE_OS_SCAN" + options: + node_id: 0 + 19: + action: "NODE_SHUTDOWN" + options: + node_id: 0 + 20: + action: NODE_STARTUP + options: + node_id: 0 + 21: + action: NODE_RESET + options: + node_id: 0 + 22: + action: "NODE_OS_SCAN" + options: + node_id: 1 + 23: + action: "NODE_SHUTDOWN" + options: + node_id: 1 + 24: + action: NODE_STARTUP + options: + node_id: 1 + 25: + action: NODE_RESET + options: + node_id: 1 + 26: # old action num: 18 + action: "NODE_OS_SCAN" + options: + node_id: 2 + 27: + action: "NODE_SHUTDOWN" + options: + node_id: 2 + 28: + action: NODE_STARTUP + options: + node_id: 2 + 29: + action: NODE_RESET + options: + node_id: 2 + 30: + action: "NODE_OS_SCAN" + options: + node_id: 3 + 31: + action: "NODE_SHUTDOWN" + options: + node_id: 3 + 32: + action: NODE_STARTUP + options: + node_id: 3 + 33: + action: NODE_RESET + options: + node_id: 3 + 34: + action: "NODE_OS_SCAN" + options: + node_id: 4 + 35: + action: "NODE_SHUTDOWN" + options: + node_id: 4 + 36: + action: NODE_STARTUP + options: + node_id: 4 + 37: + action: NODE_RESET + options: + node_id: 4 + 38: + action: "NODE_OS_SCAN" + options: + node_id: 5 + 39: # old action num: 19 # shutdown client 1 + action: "NODE_SHUTDOWN" + options: + node_id: 5 + 40: # old action num: 20 + action: NODE_STARTUP + options: + node_id: 5 + 41: # old action num: 21 + action: NODE_RESET + options: + node_id: 5 + 42: + action: "NODE_OS_SCAN" + options: + node_id: 6 + 43: + action: "NODE_SHUTDOWN" + options: + node_id: 6 + 44: + action: NODE_STARTUP + options: + node_id: 6 + 45: + action: NODE_RESET + options: + node_id: 6 + + 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" + action: "ROUTER_ACL_ADDRULE" + options: + target_router_hostname: router_1 + position: 1 + permission: 2 + source_ip_id: 7 # client 1 + dest_ip_id: 1 # ALL + source_port_id: 1 + dest_port_id: 1 + protocol_id: 1 + 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" + action: "ROUTER_ACL_ADDRULE" + options: + target_router_hostname: router_1 + position: 2 + permission: 2 + source_ip_id: 8 # client 2 + dest_ip_id: 1 # ALL + source_port_id: 1 + dest_port_id: 1 + protocol_id: 1 + 48: # old action num: 24 # block tcp traffic from client 1 to web app + action: "ROUTER_ACL_ADDRULE" + options: + target_router_hostname: router_1 + position: 3 + permission: 2 + source_ip_id: 7 # client 1 + dest_ip_id: 3 # web server + source_port_id: 1 + dest_port_id: 1 + protocol_id: 3 + 49: # old action num: 25 # block tcp traffic from client 2 to web app + action: "ROUTER_ACL_ADDRULE" + options: + target_router_hostname: router_1 + position: 4 + permission: 2 + source_ip_id: 8 # client 2 + dest_ip_id: 3 # web server + source_port_id: 1 + dest_port_id: 1 + protocol_id: 3 + 50: # old action num: 26 + action: "ROUTER_ACL_ADDRULE" + options: + target_router_hostname: router_1 + position: 5 + permission: 2 + source_ip_id: 7 # client 1 + dest_ip_id: 4 # database + source_port_id: 1 + dest_port_id: 1 + protocol_id: 3 + 51: # old action num: 27 + action: "ROUTER_ACL_ADDRULE" + options: + target_router_hostname: router_1 + position: 6 + permission: 2 + source_ip_id: 8 # client 2 + dest_ip_id: 4 # database + source_port_id: 1 + dest_port_id: 1 + protocol_id: 3 + 52: # old action num: 28 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router_hostname: router_1 + position: 0 + 53: # old action num: 29 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router_hostname: router_1 + position: 1 + 54: # old action num: 30 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router_hostname: router_1 + position: 2 + 55: # old action num: 31 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router_hostname: router_1 + position: 3 + 56: # old action num: 32 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router_hostname: router_1 + position: 4 + 57: # old action num: 33 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router_hostname: router_1 + position: 5 + 58: # old action num: 34 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router_hostname: router_1 + position: 6 + 59: # old action num: 35 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router_hostname: router_1 + position: 7 + 60: # old action num: 36 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router_hostname: router_1 + position: 8 + 61: # old action num: 37 + action: "ROUTER_ACL_REMOVERULE" + options: + target_router_hostname: router_1 + position: 9 + 62: # old action num: 38 + action: "HOST_NIC_DISABLE" + options: + node_id: 0 + nic_id: 0 + 63: # old action num: 39 + action: "HOST_NIC_ENABLE" + options: + node_id: 0 + nic_id: 0 + 64: # old action num: 40 + action: "HOST_NIC_DISABLE" + options: + node_id: 1 + nic_id: 0 + 65: # old action num: 41 + action: "HOST_NIC_ENABLE" + options: + node_id: 1 + nic_id: 0 + 66: # old action num: 42 + action: "HOST_NIC_DISABLE" + options: + node_id: 2 + nic_id: 0 + 67: # old action num: 43 + action: "HOST_NIC_ENABLE" + options: + node_id: 2 + nic_id: 0 + 68: # old action num: 44 + action: "HOST_NIC_DISABLE" + options: + node_id: 3 + nic_id: 0 + 69: # old action num: 45 + action: "HOST_NIC_ENABLE" + options: + node_id: 3 + nic_id: 0 + 70: # old action num: 46 + action: "HOST_NIC_DISABLE" + options: + node_id: 4 + nic_id: 0 + 71: # old action num: 47 + action: "HOST_NIC_ENABLE" + options: + node_id: 4 + nic_id: 0 + 72: # old action num: 48 + action: "HOST_NIC_DISABLE" + options: + node_id: 4 + nic_id: 1 + 73: # old action num: 49 + action: "HOST_NIC_ENABLE" + options: + node_id: 4 + nic_id: 1 + 74: # old action num: 50 + action: "HOST_NIC_DISABLE" + options: + node_id: 5 + nic_id: 0 + 75: # old action num: 51 + action: "HOST_NIC_ENABLE" + options: + node_id: 5 + nic_id: 0 + 76: # old action num: 52 + action: "HOST_NIC_DISABLE" + options: + node_id: 6 + nic_id: 0 + 77: # old action num: 53 + action: "HOST_NIC_ENABLE" + options: + node_id: 6 + nic_id: 0 + 78: + action: NODE_APPLICATION_INSTALL + options: + node_id: 0 + application_name: DoSBot + ip_address: 192.168.1.14 + 79: + action: NODE_APPLICATION_REMOVE + options: + node_id: 0 + application_name: DoSBot + 80: + action: NODE_APPLICATION_REMOVE + options: + node_id: 0 + application_name: WebBrowser + 81: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 0 + + + + options: + nodes: + - node_name: domain_controller + applications: + - application_name: DoSBot + - node_name: web_server + applications: + - application_name: DatabaseClient + services: + - service_name: WebServer + - node_name: database_server + folders: + - folder_name: database + files: + - file_name: database.db + services: + - service_name: DatabaseService + - node_name: backup_server + - node_name: security_suite + - node_name: client_1 + - node_name: client_2 + + max_folders_per_node: 2 + max_files_per_folder: 2 + max_services_per_node: 2 + max_nics_per_node: 8 + max_acl_rules: 10 + ip_address_order: + - node_name: domain_controller + nic_num: 1 + - node_name: web_server + nic_num: 1 + - node_name: database_server + nic_num: 1 + - node_name: backup_server + nic_num: 1 + - node_name: security_suite + nic_num: 1 + - node_name: client_1 + nic_num: 1 + - node_name: client_2 + nic_num: 1 + - node_name: security_suite + nic_num: 2 + + + reward_function: + reward_components: + - type: DATABASE_FILE_INTEGRITY + weight: 0.40 + options: + node_hostname: database_server + folder_name: database + file_name: database.db + - type: SHARED_REWARD + weight: 1.0 + options: + agent_name: client_1_green_user + - type: SHARED_REWARD + weight: 1.0 + options: + agent_name: client_2_green_user + + + + agent_settings: + flatten_obs: true + + + + + +simulation: + network: + nmne_config: + capture_nmne: true + nmne_capture_keywords: + - DELETE + nodes: + + - ref: router_1 + hostname: router_1 + type: router + num_ports: 5 + ports: + 1: + ip_address: 192.168.1.1 + subnet_mask: 255.255.255.0 + 2: + ip_address: 192.168.10.1 + subnet_mask: 255.255.255.0 + acl: + 18: + action: PERMIT + src_port: POSTGRES_SERVER + dst_port: POSTGRES_SERVER + 19: + action: PERMIT + src_port: DNS + dst_port: DNS + 20: + action: PERMIT + src_port: FTP + dst_port: FTP + 21: + action: PERMIT + src_port: HTTP + dst_port: HTTP + 22: + action: PERMIT + src_port: ARP + dst_port: ARP + 23: + action: PERMIT + protocol: ICMP + + - ref: switch_1 + hostname: switch_1 + type: switch + num_ports: 8 + + - ref: switch_2 + hostname: switch_2 + type: switch + num_ports: 8 + + - ref: domain_controller + hostname: domain_controller + type: server + ip_address: 192.168.1.10 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + services: + - ref: domain_controller_dns_server + type: DNSServer + options: + domain_mapping: + arcd.com: 192.168.1.12 # web server + + - ref: web_server + hostname: web_server + type: server + ip_address: 192.168.1.12 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + dns_server: 192.168.1.10 + services: + - ref: web_server_web_service + type: WebServer + applications: + - ref: web_server_database_client + type: DatabaseClient + options: + db_server_ip: 192.168.1.14 + + + - ref: database_server + hostname: database_server + type: server + ip_address: 192.168.1.14 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + dns_server: 192.168.1.10 + services: + - ref: database_service + type: DatabaseService + options: + backup_server_ip: 192.168.1.16 + - ref: database_ftp_client + type: FTPClient + + - ref: backup_server + hostname: backup_server + type: server + ip_address: 192.168.1.16 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + dns_server: 192.168.1.10 + services: + - ref: backup_service + type: FTPServer + + - ref: security_suite + hostname: security_suite + type: server + ip_address: 192.168.1.110 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.1.1 + dns_server: 192.168.1.10 + network_interfaces: + 2: # unfortunately this number is currently meaningless, they're just added in order and take up the next available slot + ip_address: 192.168.10.110 + subnet_mask: 255.255.255.0 + + - ref: client_1 + hostname: client_1 + type: computer + ip_address: 192.168.10.21 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.10.1 + dns_server: 192.168.1.10 + applications: + - ref: data_manipulation_bot + type: DataManipulationBot + options: + port_scan_p_of_success: 0.8 + data_manipulation_p_of_success: 0.8 + payload: "DELETE" + server_ip: 192.168.1.14 + - ref: client_1_web_browser + type: WebBrowser + options: + target_url: http://arcd.com/users/ + - ref: client_1_database_client + type: DatabaseClient + options: + db_server_ip: 192.168.1.14 + services: + - ref: client_1_dns_client + type: DNSClient + + - ref: client_2 + hostname: client_2 + type: computer + ip_address: 192.168.10.22 + subnet_mask: 255.255.255.0 + default_gateway: 192.168.10.1 + dns_server: 192.168.1.10 + applications: + - ref: client_2_web_browser + type: WebBrowser + options: + target_url: http://arcd.com/users/ + - ref: data_manipulation_bot + type: DataManipulationBot + options: + port_scan_p_of_success: 0.8 + data_manipulation_p_of_success: 0.8 + payload: "DELETE" + server_ip: 192.168.1.14 + - ref: client_2_database_client + type: DatabaseClient + options: + db_server_ip: 192.168.1.14 + services: + - ref: client_2_dns_client + type: DNSClient + + + + links: + - ref: router_1___switch_1 + endpoint_a_ref: router_1 + endpoint_a_port: 1 + endpoint_b_ref: switch_1 + endpoint_b_port: 8 + - ref: router_1___switch_2 + endpoint_a_ref: router_1 + endpoint_a_port: 2 + endpoint_b_ref: switch_2 + endpoint_b_port: 8 + - ref: switch_1___domain_controller + endpoint_a_ref: switch_1 + endpoint_a_port: 1 + endpoint_b_ref: domain_controller + endpoint_b_port: 1 + - ref: switch_1___web_server + endpoint_a_ref: switch_1 + endpoint_a_port: 2 + endpoint_b_ref: web_server + endpoint_b_port: 1 + - ref: switch_1___database_server + endpoint_a_ref: switch_1 + endpoint_a_port: 3 + endpoint_b_ref: database_server + endpoint_b_port: 1 + - ref: switch_1___backup_server + endpoint_a_ref: switch_1 + endpoint_a_port: 4 + endpoint_b_ref: backup_server + endpoint_b_port: 1 + - ref: switch_1___security_suite + endpoint_a_ref: switch_1 + endpoint_a_port: 7 + endpoint_b_ref: security_suite + endpoint_b_port: 1 + - ref: switch_2___client_1 + endpoint_a_ref: switch_2 + endpoint_a_port: 1 + endpoint_b_ref: client_1 + endpoint_b_port: 1 + - ref: switch_2___client_2 + endpoint_a_ref: switch_2 + endpoint_a_port: 2 + endpoint_b_ref: client_2 + endpoint_b_port: 1 + - ref: switch_2___security_suite + endpoint_a_ref: switch_2 + endpoint_a_port: 7 + endpoint_b_ref: security_suite + endpoint_b_port: 2 diff --git a/tests/assets/configs/test_primaite_session.yaml b/tests/assets/configs/test_primaite_session.yaml index 9391084a..8bad2f0b 100644 --- a/tests/assets/configs/test_primaite_session.yaml +++ b/tests/assets/configs/test_primaite_session.yaml @@ -37,7 +37,10 @@ agents: action_space: action_list: - type: DONOTHING - + action_map: + 0: + action: DONOTHING + options: {} options: nodes: - node_name: client_2 @@ -70,6 +73,15 @@ agents: - type: NODE_FILE_DELETE - type: NODE_FILE_CORRUPT - type: NODE_OS_SCAN + action_map: + 0: + action: DONOTHING + options: {} + 1: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 0 options: nodes: - node_name: client_1 @@ -187,14 +199,10 @@ agents: - type: NODE_SHUTDOWN - type: NODE_STARTUP - type: NODE_RESET - - type: NETWORK_ACL_ADDRULE - options: - target_router_hostname: router_1 - - type: NETWORK_ACL_REMOVERULE - options: - target_router_hostname: router_1 - - type: NETWORK_NIC_ENABLE - - type: NETWORK_NIC_DISABLE + - type: ROUTER_ACL_ADDRULE + - type: ROUTER_ACL_REMOVERULE + - type: HOST_NIC_ENABLE + - type: HOST_NIC_DISABLE action_map: 0: @@ -309,8 +317,9 @@ agents: options: node_id: 5 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -319,8 +328,9 @@ agents: dest_port_id: 1 protocol_id: 1 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -329,8 +339,9 @@ agents: dest_port_id: 1 protocol_id: 1 24: # block tcp traffic from client 1 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -339,8 +350,9 @@ agents: dest_port_id: 1 protocol_id: 3 25: # block tcp traffic from client 2 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -349,8 +361,9 @@ agents: dest_port_id: 1 protocol_id: 3 26: - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -359,8 +372,9 @@ agents: dest_port_id: 1 protocol_id: 3 27: - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -369,122 +383,132 @@ agents: dest_port_id: 1 protocol_id: 3 28: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 0 29: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 1 30: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 2 31: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 3 32: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 4 33: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 5 34: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 6 35: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 7 36: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 8 37: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 9 38: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 0 nic_id: 0 39: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 0 nic_id: 0 40: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 1 nic_id: 0 41: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 1 nic_id: 0 42: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 2 nic_id: 0 43: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 2 nic_id: 0 44: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 3 nic_id: 0 45: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 3 nic_id: 0 46: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 0 47: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 0 48: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 1 49: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 1 50: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 5 nic_id: 0 51: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 5 nic_id: 0 52: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 6 nic_id: 0 53: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 6 nic_id: 0 @@ -685,6 +709,39 @@ simulation: - ref: client_2_dns_client type: DNSClient + - ref: HP_LaserJet_Pro_4102fdn_printer + type: printer + hostname: HP_LaserJet_Pro_4102fdn_printer + ip_address: 192.168.10.99 + subnet_mask: 255.255.255.0 + + - ref: router_2 + type: wireless_router + hostname: router_2 + router_interface: + ip_address: 192.169.1.1 + subnet_mask: 255.255.255.0 + wireless_access_point: + ip_address: 192.170.1.1 + subnet_mask: 255.255.255.0 + frequency: WIFI_2_4 + acl: + 0: + action: PERMIT + src_port: POSTGRES_SERVER + dst_port: POSTGRES_SERVER + 1: + action: PERMIT + src_port: DNS + dst_port: DNS + 22: + action: PERMIT + src_port: ARP + dst_port: ARP + 23: + action: PERMIT + protocol: ICMP + links: - ref: router_1___switch_1 endpoint_a_ref: router_1 diff --git a/tests/assets/configs/train_only_primaite_session.yaml b/tests/assets/configs/train_only_primaite_session.yaml index 5e00928b..fcfbaf15 100644 --- a/tests/assets/configs/train_only_primaite_session.yaml +++ b/tests/assets/configs/train_only_primaite_session.yaml @@ -37,7 +37,10 @@ agents: # options: # execution_definition: # target_address: arcd.com - + action_map: + 0: + action: DONOTHING + options: {} options: nodes: - node_name: client_2 @@ -70,6 +73,15 @@ agents: - type: NODE_FILE_DELETE - type: NODE_FILE_CORRUPT - type: NODE_OS_SCAN + action_map: + 0: + action: DONOTHING + options: {} + 1: + action: NODE_APPLICATION_EXECUTE + options: + node_id: 0 + application_id: 0 options: nodes: - node_name: client_1 @@ -187,14 +199,10 @@ agents: - type: NODE_SHUTDOWN - type: NODE_STARTUP - type: NODE_RESET - - type: NETWORK_ACL_ADDRULE - options: - target_router_hostname: router_1 - - type: NETWORK_ACL_REMOVERULE - options: - target_router_hostname: router_1 - - type: NETWORK_NIC_ENABLE - - type: NETWORK_NIC_DISABLE + - type: ROUTER_ACL_ADDRULE + - type: ROUTER_ACL_REMOVERULE + - type: HOST_NIC_ENABLE + - type: HOST_NIC_DISABLE action_map: 0: @@ -309,8 +317,9 @@ agents: options: node_id: 5 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -319,8 +328,9 @@ agents: dest_port_id: 1 protocol_id: 1 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -329,8 +339,9 @@ agents: dest_port_id: 1 protocol_id: 1 24: # block tcp traffic from client 1 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -339,8 +350,9 @@ agents: dest_port_id: 1 protocol_id: 3 25: # block tcp traffic from client 2 to web app - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -349,8 +361,9 @@ agents: dest_port_id: 1 protocol_id: 3 26: - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -359,8 +372,9 @@ agents: dest_port_id: 1 protocol_id: 3 27: - action: "NETWORK_ACL_ADDRULE" + action: "ROUTER_ACL_ADDRULE" options: + target_router_nodename: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -369,122 +383,132 @@ agents: dest_port_id: 1 protocol_id: 3 28: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 0 29: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 1 30: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 2 31: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 3 32: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 4 33: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 5 34: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 6 35: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 7 36: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 8 37: - action: "NETWORK_ACL_REMOVERULE" + action: "ROUTER_ACL_REMOVERULE" options: + target_router_nodename: router_1 position: 9 38: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 0 nic_id: 0 39: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 0 nic_id: 0 40: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 1 nic_id: 0 41: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 1 nic_id: 0 42: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 2 nic_id: 0 43: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 2 nic_id: 0 44: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 3 nic_id: 0 45: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 3 nic_id: 0 46: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 0 47: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 0 48: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 4 nic_id: 1 49: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 4 nic_id: 1 50: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 5 nic_id: 0 51: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 5 nic_id: 0 52: - action: "NETWORK_NIC_DISABLE" + action: "HOST_NIC_DISABLE" options: node_id: 6 nic_id: 0 53: - action: "NETWORK_NIC_ENABLE" + action: "HOST_NIC_ENABLE" options: node_id: 6 nic_id: 0 diff --git a/tests/conftest.py b/tests/conftest.py index b08fd838..f5b5cb1b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -479,6 +479,8 @@ def game_and_agent(): {"type": "NODE_APPLICATION_SCAN"}, {"type": "NODE_APPLICATION_CLOSE"}, {"type": "NODE_APPLICATION_FIX"}, + {"type": "NODE_APPLICATION_INSTALL"}, + {"type": "NODE_APPLICATION_REMOVE"}, {"type": "NODE_FILE_SCAN"}, {"type": "NODE_FILE_CHECKHASH"}, {"type": "NODE_FILE_DELETE"}, @@ -493,10 +495,10 @@ def game_and_agent(): {"type": "NODE_SHUTDOWN"}, {"type": "NODE_STARTUP"}, {"type": "NODE_RESET"}, - {"type": "NETWORK_ACL_ADDRULE", "options": {"target_router_hostname": "router"}}, - {"type": "NETWORK_ACL_REMOVERULE", "options": {"target_router_hostname": "router"}}, - {"type": "NETWORK_NIC_ENABLE"}, - {"type": "NETWORK_NIC_DISABLE"}, + {"type": "ROUTER_ACL_ADDRULE"}, + {"type": "ROUTER_ACL_REMOVERULE"}, + {"type": "HOST_NIC_ENABLE"}, + {"type": "HOST_NIC_DISABLE"}, {"type": "NETWORK_PORT_ENABLE"}, {"type": "NETWORK_PORT_DISABLE"}, ] @@ -506,10 +508,16 @@ def game_and_agent(): nodes=[ { "node_name": "client_1", - "applications": [{"application_name": "WebBrowser"}], + "applications": [ + {"application_name": "WebBrowser"}, + {"application_name": "DoSBot"}, + ], "folders": [{"folder_name": "downloads", "files": [{"file_name": "cat.png"}]}], }, - {"node_name": "server_1", "services": [{"service_name": "DNSServer"}]}, + { + "node_name": "server_1", + "services": [{"service_name": "DNSServer"}], + }, {"node_name": "server_2", "services": [{"service_name": "WebServer"}]}, {"node_name": "router"}, ], diff --git a/tests/e2e_integration_tests/test_primaite_session.py b/tests/e2e_integration_tests/test_primaite_session.py index 4e9ba723..d115f255 100644 --- a/tests/e2e_integration_tests/test_primaite_session.py +++ b/tests/e2e_integration_tests/test_primaite_session.py @@ -1,6 +1,8 @@ import pydantic import pytest +from primaite.simulator.network.hardware.nodes.host.server import Printer +from primaite.simulator.network.hardware.nodes.network.wireless_router import WirelessRouter from tests import TEST_ASSETS_ROOT from tests.conftest import TempPrimaiteSession @@ -30,7 +32,11 @@ class TestPrimaiteSession: assert session.env assert session.env.game.simulation.network - assert len(session.env.game.simulation.network.nodes) == 10 + assert len(session.env.game.simulation.network.nodes) == 12 + wireless = session.env.game.simulation.network.get_node_by_hostname("router_2") + assert isinstance(wireless, WirelessRouter) + printer = session.env.game.simulation.network.get_node_by_hostname("HP_LaserJet_Pro_4102fdn_printer") + assert isinstance(printer, Printer) @pytest.mark.skip(reason="Session is not being maintained and will be removed in the subsequent beta release.") @pytest.mark.parametrize("temp_primaite_session", [[CFG_PATH]], indirect=True) diff --git a/tests/e2e_integration_tests/test_uc2_data_manipulation_scenario.py b/tests/e2e_integration_tests/test_uc2_data_manipulation_scenario.py index b68a887e..0b31a353 100644 --- a/tests/e2e_integration_tests/test_uc2_data_manipulation_scenario.py +++ b/tests/e2e_integration_tests/test_uc2_data_manipulation_scenario.py @@ -1,8 +1,13 @@ +import yaml + +from primaite.game.game import PrimaiteGame +from primaite.session.environment import PrimaiteGymEnv from primaite.simulator.network.hardware.nodes.host.computer import Computer from primaite.simulator.network.hardware.nodes.host.server import Server from primaite.simulator.system.applications.database_client import DatabaseClient from primaite.simulator.system.applications.red_applications.data_manipulation_bot import DataManipulationBot from primaite.simulator.system.services.database.database_service import DatabaseService +from tests import TEST_ASSETS_ROOT def test_data_manipulation(uc2_network): @@ -32,3 +37,41 @@ def test_data_manipulation(uc2_network): # Now check that the DB client on the web_server can successfully query the users table on the database assert db_client.query("SELECT") + + +def test_application_install_uninstall_on_uc2(): + """Test Application install and uninstall via agent actions mid episode.""" + with open(TEST_ASSETS_ROOT / "configs/test_application_install.yaml", "r") as f: + cfg = yaml.safe_load(f) + + env = PrimaiteGymEnv(game_config=cfg) + env.agent.flatten_obs = False + env.reset() + + _, _, _, _, _ = env.step(0) + domcon = env.game.simulation.network.get_node_by_hostname("domain_controller") + + # Test we cannot execute the DoSBot app as it is not installed yet + _, _, _, _, info = env.step(81) + assert info["agent_actions"]["defender"].response.status == "unreachable" + + # Test we can Install the DoSBot app + _, _, _, _, info = env.step(78) + assert "DoSBot" in domcon.software_manager.software + + # Test we can now execute the DoSBot app + _, _, _, _, info = env.step(81) + assert info["agent_actions"]["defender"].response.status == "success" + + # Test we can Uninstall the DoSBot app + _, _, _, _, info = env.step(79) + assert "DoSBot" not in domcon.software_manager.software + + # Test we cannot execute the DoSBot app as it was uninstalled + _, _, _, _, info = env.step(81) + assert info["agent_actions"]["defender"].response.status == "unreachable" + + # Test we can uninstall one of the default apps (WebBrowser) + assert "WebBrowser" in domcon.software_manager.software + _, _, _, _, info = env.step(80) + assert "WebBrowser" not in domcon.software_manager.software diff --git a/tests/integration_tests/game_layer/test_actions.py b/tests/integration_tests/game_layer/test_actions.py index b3a52cd8..3ebce6ad 100644 --- a/tests/integration_tests/game_layer/test_actions.py +++ b/tests/integration_tests/game_layer/test_actions.py @@ -10,16 +10,24 @@ # 4. Check that the simulation has changed in the way that I expect. # 5. Repeat for all actions. +from ipaddress import IPv4Address from typing import Tuple import pytest +import yaml from primaite.game.agent.interface import ProxyAgent from primaite.game.game import PrimaiteGame +from primaite.session.environment import PrimaiteGymEnv from primaite.simulator.file_system.file_system_item_abc import FileSystemItemHealthStatus +from primaite.simulator.network.transmission.network_layer import IPProtocol +from primaite.simulator.network.transmission.transport_layer import Port from primaite.simulator.system.applications.application import ApplicationOperatingState from primaite.simulator.system.applications.web_browser import WebBrowser from primaite.simulator.system.software import SoftwareHealthState +from tests import TEST_ASSETS_ROOT + +FIREWALL_ACTIONS_NETWORK = TEST_ASSETS_ROOT / "configs/firewall_actions_network.yaml" def test_do_nothing_integration(game_and_agent: Tuple[PrimaiteGame, ProxyAgent]): @@ -93,9 +101,9 @@ def test_node_service_fix_integration(game_and_agent: Tuple[PrimaiteGame, ProxyA assert svc.health_state_actual == SoftwareHealthState.GOOD -def test_network_acl_addrule_integration(game_and_agent: Tuple[PrimaiteGame, ProxyAgent]): +def test_router_acl_addrule_integration(game_and_agent: Tuple[PrimaiteGame, ProxyAgent]): """ - Test that the NetworkACLAddRuleAction can form a request and that it is accepted by the simulation. + Test that the RouterACLAddRuleAction can form a request and that it is accepted by the simulation. The ACL starts off with 4 rules, and we add a rule, and check that the ACL now has 5 rules. """ @@ -112,8 +120,9 @@ def test_network_acl_addrule_integration(game_and_agent: Tuple[PrimaiteGame, Pro # 2: Add a rule to block client 1 from reaching server 2 on router action = ( - "NETWORK_ACL_ADDRULE", + "ROUTER_ACL_ADDRULE", { + "target_router_nodename": "router", "position": 4, # 4th rule "permission": 2, # DENY "source_ip_id": 3, # 10.0.1.2 (client_1) @@ -136,8 +145,9 @@ def test_network_acl_addrule_integration(game_and_agent: Tuple[PrimaiteGame, Pro # 4: Add a rule to block server_1 from reaching server_2 on router (this should not affect comms as they are on same subnet) action = ( - "NETWORK_ACL_ADDRULE", + "ROUTER_ACL_ADDRULE", { + "target_router_nodename": "router", "position": 5, # 5th rule "permission": 2, # DENY "source_ip_id": 5, # 10.0.2.2 (server_1) @@ -155,8 +165,8 @@ def test_network_acl_addrule_integration(game_and_agent: Tuple[PrimaiteGame, Pro assert server_1.ping("10.0.2.3") # Can ping server_2 -def test_network_acl_removerule_integration(game_and_agent: Tuple[PrimaiteGame, ProxyAgent]): - """Test that the NetworkACLRemoveRuleAction can form a request and that it is accepted by the simulation.""" +def test_router_acl_removerule_integration(game_and_agent: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the RouterACLRemoveRuleAction can form a request and that it is accepted by the simulation.""" game, agent = game_and_agent # 1: Check that http traffic is going across the network nicely. @@ -171,8 +181,9 @@ def test_network_acl_removerule_integration(game_and_agent: Tuple[PrimaiteGame, # 2: Remove rule that allows HTTP traffic across the network action = ( - "NETWORK_ACL_REMOVERULE", + "ROUTER_ACL_REMOVERULE", { + "target_router_nodename": "router", "position": 3, # 4th rule }, ) @@ -187,8 +198,8 @@ def test_network_acl_removerule_integration(game_and_agent: Tuple[PrimaiteGame, assert client_1.ping("10.0.2.3") -def test_network_nic_disable_integration(game_and_agent: Tuple[PrimaiteGame, ProxyAgent]): - """Test that the NetworkNICDisableAction can form a request and that it is accepted by the simulation.""" +def test_host_nic_disable_integration(game_and_agent: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the HostNICDisableAction can form a request and that it is accepted by the simulation.""" game, agent = game_and_agent # 1: Check that client_1 can access the network @@ -203,7 +214,7 @@ def test_network_nic_disable_integration(game_and_agent: Tuple[PrimaiteGame, Pro # 2: Disable the NIC on client_1 action = ( - "NETWORK_NIC_DISABLE", + "HOST_NIC_DISABLE", { "node_id": 0, # client_1 "nic_id": 0, # the only nic (eth-1) @@ -222,8 +233,8 @@ def test_network_nic_disable_integration(game_and_agent: Tuple[PrimaiteGame, Pro assert server_1.ping("10.0.2.3") -def test_network_nic_enable_integration(game_and_agent: Tuple[PrimaiteGame, ProxyAgent]): - """Test that the NetworkNICEnableAction can form a request and that it is accepted by the simulation.""" +def test_host_nic_enable_integration(game_and_agent: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the HostNICEnableAction can form a request and that it is accepted by the simulation.""" game, agent = game_and_agent @@ -234,7 +245,7 @@ def test_network_nic_enable_integration(game_and_agent: Tuple[PrimaiteGame, Prox # 2: Use action to enable nic action = ( - "NETWORK_NIC_ENABLE", + "HOST_NIC_ENABLE", { "node_id": 0, # client_1 "nic_id": 0, # the only nic (eth-1) @@ -332,8 +343,8 @@ def test_network_router_port_disable_integration(game_and_agent: Tuple[PrimaiteG action = ( "NETWORK_PORT_DISABLE", { - "node_id": 3, # router - "port_id": 0, # port 1 + "target_nodename": "router", # router + "port_id": 1, # port 1 }, ) agent.store_action(action) @@ -364,8 +375,8 @@ def test_network_router_port_enable_integration(game_and_agent: Tuple[PrimaiteGa action = ( "NETWORK_PORT_ENABLE", { - "node_id": 3, # router - "port_id": 0, # port 1 + "target_nodename": "router", # router + "port_id": 1, # port 1 }, ) agent.store_action(action) @@ -455,3 +466,141 @@ def test_node_application_close_integration(game_and_agent: Tuple[PrimaiteGame, game.step() assert browser.operating_state == ApplicationOperatingState.CLOSED + + +def test_node_application_install_and_uninstall_integration(game_and_agent: Tuple[PrimaiteGame, ProxyAgent]): + """Test that the NodeApplicationInstallAction and NodeApplicationRemoveAction can form a request and that + it is accepted by the simulation. + + When you initiate a install action, the Application will be installed and configured on the node. + The remove action will uninstall the application from the node.""" + game, agent = game_and_agent + + client_1 = game.simulation.network.get_node_by_hostname("client_1") + + assert client_1.software_manager.software.get("DoSBot") is None + + action = ("NODE_APPLICATION_INSTALL", {"node_id": 0, "application_name": "DoSBot", "ip_address": "192.168.1.14"}) + agent.store_action(action) + game.step() + + assert client_1.software_manager.software.get("DoSBot") is not None + + action = ("NODE_APPLICATION_REMOVE", {"node_id": 0, "application_name": "DoSBot"}) + agent.store_action(action) + game.step() + + assert client_1.software_manager.software.get("DoSBot") is None + + +def test_firewall_acl_add_remove_rule_integration(): + """ + Test that FirewallACLAddRuleAction and FirewallACLRemoveRuleAction can form a request and that it is accepted by the simulation. + + Check that all the details of the ACL rules are correctly added to each ACL list of the Firewall. + Check that rules are removed as expected. + """ + with open(FIREWALL_ACTIONS_NETWORK, "r") as f: + cfg = yaml.safe_load(f) + + env = PrimaiteGymEnv(game_config=cfg) + + # 1: Check that traffic is normal and acl starts off with 4 rules. + firewall = env.game.simulation.network.get_node_by_hostname("firewall") + assert firewall.internal_inbound_acl.num_rules == 2 + assert firewall.internal_outbound_acl.num_rules == 2 + assert firewall.dmz_inbound_acl.num_rules == 2 + assert firewall.dmz_outbound_acl.num_rules == 2 + assert firewall.external_inbound_acl.num_rules == 1 + assert firewall.external_outbound_acl.num_rules == 1 + + env.step(1) # Add ACL rule to Internal Inbound + assert firewall.internal_inbound_acl.num_rules == 3 + assert firewall.internal_inbound_acl.acl[1].action.name == "PERMIT" + assert firewall.internal_inbound_acl.acl[1].src_ip_address == IPv4Address("192.168.0.10") + assert firewall.internal_inbound_acl.acl[1].dst_ip_address is None + assert firewall.internal_inbound_acl.acl[1].dst_port is None + assert firewall.internal_inbound_acl.acl[1].src_port is None + assert firewall.internal_inbound_acl.acl[1].protocol is None + + env.step(2) # Remove ACL rule from Internal Inbound + assert firewall.internal_inbound_acl.num_rules == 2 + + env.step(3) # Add ACL rule to Internal Outbound + assert firewall.internal_outbound_acl.num_rules == 3 + assert firewall.internal_outbound_acl.acl[1].action.name == "DENY" + assert firewall.internal_outbound_acl.acl[1].src_ip_address == IPv4Address("192.168.0.10") + assert firewall.internal_outbound_acl.acl[1].dst_ip_address is None + assert firewall.internal_outbound_acl.acl[1].dst_port == Port.DNS + assert firewall.internal_outbound_acl.acl[1].src_port == Port.ARP + assert firewall.internal_outbound_acl.acl[1].protocol == IPProtocol.ICMP + + env.step(4) # Remove ACL rule from Internal Outbound + assert firewall.internal_outbound_acl.num_rules == 2 + + env.step(5) # Add ACL rule to DMZ Inbound + assert firewall.dmz_inbound_acl.num_rules == 3 + assert firewall.dmz_inbound_acl.acl[1].action.name == "DENY" + assert firewall.dmz_inbound_acl.acl[1].src_ip_address == IPv4Address("192.168.10.10") + assert firewall.dmz_inbound_acl.acl[1].dst_ip_address == IPv4Address("192.168.0.10") + assert firewall.dmz_inbound_acl.acl[1].dst_port == Port.HTTP + assert firewall.dmz_inbound_acl.acl[1].src_port == Port.HTTP + assert firewall.dmz_inbound_acl.acl[1].protocol == IPProtocol.UDP + + env.step(6) # Remove ACL rule from DMZ Inbound + assert firewall.dmz_inbound_acl.num_rules == 2 + + env.step(7) # Add ACL rule to DMZ Outbound + assert firewall.dmz_outbound_acl.num_rules == 3 + assert firewall.dmz_outbound_acl.acl[2].action.name == "DENY" + assert firewall.dmz_outbound_acl.acl[2].src_ip_address == IPv4Address("192.168.10.10") + assert firewall.dmz_outbound_acl.acl[2].dst_ip_address == IPv4Address("192.168.0.10") + assert firewall.dmz_outbound_acl.acl[2].dst_port == Port.HTTP + assert firewall.dmz_outbound_acl.acl[2].src_port == Port.HTTP + assert firewall.dmz_outbound_acl.acl[2].protocol == IPProtocol.TCP + + env.step(8) # Remove ACL rule from DMZ Outbound + assert firewall.dmz_outbound_acl.num_rules == 2 + + env.step(9) # Add ACL rule to External Inbound + assert firewall.external_inbound_acl.num_rules == 2 + assert firewall.external_inbound_acl.acl[10].action.name == "DENY" + assert firewall.external_inbound_acl.acl[10].src_ip_address == IPv4Address("192.168.20.10") + assert firewall.external_inbound_acl.acl[10].dst_ip_address == IPv4Address("192.168.10.10") + assert firewall.external_inbound_acl.acl[10].dst_port == Port.POSTGRES_SERVER + assert firewall.external_inbound_acl.acl[10].src_port == Port.POSTGRES_SERVER + assert firewall.external_inbound_acl.acl[10].protocol == IPProtocol.ICMP + + env.step(10) # Remove ACL rule from External Inbound + assert firewall.external_inbound_acl.num_rules == 1 + + env.step(11) # Add ACL rule to External Outbound + assert firewall.external_outbound_acl.num_rules == 2 + assert firewall.external_outbound_acl.acl[1].action.name == "DENY" + assert firewall.external_outbound_acl.acl[1].src_ip_address == IPv4Address("192.168.20.10") + assert firewall.external_outbound_acl.acl[1].dst_ip_address == IPv4Address("192.168.0.10") + assert firewall.external_outbound_acl.acl[1].dst_port is None + assert firewall.external_outbound_acl.acl[1].src_port is None + assert firewall.external_outbound_acl.acl[1].protocol is None + + env.step(12) # Remove ACL rule from External Outbound + assert firewall.external_outbound_acl.num_rules == 1 + + +def test_firewall_port_disable_enable_integration(): + """ + Test that NetworkPortEnableAction and NetworkPortDisableAction can form a request and that it is accepted by the simulation. + """ + with open(FIREWALL_ACTIONS_NETWORK, "r") as f: + cfg = yaml.safe_load(f) + + env = PrimaiteGymEnv(game_config=cfg) + firewall = env.game.simulation.network.get_node_by_hostname("firewall") + + assert firewall.dmz_port.enabled == True + + env.step(13) # Disable Firewall DMZ Port + assert firewall.dmz_port.enabled == False + + env.step(14) # Enable Firewall DMZ Port + assert firewall.dmz_port.enabled == True diff --git a/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_router.py b/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_router.py new file mode 100644 index 00000000..be74a721 --- /dev/null +++ b/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_router.py @@ -0,0 +1,111 @@ +from ipaddress import IPv4Address + +from primaite.simulator.network.hardware.nodes.network.router import ACLAction, Router +from primaite.simulator.network.transmission.network_layer import IPProtocol +from primaite.simulator.network.transmission.transport_layer import Port + + +def test_wireless_router_from_config(): + cfg = { + "ref": "router_1", + "type": "router", + "hostname": "router_1", + "num_ports": 6, + "ports": { + 1: { + "ip_address": "192.168.1.1", + "subnet_mask": "255.255.255.0", + }, + 2: { + "ip_address": "192.168.2.1", + "subnet_mask": "255.255.255.0", + }, + }, + "acl": { + 0: { + "action": "PERMIT", + "src_port": "POSTGRES_SERVER", + "dst_port": "POSTGRES_SERVER", + }, + 1: { + "action": "PERMIT", + "protocol": "ICMP", + }, + 2: { + "action": "PERMIT", + "src_ip": "100.100.100.1", + "dst_ip": "100.100.101.1", + }, + 3: { + "action": "PERMIT", + "src_ip": "100.100.102.0", + "dst_ip": "100.100.103.0", + "src_wildcard_mask": "0.0.0.255", + "dst_wildcard_mask": "0.0.0.255", + }, + 20: { + "action": "DENY", + }, + }, + } + + rt = Router.from_config(cfg=cfg) + + assert rt.num_ports == 6 + + assert rt.network_interface[1].ip_address == IPv4Address("192.168.1.1") + assert rt.network_interface[1].subnet_mask == IPv4Address("255.255.255.0") + + assert rt.network_interface[2].ip_address == IPv4Address("192.168.2.1") + assert rt.network_interface[2].subnet_mask == IPv4Address("255.255.255.0") + + assert not rt.network_interface[3].enabled + assert not rt.network_interface[4].enabled + assert not rt.network_interface[5].enabled + assert not rt.network_interface[6].enabled + + r0 = rt.acl.acl[0] + assert r0.action == ACLAction.PERMIT + assert r0.src_port == r0.dst_port == Port.POSTGRES_SERVER + assert r0.src_ip_address == r0.dst_ip_address == r0.dst_wildcard_mask == r0.src_wildcard_mask == r0.protocol == None + + r1 = rt.acl.acl[1] + assert r1.action == ACLAction.PERMIT + assert r1.protocol == IPProtocol.ICMP + assert ( + r1.src_ip_address + == r1.dst_ip_address + == r1.dst_wildcard_mask + == r1.src_wildcard_mask + == r1.src_port + == r1.dst_port + == None + ) + + r2 = rt.acl.acl[2] + assert r2.action == ACLAction.PERMIT + assert r2.src_ip_address == IPv4Address("100.100.100.1") + assert r2.dst_ip_address == IPv4Address("100.100.101.1") + assert r2.src_wildcard_mask == r2.dst_wildcard_mask == None + assert r2.src_port == r2.dst_port == r2.protocol == None + + r3 = rt.acl.acl[3] + assert r3.action == ACLAction.PERMIT + assert r3.src_ip_address == IPv4Address("100.100.102.0") + assert r3.dst_ip_address == IPv4Address("100.100.103.0") + assert r3.src_wildcard_mask == IPv4Address("0.0.0.255") + assert r3.dst_wildcard_mask == IPv4Address("0.0.0.255") + assert r3.src_port == r3.dst_port == r3.protocol == None + + r20 = rt.acl.acl[20] + assert r20.action == ACLAction.DENY + assert ( + r20.src_ip_address + == r20.dst_ip_address + == r20.src_wildcard_mask + == r20.dst_wildcard_mask + == r20.src_port + == r20.dst_port + == r20.protocol + == None + ) diff --git a/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_wireless_router.py b/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_wireless_router.py new file mode 100644 index 00000000..494f5a15 --- /dev/null +++ b/tests/unit_tests/_primaite/_simulator/_network/_hardware/nodes/test_wireless_router.py @@ -0,0 +1,97 @@ +from ipaddress import IPv4Address + +from primaite.simulator.network.hardware.nodes.network.router import ACLAction +from primaite.simulator.network.hardware.nodes.network.wireless_router import WirelessRouter +from primaite.simulator.network.transmission.network_layer import IPProtocol +from primaite.simulator.network.transmission.transport_layer import Port + + +def test_wireless_router_from_config(): + cfg = { + "ref": "router_2", + "type": "wireless_router", + "hostname": "router_2", + "router_interface": { + "ip_address": "192.168.1.1", + "subnet_mask": "255.255.255.0", + }, + "wireless_access_point": { + "ip_address": "192.170.1.1", + "subnet_mask": "255.255.255.0", + "frequency": "WIFI_2_4", + }, + "acl": { + 0: { + "action": "PERMIT", + "src_port": "POSTGRES_SERVER", + "dst_port": "POSTGRES_SERVER", + }, + 1: { + "action": "PERMIT", + "protocol": "ICMP", + }, + 2: { + "action": "PERMIT", + "src_ip": "100.100.100.1", + "dst_ip": "100.100.101.1", + }, + 3: { + "action": "PERMIT", + "src_ip": "100.100.102.0", + "dst_ip": "100.100.103.0", + "src_wildcard_mask": "0.0.0.255", + "dst_wildcard_mask": "0.0.0.255", + }, + 20: { + "action": "DENY", + }, + }, + } + + rt = WirelessRouter.from_config(cfg=cfg) + + r0 = rt.acl.acl[0] + assert r0.action == ACLAction.PERMIT + assert r0.src_port == r0.dst_port == Port.POSTGRES_SERVER + assert r0.src_ip_address == r0.dst_ip_address == r0.dst_wildcard_mask == r0.src_wildcard_mask == r0.protocol == None + + r1 = rt.acl.acl[1] + assert r1.action == ACLAction.PERMIT + assert r1.protocol == IPProtocol.ICMP + assert ( + r1.src_ip_address + == r1.dst_ip_address + == r1.dst_wildcard_mask + == r1.src_wildcard_mask + == r1.src_port + == r1.dst_port + == None + ) + + r2 = rt.acl.acl[2] + assert r2.action == ACLAction.PERMIT + assert r2.src_ip_address == IPv4Address("100.100.100.1") + assert r2.dst_ip_address == IPv4Address("100.100.101.1") + assert r2.src_wildcard_mask == r2.dst_wildcard_mask == None + assert r2.src_port == r2.dst_port == r2.protocol == None + + r3 = rt.acl.acl[3] + assert r3.action == ACLAction.PERMIT + assert r3.src_ip_address == IPv4Address("100.100.102.0") + assert r3.dst_ip_address == IPv4Address("100.100.103.0") + assert r3.src_wildcard_mask == IPv4Address("0.0.0.255") + assert r3.dst_wildcard_mask == IPv4Address("0.0.0.255") + assert r3.src_port == r3.dst_port == r3.protocol == None + + r20 = rt.acl.acl[20] + assert r20.action == ACLAction.DENY + assert ( + r20.src_ip_address + == r20.dst_ip_address + == r20.src_wildcard_mask + == r20.dst_wildcard_mask + == r20.src_port + == r20.dst_port + == r20.protocol + == None + )