Merge remote-tracking branch 'origin/dev' into feature/2417-observation-refactor
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user