#2888: Use fixing_duration from ConfigSchema.
This commit is contained in:
@@ -70,7 +70,7 @@ Python
|
|||||||
Configuration
|
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``
|
``server_ip``
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ options
|
|||||||
|
|
||||||
The configuration options are the attributes that fall under the options for an application or service.
|
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``.
|
Optional. Default value is ``2``.
|
||||||
|
|
||||||
|
|||||||
@@ -380,8 +380,8 @@ class PrimaiteGame:
|
|||||||
new_service = new_node.software_manager.software[service_class.__name__]
|
new_service = new_node.software_manager.software[service_class.__name__]
|
||||||
|
|
||||||
# fixing duration for the service
|
# fixing duration for the service
|
||||||
if "fix_duration" in service_cfg.get("options", {}):
|
if "fixing_duration" in service_cfg.get("options", {}):
|
||||||
new_service.fixing_duration = service_cfg["options"]["fix_duration"]
|
new_service.config.fixing_duration = service_cfg["options"]["fixing_duration"]
|
||||||
|
|
||||||
_set_software_listen_on_ports(new_service, service_cfg)
|
_set_software_listen_on_ports(new_service, service_cfg)
|
||||||
# start the service
|
# start the service
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class Software(SimComponent, ABC):
|
|||||||
model_config = ConfigDict(extra="forbid")
|
model_config = ConfigDict(extra="forbid")
|
||||||
starting_health_state: SoftwareHealthState = SoftwareHealthState.UNUSED
|
starting_health_state: SoftwareHealthState = SoftwareHealthState.UNUSED
|
||||||
criticality: SoftwareCriticality = SoftwareCriticality.LOWEST
|
criticality: SoftwareCriticality = SoftwareCriticality.LOWEST
|
||||||
fix_duration: int = 2
|
fixing_duration: int = 2
|
||||||
|
|
||||||
config: ConfigSchema = Field(default_factory=lambda: Software.ConfigSchema())
|
config: ConfigSchema = Field(default_factory=lambda: Software.ConfigSchema())
|
||||||
|
|
||||||
@@ -94,8 +94,6 @@ class Software(SimComponent, ABC):
|
|||||||
"The actual health state of the software."
|
"The actual health state of the software."
|
||||||
health_state_visible: SoftwareHealthState = SoftwareHealthState.UNUSED
|
health_state_visible: SoftwareHealthState = SoftwareHealthState.UNUSED
|
||||||
"The health state of the software visible to the red agent."
|
"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
|
fixing_count: int = 0
|
||||||
"The count of patches applied to the software, defaults to 0."
|
"The count of patches applied to the software, defaults to 0."
|
||||||
scanning_count: int = 0
|
scanning_count: int = 0
|
||||||
@@ -110,16 +108,12 @@ class Software(SimComponent, ABC):
|
|||||||
"The FileSystem of the Node the Software is installed on."
|
"The FileSystem of the Node the Software is installed on."
|
||||||
folder: Optional[Folder] = None
|
folder: Optional[Folder] = None
|
||||||
"The folder on the file system the Software uses."
|
"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
|
_fixing_countdown: Optional[int] = None
|
||||||
"Current number of ticks left to patch the software."
|
"Current number of ticks left to patch the software."
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.health_state_actual = self.config.starting_health_state # don't remove this
|
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:
|
def _init_request_manager(self) -> RequestManager:
|
||||||
"""
|
"""
|
||||||
@@ -168,7 +162,7 @@ class Software(SimComponent, ABC):
|
|||||||
{
|
{
|
||||||
"health_state_actual": self.health_state_actual.value,
|
"health_state_actual": self.health_state_actual.value,
|
||||||
"health_state_visible": self.health_state_visible.value,
|
"health_state_visible": self.health_state_visible.value,
|
||||||
"criticality": self.criticality.value,
|
"criticality": self.config.criticality.value,
|
||||||
"fixing_count": self.fixing_count,
|
"fixing_count": self.fixing_count,
|
||||||
"scanning_count": self.scanning_count,
|
"scanning_count": self.scanning_count,
|
||||||
"revealed_to_red": self.revealed_to_red,
|
"revealed_to_red": self.revealed_to_red,
|
||||||
@@ -217,7 +211,7 @@ class Software(SimComponent, ABC):
|
|||||||
def fix(self) -> bool:
|
def fix(self) -> bool:
|
||||||
"""Perform a fix on the software."""
|
"""Perform a fix on the software."""
|
||||||
if self.health_state_actual in (SoftwareHealthState.COMPROMISED, SoftwareHealthState.GOOD):
|
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)
|
self.set_health_state(SoftwareHealthState.FIXING)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ simulation:
|
|||||||
options:
|
options:
|
||||||
db_server_ip: 192.168.1.10
|
db_server_ip: 192.168.1.10
|
||||||
server_password: arcd
|
server_password: arcd
|
||||||
fix_duration: 1
|
fixing_duration: 1
|
||||||
- type: DataManipulationBot
|
- type: DataManipulationBot
|
||||||
options:
|
options:
|
||||||
port_scan_p_of_success: 0.8
|
port_scan_p_of_success: 0.8
|
||||||
@@ -208,7 +208,7 @@ simulation:
|
|||||||
arcd.com: 192.168.1.10
|
arcd.com: 192.168.1.10
|
||||||
- type: DatabaseService
|
- type: DatabaseService
|
||||||
options:
|
options:
|
||||||
fix_duration: 5
|
fixing_duration: 5
|
||||||
backup_server_ip: 192.168.1.10
|
backup_server_ip: 192.168.1.10
|
||||||
- type: WebServer
|
- type: WebServer
|
||||||
- type: FTPClient
|
- type: FTPClient
|
||||||
@@ -179,19 +179,19 @@ simulation:
|
|||||||
applications:
|
applications:
|
||||||
- type: NMAP
|
- type: NMAP
|
||||||
options:
|
options:
|
||||||
fix_duration: 1
|
fixing_duration: 1
|
||||||
- type: RansomwareScript
|
- type: RansomwareScript
|
||||||
options:
|
options:
|
||||||
fix_duration: 1
|
fixing_duration: 1
|
||||||
- type: WebBrowser
|
- type: WebBrowser
|
||||||
options:
|
options:
|
||||||
target_url: http://arcd.com/users/
|
target_url: http://arcd.com/users/
|
||||||
fix_duration: 1
|
fixing_duration: 1
|
||||||
- type: DatabaseClient
|
- type: DatabaseClient
|
||||||
options:
|
options:
|
||||||
db_server_ip: 192.168.1.10
|
db_server_ip: 192.168.1.10
|
||||||
server_password: arcd
|
server_password: arcd
|
||||||
fix_duration: 1
|
fixing_duration: 1
|
||||||
- type: DataManipulationBot
|
- type: DataManipulationBot
|
||||||
options:
|
options:
|
||||||
port_scan_p_of_success: 0.8
|
port_scan_p_of_success: 0.8
|
||||||
@@ -199,44 +199,44 @@ simulation:
|
|||||||
payload: "DELETE"
|
payload: "DELETE"
|
||||||
server_ip: 192.168.1.21
|
server_ip: 192.168.1.21
|
||||||
server_password: arcd
|
server_password: arcd
|
||||||
fix_duration: 1
|
fixing_duration: 1
|
||||||
- type: DoSBot
|
- type: DoSBot
|
||||||
options:
|
options:
|
||||||
target_ip_address: 192.168.10.21
|
target_ip_address: 192.168.10.21
|
||||||
payload: SPOOF DATA
|
payload: SPOOF DATA
|
||||||
port_scan_p_of_success: 0.8
|
port_scan_p_of_success: 0.8
|
||||||
fix_duration: 1
|
fixing_duration: 1
|
||||||
services:
|
services:
|
||||||
- type: DNSClient
|
- type: DNSClient
|
||||||
options:
|
options:
|
||||||
dns_server: 192.168.1.10
|
dns_server: 192.168.1.10
|
||||||
fix_duration: 3
|
fixing_duration: 3
|
||||||
- type: DNSServer
|
- type: DNSServer
|
||||||
options:
|
options:
|
||||||
fix_duration: 3
|
fixing_duration: 3
|
||||||
domain_mapping:
|
domain_mapping:
|
||||||
arcd.com: 192.168.1.10
|
arcd.com: 192.168.1.10
|
||||||
- type: DatabaseService
|
- type: DatabaseService
|
||||||
options:
|
options:
|
||||||
backup_server_ip: 192.168.1.10
|
backup_server_ip: 192.168.1.10
|
||||||
fix_duration: 3
|
fixing_duration: 3
|
||||||
- type: WebServer
|
- type: WebServer
|
||||||
options:
|
options:
|
||||||
fix_duration: 3
|
fixing_duration: 3
|
||||||
- type: FTPClient
|
- type: FTPClient
|
||||||
options:
|
options:
|
||||||
fix_duration: 3
|
fixing_duration: 3
|
||||||
- type: FTPServer
|
- type: FTPServer
|
||||||
options:
|
options:
|
||||||
server_password: arcd
|
server_password: arcd
|
||||||
fix_duration: 3
|
fixing_duration: 3
|
||||||
- type: NTPClient
|
- type: NTPClient
|
||||||
options:
|
options:
|
||||||
ntp_server_ip: 192.168.1.10
|
ntp_server_ip: 192.168.1.10
|
||||||
fix_duration: 3
|
fixing_duration: 3
|
||||||
- type: NTPServer
|
- type: NTPServer
|
||||||
options:
|
options:
|
||||||
fix_duration: 3
|
fixing_duration: 3
|
||||||
- hostname: client_2
|
- hostname: client_2
|
||||||
type: computer
|
type: computer
|
||||||
ip_address: 192.168.10.22
|
ip_address: 192.168.10.22
|
||||||
@@ -27,27 +27,27 @@ def load_config(config_path: Union[str, Path]) -> PrimaiteGame:
|
|||||||
return PrimaiteGame.from_config(cfg)
|
return PrimaiteGame.from_config(cfg)
|
||||||
|
|
||||||
|
|
||||||
def test_default_fix_duration():
|
def test_default_fixing_duration():
|
||||||
"""Test that software with no defined fix duration in config uses the default fix duration of 2."""
|
"""Test that software with no defined fixing duration in config uses the default fixing duration of 2."""
|
||||||
game = load_config(TEST_CONFIG)
|
game = load_config(TEST_CONFIG)
|
||||||
client_2: Computer = game.simulation.network.get_node_by_hostname("client_2")
|
client_2: Computer = game.simulation.network.get_node_by_hostname("client_2")
|
||||||
|
|
||||||
database_client: DatabaseClient = client_2.software_manager.software.get("DatabaseClient")
|
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")
|
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():
|
def test_fixing_duration_set_from_config():
|
||||||
"""Test to check that the fix duration set for applications and services works as intended."""
|
"""Test to check that the fixing duration set for applications and services works as intended."""
|
||||||
game = load_config(TEST_CONFIG)
|
game = load_config(TEST_CONFIG)
|
||||||
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
|
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
|
||||||
|
|
||||||
# in config - services take 3 timesteps to fix
|
# in config - services take 3 timesteps to fix
|
||||||
for service in ["DNSClient", "DNSServer", "DatabaseService", "WebServer", "FTPClient", "FTPServer", "NTPServer"]:
|
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) 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
|
# in config - applications take 1 timestep to fix
|
||||||
# remove test applications from list
|
# remove test applications from list
|
||||||
@@ -55,27 +55,27 @@ def test_fix_duration_set_from_config():
|
|||||||
|
|
||||||
for application in ["RansomwareScript", "WebBrowser", "DataManipulationBot", "DoSBot", "DatabaseClient"]:
|
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) 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():
|
def test_fixing_duration_for_one_item():
|
||||||
"""Test that setting fix duration for one application does not affect other components."""
|
"""Test that setting fixing duration for one application does not affect other components."""
|
||||||
game = load_config(ONE_ITEM_CONFIG)
|
game = load_config(ONE_ITEM_CONFIG)
|
||||||
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
|
client_1: Computer = game.simulation.network.get_node_by_hostname("client_1")
|
||||||
|
|
||||||
# in config - services take 3 timesteps to fix
|
# in config - services take 3 timesteps to fix
|
||||||
for service in ["DNSClient", "DNSServer", "WebServer", "FTPClient", "FTPServer", "NTPServer"]:
|
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) 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
|
# in config - applications take 1 timestep to fix
|
||||||
# remove test applications from list
|
# remove test applications from list
|
||||||
for applications in ["RansomwareScript", "WebBrowser", "DataManipulationBot", "DoSBot"]:
|
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) 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")
|
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")
|
database_service: DatabaseService = client_1.software_manager.software.get("DatabaseService")
|
||||||
assert database_service.fixing_duration == 5
|
assert database_service.config.fixing_duration == 5
|
||||||
Reference in New Issue
Block a user