diff --git a/src/primaite/simulator/network/hardware/base.py b/src/primaite/simulator/network/hardware/base.py index ebf669eb..ad101f1d 100644 --- a/src/primaite/simulator/network/hardware/base.py +++ b/src/primaite/simulator/network/hardware/base.py @@ -1424,7 +1424,17 @@ class Node(SimComponent): def _start_up_actions(self): """Actions to perform when the node is starting up.""" - pass + # Turn on all the services in the node + for service_id in self.services: + self.services[service_id].start() + + # Turn on all the applications in the node + for app_id in self.applications: + self.applications[app_id].run() + + # Turn off all processes in the node + # for process_id in self.processes: + # self.processes[process_id] def __contains__(self, item: Any) -> bool: if isinstance(item, Service): diff --git a/src/primaite/simulator/system/applications/application.py b/src/primaite/simulator/system/applications/application.py index db323cf6..fb65354f 100644 --- a/src/primaite/simulator/system/applications/application.py +++ b/src/primaite/simulator/system/applications/application.py @@ -2,6 +2,7 @@ from abc import abstractmethod from enum import Enum from typing import Any, Dict, Set +from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState from primaite.simulator.system.software import IOSoftware, SoftwareHealthState @@ -61,6 +62,10 @@ class Application(IOSoftware): def run(self) -> None: """Open the Application.""" + if self.software_manager and self.software_manager.node.operating_state is not NodeOperatingState.ON: + self.sys_log.error(f"Unable to run application. {self.software_manager.node.hostname} is not turned on.") + return + if self.operating_state == ApplicationOperatingState.CLOSED: self.sys_log.info(f"Running Application {self.name}") self.operating_state = ApplicationOperatingState.RUNNING diff --git a/src/primaite/simulator/system/services/red_services/data_manipulation_bot.py b/src/primaite/simulator/system/services/red_services/data_manipulation_bot.py index 996e6790..f6662762 100644 --- a/src/primaite/simulator/system/services/red_services/data_manipulation_bot.py +++ b/src/primaite/simulator/system/services/red_services/data_manipulation_bot.py @@ -42,10 +42,13 @@ class DataManipulationBot(DatabaseClient): if self.server_ip_address and self.payload: self.sys_log.info(f"{self.name}: Attempting to start the {self.name}") super().run() - if not self.connected: - self.connect() - if self.connected: - self.query(self.payload) - self.sys_log.info(f"{self.name} payload delivered: {self.payload}") else: self.sys_log.error(f"Failed to start the {self.name} as it requires both a target_ip_address and payload.") + + def attack(self): + """Run the datab manipulation attack.""" + if not self.connected: + self.connect() + if self.connected: + self.query(self.payload) + self.sys_log.info(f"{self.name} payload delivered: {self.payload}") diff --git a/tests/conftest.py b/tests/conftest.py index 4cc36e6b..d39e96e0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -52,6 +52,12 @@ class TestService(Service): class TestApplication(Application): """Test Application class""" + def __init__(self, **kwargs): + kwargs["name"] = "TestApplication" + kwargs["port"] = Port.HTTP + kwargs["protocol"] = IPProtocol.TCP + super().__init__(**kwargs) + def describe_state(self) -> Dict: pass 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 81bbfc96..fe7bab5f 100644 --- a/tests/e2e_integration_tests/test_uc2_data_manipulation_scenario.py +++ b/tests/e2e_integration_tests/test_uc2_data_manipulation_scenario.py @@ -23,6 +23,7 @@ def test_data_manipulation(uc2_network): # Now we run the DataManipulationBot db_manipulation_bot.run() + db_manipulation_bot.attack() # Now check that the DB client on the web_server cannot query the users table on the database assert not db_client.query("SELECT") diff --git a/tests/integration_tests/system/test_app_service_on_node.py b/tests/integration_tests/system/test_app_service_on_node.py new file mode 100644 index 00000000..cbcb4ff6 --- /dev/null +++ b/tests/integration_tests/system/test_app_service_on_node.py @@ -0,0 +1,95 @@ +from typing import Tuple + +import pytest +from conftest import TestApplication, TestService + +from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState +from primaite.simulator.network.hardware.nodes.server import Server +from primaite.simulator.system.applications.application import Application, ApplicationOperatingState +from primaite.simulator.system.services.service import Service, ServiceOperatingState + + +@pytest.fixture(scope="function") +def populated_node() -> Tuple[Application, Server, Service]: + server = Server( + hostname="server", ip_address="192.168.0.1", subnet_mask="255.255.255.0", operating_state=NodeOperatingState.ON + ) + server.software_manager.install(TestService) + server.software_manager.install(TestApplication) + + app = server.software_manager.software["TestApplication"] + app.run() + service = server.software_manager.software["TestService"] + service.start() + + return app, server, service + + +def test_server_turns_off_service(populated_node): + """Check that the service is turned off when the server is turned off""" + app, server, service = populated_node + + assert server.operating_state is NodeOperatingState.ON + assert service.operating_state is ServiceOperatingState.RUNNING + assert app.operating_state is ApplicationOperatingState.RUNNING + + server.power_off() + + for i in range(server.shut_down_duration + 1): + server.apply_timestep(timestep=i) + + assert server.operating_state is NodeOperatingState.OFF + assert service.operating_state is ServiceOperatingState.STOPPED + assert app.operating_state is ApplicationOperatingState.CLOSED + + +def test_service_cannot_be_turned_on_when_server_is_off(populated_node): + """Check that the service cannot be started when the server is off.""" + app, server, service = populated_node + + assert server.operating_state is NodeOperatingState.ON + assert service.operating_state is ServiceOperatingState.RUNNING + assert app.operating_state is ApplicationOperatingState.RUNNING + + server.power_off() + + for i in range(server.shut_down_duration + 1): + server.apply_timestep(timestep=i) + + assert server.operating_state is NodeOperatingState.OFF + assert service.operating_state is ServiceOperatingState.STOPPED + assert app.operating_state is ApplicationOperatingState.CLOSED + + service.start() + app.run() + + assert server.operating_state is NodeOperatingState.OFF + assert service.operating_state is ServiceOperatingState.STOPPED + assert app.operating_state is ApplicationOperatingState.CLOSED + + +def test_server_turns_on_service(populated_node): + """Check that turning on the server turns on service.""" + app, server, service = populated_node + + assert server.operating_state is NodeOperatingState.ON + assert service.operating_state is ServiceOperatingState.RUNNING + assert app.operating_state is ApplicationOperatingState.RUNNING + + server.power_off() + + for i in range(server.shut_down_duration + 1): + server.apply_timestep(timestep=i) + + assert server.operating_state is NodeOperatingState.OFF + assert service.operating_state is ServiceOperatingState.STOPPED + assert app.operating_state is ApplicationOperatingState.CLOSED + + server.power_on() + + for i in range(server.start_up_duration + 1): + server.apply_timestep(timestep=i) + + assert server.operating_state is NodeOperatingState.ON + assert service.operating_state is ServiceOperatingState.RUNNING + assert app.operating_state is ApplicationOperatingState.RUNNING diff --git a/tests/integration_tests/system/test_service_on_node.py b/tests/integration_tests/system/test_service_on_node.py deleted file mode 100644 index e596dcd8..00000000 --- a/tests/integration_tests/system/test_service_on_node.py +++ /dev/null @@ -1,42 +0,0 @@ -from typing import Tuple - -import pytest -from conftest import TestService - -from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState -from primaite.simulator.network.hardware.nodes.server import Server -from primaite.simulator.system.services.service import Service, ServiceOperatingState - - -@pytest.fixture(scope="function") -def service_on_node() -> Tuple[Server, Service]: - server = Server( - hostname="server", ip_address="192.168.0.1", subnet_mask="255.255.255.0", operating_state=NodeOperatingState.ON - ) - server.software_manager.install(TestService) - - service = server.software_manager.software["TestService"] - service.start() - - return server, service - - -def test_server_turns_off_service(service_on_node): - """Check that the service is turned off when the server is turned off""" - server, service = service_on_node - - assert server.operating_state is NodeOperatingState.ON - assert service.operating_state is ServiceOperatingState.RUNNING - - server.power_off() - - for i in range(server.shut_down_duration + 1): - server.apply_timestep(timestep=i) - - assert server.operating_state is NodeOperatingState.OFF - assert service.operating_state is ServiceOperatingState.STOPPED - - -def test_server_turns_on_service(service_on_node): - """Check that turning on the server turns on service.""" - pass