Merge branch 'dev' into feature/2879-log-random-seed-value
This commit is contained in:
@@ -5,12 +5,17 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
## [3.3.0] - 2024-09-04
|
||||
|
||||
### Added
|
||||
- Log observation space data by episode and step.
|
||||
|
||||
### Changed
|
||||
- ACL's are no longer applied to layer-2 traffic.
|
||||
- Random number seed values are recorded in simulation/seed.log if the seed is set in the config file
|
||||
or `generate_seed_value` is set to `true`.
|
||||
- ARP .show() method will now include the port number associated with each entry.
|
||||
- Added `services_requires_scan` and `applications_requires_scan` to agent observation space config to allow the agents to be able to see actual health states of services and applications without requiring scans (Default `True`, set to `False` to allow agents to see actual health state without scanning).
|
||||
|
||||
## [3.3.0] - 2024-09-04
|
||||
### Added
|
||||
|
||||
@@ -24,6 +24,8 @@ PrimAITE presents the following features:
|
||||
|
||||
- Support for multiple agents, each having their own customisable observation space, action space, and reward function definition, and either deterministic or RL-directed behaviour
|
||||
|
||||
Whilst PrimAITE ships with a number of example modelled scenarios (a.k.a. Use Cases), it has not been developed to mandate the solving of a single cyber challenge, and instead provides a highly flexible environment application that can be extended and reconfigured by the user to suit their specific cyber defence training and evaluation needs. PrimAITE provides default networks, red agent and green agent behaviour, reward functions, and action / observation space configuration, all of which can be utilised out of the box, but which ultimately can (and in some instances should) be built upon and / or reconfigured to meet the needs of different defensive agent developers. The PrimAITE user guide provides comprehensive instruction on all PrimAITE features, functionality and components, and can be consulted in order to help guide users in any reconfiguration or enhancements they wish to undertake; a library of example Jupyter notebooks are also provided to support such work.
|
||||
|
||||
## Getting Started with PrimAITE
|
||||
|
||||
### 💫 Installation
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 80 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
@@ -0,0 +1,38 @@
|
||||
# PrimAITE v3.3.0 Learning Benchmark
|
||||
## PrimAITE Dev Team
|
||||
### 2024-09-02
|
||||
|
||||
---
|
||||
## 1 Introduction
|
||||
PrimAITE v3.3.0 was benchmarked automatically upon release. Learning rate metrics were captured to be referenced during system-level testing and user acceptance testing (UAT).
|
||||
The benchmarking process consists of running 5 training session using the same config file. Each session trains an agent for 1000 episodes, with each episode consisting of 128 steps.
|
||||
The total reward per episode from each session is captured. This is then used to calculate an caverage total reward per episode from the 5 individual sessions for smoothing. Finally, a 25-widow rolling average of the average total reward per session is calculated for further smoothing.
|
||||
## 2 System Information
|
||||
### 2.1 Python
|
||||
**Version:** 3.10.14 (main, Apr 6 2024, 18:45:05) [GCC 9.4.0]
|
||||
### 2.2 System
|
||||
- **OS:** Linux
|
||||
- **OS Version:** #76~20.04.1-Ubuntu SMP Thu Jun 13 18:00:23 UTC 2024
|
||||
- **Machine:** x86_64
|
||||
- **Processor:** x86_64
|
||||
### 2.3 CPU
|
||||
- **Physical Cores:** 2
|
||||
- **Total Cores:** 4
|
||||
- **Max Frequency:** 0.00Mhz
|
||||
### 2.4 Memory
|
||||
- **Total:** 15.62GB
|
||||
- **Swap Total:** 0.00B
|
||||
## 3 Stats
|
||||
- **Total Sessions:** 5
|
||||
- **Total Episodes:** 5005
|
||||
- **Total Steps:** 640000
|
||||
- **Av Session Duration (s):** 1458.2831
|
||||
- **Av Step Duration (s):** 0.0456
|
||||
- **Av Duration per 100 Steps per 10 Nodes (s):** 4.5571
|
||||
## 4 Graphs
|
||||
### 4.1 v3.3.0 Learning Benchmark Plot
|
||||

|
||||
### 4.2 Learning Benchmark of Minor and Bugfix Releases for Major Version 3
|
||||

|
||||
### 4.3 Performance of Minor and Bugfix Releases for Major Version 3
|
||||

|
||||
BIN
benchmark/results/v3/v3.3.0/PrimAITE v3.3.0 Benchmark Report.pdf
Normal file
BIN
benchmark/results/v3/v3.3.0/PrimAITE v3.3.0 Benchmark Report.pdf
Normal file
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 156 KiB |
1009
benchmark/results/v3/v3.3.0/session_metadata/1.json
Normal file
1009
benchmark/results/v3/v3.3.0/session_metadata/1.json
Normal file
File diff suppressed because it is too large
Load Diff
1009
benchmark/results/v3/v3.3.0/session_metadata/2.json
Normal file
1009
benchmark/results/v3/v3.3.0/session_metadata/2.json
Normal file
File diff suppressed because it is too large
Load Diff
1009
benchmark/results/v3/v3.3.0/session_metadata/3.json
Normal file
1009
benchmark/results/v3/v3.3.0/session_metadata/3.json
Normal file
File diff suppressed because it is too large
Load Diff
1009
benchmark/results/v3/v3.3.0/session_metadata/4.json
Normal file
1009
benchmark/results/v3/v3.3.0/session_metadata/4.json
Normal file
File diff suppressed because it is too large
Load Diff
1009
benchmark/results/v3/v3.3.0/session_metadata/5.json
Normal file
1009
benchmark/results/v3/v3.3.0/session_metadata/5.json
Normal file
File diff suppressed because it is too large
Load Diff
7445
benchmark/results/v3/v3.3.0/v3.3.0_benchmark_metadata.json
Normal file
7445
benchmark/results/v3/v3.3.0/v3.3.0_benchmark_metadata.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -60,6 +60,8 @@ The ARCD Primary-level AI Training Environment (**PrimAITE**) provides an effect
|
||||
- Modelling background (green) pattern-of-life;
|
||||
- Operates at machine-speed to enable fast training cycles via Reinforcement Learning (RL).
|
||||
|
||||
PrimAITE has been designed as an extensible environment and toolkit to support the development, test, training and evaluation of AI-based cyber defensive agents. Whilst PrimAITE ships with a number of example modelled scenarios (a.k.a. Use Cases), it has not been developed to mandate the solving of a single cyber challenge, and instead provides a highly flexible environment application that can be extended and reconfigured by the user to suit their specific cyber defence training and evaluation needs. PrimAITE provides default networks, red agent and green agent behaviour, reward functions, and action / observation space configuration, all of which can be utilised out of the box, but which ultimately can (and in some instances should) be built upon and / or reconfigured to meet the needs of different defensive agent developers. The PrimAITE user guide provides comprehensive instruction on all PrimAITE features, functionality and components, and can be consulted in order to help guide users in any reconfiguration or enhancements they wish to undertake; a library of example Jupyter notebooks are also provided to support such work.
|
||||
|
||||
Features
|
||||
^^^^^^^^
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ about which actions are invalid based on the current environment state. For inst
|
||||
software on a node that is turned off. Therefore, if an agent has a NODE_SOFTWARE_INSTALL in it's action map for that node,
|
||||
the action mask will show `0` in the corresponding entry.
|
||||
|
||||
*Note: just because an action is available in the action mask does not mean it will be successful when executed. It just means it's possible to try to execute the action at this time.*
|
||||
|
||||
Configuration
|
||||
=============
|
||||
Action masking is supported for agents that use the `ProxyAgent` class (the class used for connecting to RL algorithms).
|
||||
@@ -23,95 +25,121 @@ The following logic is applied:
|
||||
+==========================================+=====================================================================+
|
||||
| **DONOTHING** | Always Possible. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_SERVICE_SCAN** | Node is on. Service is running. |
|
||||
| **NODE_SERVICE_SCAN** | Node is on. Service is running. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_SERVICE_STOP** | Node is on. Service is running. |
|
||||
| **NODE_SERVICE_STOP** | Node is on. Service is running. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_SERVICE_START** | Node is on. Service is stopped. |
|
||||
| **NODE_SERVICE_START** | Node is on. Service is stopped. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_SERVICE_PAUSE** | Node is on. Service is running. |
|
||||
| **NODE_SERVICE_PAUSE** | Node is on. Service is running. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_SERVICE_RESUME** | Node is on. Service is paused. |
|
||||
| **NODE_SERVICE_RESUME** | Node is on. Service is paused. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_SERVICE_RESTART** | Node is on. Service is running. |
|
||||
| **NODE_SERVICE_RESTART** | Node is on. Service is running. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_SERVICE_DISABLE** | Node is on. |
|
||||
| **NODE_SERVICE_DISABLE** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_SERVICE_ENABLE** | Node is on. Service is disabled. |
|
||||
| **NODE_SERVICE_ENABLE** | Node is on. Service is disabled. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_SERVICE_FIX** | Node is on. Service is running. |
|
||||
| **NODE_SERVICE_FIX** | Node is on. Service is running. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_APPLICATION_EXECUTE** | Node is on. |
|
||||
| **NODE_APPLICATION_EXECUTE** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_APPLICATION_SCAN** | Node is on. Application is running. |
|
||||
| **NODE_APPLICATION_SCAN** | Node is on. Application is running. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_APPLICATION_CLOSE** | Node is on. Application is running. |
|
||||
| **NODE_APPLICATION_CLOSE** | Node is on. Application is running. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_APPLICATION_FIX** | Node is on. Application is running. |
|
||||
| **NODE_APPLICATION_FIX** | Node is on. Application is running. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_APPLICATION_INSTALL** | Node is on. |
|
||||
| **NODE_APPLICATION_INSTALL** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_APPLICATION_REMOVE** | Node is on. |
|
||||
| **NODE_APPLICATION_REMOVE** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FILE_SCAN** | Node is on. File exists. File not deleted. |
|
||||
| **NODE_FILE_SCAN** | Node is on. File exists. File not deleted. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FILE_CREATE** | Node is on. |
|
||||
| **NODE_FILE_CREATE** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FILE_CHECKHASH** | Node is on. File exists. File not deleted. |
|
||||
| **NODE_FILE_CHECKHASH** | Node is on. File exists. File not deleted. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FILE_DELETE** | Node is on. File exists. |
|
||||
| **NODE_FILE_DELETE** | Node is on. File exists. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FILE_REPAIR** | Node is on. File exists. File not deleted. |
|
||||
| **NODE_FILE_REPAIR** | Node is on. File exists. File not deleted. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FILE_RESTORE** | Node is on. File exists. File is deleted. |
|
||||
| **NODE_FILE_RESTORE** | Node is on. File exists. File is deleted. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FILE_CORRUPT** | Node is on. File exists. File not deleted. |
|
||||
| **NODE_FILE_CORRUPT** | Node is on. File exists. File not deleted. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FILE_ACCESS** | Node is on. File exists. File not deleted. |
|
||||
| **NODE_FILE_ACCESS** | Node is on. File exists. File not deleted. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FOLDER_CREATE** | Node is on. |
|
||||
| **NODE_FOLDER_CREATE** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FOLDER_SCAN** | Node is on. Folder exists. Folder not deleted. |
|
||||
| **NODE_FOLDER_SCAN** | Node is on. Folder exists. Folder not deleted. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FOLDER_CHECKHASH** | Node is on. Folder exists. Folder not deleted. |
|
||||
| **NODE_FOLDER_CHECKHASH** | Node is on. Folder exists. Folder not deleted. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FOLDER_REPAIR** | Node is on. Folder exists. Folder not deleted. |
|
||||
| **NODE_FOLDER_REPAIR** | Node is on. Folder exists. Folder not deleted. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_FOLDER_RESTORE** | Node is on. Folder exists. Folder is deleted. |
|
||||
| **NODE_FOLDER_RESTORE** | Node is on. Folder exists. Folder is deleted. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_OS_SCAN** | Node is on. |
|
||||
| **NODE_OS_SCAN** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_NIC_ENABLE** | NIC is disabled. Node is on. |
|
||||
| **HOST_NIC_ENABLE** | NIC is disabled. Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_NIC_DISABLE** | NIC is enabled. Node is on. |
|
||||
| **HOST_NIC_DISABLE** | NIC is enabled. Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_SHUTDOWN** | Node is on. |
|
||||
| **NODE_SHUTDOWN** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_STARTUP** | Node is off. |
|
||||
| **NODE_STARTUP** | Node is off. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_RESET** | Node is on. |
|
||||
| **NODE_RESET** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_NMAP_PING_SCAN** | Node is on. |
|
||||
| **NODE_NMAP_PING_SCAN** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_NMAP_PORT_SCAN** | Node is on. |
|
||||
| **NODE_NMAP_PORT_SCAN** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_HOST_NMAP_NETWORK_SERVICE_RECON** | Node is on. |
|
||||
| **NODE_NMAP_NETWORK_SERVICE_RECON** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_ROUTER_PORT_ENABLE** | Router is on. |
|
||||
| **NETWORK_PORT_ENABLE** | Node is on. Router is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_ROUTER_PORT_DISABLE** | Router is on. |
|
||||
| **NETWORK_PORT_DISABLE** | Router is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_ROUTER_ACL_ADDRULE** | Router is on. |
|
||||
| **ROUTER_ACL_ADDRULE** | Router is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_ROUTER_ACL_REMOVERULE** | Router is on. |
|
||||
| **ROUTER_ACL_REMOVERULE** | Router is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_FIREWALL_PORT_ENABLE** | Firewall is on. |
|
||||
| **FIREWALL_ACL_ADDRULE** | Firewall is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_FIREWALL_PORT_DISABLE** | Firewall is on. |
|
||||
| **FIREWALL_ACL_REMOVERULE** | Firewall is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_FIREWALL_ACL_ADDRULE** | Firewall is on. |
|
||||
| **NODE_NMAP_PING_SCAN** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_FIREWALL_ACL_REMOVERULE** | Firewall is on. |
|
||||
| **NODE_NMAP_PORT_SCAN** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_NMAP_NETWORK_SERVICE_RECON** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **CONFIGURE_DATABASE_CLIENT** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **CONFIGURE_RANSOMWARE_SCRIPT** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **CONFIGURE_DOSBOT** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **CONFIGURE_C2_BEACON** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **C2_SERVER_RANSOMWARE_LAUNCH** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **C2_SERVER_RANSOMWARE_CONFIGURE** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **C2_SERVER_TERMINAL_COMMAND** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **C2_SERVER_DATA_EXFILTRATE** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_ACCOUNTS_CHANGE_PASSWORD** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **SSH_TO_REMOTE** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **SESSIONS_REMOTE_LOGOFF** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
| **NODE_SEND_REMOTE_COMMAND** | Node is on. |
|
||||
+------------------------------------------+---------------------------------------------------------------------+
|
||||
|
||||
|
||||
|
||||
@@ -172,3 +172,8 @@ The amount of timesteps that the frequency can randomly change.
|
||||
---------------
|
||||
|
||||
If ``True``, gymnasium flattening will be performed on the observation space before sending to the agent. Set this to ``True`` if your agent does not support nested observation spaces.
|
||||
|
||||
``Agent History``
|
||||
-----------------
|
||||
|
||||
Agents will record their action log for each step. This is a summary of what the agent did, along with response information from requests within the simulation.
|
||||
|
||||
@@ -28,6 +28,7 @@ This section defines high-level settings that apply across the game, currently i
|
||||
high: 10
|
||||
medium: 5
|
||||
low: 0
|
||||
seed: 1
|
||||
|
||||
``max_episode_length``
|
||||
----------------------
|
||||
@@ -54,3 +55,8 @@ See :ref:`List of IPProtocols <List of IPProtocols>` for a list of protocols.
|
||||
--------------
|
||||
|
||||
These are used to determine the thresholds of high, medium and low categories for counted observation occurrences.
|
||||
|
||||
``seed``
|
||||
--------
|
||||
|
||||
Used to configure the random seeds used within PrimAITE, ensuring determinism within episode/session runs. If empty or set to -1, no seed is set.
|
||||
|
||||
@@ -91,7 +91,7 @@ List of file types: :py:mod:`primaite.simulator.file_system.file_type.FileType`
|
||||
---------
|
||||
|
||||
The list of pre-existing users that are additional to the default admin user (``username=admin``, ``password=admin``).
|
||||
Additional users are configured as an array nd must contain a ``username``, ``password``, and can contain an optional
|
||||
Additional users are configured as an array and must contain a ``username``, ``password``, and can contain an optional
|
||||
boolean ``is_admin``.
|
||||
|
||||
Example of adding two additional users to a node:
|
||||
@@ -101,11 +101,8 @@ Example of adding two additional users to a node:
|
||||
simulation:
|
||||
network:
|
||||
nodes:
|
||||
- hostname: client_1
|
||||
type: computer
|
||||
ip_address: 192.168.10.11
|
||||
subnet_mask: 255.255.255.0
|
||||
default_gateway: 192.168.10.1
|
||||
- hostname: [hostname]
|
||||
type: [Node Type]
|
||||
users:
|
||||
- username: jane.doe
|
||||
password: '1234'
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
+===================+=========+====================================+=======================================================================================================+====================================================================+
|
||||
| gymnasium | 0.28.1 | MIT License | A standard API for reinforcement learning and a diverse set of reference environments (formerly Gym). | https://farama.org |
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
| ipywidgets | 8.1.3 | BSD License | Jupyter interactive widgets | http://jupyter.org |
|
||||
| ipywidgets | 8.1.5 | BSD License | Jupyter interactive widgets | http://jupyter.org |
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
| jupyterlab | 3.6.1 | BSD License | JupyterLab computational environment | https://jupyter.org |
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
@@ -23,7 +23,7 @@
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
| plotly | 5.15.0 | MIT License | An open-source, interactive data visualization library for Python | https://plotly.com/python/ |
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
| polars | 0.18.4 | MIT License | Blazingly fast DataFrame library | https://www.pola.rs/ |
|
||||
| polars | 0.20.30 | MIT License | Blazingly fast DataFrame library | https://www.pola.rs/ |
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
| prettytable | 3.8.0 | BSD License (BSD (3 clause)) | A simple Python library for easily displaying tabular data in a visually appealing ASCII table format | https://github.com/jazzband/prettytable |
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
@@ -31,7 +31,7 @@
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
| PyYAML | 6.0 | MIT License | YAML parser and emitter for Python | https://pyyaml.org/ |
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
| ray | 2.23.0 | Apache 2.0 | Ray provides a simple, universal API for building distributed applications. | https://github.com/ray-project/ray |
|
||||
| ray | 2.32.0 | Apache 2.0 | Ray provides a simple, universal API for building distributed applications. | https://github.com/ray-project/ray |
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
| stable-baselines3 | 2.1.0 | MIT | Pytorch version of Stable Baselines, implementations of reinforcement learning algorithms. | https://github.com/DLR-RM/stable-baselines3 |
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
@@ -39,7 +39,7 @@
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
| typer | 0.9.0 | MIT License | Typer, build great CLIs. Easy to code. Based on Python type hints. | https://github.com/tiangolo/typer |
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
| Deepdiff | 7.0.1 | MIT License | Deep difference of dictionaries, iterables, strings, and any other object objects. | https://github.com/seperman/deepdiff |
|
||||
| Deepdiff | 8.0.1 | MIT License | Deep difference of dictionaries, iterables, strings, and any other object objects. | https://github.com/seperman/deepdiff |
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
| sb3_contrib | 2.3.0 | MIT License | Contrib package for Stable-Baselines3 - Experimental reinforcement learning (RL) code (Action Masking)| https://github.com/Stable-Baselines-Team/stable-baselines3-contrib |
|
||||
| sb3_contrib | 2.1.0 | MIT License | Contrib package for Stable-Baselines3 - Experimental reinforcement learning (RL) code (Action Masking)| https://github.com/Stable-Baselines-Team/stable-baselines3-contrib |
|
||||
+-------------------+---------+------------------------------------+-------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------+
|
||||
|
||||
@@ -7,6 +7,9 @@ Rewards
|
||||
|
||||
Rewards in PrimAITE are based on a system of individual components that react to events in the simulation. An agent's reward function is calculated as the weighted sum of several reward components.
|
||||
|
||||
Some rewards, such as the ``GreenAdminDatabaseUnreachablePenalty``, can be marked as 'sticky' in their configuration. Setting this to ``True`` will mean that they continue to output the same value after an event until another event of that type.
|
||||
In the instance of the ``GreenAdminDatabaseUnreachablePenalty``, the database admin reward will stay negative until the next successful database request is made, even if the database admin agents do nothing and the database returns a good state.
|
||||
|
||||
Components
|
||||
**********
|
||||
The following API pages describe the use of each reward component and the possible configuration options. An example of configuring each via yaml is also provided.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
© Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
|
||||
|
||||
######
|
||||
Router
|
||||
Wireless Router
|
||||
######
|
||||
|
||||
The ``WirelessRouter`` class extends the functionality of the standard ``Router`` class within PrimAITE,
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
Command and Control Application Suite
|
||||
#####################################
|
||||
|
||||
Comprising of two applications, the Command and Control (C2) suites intends to introduce
|
||||
malicious network architecture and begin to further the realism of red agents within primAITE.
|
||||
Comprising of two applications, the Command and Control (C2) suite intends to introduce
|
||||
malicious network architecture and further the realism of red agents within PrimAITE.
|
||||
|
||||
Overview:
|
||||
=========
|
||||
@@ -24,7 +24,7 @@ The C2 Server application is intended to represent the malicious infrastructure
|
||||
|
||||
The C2 Server is configured to listen and await ``keep alive`` traffic from a C2 beacon. Once received the C2 Server is able to send and receive C2 commands.
|
||||
|
||||
Currently, the C2 Server offers three commands:
|
||||
Currently, the C2 Server offers four commands:
|
||||
|
||||
+---------------------+---------------------------------------------------------------------------+
|
||||
|C2 Command | Meaning |
|
||||
@@ -40,12 +40,12 @@ Currently, the C2 Server offers three commands:
|
||||
|
||||
|
||||
It's important to note that in order to keep PrimAITE realistic from a cyber perspective,
|
||||
The C2 Server application should never be visible or actionable upon directly by the blue agent.
|
||||
the C2 Server application should never be visible or actionable upon directly by the blue agent.
|
||||
|
||||
This is because in the real world, C2 servers are hosted on ephemeral public domains that would not be accessible by private network blue agent.
|
||||
Therefore granting blue agent(s) the ability to perform counter measures directly against the application would be unrealistic.
|
||||
|
||||
It is more accurate to see the host that the C2 Server is installed on as being able to route to the C2 Server (Internet Access).
|
||||
It is more accurate to see the host that the C2 Beacon is installed on as being able to route to the C2 Server (Internet Access).
|
||||
|
||||
``C2 Beacon``
|
||||
"""""""""""""
|
||||
@@ -54,19 +54,19 @@ The C2 Beacon application is intended to represent malware that is used to estab
|
||||
|
||||
A C2 Beacon will need to be first configured with the C2 Server IP Address which can be done via the ``configure`` method.
|
||||
|
||||
Once installed and configured; the c2 beacon can establish connection with the C2 Server via executing the application.
|
||||
Once installed and configured; the C2 beacon can establish connection with the C2 Server via executing the application.
|
||||
|
||||
This will send an initial ``keep alive`` to the given C2 Server (The C2 Server IPv4Address must be given upon C2 Beacon configuration).
|
||||
Which is then resolved and responded by another ``Keep Alive`` by the c2 server back to the C2 beacon to confirm connection.
|
||||
Which is then resolved and responded by another ``Keep Alive`` by the C2 server back to the C2 beacon to confirm connection.
|
||||
|
||||
The C2 Beacon will send out periodic keep alive based on it's configuration parameters to configure it's active connection with the c2 server.
|
||||
The C2 Beacon will send out periodic keep alive based on its configuration parameters to configure it's active connection with the C2 server.
|
||||
|
||||
It's recommended that a C2 Beacon is installed and configured mid episode by a Red Agent for a more cyber realistic simulation.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
As mentioned, the C2 Suite is intended to grant Red Agents further flexibility whilst also expanding a blue agent's observation_space.
|
||||
As mentioned, the C2 Suite is intended to grant Red Agents further flexibility whilst also expanding a blue agent's observation space.
|
||||
|
||||
Adding to this, the following behaviour of the C2 beacon can be configured by users for increased domain randomisation:
|
||||
|
||||
@@ -254,11 +254,6 @@ Via Configuration
|
||||
C2 Beacon Configuration
|
||||
=======================
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: C2Beacon
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``C2Beacon``
|
||||
|
||||
``c2_server_ip_address``
|
||||
""""""""""""""""""""""""
|
||||
|
||||
@@ -275,7 +270,7 @@ How often should the C2 Beacon confirm it's connection in timesteps.
|
||||
For example, if the keep alive Frequency is set to one then every single timestep
|
||||
the C2 connection will be confirmed.
|
||||
|
||||
It's worth noting that this may be useful option when investigating
|
||||
It's worth noting that this may be a useful option when investigating
|
||||
network blue agent observation space.
|
||||
|
||||
This must be a valid integer i.e ``10``. Defaults to ``5``.
|
||||
@@ -288,7 +283,7 @@ The protocol that the C2 Beacon will use to communicate to the C2 Server with.
|
||||
|
||||
Currently only ``TCP`` and ``UDP`` are valid masquerade protocol options.
|
||||
|
||||
It's worth noting that this may be useful option to bypass ACL rules.
|
||||
It's worth noting that this may be a useful option to bypass ACL rules.
|
||||
|
||||
This must be a string i.e *UDP*. Defaults to ``TCP``.
|
||||
|
||||
@@ -301,19 +296,24 @@ What port that the C2 Beacon will use to communicate to the C2 Server with.
|
||||
|
||||
Currently only ``FTP``, ``HTTP`` and ``DNS`` are valid masquerade port options.
|
||||
|
||||
It's worth noting that this may be useful option to bypass ACL rules.
|
||||
It's worth noting that this may be a useful option to bypass ACL rules.
|
||||
|
||||
This must be a string i.e ``DNS``. Defaults to ``HTTP``.
|
||||
|
||||
*Please refer to the ``IPProtocol`` class for further reference.*
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
|
||||
C2 Server Configuration
|
||||
=======================
|
||||
|
||||
*The C2 Server does not currently offer any unique configuration options and will configure itself to match the C2 beacon's network behaviour.*
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: C2Server
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``C2Server``
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -158,10 +158,6 @@ If not using the data manipulation bot manually, it needs to be used with a data
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: DataManipulationBot
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``DataManipulationBot``
|
||||
|
||||
``server_ip``
|
||||
"""""""""""""
|
||||
@@ -203,3 +199,8 @@ Optional. Default value is ``0.1``.
|
||||
The chance of the ``DataManipulationBot`` to succeed with a data manipulation attack.
|
||||
|
||||
This must be a float value between ``0`` and ``1``.
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -90,11 +90,6 @@ Via Configuration
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: DatabaseClient
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``DatabaseClient``
|
||||
|
||||
|
||||
``db_server_ip``
|
||||
""""""""""""""""
|
||||
@@ -109,3 +104,8 @@ This must be a valid octet i.e. in the range of ``0.0.0.0`` and ``255.255.255.25
|
||||
Optional. Default value is ``None``.
|
||||
|
||||
The password that the ``DatabaseClient`` will use to access the :ref:`DatabaseService`.
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -98,11 +98,6 @@ Via Configuration
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: DoSBot
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``DoSBot``
|
||||
|
||||
``target_ip_address``
|
||||
"""""""""""""""""""""
|
||||
|
||||
@@ -161,3 +156,8 @@ Optional. Default value is ``1000``.
|
||||
The maximum number of sessions the ``DoSBot`` is able to make.
|
||||
|
||||
This must be an integer value equal to or greater than ``0``.
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -346,10 +346,8 @@ Perform a full box scan on all ports, over both TCP and UDP, on a whole subnet:
|
||||
| 192.168.1.13 | 219 | ARP | UDP |
|
||||
+--------------+------+-----------------+----------+
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
``Common Attributes``
|
||||
"""""""""""""""""""""
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: NMAP
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``NMAP``
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -72,10 +72,6 @@ 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``.
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: RansomwareScript
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``RansomwareScript``
|
||||
|
||||
``server_ip``
|
||||
"""""""""""""
|
||||
@@ -83,3 +79,8 @@ The RansomwareScript inherits configuration options such as ``fix_duration`` fro
|
||||
IP address of the :ref:`DatabaseService` which the ``RansomwareScript`` will encrypt.
|
||||
|
||||
This must be a valid octet i.e. in the range of ``0.0.0.0`` and ``255.255.255.255``.
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -92,10 +92,6 @@ Via Configuration
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: WebBrowser
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``WebBrowser``
|
||||
|
||||
``target_url``
|
||||
""""""""""""""
|
||||
@@ -109,3 +105,9 @@ The domain ``arcd.com`` can be matched by
|
||||
- http://arcd.com/
|
||||
- http://arcd.com/users/
|
||||
- arcd.com
|
||||
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -2,35 +2,38 @@
|
||||
|
||||
© Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
|
||||
|
||||
``ref``
|
||||
=======
|
||||
.. _Common Configuration:
|
||||
|
||||
Human readable name used as reference for the |SOFTWARE_NAME_BACKTICK|. Not used in code.
|
||||
Common Configuration
|
||||
""""""""""""""""""""
|
||||
|
||||
``type``
|
||||
========
|
||||
ref
|
||||
"""
|
||||
|
||||
The type of software that should be added. To add |SOFTWARE_NAME| this must be |SOFTWARE_NAME_BACKTICK|.
|
||||
Human readable name used as reference for the software class. Not used in code.
|
||||
|
||||
``options``
|
||||
===========
|
||||
type
|
||||
""""
|
||||
|
||||
The configuration options are the attributes that fall under the options for an application.
|
||||
The type of software that should be added. To add the required software, this must be it's name.
|
||||
|
||||
options
|
||||
"""""""
|
||||
|
||||
The configuration options are the attributes that fall under the options for an application or service.
|
||||
|
||||
``fix_duration``
|
||||
""""""""""""""""
|
||||
fix_duration
|
||||
""""""""""""
|
||||
|
||||
Optional. Default value is ``2``.
|
||||
|
||||
The number of timesteps the |SOFTWARE_NAME| will remain in a ``FIXING`` state before going into a ``GOOD`` state.
|
||||
The number of timesteps the software will remain in a ``FIXING`` state before going into a ``GOOD`` state.
|
||||
|
||||
|
||||
``listen_on_ports``
|
||||
"""""""""""""""""""
|
||||
listen_on_ports
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The set of ports to listen on. This is in addition to the main port the software is designated. This set can either be
|
||||
Optional. The set of ports to listen on. This is in addition to the main port the software is designated. This can either be
|
||||
the string name of ports or the port integers
|
||||
|
||||
Example:
|
||||
@@ -40,20 +43,15 @@ Example:
|
||||
simulation:
|
||||
network:
|
||||
nodes:
|
||||
- hostname: client
|
||||
type: computer
|
||||
ip_address: 192.168.10.11
|
||||
subnet_mask: 255.255.255.0
|
||||
default_gateway: 192.168.10.1
|
||||
- hostname: [hostname]
|
||||
type: [Node Type]
|
||||
services:
|
||||
- type: DatabaseService
|
||||
- type: [Service Type]
|
||||
options:
|
||||
backup_server_ip: 10.10.1.12
|
||||
listen_on_ports:
|
||||
- 631
|
||||
applications:
|
||||
- type: WebBrowser
|
||||
- type: [Application Type]
|
||||
options:
|
||||
target_url: http://sometech.ai
|
||||
listen_on_ports:
|
||||
- SMB
|
||||
|
||||
@@ -94,11 +94,6 @@ Via Configuration
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: DatabaseService
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``DatabaseService``
|
||||
|
||||
``backup_server_ip``
|
||||
""""""""""""""""""""
|
||||
|
||||
@@ -114,3 +109,8 @@ This must be a valid octet i.e. in the range of ``0.0.0.0`` and ``255.255.255.25
|
||||
Optional. Default value is ``None``.
|
||||
|
||||
The password that needs to be provided by connecting clients in order to create a successful connection.
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -84,10 +84,6 @@ Via Configuration
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: DNSClient
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``DNSClient``
|
||||
|
||||
``dns_server``
|
||||
""""""""""""""
|
||||
@@ -97,3 +93,8 @@ Optional. Default value is ``None``.
|
||||
The IP Address of the :ref:`DNSServer`.
|
||||
|
||||
This must be a valid octet i.e. in the range of ``0.0.0.0`` and ``255.255.255.255``.
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -83,16 +83,17 @@ Via Configuration
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: DNSServer
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``DNSServer``
|
||||
|
||||
domain_mapping
|
||||
""""""""""""""
|
||||
``domain_mapping``
|
||||
""""""""""""""""""
|
||||
|
||||
Domain mapping takes the domain and IP Addresses as a key-value pairs i.e.
|
||||
|
||||
If the domain is "arcd.com" and the IP Address attributed to the domain is 192.168.0.10, then the value should be ``arcd.com: 192.168.0.10``
|
||||
|
||||
The key must be a string and the IP Address must be a valid octet i.e. in the range of ``0.0.0.0`` and ``255.255.255.255``.
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -83,7 +83,7 @@ Via Configuration
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: FTPClient
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``FTPClient``
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -81,14 +81,14 @@ Via Configuration
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: FTPServer
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``FTPServer``
|
||||
|
||||
``server_password``
|
||||
"""""""""""""""""""
|
||||
|
||||
Optional. Default value is ``None``.
|
||||
|
||||
The password that needs to be provided by a connecting :ref:`FTPClient` in order to create a successful connection.
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -80,11 +80,6 @@ Via Configuration
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: NTPClient
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``NTPClient``
|
||||
|
||||
``ntp_server_ip``
|
||||
"""""""""""""""""
|
||||
|
||||
@@ -93,3 +88,8 @@ Optional. Default value is ``None``.
|
||||
The IP address of an NTP Server which provides a time that the ``NTPClient`` can synchronise to.
|
||||
|
||||
This must be a valid octet i.e. in the range of ``0.0.0.0`` and ``255.255.255.255``.
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -75,10 +75,8 @@ Via Configuration
|
||||
- ref: ntp_server
|
||||
type: NTPServer
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: NTPServer
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``NTPServer``
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -23,13 +23,6 @@ Key capabilities
|
||||
- Simulates common Terminal processes/commands.
|
||||
- Leverages the Service base class for install/uninstall, status tracking etc.
|
||||
|
||||
Usage
|
||||
"""""
|
||||
|
||||
- Pre-Installs on any `Node` (component with the exception of `Switches`).
|
||||
- Terminal Clients connect, execute commands and disconnect from remote nodes.
|
||||
- Ensures that users are logged in to the component before executing any commands.
|
||||
- Service runs on SSH port 22 by default.
|
||||
|
||||
Implementation
|
||||
""""""""""""""
|
||||
@@ -40,6 +33,14 @@ Implementation
|
||||
- A detailed guide on the implementation and functionality of the Terminal class can be found in the "Terminal-Processing" jupyter notebook.
|
||||
|
||||
|
||||
Usage
|
||||
"""""
|
||||
|
||||
- Pre-Installs on all ``Nodes`` (with the exception of ``Switches``).
|
||||
- Terminal Clients connect, execute commands and disconnect from remote nodes.
|
||||
- Ensures that users are logged in to the component before executing any commands.
|
||||
- Service runs on SSH port 22 by default.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
@@ -172,3 +173,9 @@ Disconnect from Remote Node
|
||||
term_a_term_b_remote_connection: RemoteTerminalConnection = terminal_a.login(username="admin", password="Admin123!", ip_address="192.168.0.11")
|
||||
|
||||
term_a_term_b_remote_connection.disconnect()
|
||||
|
||||
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -75,10 +75,8 @@ Via Configuration
|
||||
- ref: web_server
|
||||
type: WebServer
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
.. include:: ../common/common_configuration.rst
|
||||
``Common Attributes``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. |SOFTWARE_NAME| replace:: WebServer
|
||||
.. |SOFTWARE_NAME_BACKTICK| replace:: ``WebServer``
|
||||
See :ref:`Common Configuration`
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
© Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
|
||||
|
||||
.. _software:
|
||||
|
||||
|
||||
Software
|
||||
========
|
||||
@@ -63,3 +65,10 @@ Processes
|
||||
#########
|
||||
|
||||
`To be implemented`
|
||||
|
||||
Common Software Configuration
|
||||
#############################
|
||||
|
||||
Below is a list of the common configuration items within Software components of PrimAITE:
|
||||
|
||||
.. include:: common/common_configuration.rst
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.3.0-dev0
|
||||
3.3.0
|
||||
|
||||
@@ -52,6 +52,14 @@ class HostObservation(AbstractObservation, identifier="HOST"):
|
||||
"""
|
||||
If True, files and folders must be scanned to update the health state. If False, true state is always shown.
|
||||
"""
|
||||
services_requires_scan: Optional[bool] = None
|
||||
"""
|
||||
If True, services must be scanned to update the health state. If False, true state is always shown.
|
||||
"""
|
||||
applications_requires_scan: Optional[bool] = None
|
||||
"""
|
||||
If True, applications must be scanned to update the health state. If False, true state is always shown.
|
||||
"""
|
||||
include_users: Optional[bool] = True
|
||||
"""If True, report user session information."""
|
||||
|
||||
@@ -71,6 +79,8 @@ class HostObservation(AbstractObservation, identifier="HOST"):
|
||||
monitored_traffic: Optional[Dict],
|
||||
include_num_access: bool,
|
||||
file_system_requires_scan: bool,
|
||||
services_requires_scan: bool,
|
||||
applications_requires_scan: bool,
|
||||
include_users: bool,
|
||||
) -> None:
|
||||
"""
|
||||
@@ -106,6 +116,12 @@ class HostObservation(AbstractObservation, identifier="HOST"):
|
||||
:param file_system_requires_scan: If True, the files and folders must be scanned to update the health state.
|
||||
If False, the true state is always shown.
|
||||
:type file_system_requires_scan: bool
|
||||
:param services_requires_scan: If True, services must be scanned to update the health state.
|
||||
If False, the true state is always shown.
|
||||
:type services_requires_scan: bool
|
||||
:param applications_requires_scan: If True, applications must be scanned to update the health state.
|
||||
If False, the true state is always shown.
|
||||
:type applications_requires_scan: bool
|
||||
:param include_users: If True, report user session information.
|
||||
:type include_users: bool
|
||||
"""
|
||||
@@ -119,7 +135,7 @@ class HostObservation(AbstractObservation, identifier="HOST"):
|
||||
# Ensure lists have lengths equal to specified counts by truncating or padding
|
||||
self.services: List[ServiceObservation] = services
|
||||
while len(self.services) < num_services:
|
||||
self.services.append(ServiceObservation(where=None))
|
||||
self.services.append(ServiceObservation(where=None, services_requires_scan=services_requires_scan))
|
||||
while len(self.services) > num_services:
|
||||
truncated_service = self.services.pop()
|
||||
msg = f"Too many services in Node observation space for node. Truncating service {truncated_service.where}"
|
||||
@@ -127,7 +143,9 @@ class HostObservation(AbstractObservation, identifier="HOST"):
|
||||
|
||||
self.applications: List[ApplicationObservation] = applications
|
||||
while len(self.applications) < num_applications:
|
||||
self.applications.append(ApplicationObservation(where=None))
|
||||
self.applications.append(
|
||||
ApplicationObservation(where=None, applications_requires_scan=applications_requires_scan)
|
||||
)
|
||||
while len(self.applications) > num_applications:
|
||||
truncated_application = self.applications.pop()
|
||||
msg = f"Too many applications in Node observation space for node. Truncating {truncated_application.where}"
|
||||
@@ -263,6 +281,10 @@ class HostObservation(AbstractObservation, identifier="HOST"):
|
||||
folder_config.file_system_requires_scan = config.file_system_requires_scan
|
||||
for nic_config in config.network_interfaces:
|
||||
nic_config.include_nmne = config.include_nmne
|
||||
for service_config in config.services:
|
||||
service_config.services_requires_scan = config.services_requires_scan
|
||||
for application_config in config.applications:
|
||||
application_config.applications_requires_scan = config.applications_requires_scan
|
||||
|
||||
services = [ServiceObservation.from_config(config=c, parent_where=where) for c in config.services]
|
||||
applications = [ApplicationObservation.from_config(config=c, parent_where=where) for c in config.applications]
|
||||
@@ -293,5 +315,7 @@ class HostObservation(AbstractObservation, identifier="HOST"):
|
||||
monitored_traffic=config.monitored_traffic,
|
||||
include_num_access=config.include_num_access,
|
||||
file_system_requires_scan=config.file_system_requires_scan,
|
||||
services_requires_scan=config.services_requires_scan,
|
||||
applications_requires_scan=config.applications_requires_scan,
|
||||
include_users=config.include_users,
|
||||
)
|
||||
|
||||
@@ -45,7 +45,13 @@ class NodesObservation(AbstractObservation, identifier="NODES"):
|
||||
include_num_access: Optional[bool] = None
|
||||
"""Flag to include the number of accesses."""
|
||||
file_system_requires_scan: bool = True
|
||||
"""If True, the folder must be scanned to update the health state. Tf False, the true state is always shown."""
|
||||
"""If True, the folder must be scanned to update the health state. If False, the true state is always shown."""
|
||||
services_requires_scan: bool = True
|
||||
"""If True, the services must be scanned to update the health state.
|
||||
If False, the true state is always shown."""
|
||||
applications_requires_scan: bool = True
|
||||
"""If True, the applications must be scanned to update the health state.
|
||||
If False, the true state is always shown."""
|
||||
include_users: Optional[bool] = True
|
||||
"""If True, report user session information."""
|
||||
num_ports: Optional[int] = None
|
||||
@@ -193,6 +199,10 @@ class NodesObservation(AbstractObservation, identifier="NODES"):
|
||||
host_config.include_num_access = config.include_num_access
|
||||
if host_config.file_system_requires_scan is None:
|
||||
host_config.file_system_requires_scan = config.file_system_requires_scan
|
||||
if host_config.services_requires_scan is None:
|
||||
host_config.services_requires_scan = config.services_requires_scan
|
||||
if host_config.applications_requires_scan is None:
|
||||
host_config.applications_requires_scan = config.applications_requires_scan
|
||||
if host_config.include_users is None:
|
||||
host_config.include_users = config.include_users
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Dict
|
||||
from typing import Dict, Optional
|
||||
|
||||
from gymnasium import spaces
|
||||
from gymnasium.core import ObsType
|
||||
@@ -19,7 +19,10 @@ class ServiceObservation(AbstractObservation, identifier="SERVICE"):
|
||||
service_name: str
|
||||
"""Name of the service, used for querying simulation state dictionary"""
|
||||
|
||||
def __init__(self, where: WhereType) -> None:
|
||||
services_requires_scan: Optional[bool] = None
|
||||
"""If True, services must be scanned to update the health state. If False, true state is always shown."""
|
||||
|
||||
def __init__(self, where: WhereType, services_requires_scan: bool) -> None:
|
||||
"""
|
||||
Initialise a service observation instance.
|
||||
|
||||
@@ -28,6 +31,7 @@ class ServiceObservation(AbstractObservation, identifier="SERVICE"):
|
||||
:type where: WhereType
|
||||
"""
|
||||
self.where = where
|
||||
self.services_requires_scan = services_requires_scan
|
||||
self.default_observation = {"operating_status": 0, "health_status": 0}
|
||||
|
||||
def observe(self, state: Dict) -> ObsType:
|
||||
@@ -44,7 +48,9 @@ class ServiceObservation(AbstractObservation, identifier="SERVICE"):
|
||||
return self.default_observation
|
||||
return {
|
||||
"operating_status": service_state["operating_state"],
|
||||
"health_status": service_state["health_state_visible"],
|
||||
"health_status": service_state["health_state_visible"]
|
||||
if self.services_requires_scan
|
||||
else service_state["health_state_actual"],
|
||||
}
|
||||
|
||||
@property
|
||||
@@ -70,7 +76,9 @@ class ServiceObservation(AbstractObservation, identifier="SERVICE"):
|
||||
:return: Constructed service observation instance.
|
||||
:rtype: ServiceObservation
|
||||
"""
|
||||
return cls(where=parent_where + ["services", config.service_name])
|
||||
return cls(
|
||||
where=parent_where + ["services", config.service_name], services_requires_scan=config.services_requires_scan
|
||||
)
|
||||
|
||||
|
||||
class ApplicationObservation(AbstractObservation, identifier="APPLICATION"):
|
||||
@@ -82,7 +90,12 @@ class ApplicationObservation(AbstractObservation, identifier="APPLICATION"):
|
||||
application_name: str
|
||||
"""Name of the application, used for querying simulation state dictionary"""
|
||||
|
||||
def __init__(self, where: WhereType) -> None:
|
||||
applications_requires_scan: Optional[bool] = None
|
||||
"""
|
||||
If True, applications must be scanned to update the health state. If False, true state is always shown.
|
||||
"""
|
||||
|
||||
def __init__(self, where: WhereType, applications_requires_scan: bool) -> None:
|
||||
"""
|
||||
Initialise an application observation instance.
|
||||
|
||||
@@ -92,6 +105,7 @@ class ApplicationObservation(AbstractObservation, identifier="APPLICATION"):
|
||||
:type where: WhereType
|
||||
"""
|
||||
self.where = where
|
||||
self.applications_requires_scan = applications_requires_scan
|
||||
self.default_observation = {"operating_status": 0, "health_status": 0, "num_executions": 0}
|
||||
|
||||
# TODO: allow these to be configured in yaml
|
||||
@@ -128,7 +142,9 @@ class ApplicationObservation(AbstractObservation, identifier="APPLICATION"):
|
||||
return self.default_observation
|
||||
return {
|
||||
"operating_status": application_state["operating_state"],
|
||||
"health_status": application_state["health_state_visible"],
|
||||
"health_status": application_state["health_state_visible"]
|
||||
if self.applications_requires_scan
|
||||
else application_state["health_state_actual"],
|
||||
"num_executions": self._categorise_num_executions(application_state["num_executions"]),
|
||||
}
|
||||
|
||||
@@ -161,4 +177,7 @@ class ApplicationObservation(AbstractObservation, identifier="APPLICATION"):
|
||||
:return: Constructed application observation instance.
|
||||
:rtype: ApplicationObservation
|
||||
"""
|
||||
return cls(where=parent_where + ["applications", config.application_name])
|
||||
return cls(
|
||||
where=parent_where + ["applications", config.application_name],
|
||||
applications_requires_scan=config.applications_requires_scan,
|
||||
)
|
||||
|
||||
@@ -188,7 +188,7 @@
|
||||
"source": [
|
||||
"## **Notebook Setup** | Network Prerequisites\n",
|
||||
"\n",
|
||||
"Before the Red Agent is able to perform any C2 specific actions, the C2 Server needs to be installed and run before the Red Agent can perform any C2 specific action.\n",
|
||||
"Before the Red Agent is able to perform any C2 specific actions, the C2 Server needs to be installed and run.\n",
|
||||
"This is because in higher fidelity environments (and the real-world) a C2 server would not be accessible by a private network blue agent and the C2 Server would already be in place before the an adversary (Red Agent) starts.\n",
|
||||
"\n",
|
||||
"The cells below install and run the C2 Server on client_1 directly via the simulation API."
|
||||
@@ -1164,7 +1164,7 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now we are unable to do so as the C2 Server is unable has lost it's connection to the C2 Beacon:"
|
||||
"Now we are unable to do so as the C2 Server has lost its connection to the C2 Beacon:"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1276,7 +1276,7 @@
|
||||
"source": [
|
||||
"#### Blocking C2 Traffic via ACL.\n",
|
||||
"\n",
|
||||
"Another potential option a blue agent could take is by placing an ACL rule which blocks traffic between the C2 Server can C2 Beacon.\n",
|
||||
"Another potential option a blue agent could take is by placing an ACL rule which blocks traffic between the C2 Server and C2 Beacon.\n",
|
||||
"\n",
|
||||
"It's worth noting the potential effectiveness of this approach is connected to the current green agent traffic on the network. For example, if there are multiple green agents using the C2 Beacon's host node then blocking all traffic would lead to a negative reward. The same applies for the previous example."
|
||||
]
|
||||
@@ -1450,7 +1450,7 @@
|
||||
"source": [
|
||||
"### **Command and Control** | Configurability | C2 Server IP Address\n",
|
||||
"\n",
|
||||
"As with a majority of client and server based application configuration in primaite, the remote IP of server must be supplied.\n",
|
||||
"As with a majority of client and server based application configurations in primaite, the remote IP of a server must be supplied.\n",
|
||||
"\n",
|
||||
"In the case of the C2 Beacon, the C2 Server's IP address must be supplied before the C2 beacon will be able to perform any other actions (including ``APPLICATION EXECUTE``).\n",
|
||||
"\n",
|
||||
@@ -1727,7 +1727,7 @@
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"The next set of code cells will demonstrate the impact this option from a blue agent perspective."
|
||||
"The next set of code cells will demonstrate the impact of this option from a blue agent perspective."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1818,7 +1818,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.12"
|
||||
"version": "3.10.11"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
" .environment(env=PrimaiteRayMARLEnv, env_config=cfg)\n",
|
||||
" .env_runners(num_env_runners=0)\n",
|
||||
" .training(train_batch_size=128)\n",
|
||||
" .evaluation(evaluation_duration=1)\n",
|
||||
" )\n"
|
||||
]
|
||||
},
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
" .environment(env=PrimaiteRayEnv, env_config=env_config)\n",
|
||||
" .env_runners(num_env_runners=0)\n",
|
||||
" .training(train_batch_size=128)\n",
|
||||
" .evaluation(evaluation_duration=1)\n",
|
||||
")\n"
|
||||
]
|
||||
},
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Episode 0\n",
|
||||
"Let' run the episodes to verify that the agents are changing as expected. In episode 0, there should be no green or red agents, just the defender blue agent."
|
||||
"Let's run the episodes to verify that the agents are changing as expected. In episode 0, there should be no green or red agents, just the defender blue agent."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -47,7 +47,7 @@ class ARP(Service):
|
||||
|
||||
:param markdown: If True, format the output as Markdown. Otherwise, use plain text.
|
||||
"""
|
||||
table = PrettyTable(["IP Address", "MAC Address", "Via"])
|
||||
table = PrettyTable(["IP Address", "MAC Address", "Via", "Port"])
|
||||
if markdown:
|
||||
table.set_style(MARKDOWN)
|
||||
table.align = "l"
|
||||
@@ -58,6 +58,7 @@ class ARP(Service):
|
||||
str(ip),
|
||||
arp.mac_address,
|
||||
self.software_manager.node.network_interfaces[arp.network_interface_uuid].mac_address,
|
||||
self.software_manager.node.network_interfaces[arp.network_interface_uuid].port_num,
|
||||
]
|
||||
)
|
||||
print(table)
|
||||
|
||||
@@ -39,6 +39,8 @@ def test_host_observation(simulation):
|
||||
folders=[],
|
||||
network_interfaces=[],
|
||||
file_system_requires_scan=True,
|
||||
services_requires_scan=True,
|
||||
applications_requires_scan=True,
|
||||
include_users=False,
|
||||
)
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@ def test_service_observation(simulation):
|
||||
ntp_server = pc.software_manager.software.get("NTPServer")
|
||||
assert ntp_server
|
||||
|
||||
service_obs = ServiceObservation(where=["network", "nodes", pc.hostname, "services", "NTPServer"])
|
||||
service_obs = ServiceObservation(
|
||||
where=["network", "nodes", pc.hostname, "services", "NTPServer"], services_requires_scan=True
|
||||
)
|
||||
|
||||
assert service_obs.space["operating_status"] == spaces.Discrete(7)
|
||||
assert service_obs.space["health_status"] == spaces.Discrete(5)
|
||||
@@ -54,7 +56,9 @@ def test_application_observation(simulation):
|
||||
web_browser: WebBrowser = pc.software_manager.software.get("WebBrowser")
|
||||
assert web_browser
|
||||
|
||||
app_obs = ApplicationObservation(where=["network", "nodes", pc.hostname, "applications", "WebBrowser"])
|
||||
app_obs = ApplicationObservation(
|
||||
where=["network", "nodes", pc.hostname, "applications", "WebBrowser"], applications_requires_scan=True
|
||||
)
|
||||
|
||||
web_browser.close()
|
||||
observation_state = app_obs.observe(simulation.describe_state())
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
|
||||
import json
|
||||
from typing import List
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
from primaite.game.agent.observations import ObservationManager
|
||||
from primaite.game.agent.observations import ApplicationObservation, ObservationManager, ServiceObservation
|
||||
from primaite.game.agent.observations.file_system_observations import FileObservation, FolderObservation
|
||||
from primaite.game.agent.observations.host_observations import HostObservation
|
||||
|
||||
@@ -130,3 +131,227 @@ class TestFileSystemRequiresScan:
|
||||
[], files=[], num_files=0, include_num_access=False, file_system_requires_scan=False
|
||||
)
|
||||
assert obs_not_requiring_scan.observe(folder_state)["health_status"] == 3
|
||||
|
||||
|
||||
class TestServicesRequiresScan:
|
||||
@pytest.mark.parametrize(
|
||||
("yaml_option_string", "expected_val"),
|
||||
(
|
||||
("services_requires_scan: true", True),
|
||||
("services_requires_scan: false", False),
|
||||
(" ", True),
|
||||
),
|
||||
)
|
||||
def test_obs_config(self, yaml_option_string, expected_val):
|
||||
"""Check that the default behaviour is to set service_requires_scan to True."""
|
||||
obs_cfg_yaml = f"""
|
||||
type: CUSTOM
|
||||
options:
|
||||
components:
|
||||
- type: NODES
|
||||
label: NODES
|
||||
options:
|
||||
hosts:
|
||||
- hostname: domain_controller
|
||||
- hostname: web_server
|
||||
services:
|
||||
- service_name: WebServer
|
||||
- service_name: DNSClient
|
||||
- hostname: database_server
|
||||
folders:
|
||||
- folder_name: database
|
||||
files:
|
||||
- file_name: database.db
|
||||
- hostname: backup_server
|
||||
services:
|
||||
- service_name: FTPServer
|
||||
- hostname: security_suite
|
||||
- hostname: client_1
|
||||
- hostname: client_2
|
||||
num_services: 3
|
||||
num_applications: 0
|
||||
num_folders: 1
|
||||
num_files: 1
|
||||
num_nics: 2
|
||||
include_num_access: false
|
||||
{yaml_option_string}
|
||||
include_nmne: true
|
||||
monitored_traffic:
|
||||
icmp:
|
||||
- NONE
|
||||
tcp:
|
||||
- DNS
|
||||
routers:
|
||||
- hostname: router_1
|
||||
num_ports: 0
|
||||
ip_list:
|
||||
- 192.168.1.10
|
||||
- 192.168.1.12
|
||||
- 192.168.1.14
|
||||
- 192.168.1.16
|
||||
- 192.168.1.110
|
||||
- 192.168.10.21
|
||||
- 192.168.10.22
|
||||
- 192.168.10.110
|
||||
wildcard_list:
|
||||
- 0.0.0.1
|
||||
port_list:
|
||||
- 80
|
||||
- 5432
|
||||
protocol_list:
|
||||
- ICMP
|
||||
- TCP
|
||||
- UDP
|
||||
num_rules: 10
|
||||
|
||||
- type: LINKS
|
||||
label: LINKS
|
||||
options:
|
||||
link_references:
|
||||
- router_1:eth-1<->switch_1:eth-8
|
||||
- router_1:eth-2<->switch_2:eth-8
|
||||
- switch_1:eth-1<->domain_controller:eth-1
|
||||
- switch_1:eth-2<->web_server:eth-1
|
||||
- switch_1:eth-3<->database_server:eth-1
|
||||
- switch_1:eth-4<->backup_server:eth-1
|
||||
- switch_1:eth-7<->security_suite:eth-1
|
||||
- switch_2:eth-1<->client_1:eth-1
|
||||
- switch_2:eth-2<->client_2:eth-1
|
||||
- switch_2:eth-7<->security_suite:eth-2
|
||||
- type: "NONE"
|
||||
label: ICS
|
||||
options: {{}}
|
||||
|
||||
"""
|
||||
|
||||
cfg = yaml.safe_load(obs_cfg_yaml)
|
||||
manager = ObservationManager.from_config(cfg)
|
||||
|
||||
hosts: List[HostObservation] = manager.obs.components["NODES"].hosts
|
||||
for i, host in enumerate(hosts):
|
||||
services: List[ServiceObservation] = host.services
|
||||
for j, service in enumerate(services):
|
||||
val = service.services_requires_scan
|
||||
print(f"host {i} service {j} {val}")
|
||||
assert val == expected_val # Make sure services require scan by default
|
||||
|
||||
def test_services_requires_scan(self):
|
||||
state = {"health_state_actual": 3, "health_state_visible": 1, "operating_state": 1}
|
||||
|
||||
obs_requiring_scan = ServiceObservation([], services_requires_scan=True)
|
||||
assert obs_requiring_scan.observe(state)["health_status"] == 1 # should be visible value
|
||||
|
||||
obs_not_requiring_scan = ServiceObservation([], services_requires_scan=False)
|
||||
assert obs_not_requiring_scan.observe(state)["health_status"] == 3 # should be actual value
|
||||
|
||||
|
||||
class TestApplicationsRequiresScan:
|
||||
@pytest.mark.parametrize(
|
||||
("yaml_option_string", "expected_val"),
|
||||
(
|
||||
("applications_requires_scan: true", True),
|
||||
("applications_requires_scan: false", False),
|
||||
(" ", True),
|
||||
),
|
||||
)
|
||||
def test_obs_config(self, yaml_option_string, expected_val):
|
||||
"""Check that the default behaviour is to set applications_requires_scan to True."""
|
||||
obs_cfg_yaml = f"""
|
||||
type: CUSTOM
|
||||
options:
|
||||
components:
|
||||
- type: NODES
|
||||
label: NODES
|
||||
options:
|
||||
hosts:
|
||||
- hostname: domain_controller
|
||||
- hostname: web_server
|
||||
- hostname: database_server
|
||||
folders:
|
||||
- folder_name: database
|
||||
files:
|
||||
- file_name: database.db
|
||||
- hostname: backup_server
|
||||
- hostname: security_suite
|
||||
- hostname: client_1
|
||||
applications:
|
||||
- application_name: WebBrowser
|
||||
- hostname: client_2
|
||||
applications:
|
||||
- application_name: WebBrowser
|
||||
- application_name: DatabaseClient
|
||||
num_services: 0
|
||||
num_applications: 3
|
||||
num_folders: 1
|
||||
num_files: 1
|
||||
num_nics: 2
|
||||
include_num_access: false
|
||||
{yaml_option_string}
|
||||
include_nmne: true
|
||||
monitored_traffic:
|
||||
icmp:
|
||||
- NONE
|
||||
tcp:
|
||||
- DNS
|
||||
routers:
|
||||
- hostname: router_1
|
||||
num_ports: 0
|
||||
ip_list:
|
||||
- 192.168.1.10
|
||||
- 192.168.1.12
|
||||
- 192.168.1.14
|
||||
- 192.168.1.16
|
||||
- 192.168.1.110
|
||||
- 192.168.10.21
|
||||
- 192.168.10.22
|
||||
- 192.168.10.110
|
||||
wildcard_list:
|
||||
- 0.0.0.1
|
||||
port_list:
|
||||
- 80
|
||||
- 5432
|
||||
protocol_list:
|
||||
- ICMP
|
||||
- TCP
|
||||
- UDP
|
||||
num_rules: 10
|
||||
|
||||
- type: LINKS
|
||||
label: LINKS
|
||||
options:
|
||||
link_references:
|
||||
- router_1:eth-1<->switch_1:eth-8
|
||||
- router_1:eth-2<->switch_2:eth-8
|
||||
- switch_1:eth-1<->domain_controller:eth-1
|
||||
- switch_1:eth-2<->web_server:eth-1
|
||||
- switch_1:eth-3<->database_server:eth-1
|
||||
- switch_1:eth-4<->backup_server:eth-1
|
||||
- switch_1:eth-7<->security_suite:eth-1
|
||||
- switch_2:eth-1<->client_1:eth-1
|
||||
- switch_2:eth-2<->client_2:eth-1
|
||||
- switch_2:eth-7<->security_suite:eth-2
|
||||
- type: "NONE"
|
||||
label: ICS
|
||||
options: {{}}
|
||||
|
||||
"""
|
||||
|
||||
cfg = yaml.safe_load(obs_cfg_yaml)
|
||||
manager = ObservationManager.from_config(cfg)
|
||||
|
||||
hosts: List[HostObservation] = manager.obs.components["NODES"].hosts
|
||||
for i, host in enumerate(hosts):
|
||||
services: List[ServiceObservation] = host.services
|
||||
for j, service in enumerate(services):
|
||||
val = service.services_requires_scan
|
||||
print(f"host {i} service {j} {val}")
|
||||
assert val == expected_val # Make sure applications require scan by default
|
||||
|
||||
def test_applications_requires_scan(self):
|
||||
state = {"health_state_actual": 3, "health_state_visible": 1, "operating_state": 1, "num_executions": 1}
|
||||
|
||||
obs_requiring_scan = ApplicationObservation([], applications_requires_scan=True)
|
||||
assert obs_requiring_scan.observe(state)["health_status"] == 1 # should be visible value
|
||||
|
||||
obs_not_requiring_scan = ApplicationObservation([], applications_requires_scan=False)
|
||||
assert obs_not_requiring_scan.observe(state)["health_status"] == 3 # should be actual value
|
||||
|
||||
Reference in New Issue
Block a user