From cb4e10921ee03b194d5810ce1a016adceba7ad8f Mon Sep 17 00:00:00 2001 From: Nick Todd Date: Mon, 6 Jan 2025 16:33:57 +0000 Subject: [PATCH] #2888: Use fixing_duration from ConfigSchema. --- .../system/applications/ransomware_script.rst | 2 +- .../system/common/common_configuration.rst | 4 +-- src/primaite/game/game.py | 4 +-- src/primaite/simulator/system/software.py | 12 ++------ ...tem.yaml => fixing_duration_one_item.yaml} | 4 +-- ...ion.yaml => software_fixing_duration.yaml} | 28 +++++++++---------- ...on.py => test_software_fixing_duration.py} | 28 +++++++++---------- 7 files changed, 38 insertions(+), 44 deletions(-) rename tests/assets/configs/{fix_duration_one_item.yaml => fixing_duration_one_item.yaml} (99%) rename tests/assets/configs/{software_fix_duration.yaml => software_fixing_duration.yaml} (93%) rename tests/integration_tests/configuration_file_parsing/{test_software_fix_duration.py => test_software_fixing_duration.py} (77%) diff --git a/docs/source/simulation_components/system/applications/ransomware_script.rst b/docs/source/simulation_components/system/applications/ransomware_script.rst index b79ca802..192618fc 100644 --- a/docs/source/simulation_components/system/applications/ransomware_script.rst +++ b/docs/source/simulation_components/system/applications/ransomware_script.rst @@ -70,7 +70,7 @@ Python Configuration ============= -The RansomwareScript inherits configuration options such as ``fix_duration`` from its parent class. However, for the ``RansomwareScript`` the most relevant option is ``server_ip``. +The RansomwareScript inherits configuration options such as ``fixing_duration`` from its parent class. However, for the ``RansomwareScript`` the most relevant option is ``server_ip``. ``server_ip`` diff --git a/docs/source/simulation_components/system/common/common_configuration.rst b/docs/source/simulation_components/system/common/common_configuration.rst index 411fd529..c1bbd4b2 100644 --- a/docs/source/simulation_components/system/common/common_configuration.rst +++ b/docs/source/simulation_components/system/common/common_configuration.rst @@ -22,8 +22,8 @@ options The configuration options are the attributes that fall under the options for an application or service. -fix_duration -"""""""""""" +fixing_duration +""""""""""""""" Optional. Default value is ``2``. diff --git a/src/primaite/game/game.py b/src/primaite/game/game.py index 5764ad11..d8b28e94 100644 --- a/src/primaite/game/game.py +++ b/src/primaite/game/game.py @@ -380,8 +380,8 @@ class PrimaiteGame: new_service = new_node.software_manager.software[service_class.__name__] # fixing duration for the service - if "fix_duration" in service_cfg.get("options", {}): - new_service.fixing_duration = service_cfg["options"]["fix_duration"] + if "fixing_duration" in service_cfg.get("options", {}): + new_service.config.fixing_duration = service_cfg["options"]["fixing_duration"] _set_software_listen_on_ports(new_service, service_cfg) # start the service diff --git a/src/primaite/simulator/system/software.py b/src/primaite/simulator/system/software.py index 12e3b2f2..25b2366c 100644 --- a/src/primaite/simulator/system/software.py +++ b/src/primaite/simulator/system/software.py @@ -84,7 +84,7 @@ class Software(SimComponent, ABC): model_config = ConfigDict(extra="forbid") starting_health_state: SoftwareHealthState = SoftwareHealthState.UNUSED criticality: SoftwareCriticality = SoftwareCriticality.LOWEST - fix_duration: int = 2 + fixing_duration: int = 2 config: ConfigSchema = Field(default_factory=lambda: Software.ConfigSchema()) @@ -94,8 +94,6 @@ class Software(SimComponent, ABC): "The actual health state of the software." health_state_visible: SoftwareHealthState = SoftwareHealthState.UNUSED "The health state of the software visible to the red agent." - criticality: SoftwareCriticality = SoftwareCriticality.LOWEST - "The criticality level of the software." fixing_count: int = 0 "The count of patches applied to the software, defaults to 0." scanning_count: int = 0 @@ -110,16 +108,12 @@ class Software(SimComponent, ABC): "The FileSystem of the Node the Software is installed on." folder: Optional[Folder] = None "The folder on the file system the Software uses." - fixing_duration: int = 2 - "The number of ticks it takes to patch the software." _fixing_countdown: Optional[int] = None "Current number of ticks left to patch the software." def __init__(self, **kwargs): super().__init__(**kwargs) self.health_state_actual = self.config.starting_health_state # don't remove this - self.criticality = self.config.criticality - self.fixing_duration = self.config.fix_duration def _init_request_manager(self) -> RequestManager: """ @@ -168,7 +162,7 @@ class Software(SimComponent, ABC): { "health_state_actual": self.health_state_actual.value, "health_state_visible": self.health_state_visible.value, - "criticality": self.criticality.value, + "criticality": self.config.criticality.value, "fixing_count": self.fixing_count, "scanning_count": self.scanning_count, "revealed_to_red": self.revealed_to_red, @@ -217,7 +211,7 @@ class Software(SimComponent, ABC): def fix(self) -> bool: """Perform a fix on the software.""" if self.health_state_actual in (SoftwareHealthState.COMPROMISED, SoftwareHealthState.GOOD): - self._fixing_countdown = self.fixing_duration + self._fixing_countdown = self.config.fixing_duration self.set_health_state(SoftwareHealthState.FIXING) return True return False diff --git a/tests/assets/configs/fix_duration_one_item.yaml b/tests/assets/configs/fixing_duration_one_item.yaml similarity index 99% rename from tests/assets/configs/fix_duration_one_item.yaml rename to tests/assets/configs/fixing_duration_one_item.yaml index bd0fb61f..57c1c4ce 100644 --- a/tests/assets/configs/fix_duration_one_item.yaml +++ b/tests/assets/configs/fixing_duration_one_item.yaml @@ -185,7 +185,7 @@ simulation: options: db_server_ip: 192.168.1.10 server_password: arcd - fix_duration: 1 + fixing_duration: 1 - type: DataManipulationBot options: port_scan_p_of_success: 0.8 @@ -208,7 +208,7 @@ simulation: arcd.com: 192.168.1.10 - type: DatabaseService options: - fix_duration: 5 + fixing_duration: 5 backup_server_ip: 192.168.1.10 - type: WebServer - type: FTPClient diff --git a/tests/assets/configs/software_fix_duration.yaml b/tests/assets/configs/software_fixing_duration.yaml similarity index 93% rename from tests/assets/configs/software_fix_duration.yaml rename to tests/assets/configs/software_fixing_duration.yaml index 1a28258b..bb1254ed 100644 --- a/tests/assets/configs/software_fix_duration.yaml +++ b/tests/assets/configs/software_fixing_duration.yaml @@ -179,19 +179,19 @@ simulation: applications: - type: NMAP options: - fix_duration: 1 + fixing_duration: 1 - type: RansomwareScript options: - fix_duration: 1 + fixing_duration: 1 - type: WebBrowser options: target_url: http://arcd.com/users/ - fix_duration: 1 + fixing_duration: 1 - type: DatabaseClient options: db_server_ip: 192.168.1.10 server_password: arcd - fix_duration: 1 + fixing_duration: 1 - type: DataManipulationBot options: port_scan_p_of_success: 0.8 @@ -199,44 +199,44 @@ simulation: payload: "DELETE" server_ip: 192.168.1.21 server_password: arcd - fix_duration: 1 + fixing_duration: 1 - type: DoSBot options: target_ip_address: 192.168.10.21 payload: SPOOF DATA port_scan_p_of_success: 0.8 - fix_duration: 1 + fixing_duration: 1 services: - type: DNSClient options: dns_server: 192.168.1.10 - fix_duration: 3 + fixing_duration: 3 - type: DNSServer options: - fix_duration: 3 + fixing_duration: 3 domain_mapping: arcd.com: 192.168.1.10 - type: DatabaseService options: backup_server_ip: 192.168.1.10 - fix_duration: 3 + fixing_duration: 3 - type: WebServer options: - fix_duration: 3 + fixing_duration: 3 - type: FTPClient options: - fix_duration: 3 + fixing_duration: 3 - type: FTPServer options: server_password: arcd - fix_duration: 3 + fixing_duration: 3 - type: NTPClient options: ntp_server_ip: 192.168.1.10 - fix_duration: 3 + fixing_duration: 3 - type: NTPServer options: - fix_duration: 3 + fixing_duration: 3 - hostname: client_2 type: computer ip_address: 192.168.10.22 diff --git a/tests/integration_tests/configuration_file_parsing/test_software_fix_duration.py b/tests/integration_tests/configuration_file_parsing/test_software_fixing_duration.py similarity index 77% rename from tests/integration_tests/configuration_file_parsing/test_software_fix_duration.py rename to tests/integration_tests/configuration_file_parsing/test_software_fixing_duration.py index b1c644cc..8e8013d5 100644 --- a/tests/integration_tests/configuration_file_parsing/test_software_fix_duration.py +++ b/tests/integration_tests/configuration_file_parsing/test_software_fixing_duration.py @@ -27,27 +27,27 @@ def load_config(config_path: Union[str, Path]) -> PrimaiteGame: return PrimaiteGame.from_config(cfg) -def test_default_fix_duration(): - """Test that software with no defined fix duration in config uses the default fix duration of 2.""" +def test_default_fixing_duration(): + """Test that software with no defined fixing duration in config uses the default fixing duration of 2.""" game = load_config(TEST_CONFIG) client_2: Computer = game.simulation.network.get_node_by_hostname("client_2") database_client: DatabaseClient = client_2.software_manager.software.get("DatabaseClient") - assert database_client.fixing_duration == 2 + assert database_client.config.fixing_duration == 2 dns_client: DNSClient = client_2.software_manager.software.get("DNSClient") - assert dns_client.fixing_duration == 2 + assert dns_client.config.fixing_duration == 2 -def test_fix_duration_set_from_config(): - """Test to check that the fix duration set for applications and services works as intended.""" +def test_fixing_duration_set_from_config(): + """Test to check that the fixing duration set for applications and services works as intended.""" game = load_config(TEST_CONFIG) client_1: Computer = game.simulation.network.get_node_by_hostname("client_1") # in config - services take 3 timesteps to fix for service in ["DNSClient", "DNSServer", "DatabaseService", "WebServer", "FTPClient", "FTPServer", "NTPServer"]: assert client_1.software_manager.software.get(service) is not None - assert client_1.software_manager.software.get(service).fixing_duration == 3 + assert client_1.software_manager.software.get(service).config.fixing_duration == 3 # in config - applications take 1 timestep to fix # remove test applications from list @@ -55,27 +55,27 @@ def test_fix_duration_set_from_config(): for application in ["RansomwareScript", "WebBrowser", "DataManipulationBot", "DoSBot", "DatabaseClient"]: assert client_1.software_manager.software.get(application) is not None - assert client_1.software_manager.software.get(application).fixing_duration == 1 + assert client_1.software_manager.software.get(application).config.fixing_duration == 1 -def test_fix_duration_for_one_item(): - """Test that setting fix duration for one application does not affect other components.""" +def test_fixing_duration_for_one_item(): + """Test that setting fixing duration for one application does not affect other components.""" game = load_config(ONE_ITEM_CONFIG) client_1: Computer = game.simulation.network.get_node_by_hostname("client_1") # in config - services take 3 timesteps to fix for service in ["DNSClient", "DNSServer", "WebServer", "FTPClient", "FTPServer", "NTPServer"]: assert client_1.software_manager.software.get(service) is not None - assert client_1.software_manager.software.get(service).fixing_duration == 2 + assert client_1.software_manager.software.get(service).config.fixing_duration == 2 # in config - applications take 1 timestep to fix # remove test applications from list for applications in ["RansomwareScript", "WebBrowser", "DataManipulationBot", "DoSBot"]: assert client_1.software_manager.software.get(applications) is not None - assert client_1.software_manager.software.get(applications).fixing_duration == 2 + assert client_1.software_manager.software.get(applications).config.fixing_duration == 2 database_client: DatabaseClient = client_1.software_manager.software.get("DatabaseClient") - assert database_client.fixing_duration == 1 + assert database_client.config.fixing_duration == 1 database_service: DatabaseService = client_1.software_manager.software.get("DatabaseService") - assert database_service.fixing_duration == 5 + assert database_service.config.fixing_duration == 5