diff --git a/docs/Makefile b/docs/Makefile
index 99e19d16..d0f9af01 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -1,4 +1,4 @@
-# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
# Minimal makefile for Sphinx documentation
# You can set these variables from the command line, and also
# from the environment for the first two.
diff --git a/docs/build-sphinx-docs-to-github-pages.sh b/docs/build-sphinx-docs-to-github-pages.sh
index 9e43a2b4..a180f168 100644
--- a/docs/build-sphinx-docs-to-github-pages.sh
+++ b/docs/build-sphinx-docs-to-github-pages.sh
@@ -1,4 +1,4 @@
-# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
#!/bin/bash
set -x
diff --git a/src/primaite/config/_package_data/uc7_config.yaml b/src/primaite/config/_package_data/uc7_config.yaml
new file mode 100644
index 00000000..f5d4ac54
--- /dev/null
+++ b/src/primaite/config/_package_data/uc7_config.yaml
@@ -0,0 +1,2677 @@
+##########################################################
+# USE CASE 7 CONFIGURATION YAML FILE #
+##########################################################
+
+
+##########################################
+# PrimAITE Game and Logging Settings #
+##########################################
+
+
+# PrimAITE I/O Settings #
+
+io_settings:
+ save_agent_actions: false
+ save_step_metadata: false
+ save_pcap_logs: false
+ save_sys_logs: false
+ save_agent_logs: false
+ write_sys_log_to_terminal: false
+
+
+# PrimAITE Game Settings #
+
+game:
+ max_episode_length: 128
+ ports:
+ - FTP
+ - DNS
+ - HTTP
+ - NTP
+ - POSTGRES_SERVER
+ - SSH
+ protocols:
+ - ICMP
+ - TCP
+ - UDP
+ thresholds:
+ nmne:
+ high: 10
+ medium: 5
+ low: 0
+
+############################################
+# PrimAITE Use Case 7 Simulation #
+############################################
+
+##########################################
+# Configuration Variables (Yaml Anchors) #
+##########################################
+
+# External Network Address List #
+
+DNS_SUBNET: &DNS_SUBNET 255.255.255.240 # | 8.8.8.0 / 28
+HOME_INTERNET_SUBNET: &HOME_INTERNET_SUBNET 255.255.255.252 # | 10.1.0.0 / 30
+REMOTE_INTERNET_SUBNET: &REMOTE_INTERNET_SUBNET 255.255.255.252 # | 10.1.10.0 / 30
+SOME_TECH_INTERNET_SUBNET: &ST_INTERNET_SUBNET 255.255.255.252 # | 10.1.100.0 / 30
+HOME_OFFICE_SUBNET: &HOME_SUBNET 255.255.255.0 # | 192.168.1.0 / 26
+REMOTE_SUBNET_DMZ: &REMOTE_SUBNET_DMZ 255.255.255.252 # | 192.168.10.0 / 30
+REMOTE_SUBNET: &REMOTE_SUBNET 255.255.255.240 # | 192.168.20.0 / 28
+
+# SOME_TECH (ST) Network Address List #
+
+SOME_TECH_DMZ_SUBNET: &ST_DMZ_SUBNET 255.255.255.252 # | 192.168.100.0 / 30
+SOME_TECH_INTRANET_RT_CR_SUBNET: &ST_INTRA_CR_SUBNET 255.255.255.240 # | 192.168.150.0 / 28
+SOME_TECH_INTRANET_RT_DR_ONE_SUBNET: &ST_INTRA_DR_ONE_SUBNET 255.255.255.252 # | 192.168.160.0 / 30
+SOME_TECH_INTRANET_RT_DR_TWO_SUBNET: &ST_INTRA_DR_TWO_SUBNET 255.255.255.252 # | 192.168.170.0 / 30
+SOME_TECH_HEAD_OFFICE_SUBNET: &ST_HO_SUBNET 255.255.255.248 # | 192.168.200.0 / 29
+SOME_TECH_HUMAN_RESOURCES_SUBNET: &ST_HR_SUBNET 255.255.255.248 # | 192.168.210.0 / 29
+SOME_TECH_DATA_SUBNET: &ST_DATA_SUBNET 255.255.255.248 # | 192.168.220.0 / 29
+SOME_TECH_PROJECT_A_SUBNET: &ST_PROJ_A_SUBNET 255.255.255.248 # | 192.168.230.0 / 29
+SOME_TECH_PROJECT_B_SUBNET: &ST_PROJ_B_SUBNET 255.255.255.248 # | 192.168.240.0 / 29
+SOME_TECH_PROJECT_C_SUBNET: &ST_PROJ_C_SUBNET 255.255.255.248 # | 192.168.250.0 / 29
+
+# Host & Server Configurations #
+
+# ST Public Web Server | web-server | ST_DMZ-PUB-SRV-WEB
+SOME_TECH_PUBLIC_SERVER_WEB_IP_ADDRESS: &ST_PUB_SRV_WEB_IP 192.168.100.2
+SOME_TECH_PUBLIC_SERVER_WEB_CONFIG: &ST_SRV_WEB_CONFIG #
+ - type: web-server
+
+# ISP Public DNS | dns-server | ISP-PUB-SRV-DNS
+PUBLIC_DNS_IP_ADDRESS: &PUBLIC_DNS_IP 8.8.8.8
+PUBLIC_DNS_CONFIG: &PUBLIC_DNS_CONFIG #
+ - type: dns-server
+ options:
+ domain_mapping:
+ some_tech.com: *ST_PUB_SRV_WEB_IP
+
+# ST Private Storage Server | ftp-server | ST_DATA-PRV-SRV-STORAGE
+SOME_TECH_PRIVATE_SERVER_STORAGE_IP: &ST_SRV_STORAGE_IP 192.168.220.2
+SOME_TECH_PRIVATE_SERVER_STORAGE_CONFIG: &ST_SRV_STORAGE_CONFIG
+ - type: ftp-server
+
+# ST Private Database Server | database-client & ftp-client | ST_DATA-PRV-SRV-DB
+SOME_TECH_PRIVATE_SERVER_DATABASE_IP: &ST_SRV_DB_IP 192.168.220.3
+SOME_TECH_PRIVATE_SERVER_DATABASE_CONFIG: &ST_SRV_DB_CONFIG
+ - type: database-service
+ options:
+ backup_server_ip: *ST_SRV_STORAGE_IP
+ - type: ftp-client
+
+# Default PC Configuration | Database Client & Web Server
+PERSONAL_COMPUTER_DEFAULT_CONFIG: &PC_DEFAULT_CONFIG
+ - type: database-client
+ options:
+ db_server_ip: *ST_SRV_DB_IP
+ - type: web-browser
+ options:
+ target_url: http://some_tech.com
+
+
+##############################
+# Simulation Configuration #
+##############################
+
+simulation:
+ defaults:
+ folder_scan_duration: 0
+ folder_restore_duration: 3
+ service_fix_duration: 2
+ service_restart_duration: 2
+ software_install_duration: 0
+ node_start_up_duration: 3
+ node_shut_down_duration: 3
+ node_scan_duration: 8
+ network:
+ nmne_config:
+ capture_nmne: true
+ nmne_capture_keywords:
+ - DELETE
+ - ENCRYPT
+ nodes:
+ ######################
+ # HOME OFFICE SUBNET #
+ ######################
+ - hostname: HOME-PUB-RT-DR
+ type: router
+ default_gateway: 10.1.0.1
+ ports:
+ 1:
+ ip_address: 192.168.1.1
+ subnet_mask: *HOME_SUBNET
+ 2:
+ ip_address: 10.1.0.2
+ subnet_mask: *HOME_INTERNET_SUBNET
+ default_route:
+ next_hop_ip_address: 10.1.0.1
+ acl:
+ 5:
+ action: PERMIT
+
+ - hostname: HOME-PUB-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: HOME-PUB-PC-1
+ type: computer
+ ip_address: 192.168.1.2
+ default_gateway: 192.168.1.1
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: HOME-PUB-PC-2
+ type: computer
+ ip_address: 192.168.1.3
+ default_gateway: 192.168.1.1
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: HOME-PUB-SRV
+ type: server
+ ip_address: 192.168.1.4
+ default_gateway: 192.168.1.1
+ dns_server: *PUBLIC_DNS_IP
+
+ ######################
+ # INTERNET SUBNET #
+ ######################
+ - hostname: ISP-PUB-RT-BR
+ type: router
+ ports:
+ 1:
+ ip_address: 10.1.0.1
+ subnet_mask: *HOME_INTERNET_SUBNET
+ 2:
+ ip_address: 8.8.8.1
+ subnet_mask: *DNS_SUBNET
+ 3:
+ ip_address: 10.1.10.1
+ subnet_mask: *REMOTE_INTERNET_SUBNET
+ 4:
+ ip_address: 10.1.100.1
+ subnet_mask: *ST_INTERNET_SUBNET
+ routes:
+ - address: 192.168.1.0
+ subnet_mask: *HOME_SUBNET
+ next_hop_ip_address: 10.1.0.2
+
+ - address: 8.8.8.0
+ subnet_mask: *DNS_SUBNET
+ next_hop_ip_address: 8.8.8.8
+
+ - address: 192.168.10.0
+ subnet_mask: *REMOTE_SUBNET_DMZ
+ next_hop_ip_address: 10.1.10.2
+
+ - address: 192.168.20.0
+ subnet_mask: *REMOTE_SUBNET
+ next_hop_ip_address: 10.1.10.2
+
+ default_route:
+ next_hop_ip_address: 10.1.100.2 # SOME_TECH Firewall
+
+ acl:
+ 5:
+ action: PERMIT
+
+ ################
+ # DNS SUBNET #
+ ################
+ - hostname: ISP-PUB-SRV-DNS
+ type: server
+ ip_address: 8.8.8.8
+ subnet_mask: *DNS_SUBNET
+ default_gateway: 8.8.8.1
+ services:
+ *PUBLIC_DNS_CONFIG
+ applications:
+ - type: c2-server # Represents the external internet.
+ options:
+ listen_on_ports:
+ - 80
+ - 53
+ - 21
+ ########################
+ # REMOTE SITE SUBNET #
+ ########################
+ - hostname: REM-PUB-FW
+ type: firewall
+ ports:
+ external_port: # Public Internet facing
+ ip_address: 10.1.10.2
+ subnet_mask: *REMOTE_INTERNET_SUBNET
+ internal_port: # Remote Site (DMZ Subnet) facing
+ ip_address: 192.168.10.1
+ subnet_mask: *REMOTE_SUBNET_DMZ
+ routes:
+ - address: 192.168.20.0 # Remote Site Network
+ subnet_mask: *REMOTE_SUBNET
+ next_hop_ip_address: 192.168.10.2
+ default_route:
+ next_hop_ip_address: 10.1.10.1 # Forward to internet router port 3
+ acl:
+ internal_inbound_acl:
+ 1:
+ action: PERMIT
+ internal_outbound_acl:
+ 1:
+ action: PERMIT
+ dmz_inbound_acl:
+ 1:
+ action: PERMIT
+ dmz_outbound_acl:
+ 1:
+ action: PERMIT
+ external_inbound_acl:
+ 1:
+ action: PERMIT
+ external_outbound_acl:
+ 1:
+ action: PERMIT
+
+ - hostname: REM-PUB-RT-DR
+ type: router
+ default_gateway: 192.168.10.1
+ ports:
+ 1:
+ ip_address: 192.168.10.2
+ subnet_mask: *REMOTE_SUBNET_DMZ
+ 2:
+ ip_address: 192.168.20.1
+ subnet_mask: *REMOTE_SUBNET
+ default_route:
+ next_hop_ip_address: 192.168.10.1
+ acl:
+ 5:
+ action: PERMIT
+
+ - hostname: REM-PUB-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: REM-PUB-PC-1
+ type: computer
+ ip_address: 192.168.20.2
+ default_gateway: 192.168.20.1
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: REM-PUB-PC-2
+ type: computer
+ ip_address: 192.168.20.3
+ default_gateway: 192.168.20.1
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: REM-PUB-SRV
+ type: server
+ ip_address: 192.168.20.4
+ default_gateway: 192.168.20.1
+ dns_server: *PUBLIC_DNS_IP
+
+
+ ########################
+ # SOME_TECH DMZ SUBNET #
+ ########################
+
+ - hostname: ST_PUB-FW
+ type: firewall
+ ports:
+ external_port: # Public Internet Facing Port
+ ip_address: 10.1.100.2
+ subnet_mask: *ST_INTERNET_SUBNET
+ internal_port: # SOME_TECH Intranet Port
+ ip_address: 192.168.150.1
+ subnet_mask: *ST_INTRA_CR_SUBNET
+ dmz_port: # SOME_TECH Port Facing Port
+ ip_address: 192.168.100.1
+ subnet_mask: *ST_DMZ_SUBNET
+ acl:
+ internal_inbound_acl:
+ 5:
+ action: PERMIT
+ internal_outbound_acl:
+ 5:
+ action: PERMIT
+ dmz_inbound_acl:
+ 5:
+ action: PERMIT
+ dmz_outbound_acl:
+ 5:
+ action: PERMIT
+ external_inbound_acl:
+ 5:
+ action: PERMIT
+ external_outbound_acl:
+ 5:
+ action: PERMIT
+ routes:
+ - address: 10.1.100.0
+ subnet_mask: *ST_INTERNET_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 10.1.10.0
+ subnet_mask: *REMOTE_INTERNET_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 10.1.0.0
+ subnet_mask: *HOME_INTERNET_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 192.168.1.0
+ subnet_mask: *HOME_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 192.168.10.0
+ subnet_mask: *REMOTE_SUBNET_DMZ
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 192.168.20.0
+ subnet_mask: *REMOTE_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 8.8.8.0
+ subnet_mask: *DNS_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ default_route:
+ next_hop_ip_address: 192.168.150.2
+
+ - hostname: ST_DMZ-PUB-SRV-WEB
+ type: server
+ ip_address: *ST_PUB_SRV_WEB_IP
+ subnet_mask: *ST_DMZ_SUBNET
+ default_gateway: 192.168.100.1
+ services:
+ *ST_SRV_WEB_CONFIG
+
+ #############################
+ # SOME_TECH INTRANET SUBNET #
+ #############################
+
+ - hostname: ST_INTRA-PRV-RT-CR
+ type: router
+ ports:
+ 1:
+ ip_address: 192.168.150.2
+ subnet_mask: *ST_INTRA_CR_SUBNET
+ 2:
+ ip_address: 192.168.160.1
+ subnet_mask: *ST_INTRA_DR_ONE_SUBNET
+ 3:
+ ip_address: 192.168.170.1
+ subnet_mask: *ST_INTRA_DR_TWO_SUBNET
+ 4:
+ ip_address: 192.168.220.1
+ subnet_mask: *ST_DATA_SUBNET
+
+ routes:
+ - address: 192.168.200.0
+ subnet_mask: *ST_HO_SUBNET
+ next_hop_ip_address: 192.168.170.2 # ST Intra Router Two
+ - address: 192.168.210.0
+ subnet_mask: *ST_HR_SUBNET
+ next_hop_ip_address: 192.168.170.2 # ST Intra Router Two
+ - address: 192.168.230.0
+ subnet_mask: *ST_PROJ_A_SUBNET
+ next_hop_ip_address: 192.168.160.2 # ST Intra Router One
+ - address: 192.168.240.0
+ subnet_mask: *ST_PROJ_B_SUBNET
+ next_hop_ip_address: 192.168.160.2 # ST Intra Router One
+ - address: 192.168.250.0
+ subnet_mask: *ST_PROJ_C_SUBNET
+ next_hop_ip_address: 192.168.160.2 # ST Intra Router One
+
+ default_route:
+ next_hop_ip_address: 192.168.150.1 # ST Public Firewall Internal Port
+ acl:
+ 5:
+ action: PERMIT
+
+ - hostname: ST_INTRA-PRV-RT-DR-1
+ type: router
+ ports:
+ 1:
+ ip_address: 192.168.160.2
+ subnet_mask: *ST_INTRA_DR_ONE_SUBNET
+ 2:
+ ip_address: 192.168.230.1
+ subnet_mask: *ST_PROJ_A_SUBNET
+ 3:
+ ip_address: 192.168.240.1
+ subnet_mask: *ST_PROJ_B_SUBNET
+ 4:
+ ip_address: 192.168.250.1
+ subnet_mask: *ST_PROJ_C_SUBNET
+ default_route:
+ next_hop_ip_address: 192.168.160.1 # ST Intranet CR Router Port 2
+ acl:
+ 5:
+ action: PERMIT
+
+ - hostname: ST_INTRA-PRV-RT-DR-2
+ type: router
+ default_gateway: 192.168.170.1
+ ports:
+ 1:
+ ip_address: 192.168.170.2
+ subnet_mask: *ST_INTRA_DR_TWO_SUBNET
+ 2:
+ ip_address: 192.168.200.1
+ subnet_mask: *ST_HO_SUBNET
+ 3:
+ ip_address: 192.168.210.1
+ subnet_mask: *ST_HR_SUBNET
+ default_route:
+ next_hop_ip_address: 192.168.170.1 # ST Intranet CR Router Port 3
+ acl:
+ 5:
+ action: PERMIT
+
+ ################################
+ # SOME_TECH HEAD OFFICE SUBNET #
+ ################################
+
+ - hostname: ST_HO-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_HO-PRV-PC-1
+ type: computer
+ ip_address: 192.168.200.2
+ default_gateway: 192.168.200.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_HO-PRV-PC-2
+ type: computer
+ ip_address: 192.168.200.3
+ default_gateway: 192.168.200.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_HO-PRV-PC-3
+ type: computer
+ ip_address: 192.168.200.4
+ default_gateway: 192.168.200.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ ####################################
+ # SOME_TECH HUMAN RESOURCES SUBNET #
+ ####################################
+
+ - hostname: ST_HR-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_HR-PRV-PC-1
+ type: computer
+ ip_address: 192.168.210.2
+ default_gateway: 192.168.210.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_HR-PRV-PC-2
+ type: computer
+ ip_address: 192.168.210.3
+ default_gateway: 192.168.210.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_HR-PRV-PC-3
+ type: computer
+ ip_address: 192.168.210.4
+ default_gateway: 192.168.210.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ #########################
+ # SOME_TECH DATA SUBNET #
+ #########################
+
+ - hostname: ST_DATA-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_DATA-PRV-SRV-STORAGE
+ type: server
+ ip_address: *ST_SRV_STORAGE_IP
+ subnet_mask: *ST_DATA_SUBNET
+ default_gateway: 192.168.220.1
+ dns_server: *PUBLIC_DNS_IP
+ services:
+ *ST_SRV_STORAGE_CONFIG
+
+ - hostname: ST_DATA-PRV-SRV-DB
+ type: server
+ ip_address: *ST_SRV_DB_IP
+ subnet_mask: *ST_DATA_SUBNET
+ default_gateway: 192.168.220.1
+ dns_server: *PUBLIC_DNS_IP
+ services:
+ *ST_SRV_DB_CONFIG
+
+ #######################
+ # SOME_TECH PROJECT A #
+ #######################
+
+ - hostname: ST_PROJ-A-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_PROJ-A-PRV-PC-1
+ type: computer
+ ip_address: 192.168.230.2
+ default_gateway: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-A-PRV-PC-2
+ type: computer
+ ip_address: 192.168.230.3
+ default_gateway: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-A-PRV-PC-3
+ type: computer
+ ip_address: 192.168.230.4
+ default_gateway: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ #######################
+ # SOME_TECH PROJECT B #
+ #######################
+
+ - hostname: ST_PROJ-B-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_PROJ-B-PRV-PC-1
+ type: computer
+ ip_address: 192.168.240.2
+ default_gateway: 192.168.240.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-B-PRV-PC-2
+ type: computer
+ ip_address: 192.168.240.3
+ default_gateway: 192.168.240.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-B-PRV-PC-3
+ type: computer
+ ip_address: 192.168.240.4
+ default_gateway: 192.168.240.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ #######################
+ # SOME_TECH PROJECT C #
+ #######################
+
+ - hostname: ST_PROJ-C-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_PROJ-C-PRV-PC-1
+ type: computer
+ ip_address: 192.168.250.2
+ default_gateway: 192.168.250.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-C-PRV-PC-2
+ type: computer
+ ip_address: 192.168.250.3
+ default_gateway: 192.168.250.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-C-PRV-PC-3
+ type: computer
+ ip_address: 192.168.250.4
+ default_gateway: 192.168.250.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+
+ ##############################
+ # Simulation Network Links #
+ ##############################
+ links:
+
+ ############################
+ # HOME OFFICE SUBNET LINKS #
+ ############################
+
+ # Home Switch (Port 1) --> Home Router (Port 1)
+ - endpoint_a_hostname: HOME-PUB-SW-AS
+ endpoint_a_port: 1
+ endpoint_b_hostname: HOME-PUB-RT-DR
+ endpoint_b_port: 1
+
+ # Home Switch (Port 2) --> PC 1 (Port 1)
+ - endpoint_a_hostname: HOME-PUB-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: HOME-PUB-PC-1
+ endpoint_b_port: 1
+
+ # Home Switch (Port 3) --> PC 2 (Port 1)
+ - endpoint_a_hostname: HOME-PUB-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: HOME-PUB-PC-2
+ endpoint_b_port: 1
+
+ # Home Switch (Port 4) --> PC SRV (Port 1)
+ - endpoint_a_hostname: HOME-PUB-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: HOME-PUB-SRV
+ endpoint_b_port: 1
+
+ ##################
+ # Internet Links #
+ ##################
+
+ # Internet Router (Port 1) --> Home Router (Port 2)
+ - endpoint_a_hostname: ISP-PUB-RT-BR
+ endpoint_a_port: 1
+ endpoint_b_hostname: HOME-PUB-RT-DR
+ endpoint_b_port: 2
+
+ # Internet Router (Port 2) --> DNS Server (Port 1)
+ - endpoint_a_hostname: ISP-PUB-RT-BR
+ endpoint_a_port: 2
+ endpoint_b_hostname: ISP-PUB-SRV-DNS
+ endpoint_b_port: 1
+
+ # Internet Router (Port 3) --> Remote Firewall (External Port)
+ - endpoint_a_hostname: ISP-PUB-RT-BR
+ endpoint_a_port: 3
+ endpoint_b_hostname: REM-PUB-FW
+ endpoint_b_port: 1
+
+ ####################
+ # Remote DMZ Links #
+ ####################
+
+ # Remote Firewall (Internal Port) --> Remote Site Router (Port 1)
+ - endpoint_a_hostname: REM-PUB-FW
+ endpoint_a_port: 2
+ endpoint_b_hostname: REM-PUB-RT-DR
+ endpoint_b_port: 1
+
+ ####################
+ # Remote Site Link #
+ ####################
+
+ # Remote Site Router (Port 2) --> Remote Site Switch (Port 1)
+ - endpoint_a_hostname: REM-PUB-RT-DR
+ endpoint_a_port: 2
+ endpoint_b_hostname: REM-PUB-SW-AS
+ endpoint_b_port: 1
+
+ # Remote Site Switch (Port 2) --> Remote Site PC 1 (Port 1)
+ - endpoint_a_hostname: REM-PUB-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: REM-PUB-PC-1
+ endpoint_b_port: 1
+
+ # Remote Site Switch (Port 3) --> Remote Site PC 2 (Port 1)
+ - endpoint_a_hostname: REM-PUB-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: REM-PUB-PC-2
+ endpoint_b_port: 1
+
+ # Remote Site Switch (Port 4) --> Remote Site Server (Port 1)
+ - endpoint_a_hostname: REM-PUB-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: REM-PUB-SRV
+ endpoint_b_port: 1
+
+ #######################
+ # SOME_TECH DMZ Links #
+ #######################
+
+ # Internet Router (Port 4) --> Some Tech DMZ Firewall (External Port)
+ - endpoint_a_hostname: ISP-PUB-RT-BR
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PUB-FW
+ endpoint_b_port: 1
+
+ # Some Tech DMZ Firewall (DMZ Port) --> Some Tech Web Server (Port 1)
+ - endpoint_a_hostname: ST_PUB-FW
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_DMZ-PUB-SRV-WEB
+ endpoint_b_port: 1
+
+ ############################
+ # SOME_TECH INTRANET Links #
+ ############################
+
+ # Some Tech Intranet CR Router (Port 1) --> Some Tech DMZ Firewall (Internal Port)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-CR
+ endpoint_a_port: 1
+ endpoint_b_hostname: ST_PUB-FW
+ endpoint_b_port: 2
+
+ # Some Tech Intranet CR Router (Port 2) --> Some Tech Intranet DR Router 1 (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-CR
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_INTRA-PRV-RT-DR-1
+ endpoint_b_port: 1
+
+ # Some Tech Intranet CR Router (Port 3) --> Some Tech Intranet DR Router 2 (Port 2)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-CR
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_INTRA-PRV-RT-DR-2
+ endpoint_b_port: 1
+
+ # Some Tech Intranet Private Router CR (Port 4) --> Some Tech Data Private Switch (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-CR
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_DATA-PRV-SW-AS
+ endpoint_b_port: 1
+
+
+ ###############################
+ # SOME_TECH HEAD OFFICE Links #
+ ###############################
+
+ # Some Tech Head Office Switch (Port 1) --> Some Tech Intranet Private Router DR 2 (Port 2)
+ - endpoint_a_hostname: ST_HO-PRV-SW-AS
+ endpoint_a_port: 1
+ endpoint_b_hostname: ST_INTRA-PRV-RT-DR-2
+ endpoint_b_port: 2
+
+ # Some Tech Head Office Switch (Port 2) --> Some Tech Head Office PC 1 (Port 1)
+ - endpoint_a_hostname: ST_HO-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_HO-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Head Office Switch (Port 3) --> Some Tech Head Office PC 2 (Port 1)
+ - endpoint_a_hostname: ST_HO-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_HO-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Head Office Switch (Port 4) --> Some Tech Head Office PC 3 (Port 1)
+ - endpoint_a_hostname: ST_HO-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_HO-PRV-PC-3
+ endpoint_b_port: 1
+
+
+ ###################################
+ # SOME_TECH HUMAN RESOURCES Links #
+ ###################################
+
+ # Some Tech Human Resources Switch (Port 1) --> Some Tech Intranet Private Router DR 2 (Port 3)
+ - endpoint_a_hostname: ST_HR-PRV-SW-AS
+ endpoint_a_port: 1
+ endpoint_b_hostname: ST_INTRA-PRV-RT-DR-2
+ endpoint_b_port: 3
+
+ # Some Tech Human Resources Switch (Port 2) --> Some Tech Human Resources PC 1 (Port 1)
+ - endpoint_a_hostname: ST_HR-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_HR-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Human Resources Switch (Port 3) --> Some Tech Human Resources PC 2 (Port 1)
+ - endpoint_a_hostname: ST_HR-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_HR-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Human Resources Switch (Port 4) --> Some Tech Human Resources PC 3 (Port 1)
+ - endpoint_a_hostname: ST_HR-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_HR-PRV-PC-3
+ endpoint_b_port: 1
+
+ ########################
+ # SOME_TECH DATA Links #
+ ########################
+
+ # Some Tech Data Switch (Port 2) --> Some Tech Data Private Storage Server (Port 1)
+ - endpoint_a_hostname: ST_DATA-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_DATA-PRV-SRV-STORAGE
+ endpoint_b_port: 1
+
+ # Some Tech Data Switch (Port 3) --> Some Tech Data Private Database Server (Port 1)
+
+ - endpoint_a_hostname: ST_DATA-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_DATA-PRV-SRV-DB
+ endpoint_b_port: 1
+
+ #############################
+ # SOME_TECH PROJECT A Links #
+ #############################
+
+ # Some Tech Intranet Private Router DR 1 (Port 2) --> Some Tech Private Project A Switch (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-DR-1
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_PROJ-A-PRV-SW-AS
+ endpoint_b_port: 1
+
+ # Some Tech Private Project A Switch (Port 2) --> Some Tech Project A PC 1
+ - endpoint_a_hostname: ST_PROJ-A-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_PROJ-A-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Private Project A Switch (Port 3) --> Some Tech Project A PC 2
+ - endpoint_a_hostname: ST_PROJ-A-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_PROJ-A-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Private Project A Switch (Port 4) --> Some Tech Project A PC 3
+ - endpoint_a_hostname: ST_PROJ-A-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PROJ-A-PRV-PC-3
+ endpoint_b_port: 1
+
+ #############################
+ # SOME_TECH PROJECT B Links #
+ #############################
+
+ # Some Tech Intranet Private Router DR 1 (Port 3) --> Some Tech Private Project B Switch (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-DR-1
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_PROJ-B-PRV-SW-AS
+ endpoint_b_port: 1
+
+ # Some Tech Private Project B Switch (Port 2) --> Some Tech Project B PC 1
+ - endpoint_a_hostname: ST_PROJ-B-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_PROJ-B-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Private Project B Switch (Port 3) --> Some Tech Project B PC 2
+ - endpoint_a_hostname: ST_PROJ-B-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_PROJ-B-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Private Project B Switch (Port 4) --> Some Tech Project B PC 3
+ - endpoint_a_hostname: ST_PROJ-B-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PROJ-B-PRV-PC-3
+ endpoint_b_port: 1
+
+ #############################
+ # SOME_TECH PROJECT C Links #
+ #############################
+
+ # Some Tech Intranet Private Router DR 1 (Port 4) --> Some Tech Private Project C Switch (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-DR-1
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PROJ-C-PRV-SW-AS
+ endpoint_b_port: 1
+
+ # Some Tech Private Project C Switch (Port 2) --> Some Tech Project C PC 1
+ - endpoint_a_hostname: ST_PROJ-C-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_PROJ-C-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Private Project C Switch (Port 3) --> Some Tech Project C PC 2
+ - endpoint_a_hostname: ST_PROJ-C-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_PROJ-C-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Private Project C Switch (Port 4) --> Some Tech Project C PC 3
+ - endpoint_a_hostname: ST_PROJ-C-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PROJ-C-PRV-PC-3
+ endpoint_b_port: 1
+
+##################################
+# Use Case 7 Agent YAML Anchors #
+##################################
+
+##############################
+# Green Agent YAML Anchors #
+##############################
+
+# Green Agent Reward Impacts Values #
+
+LOW_WEIGHT_IMPACT: &LOW_WEIGHT_IMPACT 0.2
+MEDIUM_WEIGHT_IMPACT: &MEDIUM_WEIGHT_IMPACT 0.5
+HIGH_WEIGHT_IMPACT: &HIGH_WEIGHT_IMPACT 0.95
+
+LOW_WEIGHT_IMPACT_NEGATIVE: &LOW_WEIGHT_IMPACT_NEG -0.2
+MEDIUM_WEIGHT_IMPACT_NEGATIVE: &MEDIUM_WEIGHT_IMPACT_NEG -0.5
+HIGH_WEIGHT_IMPACT_NEGATIVE: &HIGH_WEIGHT_IMPACT_NEG -0.8
+
+# Default Green Agent Action Space Configuration Anchor #
+
+DEFAULT_GREEN_AGENT_MAX_EXECUTIONS: &DEFAULT_GREEN_AGENT_MAX_EXECUTIONS 1000 # Ensures green agent activity through-out an episode
+
+#################################################
+# Probabilistic Green Agent Config Yaml Anchors #
+#################################################
+
+# Probabilistic Green Agent | 20% node-application-execute | 80% do-nothing #
+PROBABILISTIC_CONFIG_20_PERCENTAGE_PROBABILITY: &GREEN_PROBABILISTIC_20
+ action_probabilities:
+ 0: 0.8
+ 1: 0.2
+
+# Probabilistic Green Agent | 40% node-application-execute | 60% do-nothing #
+PROBABILISTIC_CONFIG_40_PERCENTAGE_PROBABILITY: &GREEN_PROBABILISTIC_40
+ action_probabilities:
+ 0: 0.6
+ 1: 0.4
+
+# Probabilistic Green Agent | 60% node-application-execute | 40% do-nothing #
+PROBABILISTIC_CONFIG_60_PERCENTAGE_PROBABILITY: &GREEN_PROBABILISTIC_60
+ action_probabilities:
+ 0: 0.4
+ 1: 0.6
+
+
+# System Green Agent Config UC7 Network Wide Yaml Anchor #
+
+# Lists the IP_Address of all hosts that contain DNS and NTP Service Clients
+UC7_IP_LIST: &UC7_IP_LIST
+ # ====== Home Office ========
+ - 192.168.1.2 # HOME-PUB-PC-1 | ip_id: 2
+ - 192.168.1.3 # HOME-PUB-PC-2 | ip_id: 3
+ - 192.168.1.4 # HOME-PUB-PC-SRV | ip_id: 4
+ # ====== Remote Site ========
+ - 192.168.20.2 # REM-PUB-PC-1 | ip_id: 5
+ - 192.168.20.3 # REM-PUB-PC-2 | ip_id: 6
+ - 192.168.20.4 # REM-PUB-SRV | ip_id: 7
+ # ====== ST Public DMZ =======
+ - *ST_PUB_SRV_WEB_IP # 192.168.100.2 (ST_DMZ-PUB-SRV-WEB) | ip_id: 8
+ # ====== ST Head Office =======
+ - 192.168.200.2 # ST_HO-PRV-PC-1 | ip_id: 9
+ - 192.168.200.3 # ST_HO-PRV-PC-2 | ip_id: 10
+ - 192.168.200.4 # ST_HO-PRV-PC-3 | ip_id: 11
+ # ===== ST Human Resources ======
+ - 192.168.210.2 # ST_HR-PRV-PC-1 | ip_id: 12
+ - 192.168.210.3 # ST_HR-PRV-PC-2 | ip_id: 13
+ - 192.168.210.4 # ST_HR-PRV-PC-3 | ip_id: 14
+ # ====== ST DATA Servers =======
+ - *ST_SRV_STORAGE_IP # 192.168.220.2 (ST_DATA-PRV-SRV-STORAGE) | ip_id: 15
+ - *ST_SRV_DB_IP # 192.168.220.3 (ST_DATA-PRV-SRV-DB) | ip_id: 16
+ # ====== ST Project A =======
+ - 192.168.230.2 # PROJ-A-PRV-PC-1 | ip_id: 17
+ - 192.168.230.3 # PROJ-A-PRV-PC-2 | ip_id: 18
+ - 192.168.230.4 # PROJ-A-PRV-PC-3 | ip_id: 19
+ # ====== ST Project B =======
+ - 192.168.240.2 # PROJ-B-PRV-PC-1 | ip_id: 20
+ - 192.168.240.3 # PROJ-B-PRV-PC-2 | ip_id: 21
+ - 192.168.240.4 # PROJ-B-PRV-PC-3 | ip_id: 22
+ # ====== ST Project C =======
+ - 192.168.250.2 # PROJ-C-PRV-PC-1 | ip_id: 23
+ - 192.168.250.3 # PROJ-C-PRV-PC-2 | ip_id: 24
+ - 192.168.250.4 # PROJ-C-PRV-PC-3 | ip_id: 25
+
+############################################
+# Use Case 7 Agent Configuration Section #
+############################################
+
+agents:
+ #######################################################
+ # UC7 Green Agents Path of Life (POL) Configuration #
+ #######################################################
+
+
+ ####################################
+ # Home Office Network POL Config #
+ ####################################
+
+ # Home Office Green Agent Pattern Of Life
+ # ======================================
+ # 1. Three Home workers accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. Three Home workers accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: HOME_WORKER-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["HOME-PUB-PC-1"]
+ target_application: "database-client"
+ start_step: 4
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: HOME-PUB-PC-1
+
+ - ref: HOME_WORKER-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: HOME-PUB-PC-1
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: HOME-PUB-PC-1
+
+ - ref: HOME_WORKER-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["HOME-PUB-PC-2"]
+ target_application: "database-client"
+ start_step: 8
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: HOME-PUB-PC-2
+
+ - ref: HOME_WORKER-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: HOME-PUB-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: HOME-PUB-PC-2
+
+ ####################################
+ # Remote Site Network POL Config #
+ ####################################
+
+ # Remote Site Green Agent Pattern Of Life
+ # ======================================
+ # 1. Three Remote workers accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. Three Remote workers accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: REMOTE_WORKER-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["REM-PUB-PC-1"]
+ target_application: "database-client"
+ start_step: 12
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: REM-PUB-PC-1
+
+ - ref: REMOTE_WORKER-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: REM-PUB-PC-1
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: REM-PUB-PC-1
+
+ - ref: REMOTE_WORKER-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["REM-PUB-PC-2"]
+ target_application: "database-client"
+ start_step: 16
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: REM-PUB-PC-2
+
+ - ref: REMOTE_WORKER-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: REM-PUB-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: REM-PUB-PC-2
+
+ ####################################
+ # ST Project A Network POL Config #
+ ####################################
+
+ # ST Project A Green Agent Pattern Of Life
+ # ========================================
+ # 1. A Senior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. A Senior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 3. Two Junior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 4. Two Junior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+
+ - ref: PROJ_A-SENIOR-DEV-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-A-PRV-PC-1"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-1
+
+ - ref: PROJ_A-SENIOR-DEV-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_40
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-1
+
+ - ref: PROJ_A-JUNIOR-DEV-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-A-PRV-PC-2"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-2
+
+ - ref: PROJ_A-JUNIOR-DEV-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-A-PRV-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-2
+
+ - ref: PROJ_A-JUNIOR-DEV-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-A-PRV-PC-3"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-3
+
+ - ref: PROJ_A-JUNIOR-DEV-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-A-PRV-PC-3
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-3
+
+ ####################################
+ # ST Project B Network POL Config #
+ ####################################
+
+ # ST Project B Green Agent Pattern Of Life
+ # ========================================
+ # 1. A Senior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. A Senior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 3. Two Junior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 4. Two Junior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: PROJ_B-SENIOR-DEV-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-B-PRV-PC-1"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-1
+
+ - ref: PROJ_B-SENIOR-DEV-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-B-PRV-PC-1
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_40
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-1
+
+ - ref: PROJ_B-JUNIOR-DEV-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-B-PRV-PC-2"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-2
+
+ - ref: PROJ_B-JUNIOR-DEV-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-2
+
+ - ref: PROJ_B-JUNIOR-DEV-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-B-PRV-PC-3"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-3
+
+ - ref: PROJ_B-JUNIOR-DEV-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-B-PRV-PC-3
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-3
+
+ ####################################
+ # ST Project C Network POL Config #
+ ####################################
+
+ # ST Project C Green Agent Pattern Of Life
+ # ========================================
+ # 1. A Senior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. A Senior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 3. Two Junior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 4. Two Junior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: PROJ_C-SENIOR-DEV-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-C-PRV-PC-1"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-1
+
+ - ref: PROJ_C-SENIOR-DEV-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-C-PRV-PC-1
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_40
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-1
+
+ - ref: PROJ_C-JUNIOR-DEV-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-C-PRV-PC-2"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-2
+
+ - ref: PROJ_C-JUNIOR-DEV-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-C-PRV-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-2
+
+ - ref: PROJ_C-JUNIOR-DEV-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-C-PRV-PC-3"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-3
+
+ - ref: PROJ_C-JUNIOR-DEV-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-3
+
+ ######################################
+ # ST Head Office Network POL Config #
+ ######################################
+
+ # ST Head Office Green Agent Pattern Of Life
+ # ==========================================
+ # 1. The ST CEO accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 2. The ST CTO accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 3. The ST CFO accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: CEO
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HO-PRV-PC-1
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *HIGH_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HO-PRV-PC-1
+
+ - ref: CTO
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HO-PRV-PC-2
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HO-PRV-PC-2
+
+ - ref: CFO
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HO-PRV-PC-3
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HO-PRV-PC-3
+
+ ##########################################
+ # ST Human Resources Network POL Config #
+ ##########################################
+
+ # ST Head Office Green Agent Pattern Of Life
+ # ==========================================
+ # 1. A senior HR staff accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 2. Two junior HR staff accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: SENIOR_HR
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HR-PRV-PC-1
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HR-PRV-PC-1
+
+ - ref: JUNIOR_HR-1
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HR-PRV-PC-2
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HR-PRV-PC-2
+
+ - ref: JUNIOR_HR-2
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HR-PRV-PC-3
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HR-PRV-PC-3
+
+ ##########################
+ # UC7 Red Agent Config #
+ ##########################
+
+ - ref: attacker
+ team: RED
+ type: tap-001
+ agent_settings:
+ start_step: 1
+ frequency: 5
+ variance: 0
+ repeat_kill_chain: false
+ repeat_kill_chain_stages: true
+ default_target_ip: *ST_SRV_DB_IP
+ default_starting_node: "ST_PROJ-A-PRV-PC-1"
+ # starting_nodes: ["ST_PROJ-A-PRV-PC-1", "ST_PROJ-B-PRV-PC-2", "ST_PROJ-C-PRV-PC-3"]
+ starting_nodes:
+ kill_chain:
+ ACTIVATE:
+ probability: 1
+ PROPAGATE:
+ probability: 1
+ scan_attempts: 20
+ repeat_scan: false
+ network_addresses:
+ - 192.168.230.0/29 # ST Project A
+ - 192.168.10.0/26 # Remote Site
+ - 192.168.20.0/30 # Remote DMZ
+ - 192.168.220.0/29 # ST Data (Contains Target)
+ COMMAND_AND_CONTROL:
+ probability: 1
+ keep_alive_frequency: 5
+ masquerade_port: HTTP
+ masquerade_protocol: TCP
+ c2_server_name: ISP-PUB-SRV-DNS
+ c2_server_ip: *PUBLIC_DNS_IP
+ PAYLOAD:
+ probability: 1
+ exfiltrate: true
+ corrupt: true
+ exfiltration_folder_name:
+ target_username: admin
+ target_password: admin
+ continue_on_failed_exfil: True
+
+
+###########################
+# UC7 Blue Agent Config #
+###########################
+
+ - ref: defender
+ team: BLUE
+ type: proxy-agent
+ observation_space:
+ type: custom
+ options:
+ components:
+ - type: nodes
+ label: NODES
+ options:
+ hosts:
+ # TAP001 Potential Starting Note | ST_PROJ-A-PRV-PC-1
+ - hostname: ST_PROJ-A-PRV-PC-1
+ services:
+ - service_name: ftp-client
+ applications:
+ - application_name: ransomware-script
+ - application_name: database-client
+ folders:
+ - folder_name: downloads
+ files:
+ - file_name: malware_dropper.ps1
+ - folder_name: exfiltration_folder
+ files:
+ - file_name: database.db
+ # TAP001 Potential Starting Note | ST_PROJ-B-PRV-PC-2
+ - hostname: ST_PROJ-B-PRV-PC-2
+ services:
+ - service_name: ftp-client
+ applications:
+ - application_name: ransomware-script
+ - application_name: database-client
+ folders:
+ - folder_name: downloads
+ files:
+ - file_name: malware_dropper.ps1
+ - folder_name: exfiltration_folder
+ files:
+ - file_name: database.db
+ # TAP001 Potential Starting Note | ST_PROJ-C-PRV-PC-3
+ - hostname: ST_PROJ-C-PRV-PC-3
+ services:
+ - service_name: ftp-client
+ applications:
+ - application_name: ransomware-script
+ - application_name: database-client
+ folders:
+ - folder_name: downloads
+ files:
+ - file_name: malware_dropper.ps1
+ - folder_name: exfiltration_folder
+ files:
+ - file_name: database.db
+ # ST DATA Server Database
+ - hostname: ST_DATA-PRV-SRV-DB
+ folders:
+ - folder_name: database
+ files:
+ - file_name: database.db
+ routers:
+ - hostname: ST_INTRA-PRV-RT-CR # TAP003 Malicious ACL Target | ROUTER0
+ - hostname: ST_INTRA-PRV-RT-DR-1 # TAP003 Malicious ACL Target | ROUTER1
+ - hostname: REM-PUB-RT-DR # TAP003 Malicious ACL Target | ROUTER2
+ num_ports: 5
+ num_services: 2
+ num_applications: 2
+ num_folders: 2
+ num_files: 1
+ num_nics: 1
+ ip_list:
+ # ip_list is indexed at 2:
+ # 0 reserved for padding to align with observations
+ # 1 reserved for ALL ips
+ *UC7_IP_LIST
+ wildcard_list:
+ - 0.0.0.1 # 0
+ - 0.0.0.255 # 1
+ - 0.0.255.255 # 2
+ port_list:
+ # 0 is a padding placeholder
+ # 1 means ALL ports
+ - FTP # 2
+ - DNS # 3
+ - HTTP # 4
+ - NTP # 5
+ - POSTGRES_SERVER # 6
+ - SSH # 7
+
+ protocol_list:
+ # 0 is padding placeholder
+ # 1 means ALL protocols
+ - ICMP # 2
+ - TCP # 3
+ - UDP # 4
+ num_rules: 5
+ include_num_access: true
+ include_nmne: true
+ monitored_traffic:
+ tcp:
+ - HTTP
+ - POSTGRES_SERVER
+ icmp:
+ - NONE
+ - type: links
+ label: LINKS
+ options:
+ link_references:
+ # HOME OFFICE SUBNET LINKS
+ - HOME-PUB-SW-AS:eth-1<->HOME-PUB-RT-DR:eth-1 # 1
+ - HOME-PUB-SW-AS:eth-1<->HOME-PUB-PC-1:eth-1 # 2
+ - HOME-PUB-SW-AS:eth-1<->HOME-PUB-PC-2:eth-1 # 3
+ - HOME-PUB-SW-AS:eth-1<->HOME-PUB-SRV:eth-1 # 4
+ # Internet LINKS
+ - ISP-PUB-RT-BR:eth-1<->HOME-PUB-RT-DR:eth-2 # 5
+ - ISP-PUB-RT-BR:eth-2<->ISP-PUB-SRV-DNS:eth-1 # 6
+ - ISP-PUB-RT-BR:eth-3<->REM-PUB-FW:eth-1 # 7
+ # Remote DMZ Links
+ - REM-PUB-FW:eth-2<->REM-PUB-RT-DR:eth-1 # 8
+ # Remote Site Links
+ - REM-PUB-RT-DR:eth-2<->REM-PUB-SW-AS:eth-1 # 9
+ - REM-PUB-SW-AS:eth-2<->REM-PUB-PC-1:eth-1 # 10
+ - REM-PUB-SW-AS:eth-3<->REM-PUB-PC-2:eth-1 # 11
+ - REM-PUB-SW-AS:eth-4<->REM-PUB-SRV:eth-1 # 12
+ # SOME_TECH DMZ
+ - ISP-PUB-RT-BR:eth-4<->ST_PUB-FW:eth-1 # 13
+ - ST_PUB-FW:eth-3<->ST_DMZ-PUB-SRV-WEB:eth-1 # 14
+ # SOME_TECH Intranet
+ - ST_INTRA-PRV-RT-CR:eth-1<->ST_PUB-FW:eth-2 # 15
+ - ST_INTRA-PRV-RT-CR:eth-2<->ST_INTRA-PRV-RT-DR-1:eth-1 # 16
+ - ST_INTRA-PRV-RT-CR:eth-3<->ST_INTRA-PRV-RT-DR-2:eth-1 # 17
+ - ST_INTRA-PRV-RT-CR:eth-4<->ST_DATA-PRV-SW-AS:eth-1 # 18
+ # SOME_TECH Head Office
+ - ST_HO-PRV-SW-AS:eth-1<->ST_INTRA-PRV-RT-DR-2:eth-2 # 19
+ - ST_HO-PRV-SW-AS:eth-2<->ST_HO-PRV-PC-1:eth-1 # 20
+ - ST_HO-PRV-SW-AS:eth-3<->ST_HO-PRV-PC-2:eth-1 # 21
+ - ST_HO-PRV-SW-AS:eth-4<->ST_HO-PRV-PC-3:eth-1 # 22
+ # SOME_TECH Human Resources
+ - ST_HR-PRV-SW-AS:eth-1<->ST_INTRA-PRV-RT-DR-2:eth-3 # 23
+ - ST_HR-PRV-SW-AS:eth-2<->ST_HR-PRV-PC-1:eth-1 # 24
+ - ST_HR-PRV-SW-AS:eth-3<->ST_HR-PRV-PC-2:eth-1 # 25
+ - ST_HR-PRV-SW-AS:eth-4<->ST_HR-PRV-PC-3:eth-1 # 26
+ # SOME_TECH Data Links
+ - ST_DATA-PRV-SW-AS:eth-2<->ST_DATA-PRV-SRV-STORAGE:eth-1 # 27
+ - ST_DATA-PRV-SW-AS:eth-3<->ST_DATA-PRV-SRV-DB:eth-1 # 28
+ # SOME_TECH Project A Links
+ - ST_INTRA-PRV-RT-DR-1:eth-2<->ST_PROJ-A-PRV-SW-AS:eth-1 # 29
+ - ST_PROJ-A-PRV-SW-AS:eth2<->ST_PROJ-A-PRV-PC-1:eth-1 # 31
+ - ST_PROJ-A-PRV-SW-AS:eth3<->ST_PROJ-A-PRV-PC-2:eth-1 # 32
+ - ST_PROJ-A-PRV-SW-AS:eth4<->ST_PROJ-A-PRV-PC-3:eth-1 # 33
+ # SOME_TECH Project B Links
+ - ST_INTRA-PRV-RT-DR-1:eth-3<->ST_PROJ-B-PRV-SW-AS:eth-1 # 34
+ - ST_PROJ-B-PRV-SW-AS:eth2<->ST_PROJ-B-PRV-PC-1:eth-1 # 35
+ - ST_PROJ-B-PRV-SW-AS:eth3<->ST_PROJ-B-PRV-PC-2:eth-1 # 36
+ - ST_PROJ-B-PRV-SW-AS:eth4<->ST_PROJ-B-PRV-PC-3:eth-1 # 37
+ # SOME_TECH Project C Links
+ - ST_INTRA-PRV-RT-DR-1:eth-4<->ST_PROJ-C-PRV-SW-AS:eth-1 # 38
+ - ST_PROJ-A-PRV-SW-AS:eth2<->ST_PROJ-C-PRV-PC-1:eth-1 # 39
+ - ST_PROJ-A-PRV-SW-AS:eth3<->ST_PROJ-C-PRV-PC-2:eth-1 # 40
+ - ST_PROJ-A-PRV-SW-AS:eth4<->ST_PROJ-C-PRV-PC-3:eth-1 # 41
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+
+ # |======================================|
+ # | ST_PROJ-A-PRV-PC-1 |
+ # |======================================|
+
+ # ST_PROJ-A-PRV-PC-1 | node-os-scan
+ 1:
+ action: node-os-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ # ST_PROJ-A-PRV-PC-1 | node-shutdown
+ 2:
+ action: node-shutdown
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ # ST_PROJ-A-PRV-PC-1 | node-startup
+ 3:
+ action: node-startup
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ # ST_PROJ-A-PRV-PC-1 | node-reset
+ 4:
+ action: node-reset
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ # ST_PROJ-A-PRV-PC-1 | host-nic-disable
+ 5:
+ action: host-nic-disable
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ nic_num: 0
+ # ST_PROJ-A-PRV-PC-1 | host-nic-enable
+ 6:
+ action: host-nic-enable
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ nic_num: 0
+ # ST_PROJ-A-PRV-PC-1 | node-application-close | database-client
+ 7:
+ action: node-application-close
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: database-client
+
+ # ST_PROJ-A-PRV-PC-1 | node-application-scan | database-client
+ 8:
+ action: node-application-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: database-client
+
+ # ST_PROJ-A-PRV-PC-1 | node-application-fix | database-client
+ 9:
+ action: node-application-fix
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: database-client
+
+ # ST_PROJ-A-PRV-PC-1 | node-application-remove | database-client
+ 10:
+ action: node-application-remove
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: database-client
+
+
+ # ST_PROJ-A-PRV-PC-1 | node-file-scan | downloads/malware_dropper.ps1
+ 11:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ folder_name: downloads
+ file_name: malware_dropper.ps1
+
+ # ST_PROJ-A-PRV-PC-1 | node-file-scan | exfiltration_folder/database.db
+ 12:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ folder_name: exfiltration_folder
+ file_name: database.db
+
+ # ST_PROJ-A-PRV-PC-1 | node-folder-scan | downloads/
+ 13:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ folder_name: downloads
+
+ # ST_PROJ-A-PRV-PC-1 | node-folder-scan | exfiltration_folder/
+ 14:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ folder_name: exfiltration_folder
+
+ # |======================================|
+ # | ST_PROJ-B-PRV-PC-2 |
+ # |======================================|
+
+ # ST_PROJ-B-PRV-PC-2 | node-os-scan
+ 15:
+ action: node-os-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+
+ # ST_PROJ-B-PRV-PC-2 | node-shutdown
+ 16:
+ action: node-shutdown
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+
+ # ST_PROJ-B-PRV-PC-2 | node-startup
+ 17:
+ action: node-startup
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+
+ # ST_PROJ-B-PRV-PC-2 | node-reset
+ 18:
+ action: node-reset
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+
+ # ST_PROJ-B-PRV-PC-2 | host-nic-disable
+ 19:
+ action: host-nic-disable
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ nic_num: 0
+
+ # ST_PROJ-B-PRV-PC-2 | host-nic-enable
+ 20:
+ action: host-nic-enable
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ nic_num: 0
+
+ # ST_PROJ-B-PRV-PC-2 | node-application-close | database-client
+ 21:
+ action: node-application-close
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: database-client
+
+ # ST_PROJ-B-PRV-PC-2 | node-application-scan | database-client
+ 22:
+ action: node-application-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: database-client
+
+ # ST_PROJ-B-PRV-PC-2 | node-application-fix | database-client
+ 23:
+ action: node-application-fix
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: database-client
+
+ # ST_PROJ-B-PRV-PC-2 | node-application-remove | database-client
+ 24:
+ action: node-application-remove
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: database-client
+
+ # ST_PROJ-B-PRV-PC-2 | node-file-scan | downloads/malware_dropper.ps1
+ 25:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ folder_name: downloads
+ file_name: malware_dropper.ps1
+
+ # ST_PROJ-B-PRV-PC-2 | node-file-scan | exfiltration_folder/database.db
+ 26:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ folder_name: exfiltration_folder
+ file_name: database.db
+
+ # ST_PROJ-B-PRV-PC-2 | node-folder-scan | downloads/
+ 27:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ folder_name: downloads
+
+ # ST_PROJ-B-PRV-PC-2 | node-folder-scan | exfiltration_folder/
+ 28:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ folder_name: exfiltration_folder
+
+ # |======================================|
+ # | ST_PROJ-C-PRV-PC-3 |
+ # |======================================|
+
+ # ST_PROJ-C-PRV-PC-3 | node-os-scan
+ 29:
+ action: node-os-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+
+ # ST_PROJ-C-PRV-PC-3 | node-shutdown
+ 30:
+ action: node-shutdown
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+
+ # ST_PROJ-C-PRV-PC-3 | node-startup
+ 31:
+ action: node-startup
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+
+ # ST_PROJ-C-PRV-PC-3 | node-reset
+ 32:
+ action: node-reset
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+
+ # ST_PROJ-C-PRV-PC-3 | host-nic-disable
+ 33:
+ action: host-nic-disable
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ nic_num: 0
+
+ # ST_PROJ-C-PRV-PC-3 | host-nic-enable
+ 34:
+ action: host-nic-enable
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ nic_num: 0
+
+ # ST_PROJ-C-PRV-PC-3 | node-application-close | database-client
+ 35:
+ action: node-application-close
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: database-client
+
+ # ST_PROJ-C-PRV-PC-3 | node-application-scan | database-client
+ 36:
+ action: node-application-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: database-client
+
+ # ST_PROJ-C-PRV-PC-3 | node-application-fix | database-client
+ 37:
+ action: node-application-fix
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: database-client
+
+ # ST_PROJ-C-PRV-PC-3 | node-application-remove | database-client
+ 38:
+ action: node-application-remove
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: database-client
+
+ # ST_PROJ-C-PRV-PC-3 | node-file-scan | downloads/malware_dropper.ps1
+ 39:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ folder_name: downloads
+ file_name: malware_dropper.ps1
+
+ # ST_PROJ-C-PRV-PC-3 | node-file-scan | exfiltration_folder/database.db
+ 40:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ folder_name: exfiltration_folder
+ file_name: database.db
+
+ # ST_PROJ-C-PRV-PC-3 | node-folder-scan | downloads/
+ 41:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ folder_name: downloads
+
+ # ST_PROJ-C-PRV-PC-3 | node-folder-scan | exfiltration_folder/
+ 42:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ folder_name: exfiltration_folder
+
+ # |======================================|
+ # | ST_INTRA-PRV-RT-CR |
+ # |======================================|
+
+ # ST_INTRA-PRV-RT-CR | router-acl-add-rule | P2: ST_PROJ-A-PRV-PC-1 !==> ST_DATA-PRV-SRV-DB (TCP:POSTGRES_SERVER)
+ 43:
+ action: router-acl-add-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 1
+ permission: DENY
+ src_ip: 192.168.230.2 # (ST_PROJ-A-PRV-PC-1)
+ src_wildcard: 0.0.255.255
+ src_port: POSTGRES_SERVER
+ dst_ip: 192.168.220.3 # (ST_DATA-PRV-SRV-DB)
+ dst_wildcard: 0.0.255.255
+ dst_port: POSTGRES_SERVER
+ protocol_name: TCP
+
+ # ST_INTRA-PRV-RT-CR | REMOVE_ACL_ADDRULE | Removes a given ACL at position 1
+ 44:
+ action: router-acl-remove-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 1
+
+ # ST_INTRA-PRV-RT-CR | router-acl-add-rule | P3: ST_PROJ-B-PRV-PC-2 !==> ST_DATA-PRV-SRV-DB (TCP:POSTGRES_SERVER)
+ 45:
+ action: router-acl-add-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 2
+ permission: DENY
+ src_ip: 192.168.240.3 # (ST_PROJ-B-PRV-PC-2)
+ src_wildcard: 0.0.255.255
+ src_port: POSTGRES_SERVER
+ dst_ip: 192.168.220.3 # (ST_DATA-PRV-SRV-DB)
+ dst_wildcard: 0.0.255.255
+ dst_port: POSTGRES_SERVER
+ protocol_name: TCP
+ # ST_INTRA-PRV-RT-CR | REMOVE_ACL_ADDRULE | Removes a given ACL at position 2
+ 46:
+ action: router-acl-remove-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 2
+
+ # ST_INTRA-PRV-RT-CR | router-acl-add-rule | P4: ST_PROJ-C-PRV-PC-3 !==> ST_DATA-PRV-SRV-DB (TCP:POSTGRES_SERVER)
+ 47:
+ action: router-acl-add-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 3
+ permission: DENY
+ src_ip: 192.168.250.4 # (ST_PROJ-C-PRV-PC-3)
+ src_wildcard: 0.0.255.255
+ src_port: POSTGRES_SERVER
+ dst_ip: 192.168.220.3 # (ST_DATA-PRV-SRV-DB)
+ dst_wildcard: 0.0.255.255
+ dst_port: POSTGRES_SERVER
+ protocol_name: TCP
+
+ # ST_INTRA-PRV-RT-CR | REMOVE_ACL_ADDRULE | Removes a given ACL at position 3
+ 48:
+ action: router-acl-remove-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 3
+
+ # |======================================|
+ # | ST_DATA-PRV-SRV-DB |
+ # |======================================|
+
+ # ST_DATA-PRV-SRV-DB | node-file-scan | Scans the database.db file (health status)
+ 49:
+ action: node-file-scan
+ options:
+ node_name: ST_DATA-PRV-SRV-DB
+ folder_name: database
+ file_name: database.db
+
+ # ST_DATA-PRV-SRV-DB | node-account-change-password | Changes the password of a user account
+ 50:
+ action: node-account-change-password
+ options:
+ node_name: ST_DATA-PRV-SRV-DB
+ username: admin # default account
+ current_password: admin # default password
+ new_password: thr33_alert_wolv3z # A more 'secure' password
+
+ # |======================================|
+ # | ST_INTRA-PRV-RT-DR-1 |
+ # |======================================|
+
+ # ST_INTRA-PRV-RT-DR-1 | router-acl-add-rule | P1: ST_INTRA-PRV-RT-DR-1 !==> ANY (TCP:SSH)
+ 51:
+ action: router-acl-add-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-DR-1
+ position: 1
+ permission: DENY
+ src_ip: 192.168.230.2 # (ST_PROJ-A-PRV-PC-1)
+ src_wildcard: 0.0.255.255
+ src_port: SSH
+ dst_ip: ALL
+ dst_wildcard: 0.0.255.255
+ dst_port: SSH
+ protocol_name: TCP
+
+ # ST_INTRA-PRV-RT-DR-1 | node-account-change-password
+ 52:
+ action: node-account-change-password
+ options:
+ node_name: ST_INTRA-PRV-RT-DR-1
+ username: admin
+ current_password: admin
+ new_password: secure_password
+
+ # ST_INTRA-PRV-RT-DR-1 | router-acl-remove-rule | Removes the given ACL at position 1
+ 53:
+ action: router-acl-remove-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-DR-1
+ position: 1
+
+ # |======================================|
+ # | REM-PUB-RT-DR |
+ # |======================================|
+
+ # REM-PUB-RT-DR | node-account-change-password
+ 54:
+ action: node-account-change-password
+ options:
+ node_name: REM-PUB-RT-DR
+ username: admin
+ current_password: admin
+ new_password: secure_password
+
+ # REM-PUB-RT-DR | router-acl-remove-rule | Removes the given ACL at position 1
+ 55:
+ action: router-acl-remove-rule
+ options:
+ target_router: REM-PUB-RT-DR
+ position: 1
+
+ reward_function:
+ reward_components:
+ - type: database-file-integrity
+ weight: *HIGH_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_DATA-PRV-SRV-DB
+ folder_name: database
+ file_name: database.db
+
+ # Home Site Green Agents (32 Green Agents each contributing 0.03125 of blue reward)
+
+ # Blue Shared Reward | HOME_WORKER-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: HOME_WORKER-1-DB
+
+ # Blue Shared Reward | HOME_WORKER-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: HOME_WORKER-1-WEB
+
+ # Blue Shared Reward | HOME_WORKER-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: HOME_WORKER-2-DB
+
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: HOME_WORKER-2-WEB
+
+ # Remote Site Green Agents
+
+ # Blue Shared Reward | REMOTE_WORKER-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: REMOTE_WORKER-1-DB
+
+ # Blue Shared Reward | REMOTE_WORKER-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: REMOTE_WORKER-1-WEB
+
+ # Blue Shared Reward | REMOTE_WORKER-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: REMOTE_WORKER-2-DB
+
+ # Blue Shared Reward | REMOTE_WORKER-2-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: REMOTE_WORKER-2-WEB
+
+ # ST Project A Green Agents
+
+ # Blue Shared Reward | PROJ_A-SENIOR-DEV-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-SENIOR-DEV-DB
+
+ # Blue Shared Reward | PROJ_A-SENIOR-DEV-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-SENIOR-DEV-WEB
+
+ # Blue Shared Reward | PROJ_A-JUNIOR-DEV-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-JUNIOR-DEV-1-DB
+
+ # Blue Shared Reward | PROJ_A-JUNIOR-DEV-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-JUNIOR-DEV-1-WEB
+
+ # Blue Shared Reward | PROJ_A-JUNIOR-DEV-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-JUNIOR-DEV-2-DB
+
+ # Blue Shared Reward | PROJ_A-JUNIOR-DEV-2-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-JUNIOR-DEV-2-WEB
+
+ # ST Project B Green Agents
+
+ # Blue Shared Reward | PROJ_B-SENIOR-DEV-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-SENIOR-DEV-DB
+
+ # Blue Shared Reward | PROJ_B-SENIOR-DEV-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-SENIOR-DEV-WEB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-1-DB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-1-WEB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-2-DB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-2-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-2-WEB
+
+ # ST Project C Green Agents
+
+ # Blue Shared Reward | PROJ_B-SENIOR-DEV-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-SENIOR-DEV-DB
+
+ # Blue Shared Reward | PROJ_B-SENIOR-DEV-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-SENIOR-DEV-WEB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-1-DB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-1-WEB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-2-DB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-2-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-2-WEB
+
+ # ST Head Office Green Agents (CEO/CFO/CTO)
+
+ # Blue Shared Reward | CEO
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: CEO
+
+ # Blue Shared Reward | CFO
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: CFO
+
+ # Blue Shared Reward | CTO
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: CTO
+
+ # ST Human Resources Green Agents
+
+ # Blue Shared Reward | SENIOR_HR
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: SENIOR_HR
+
+ # Blue Shared Reward | SENIOR_HR
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: JUNIOR_HR-1
+
+ # Blue Shared Reward | SENIOR_HR
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: JUNIOR_HR-2
+
+ agent_settings:
+ flatten_obs: True
diff --git a/src/primaite/config/_package_data/uc7_config_tap003.yaml b/src/primaite/config/_package_data/uc7_config_tap003.yaml
new file mode 100644
index 00000000..9ac6e1ab
--- /dev/null
+++ b/src/primaite/config/_package_data/uc7_config_tap003.yaml
@@ -0,0 +1,2730 @@
+##########################################################
+# USE CASE 7 CONFIGURATION YAML FILE #
+##########################################################
+
+
+##########################################
+# PrimAITE Game and Logging Settings #
+##########################################
+
+
+# PrimAITE I/O Settings #
+
+io_settings:
+ save_agent_actions: false
+ save_step_metadata: false
+ save_pcap_logs: false
+ save_sys_logs: false
+ save_agent_logs: false
+ # save_sys_logs: true
+ write_sys_log_to_terminal: false
+
+
+# PrimAITE Game Settings #
+
+game:
+ max_episode_length: 128
+ ports:
+ - FTP
+ - DNS
+ - HTTP
+ - NTP
+ - POSTGRES_SERVER
+ - SSH
+ protocols:
+ - ICMP
+ - TCP
+ - UDP
+ thresholds:
+ nmne:
+ high: 10
+ medium: 5
+ low: 0
+
+############################################
+# PrimAITE Use Case 7 Simulation #
+############################################
+
+##########################################
+# Configuration Variables (Yaml Anchors) #
+##########################################
+
+# External Network Address List #
+
+DNS_SUBNET: &DNS_SUBNET 255.255.255.240 # | 8.8.8.0 / 28
+HOME_INTERNET_SUBNET: &HOME_INTERNET_SUBNET 255.255.255.252 # | 10.1.0.0 / 30
+REMOTE_INTERNET_SUBNET: &REMOTE_INTERNET_SUBNET 255.255.255.252 # | 10.1.10.0 / 30
+SOME_TECH_INTERNET_SUBNET: &ST_INTERNET_SUBNET 255.255.255.252 # | 10.1.100.0 / 30
+HOME_OFFICE_SUBNET: &HOME_SUBNET 255.255.255.0 # | 192.168.1.0 / 26
+REMOTE_SUBNET_DMZ: &REMOTE_SUBNET_DMZ 255.255.255.252 # | 192.168.10.0 / 30
+REMOTE_SUBNET: &REMOTE_SUBNET 255.255.255.240 # | 192.168.20.0 / 28
+
+# SOME_TECH (ST) Network Address List #
+
+SOME_TECH_DMZ_SUBNET: &ST_DMZ_SUBNET 255.255.255.252 # | 192.168.100.0 / 30
+SOME_TECH_INTRANET_RT_CR_SUBNET: &ST_INTRA_CR_SUBNET 255.255.255.240 # | 192.168.150.0 / 28
+SOME_TECH_INTRANET_RT_DR_ONE_SUBNET: &ST_INTRA_DR_ONE_SUBNET 255.255.255.252 # | 192.168.160.0 / 30
+SOME_TECH_INTRANET_RT_DR_TWO_SUBNET: &ST_INTRA_DR_TWO_SUBNET 255.255.255.252 # | 192.168.170.0 / 30
+SOME_TECH_HEAD_OFFICE_SUBNET: &ST_HO_SUBNET 255.255.255.248 # | 192.168.200.0 / 29
+SOME_TECH_HUMAN_RESOURCES_SUBNET: &ST_HR_SUBNET 255.255.255.248 # | 192.168.210.0 / 29
+SOME_TECH_DATA_SUBNET: &ST_DATA_SUBNET 255.255.255.248 # | 192.168.220.0 / 29
+SOME_TECH_PROJECT_A_SUBNET: &ST_PROJ_A_SUBNET 255.255.255.248 # | 192.168.230.0 / 29
+SOME_TECH_PROJECT_B_SUBNET: &ST_PROJ_B_SUBNET 255.255.255.248 # | 192.168.240.0 / 29
+SOME_TECH_PROJECT_C_SUBNET: &ST_PROJ_C_SUBNET 255.255.255.248 # | 192.168.250.0 / 29
+
+# Host & Server Configurations #
+
+# ST Public Web Server | web-server | ST_DMZ-PUB-SRV-WEB
+SOME_TECH_PUBLIC_SERVER_WEB_IP_ADDRESS: &ST_PUB_SRV_WEB_IP 192.168.100.2
+SOME_TECH_PUBLIC_SERVER_WEB_CONFIG: &ST_SRV_WEB_CONFIG #
+ - type: web-server
+
+# ISP Public DNS | dns-server | ISP-PUB-SRV-DNS
+PUBLIC_DNS_IP_ADDRESS: &PUBLIC_DNS_IP 8.8.8.8
+PUBLIC_DNS_CONFIG: &PUBLIC_DNS_CONFIG #
+ - type: dns-server
+ options:
+ domain_mapping:
+ some_tech.com: *ST_PUB_SRV_WEB_IP
+
+# ST Private Storage Server | ftp-server | ST_DATA-PRV-SRV-STORAGE
+SOME_TECH_PRIVATE_SERVER_STORAGE_IP: &ST_SRV_STORAGE_IP 192.168.220.2
+SOME_TECH_PRIVATE_SERVER_STORAGE_CONFIG: &ST_SRV_STORAGE_CONFIG
+ - type: ftp-server
+
+# ST Private Database Server | database-client & ftp-client | ST_DATA-PRV-SRV-DB
+SOME_TECH_PRIVATE_SERVER_DATABASE_IP: &ST_SRV_DB_IP 192.168.220.3
+SOME_TECH_PRIVATE_SERVER_DATABASE_CONFIG: &ST_SRV_DB_CONFIG
+ - type: database-service
+ options:
+ backup_server_ip: *ST_SRV_STORAGE_IP
+ - type: ftp-client
+
+# Default PC Configuration | Database Client & Web Server
+PERSONAL_COMPUTER_DEFAULT_CONFIG: &PC_DEFAULT_CONFIG
+ - type: database-client
+ options:
+ db_server_ip: *ST_SRV_DB_IP
+ - type: web-browser
+ options:
+ target_url: http://some_tech.com
+
+
+##############################
+# Simulation Configuration #
+##############################
+
+simulation:
+ defaults:
+ folder_scan_duration: 0
+ folder_restore_duration: 3
+ service_fix_duration: 2
+ service_restart_duration: 2
+ software_install_duration: 0
+ node_start_up_duration: 3
+ node_shut_down_duration: 3
+ node_scan_duration: 8
+ network:
+ nmne_config:
+ capture_nmne: true
+ nmne_capture_keywords:
+ - DELETE
+ - ENCRYPT
+ nodes:
+ ######################
+ # HOME OFFICE SUBNET #
+ ######################
+ - hostname: HOME-PUB-RT-DR
+ type: router
+ default_gateway: 10.1.0.1
+ ports:
+ 1:
+ ip_address: 192.168.1.1
+ subnet_mask: *HOME_SUBNET
+ 2:
+ ip_address: 10.1.0.2
+ subnet_mask: *HOME_INTERNET_SUBNET
+ default_route:
+ next_hop_ip_address: 10.1.0.1
+ acl:
+ 5:
+ action: PERMIT
+
+ - hostname: HOME-PUB-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: HOME-PUB-PC-1
+ type: computer
+ ip_address: 192.168.1.2
+ default_gateway: 192.168.1.1
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: HOME-PUB-PC-2
+ type: computer
+ ip_address: 192.168.1.3
+ default_gateway: 192.168.1.1
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: HOME-PUB-SRV
+ type: server
+ ip_address: 192.168.1.4
+ default_gateway: 192.168.1.1
+ dns_server: *PUBLIC_DNS_IP
+
+ ######################
+ # INTERNET SUBNET #
+ ######################
+ - hostname: ISP-PUB-RT-BR
+ type: router
+ ports:
+ 1:
+ ip_address: 10.1.0.1
+ subnet_mask: *HOME_INTERNET_SUBNET
+ 2:
+ ip_address: 8.8.8.1
+ subnet_mask: *DNS_SUBNET
+ 3:
+ ip_address: 10.1.10.1
+ subnet_mask: *REMOTE_INTERNET_SUBNET
+ 4:
+ ip_address: 10.1.100.1
+ subnet_mask: *ST_INTERNET_SUBNET
+ routes:
+ - address: 192.168.1.0
+ subnet_mask: *HOME_SUBNET
+ next_hop_ip_address: 10.1.0.2
+
+ - address: 8.8.8.0
+ subnet_mask: *DNS_SUBNET
+ next_hop_ip_address: 8.8.8.8
+
+ - address: 192.168.10.0
+ subnet_mask: *REMOTE_SUBNET_DMZ
+ next_hop_ip_address: 10.1.10.2
+
+ - address: 192.168.20.0
+ subnet_mask: *REMOTE_SUBNET
+ next_hop_ip_address: 10.1.10.2
+
+ default_route:
+ next_hop_ip_address: 10.1.100.2 # SOME_TECH Firewall
+
+ acl:
+ 5:
+ action: PERMIT
+
+ ################
+ # DNS SUBNET #
+ ################
+ - hostname: ISP-PUB-SRV-DNS
+ type: server
+ ip_address: 8.8.8.8
+ subnet_mask: *DNS_SUBNET
+ default_gateway: 8.8.8.1
+ services:
+ *PUBLIC_DNS_CONFIG
+ applications:
+ - type: c2-server # Represents the external internet.
+ options:
+ listen_on_ports:
+ - 80
+ - 53
+ - 21
+ ########################
+ # REMOTE SITE SUBNET #
+ ########################
+ - hostname: REM-PUB-FW
+ type: firewall
+ ports:
+ external_port: # Public Internet facing
+ ip_address: 10.1.10.2
+ subnet_mask: *REMOTE_INTERNET_SUBNET
+ internal_port: # Remote Site (DMZ Subnet) facing
+ ip_address: 192.168.10.1
+ subnet_mask: *REMOTE_SUBNET_DMZ
+ routes:
+ - address: 192.168.20.0 # Remote Site Network
+ subnet_mask: *REMOTE_SUBNET
+ next_hop_ip_address: 192.168.10.2
+ default_route:
+ next_hop_ip_address: 10.1.10.1 # Forward to internet router port 3
+ acl:
+ internal_inbound_acl:
+ 1:
+ action: PERMIT
+ internal_outbound_acl:
+ 1:
+ action: PERMIT
+ dmz_inbound_acl:
+ 1:
+ action: PERMIT
+ dmz_outbound_acl:
+ 1:
+ action: PERMIT
+ external_inbound_acl:
+ 1:
+ action: PERMIT
+ external_outbound_acl:
+ 1:
+ action: PERMIT
+
+ - hostname: REM-PUB-RT-DR
+ type: router
+ default_gateway: 192.168.10.1
+ ports:
+ 1:
+ ip_address: 192.168.10.2
+ subnet_mask: *REMOTE_SUBNET_DMZ
+ 2:
+ ip_address: 192.168.20.1
+ subnet_mask: *REMOTE_SUBNET
+ default_route:
+ next_hop_ip_address: 192.168.10.1
+ acl:
+ 5:
+ action: PERMIT
+
+ - hostname: REM-PUB-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: REM-PUB-PC-1
+ type: computer
+ ip_address: 192.168.20.2
+ default_gateway: 192.168.20.1
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: REM-PUB-PC-2
+ type: computer
+ ip_address: 192.168.20.3
+ default_gateway: 192.168.20.1
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: REM-PUB-SRV
+ type: server
+ ip_address: 192.168.20.4
+ default_gateway: 192.168.20.1
+ dns_server: *PUBLIC_DNS_IP
+
+
+ ########################
+ # SOME_TECH DMZ SUBNET #
+ ########################
+
+ - hostname: ST_PUB-FW
+ type: firewall
+ ports:
+ external_port: # Public Internet Facing Port
+ ip_address: 10.1.100.2
+ subnet_mask: *ST_INTERNET_SUBNET
+ internal_port: # SOME_TECH Intranet Port
+ ip_address: 192.168.150.1
+ subnet_mask: *ST_INTRA_CR_SUBNET
+ dmz_port: # SOME_TECH Port Facing Port
+ ip_address: 192.168.100.1
+ subnet_mask: *ST_DMZ_SUBNET
+ acl:
+ internal_inbound_acl:
+ 5:
+ action: PERMIT
+ internal_outbound_acl:
+ 5:
+ action: PERMIT
+ dmz_inbound_acl:
+ 5:
+ action: PERMIT
+ dmz_outbound_acl:
+ 5:
+ action: PERMIT
+ external_inbound_acl:
+ 5:
+ action: PERMIT
+ external_outbound_acl:
+ 5:
+ action: PERMIT
+ routes:
+ - address: 10.1.100.0
+ subnet_mask: *ST_INTERNET_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 10.1.10.0
+ subnet_mask: *REMOTE_INTERNET_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 10.1.0.0
+ subnet_mask: *HOME_INTERNET_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 192.168.1.0
+ subnet_mask: *HOME_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 192.168.10.0
+ subnet_mask: *REMOTE_SUBNET_DMZ
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 192.168.20.0
+ subnet_mask: *REMOTE_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 8.8.8.0
+ subnet_mask: *DNS_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ default_route:
+ next_hop_ip_address: 192.168.150.2
+
+ - hostname: ST_DMZ-PUB-SRV-WEB
+ type: server
+ ip_address: *ST_PUB_SRV_WEB_IP
+ subnet_mask: *ST_DMZ_SUBNET
+ default_gateway: 192.168.100.1
+ services:
+ *ST_SRV_WEB_CONFIG
+
+ #############################
+ # SOME_TECH INTRANET SUBNET #
+ #############################
+
+ - hostname: ST_INTRA-PRV-RT-CR
+ type: router
+ ports:
+ 1:
+ ip_address: 192.168.150.2
+ subnet_mask: *ST_INTRA_CR_SUBNET
+ 2:
+ ip_address: 192.168.160.1
+ subnet_mask: *ST_INTRA_DR_ONE_SUBNET
+ 3:
+ ip_address: 192.168.170.1
+ subnet_mask: *ST_INTRA_DR_TWO_SUBNET
+ 4:
+ ip_address: 192.168.220.1
+ subnet_mask: *ST_DATA_SUBNET
+
+ routes:
+ - address: 192.168.200.0
+ subnet_mask: *ST_HO_SUBNET
+ next_hop_ip_address: 192.168.170.2 # ST Intra Router Two
+ - address: 192.168.210.0
+ subnet_mask: *ST_HR_SUBNET
+ next_hop_ip_address: 192.168.170.2 # ST Intra Router Two
+ - address: 192.168.230.0
+ subnet_mask: *ST_PROJ_A_SUBNET
+ next_hop_ip_address: 192.168.160.2 # ST Intra Router One
+ - address: 192.168.240.0
+ subnet_mask: *ST_PROJ_B_SUBNET
+ next_hop_ip_address: 192.168.160.2 # ST Intra Router One
+ - address: 192.168.250.0
+ subnet_mask: *ST_PROJ_C_SUBNET
+ next_hop_ip_address: 192.168.160.2 # ST Intra Router One
+
+ default_route:
+ next_hop_ip_address: 192.168.150.1 # ST Public Firewall Internal Port
+ acl:
+ 5:
+ action: PERMIT
+
+ - hostname: ST_INTRA-PRV-RT-DR-1
+ type: router
+ ports:
+ 1:
+ ip_address: 192.168.160.2
+ subnet_mask: *ST_INTRA_DR_ONE_SUBNET
+ 2:
+ ip_address: 192.168.230.1
+ subnet_mask: *ST_PROJ_A_SUBNET
+ 3:
+ ip_address: 192.168.240.1
+ subnet_mask: *ST_PROJ_B_SUBNET
+ 4:
+ ip_address: 192.168.250.1
+ subnet_mask: *ST_PROJ_C_SUBNET
+ default_route:
+ next_hop_ip_address: 192.168.160.1 # ST Intranet CR Router Port 2
+ acl:
+ 5:
+ action: PERMIT
+
+ - hostname: ST_INTRA-PRV-RT-DR-2
+ type: router
+ default_gateway: 192.168.170.1
+ ports:
+ 1:
+ ip_address: 192.168.170.2
+ subnet_mask: *ST_INTRA_DR_TWO_SUBNET
+ 2:
+ ip_address: 192.168.200.1
+ subnet_mask: *ST_HO_SUBNET
+ 3:
+ ip_address: 192.168.210.1
+ subnet_mask: *ST_HR_SUBNET
+ default_route:
+ next_hop_ip_address: 192.168.170.1 # ST Intranet CR Router Port 3
+ acl:
+ 5:
+ action: PERMIT
+
+ ################################
+ # SOME_TECH HEAD OFFICE SUBNET #
+ ################################
+
+ - hostname: ST_HO-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_HO-PRV-PC-1
+ type: computer
+ ip_address: 192.168.200.2
+ default_gateway: 192.168.200.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_HO-PRV-PC-2
+ type: computer
+ ip_address: 192.168.200.3
+ default_gateway: 192.168.200.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_HO-PRV-PC-3
+ type: computer
+ ip_address: 192.168.200.4
+ default_gateway: 192.168.200.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ ####################################
+ # SOME_TECH HUMAN RESOURCES SUBNET #
+ ####################################
+
+ - hostname: ST_HR-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_HR-PRV-PC-1
+ type: computer
+ ip_address: 192.168.210.2
+ default_gateway: 192.168.210.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_HR-PRV-PC-2
+ type: computer
+ ip_address: 192.168.210.3
+ default_gateway: 192.168.210.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_HR-PRV-PC-3
+ type: computer
+ ip_address: 192.168.210.4
+ default_gateway: 192.168.210.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ #########################
+ # SOME_TECH DATA SUBNET #
+ #########################
+
+ - hostname: ST_DATA-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_DATA-PRV-SRV-STORAGE
+ type: server
+ ip_address: *ST_SRV_STORAGE_IP
+ subnet_mask: *ST_DATA_SUBNET
+ default_gateway: 192.168.220.1
+ dns_server: *PUBLIC_DNS_IP
+ services:
+ *ST_SRV_STORAGE_CONFIG
+
+ - hostname: ST_DATA-PRV-SRV-DB
+ type: server
+ ip_address: *ST_SRV_DB_IP
+ subnet_mask: *ST_DATA_SUBNET
+ default_gateway: 192.168.220.1
+ dns_server: *PUBLIC_DNS_IP
+ services:
+ *ST_SRV_DB_CONFIG
+
+ #######################
+ # SOME_TECH PROJECT A #
+ #######################
+
+ - hostname: ST_PROJ-A-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_PROJ-A-PRV-PC-1
+ type: computer
+ ip_address: 192.168.230.2
+ default_gateway: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-A-PRV-PC-2
+ type: computer
+ ip_address: 192.168.230.3
+ default_gateway: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-A-PRV-PC-3
+ type: computer
+ ip_address: 192.168.230.4
+ default_gateway: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ #######################
+ # SOME_TECH PROJECT B #
+ #######################
+
+ - hostname: ST_PROJ-B-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_PROJ-B-PRV-PC-1
+ type: computer
+ ip_address: 192.168.240.2
+ default_gateway: 192.168.240.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-B-PRV-PC-2
+ type: computer
+ ip_address: 192.168.240.3
+ default_gateway: 192.168.240.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-B-PRV-PC-3
+ type: computer
+ ip_address: 192.168.240.4
+ default_gateway: 192.168.240.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ #######################
+ # SOME_TECH PROJECT C #
+ #######################
+
+ - hostname: ST_PROJ-C-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_PROJ-C-PRV-PC-1
+ type: computer
+ ip_address: 192.168.250.2
+ default_gateway: 192.168.250.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-C-PRV-PC-2
+ type: computer
+ ip_address: 192.168.250.3
+ default_gateway: 192.168.250.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-C-PRV-PC-3
+ type: computer
+ ip_address: 192.168.250.4
+ default_gateway: 192.168.250.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+
+ ##############################
+ # Simulation Network Links #
+ ##############################
+ links:
+
+ ############################
+ # HOME OFFICE SUBNET LINKS #
+ ############################
+
+ # Home Switch (Port 1) --> Home Router (Port 1)
+ - endpoint_a_hostname: HOME-PUB-SW-AS
+ endpoint_a_port: 1
+ endpoint_b_hostname: HOME-PUB-RT-DR
+ endpoint_b_port: 1
+
+ # Home Switch (Port 2) --> PC 1 (Port 1)
+ - endpoint_a_hostname: HOME-PUB-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: HOME-PUB-PC-1
+ endpoint_b_port: 1
+
+ # Home Switch (Port 3) --> PC 2 (Port 1)
+ - endpoint_a_hostname: HOME-PUB-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: HOME-PUB-PC-2
+ endpoint_b_port: 1
+
+ # Home Switch (Port 4) --> PC SRV (Port 1)
+ - endpoint_a_hostname: HOME-PUB-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: HOME-PUB-SRV
+ endpoint_b_port: 1
+
+ ##################
+ # Internet Links #
+ ##################
+
+ # Internet Router (Port 1) --> Home Router (Port 2)
+ - endpoint_a_hostname: ISP-PUB-RT-BR
+ endpoint_a_port: 1
+ endpoint_b_hostname: HOME-PUB-RT-DR
+ endpoint_b_port: 2
+
+ # Internet Router (Port 2) --> DNS Server (Port 1)
+ - endpoint_a_hostname: ISP-PUB-RT-BR
+ endpoint_a_port: 2
+ endpoint_b_hostname: ISP-PUB-SRV-DNS
+ endpoint_b_port: 1
+
+ # Internet Router (Port 3) --> Remote Firewall (External Port)
+ - endpoint_a_hostname: ISP-PUB-RT-BR
+ endpoint_a_port: 3
+ endpoint_b_hostname: REM-PUB-FW
+ endpoint_b_port: 1
+
+ ####################
+ # Remote DMZ Links #
+ ####################
+
+ # Remote Firewall (Internal Port) --> Remote Site Router (Port 1)
+ - endpoint_a_hostname: REM-PUB-FW
+ endpoint_a_port: 2
+ endpoint_b_hostname: REM-PUB-RT-DR
+ endpoint_b_port: 1
+
+ ####################
+ # Remote Site Link #
+ ####################
+
+ # Remote Site Router (Port 2) --> Remote Site Switch (Port 1)
+ - endpoint_a_hostname: REM-PUB-RT-DR
+ endpoint_a_port: 2
+ endpoint_b_hostname: REM-PUB-SW-AS
+ endpoint_b_port: 1
+
+ # Remote Site Switch (Port 2) --> Remote Site PC 1 (Port 1)
+ - endpoint_a_hostname: REM-PUB-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: REM-PUB-PC-1
+ endpoint_b_port: 1
+
+ # Remote Site Switch (Port 3) --> Remote Site PC 2 (Port 1)
+ - endpoint_a_hostname: REM-PUB-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: REM-PUB-PC-2
+ endpoint_b_port: 1
+
+ # Remote Site Switch (Port 4) --> Remote Site Server (Port 1)
+ - endpoint_a_hostname: REM-PUB-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: REM-PUB-SRV
+ endpoint_b_port: 1
+
+ #######################
+ # SOME_TECH DMZ Links #
+ #######################
+
+ # Internet Router (Port 4) --> Some Tech DMZ Firewall (External Port)
+ - endpoint_a_hostname: ISP-PUB-RT-BR
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PUB-FW
+ endpoint_b_port: 1
+
+ # Some Tech DMZ Firewall (DMZ Port) --> Some Tech Web Server (Port 1)
+ - endpoint_a_hostname: ST_PUB-FW
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_DMZ-PUB-SRV-WEB
+ endpoint_b_port: 1
+
+ ############################
+ # SOME_TECH INTRANET Links #
+ ############################
+
+ # Some Tech Intranet CR Router (Port 1) --> Some Tech DMZ Firewall (Internal Port)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-CR
+ endpoint_a_port: 1
+ endpoint_b_hostname: ST_PUB-FW
+ endpoint_b_port: 2
+
+ # Some Tech Intranet CR Router (Port 2) --> Some Tech Intranet DR Router 1 (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-CR
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_INTRA-PRV-RT-DR-1
+ endpoint_b_port: 1
+
+ # Some Tech Intranet CR Router (Port 3) --> Some Tech Intranet DR Router 2 (Port 2)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-CR
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_INTRA-PRV-RT-DR-2
+ endpoint_b_port: 1
+
+ # Some Tech Intranet Private Router CR (Port 4) --> Some Tech Data Private Switch (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-CR
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_DATA-PRV-SW-AS
+ endpoint_b_port: 1
+
+
+ ###############################
+ # SOME_TECH HEAD OFFICE Links #
+ ###############################
+
+ # Some Tech Head Office Switch (Port 1) --> Some Tech Intranet Private Router DR 2 (Port 2)
+ - endpoint_a_hostname: ST_HO-PRV-SW-AS
+ endpoint_a_port: 1
+ endpoint_b_hostname: ST_INTRA-PRV-RT-DR-2
+ endpoint_b_port: 2
+
+ # Some Tech Head Office Switch (Port 2) --> Some Tech Head Office PC 1 (Port 1)
+ - endpoint_a_hostname: ST_HO-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_HO-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Head Office Switch (Port 3) --> Some Tech Head Office PC 2 (Port 1)
+ - endpoint_a_hostname: ST_HO-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_HO-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Head Office Switch (Port 4) --> Some Tech Head Office PC 3 (Port 1)
+ - endpoint_a_hostname: ST_HO-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_HO-PRV-PC-3
+ endpoint_b_port: 1
+
+
+ ###################################
+ # SOME_TECH HUMAN RESOURCES Links #
+ ###################################
+
+ # Some Tech Human Resources Switch (Port 1) --> Some Tech Intranet Private Router DR 2 (Port 3)
+ - endpoint_a_hostname: ST_HR-PRV-SW-AS
+ endpoint_a_port: 1
+ endpoint_b_hostname: ST_INTRA-PRV-RT-DR-2
+ endpoint_b_port: 3
+
+ # Some Tech Human Resources Switch (Port 2) --> Some Tech Human Resources PC 1 (Port 1)
+ - endpoint_a_hostname: ST_HR-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_HR-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Human Resources Switch (Port 3) --> Some Tech Human Resources PC 2 (Port 1)
+ - endpoint_a_hostname: ST_HR-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_HR-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Human Resources Switch (Port 4) --> Some Tech Human Resources PC 3 (Port 1)
+ - endpoint_a_hostname: ST_HR-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_HR-PRV-PC-3
+ endpoint_b_port: 1
+
+ ########################
+ # SOME_TECH DATA Links #
+ ########################
+
+ # Some Tech Data Switch (Port 2) --> Some Tech Data Private Storage Server (Port 1)
+ - endpoint_a_hostname: ST_DATA-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_DATA-PRV-SRV-STORAGE
+ endpoint_b_port: 1
+
+ # Some Tech Data Switch (Port 3) --> Some Tech Data Private Database Server (Port 1)
+
+ - endpoint_a_hostname: ST_DATA-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_DATA-PRV-SRV-DB
+ endpoint_b_port: 1
+
+ #############################
+ # SOME_TECH PROJECT A Links #
+ #############################
+
+ # Some Tech Intranet Private Router DR 1 (Port 2) --> Some Tech Private Project A Switch (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-DR-1
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_PROJ-A-PRV-SW-AS
+ endpoint_b_port: 1
+
+ # Some Tech Private Project A Switch (Port 2) --> Some Tech Project A PC 1
+ - endpoint_a_hostname: ST_PROJ-A-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_PROJ-A-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Private Project A Switch (Port 3) --> Some Tech Project A PC 2
+ - endpoint_a_hostname: ST_PROJ-A-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_PROJ-A-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Private Project A Switch (Port 4) --> Some Tech Project A PC 3
+ - endpoint_a_hostname: ST_PROJ-A-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PROJ-A-PRV-PC-3
+ endpoint_b_port: 1
+
+ #############################
+ # SOME_TECH PROJECT B Links #
+ #############################
+
+ # Some Tech Intranet Private Router DR 1 (Port 3) --> Some Tech Private Project B Switch (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-DR-1
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_PROJ-B-PRV-SW-AS
+ endpoint_b_port: 1
+
+ # Some Tech Private Project B Switch (Port 2) --> Some Tech Project B PC 1
+ - endpoint_a_hostname: ST_PROJ-B-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_PROJ-B-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Private Project B Switch (Port 3) --> Some Tech Project B PC 2
+ - endpoint_a_hostname: ST_PROJ-B-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_PROJ-B-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Private Project B Switch (Port 4) --> Some Tech Project B PC 3
+ - endpoint_a_hostname: ST_PROJ-B-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PROJ-B-PRV-PC-3
+ endpoint_b_port: 1
+
+ #############################
+ # SOME_TECH PROJECT C Links #
+ #############################
+
+ # Some Tech Intranet Private Router DR 1 (Port 4) --> Some Tech Private Project C Switch (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-DR-1
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PROJ-C-PRV-SW-AS
+ endpoint_b_port: 1
+
+ # Some Tech Private Project C Switch (Port 2) --> Some Tech Project C PC 1
+ - endpoint_a_hostname: ST_PROJ-C-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_PROJ-C-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Private Project C Switch (Port 3) --> Some Tech Project C PC 2
+ - endpoint_a_hostname: ST_PROJ-C-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_PROJ-C-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Private Project C Switch (Port 4) --> Some Tech Project C PC 3
+ - endpoint_a_hostname: ST_PROJ-C-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PROJ-C-PRV-PC-3
+ endpoint_b_port: 1
+
+##################################
+# Use Case 7 Agent YAML Anchors #
+##################################
+
+##############################
+# Green Agent YAML Anchors #
+##############################
+
+# Green Agent Reward Impacts Values #
+
+LOW_WEIGHT_IMPACT: &LOW_WEIGHT_IMPACT 0.2
+MEDIUM_WEIGHT_IMPACT: &MEDIUM_WEIGHT_IMPACT 0.5
+HIGH_WEIGHT_IMPACT: &HIGH_WEIGHT_IMPACT 0.95
+
+LOW_WEIGHT_IMPACT_NEGATIVE: &LOW_WEIGHT_IMPACT_NEG -0.2
+MEDIUM_WEIGHT_IMPACT_NEGATIVE: &MEDIUM_WEIGHT_IMPACT_NEG -0.5
+HIGH_WEIGHT_IMPACT_NEGATIVE: &HIGH_WEIGHT_IMPACT_NEG -0.8
+
+# Default Green Agent Action Space Configuration Anchor #
+
+DEFAULT_GREEN_AGENT_MAX_EXECUTIONS: &DEFAULT_GREEN_AGENT_MAX_EXECUTIONS 1000 # Ensures green agent activity through-out an episode
+
+#################################################
+# Probabilistic Green Agent Config Yaml Anchors #
+#################################################
+
+# Probabilistic Green Agent | 20% node-application-execute | 80% do-nothing #
+PROBABILISTIC_CONFIG_20_PERCENTAGE_PROBABILITY: &GREEN_PROBABILISTIC_20
+ action_probabilities:
+ 0: 0.8
+ 1: 0.2
+
+# Probabilistic Green Agent | 40% node-application-execute | 60% do-nothing #
+PROBABILISTIC_CONFIG_40_PERCENTAGE_PROBABILITY: &GREEN_PROBABILISTIC_40
+ action_probabilities:
+ 0: 0.6
+ 1: 0.4
+
+# Probabilistic Green Agent | 60% node-application-execute | 40% do-nothing #
+PROBABILISTIC_CONFIG_60_PERCENTAGE_PROBABILITY: &GREEN_PROBABILISTIC_60
+ action_probabilities:
+ 0: 0.4
+ 1: 0.6
+
+
+# System Green Agent Config UC7 Network Wide Yaml Anchor #
+
+# Lists the IP_Address of all hosts that contain DNS and NTP Service Clients
+UC7_IP_LIST: &UC7_IP_LIST
+ # ====== Home Office ========
+ - 192.168.1.2 # HOME-PUB-PC-1 | ip_id: 2
+ - 192.168.1.3 # HOME-PUB-PC-2 | ip_id: 3
+ - 192.168.1.4 # HOME-PUB-PC-SRV | ip_id: 4
+ # ====== Remote Site ========
+ - 192.168.20.2 # REM-PUB-PC-1 | ip_id: 5
+ - 192.168.20.3 # REM-PUB-PC-2 | ip_id: 6
+ - 192.168.20.4 # REM-PUB-SRV | ip_id: 7
+ # ====== ST Public DMZ =======
+ - *ST_PUB_SRV_WEB_IP # 192.168.100.2 (ST_DMZ-PUB-SRV-WEB) | ip_id: 8
+ # ====== ST Head Office =======
+ - 192.168.200.2 # ST_HO-PRV-PC-1 | ip_id: 9
+ - 192.168.200.3 # ST_HO-PRV-PC-2 | ip_id: 10
+ - 192.168.200.4 # ST_HO-PRV-PC-3 | ip_id: 11
+ # ===== ST Human Resources ======
+ - 192.168.210.2 # ST_HR-PRV-PC-1 | ip_id: 12
+ - 192.168.210.3 # ST_HR-PRV-PC-2 | ip_id: 13
+ - 192.168.210.4 # ST_HR-PRV-PC-3 | ip_id: 14
+ # ====== ST DATA Servers =======
+ - *ST_SRV_STORAGE_IP # 192.168.220.2 (ST_DATA-PRV-SRV-STORAGE) | ip_id: 15
+ - *ST_SRV_DB_IP # 192.168.220.3 (ST_DATA-PRV-SRV-DB) | ip_id: 16
+ # ====== ST Project A =======
+ - 192.168.230.2 # PROJ-A-PRV-PC-1 | ip_id: 17
+ - 192.168.230.3 # PROJ-A-PRV-PC-2 | ip_id: 18
+ - 192.168.230.4 # PROJ-A-PRV-PC-3 | ip_id: 19
+ # ====== ST Project B =======
+ - 192.168.240.2 # PROJ-B-PRV-PC-1 | ip_id: 20
+ - 192.168.240.3 # PROJ-B-PRV-PC-2 | ip_id: 21
+ - 192.168.240.4 # PROJ-B-PRV-PC-3 | ip_id: 22
+ # ====== ST Project C =======
+ - 192.168.250.2 # PROJ-C-PRV-PC-1 | ip_id: 23
+ - 192.168.250.3 # PROJ-C-PRV-PC-2 | ip_id: 24
+ - 192.168.250.4 # PROJ-C-PRV-PC-3 | ip_id: 25
+
+############################################
+# Use Case 7 Agent Configuration Section #
+############################################
+
+agents:
+ #######################################################
+ # UC7 Green Agents Path of Life (POL) Configuration #
+ #######################################################
+
+
+ ####################################
+ # Home Office Network POL Config #
+ ####################################
+
+ # Home Office Green Agent Pattern Of Life
+ # ======================================
+ # 1. Three Home workers accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. Three Home workers accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: HOME_WORKER-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["HOME-PUB-PC-1"]
+ target_application: "database-client"
+ start_step: 4
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: HOME-PUB-PC-1
+
+ - ref: HOME_WORKER-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: HOME-PUB-PC-1
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: HOME-PUB-PC-1
+
+ - ref: HOME_WORKER-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["HOME-PUB-PC-2"]
+ target_application: "database-client"
+ start_step: 8
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: HOME-PUB-PC-2
+
+ - ref: HOME_WORKER-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: HOME-PUB-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: HOME-PUB-PC-2
+
+ ####################################
+ # Remote Site Network POL Config #
+ ####################################
+
+ # Remote Site Green Agent Pattern Of Life
+ # ======================================
+ # 1. Three Remote workers accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. Three Remote workers accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: REMOTE_WORKER-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["REM-PUB-PC-1"]
+ target_application: "database-client"
+ start_step: 12
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: REM-PUB-PC-1
+
+ - ref: REMOTE_WORKER-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: REM-PUB-PC-1
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: REM-PUB-PC-1
+
+ - ref: REMOTE_WORKER-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["REM-PUB-PC-2"]
+ target_application: "database-client"
+ start_step: 16
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: REM-PUB-PC-2
+
+ - ref: REMOTE_WORKER-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: REM-PUB-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: REM-PUB-PC-2
+
+ ####################################
+ # ST Project A Network POL Config #
+ ####################################
+
+ # ST Project A Green Agent Pattern Of Life
+ # ========================================
+ # 1. A Senior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. A Senior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 3. Two Junior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 4. Two Junior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+
+ - ref: PROJ_A-SENIOR-DEV-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-A-PRV-PC-1"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-1
+
+ - ref: PROJ_A-SENIOR-DEV-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_40
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-1
+
+ - ref: PROJ_A-JUNIOR-DEV-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-A-PRV-PC-2"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-2
+
+ - ref: PROJ_A-JUNIOR-DEV-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-A-PRV-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-2
+
+ - ref: PROJ_A-JUNIOR-DEV-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-A-PRV-PC-3"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-3
+
+ - ref: PROJ_A-JUNIOR-DEV-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-A-PRV-PC-3
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-3
+
+ ####################################
+ # ST Project B Network POL Config #
+ ####################################
+
+ # ST Project B Green Agent Pattern Of Life
+ # ========================================
+ # 1. A Senior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. A Senior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 3. Two Junior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 4. Two Junior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: PROJ_B-SENIOR-DEV-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-B-PRV-PC-1"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-1
+
+ - ref: PROJ_B-SENIOR-DEV-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-B-PRV-PC-1
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_40
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-1
+
+ - ref: PROJ_B-JUNIOR-DEV-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-B-PRV-PC-2"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-2
+
+ - ref: PROJ_B-JUNIOR-DEV-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-2
+
+ - ref: PROJ_B-JUNIOR-DEV-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-B-PRV-PC-3"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-3
+
+ - ref: PROJ_B-JUNIOR-DEV-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-B-PRV-PC-3
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-3
+
+ ####################################
+ # ST Project C Network POL Config #
+ ####################################
+
+ # ST Project C Green Agent Pattern Of Life
+ # ========================================
+ # 1. A Senior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. A Senior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 3. Two Junior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 4. Two Junior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: PROJ_C-SENIOR-DEV-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-C-PRV-PC-1"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-1
+
+ - ref: PROJ_C-SENIOR-DEV-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-C-PRV-PC-1
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_40
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-1
+
+ - ref: PROJ_C-JUNIOR-DEV-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-C-PRV-PC-2"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-2
+
+ - ref: PROJ_C-JUNIOR-DEV-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-C-PRV-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-2
+
+ - ref: PROJ_C-JUNIOR-DEV-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-C-PRV-PC-3"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-3
+
+ - ref: PROJ_C-JUNIOR-DEV-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-3
+
+ ######################################
+ # ST Head Office Network POL Config #
+ ######################################
+
+ # ST Head Office Green Agent Pattern Of Life
+ # ==========================================
+ # 1. The ST CEO accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 2. The ST CTO accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 3. The ST CFO accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: CEO
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HO-PRV-PC-1
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *HIGH_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HO-PRV-PC-1
+
+ - ref: CTO
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HO-PRV-PC-2
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HO-PRV-PC-2
+
+ - ref: CFO
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HO-PRV-PC-3
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HO-PRV-PC-3
+
+ ##########################################
+ # ST Human Resources Network POL Config #
+ ##########################################
+
+ # ST Head Office Green Agent Pattern Of Life
+ # ==========================================
+ # 1. A senior HR staff accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 2. Two junior HR staff accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: SENIOR_HR
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HR-PRV-PC-1
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HR-PRV-PC-1
+
+ - ref: JUNIOR_HR-1
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HR-PRV-PC-2
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HR-PRV-PC-2
+
+ - ref: JUNIOR_HR-2
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HR-PRV-PC-3
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HR-PRV-PC-3
+
+ ##########################
+ # UC7 Red Agent Config #
+ ##########################
+
+ - ref: attacker
+ team: RED
+ type: tap-003
+ observation_space: {}
+ action_space: {}
+ agent_settings:
+ start_step: 1
+ frequency: 3
+ variance: 0
+ repeat_kill_chain: false
+ repeat_kill_chain_stages: true
+ default_starting_node: "ST_PROJ-A-PRV-PC-1"
+ starting_nodes:
+ # starting_nodes: ["ST_PROJ-A-PRV-PC-1", "ST_PROJ-B-PRV-PC-2", "ST_PROJ-C-PRV-PC-3"]
+ kill_chain:
+ PLANNING:
+ probability: 1
+ starting_network_knowledge:
+ credentials:
+ ST_PROJ-A-PRV-PC-1:
+ username: admin
+ password: admin
+ ST_PROJ-B-PRV-PC-2:
+ username: admin
+ password: admin
+ ST_PROJ-C-PRV-PC-3:
+ username: admin
+ password: admin
+ ST_INTRA-PRV-RT-DR-1:
+ ip_address: 192.168.230.1
+ username: admin
+ password: admin
+ ST_INTRA-PRV-RT-CR:
+ ip_address: 192.168.160.1
+ username: admin
+ password: admin
+ REM-PUB-RT-DR:
+ ip_address: 192.168.10.2
+ username: admin
+ password: admin
+ ACCESS:
+ probability: 1
+ MANIPULATION:
+ probability: 1
+ account_changes:
+ - host: ST_INTRA-PRV-RT-DR-1
+ ip_address: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1
+ action: change_password
+ username: admin
+ new_password: "red_pass"
+ - host: ST_INTRA-PRV-RT-CR
+ ip_address: 192.168.160.1 # ST_INTRA-PRV-RT-CR
+ action: change_password
+ username: "admin"
+ new_password: "red_pass"
+ - host: REM-PUB-RT-DR
+ ip_address: 192.168.10.2 # REM-PUB-RT-DR
+ action: change_password
+ username: "admin"
+ new_password: "red_pass"
+ EXPLOIT:
+ probability: 1
+ malicious_acls:
+ - target_router: ST_INTRA-PRV-RT-DR-1
+ position: 1
+ permission: DENY
+ src_ip: ALL
+ src_wildcard: 0.0.255.255
+ dst_ip: ALL
+ dst_wildcard: 0.0.255.255
+ src_port: POSTGRES_SERVER
+ dst_port: POSTGRES_SERVER
+ protocol_name: TCP
+ - target_router: ST_INTRA-PRV-RT-CR
+ position: 1
+ permission: DENY
+ src_ip: ALL
+ src_wildcard: 0.0.255.255
+ dst_ip: ALL
+ dst_wildcard: 0.0.255.255
+ src_port: HTTP
+ dst_port: HTTP
+ protocol_name: TCP
+ - target_router: REM-PUB-RT-DR
+ position: 1
+ permission: DENY
+ src_ip: ALL
+ src_wildcard: 0.0.255.255
+ dst_ip: ALL
+ dst_wildcard: 0.0.255.255
+ src_port: DNS
+ dst_port: DNS
+ protocol_name: TCP
+
+###########################
+# UC7 Blue Agent Config #
+###########################
+
+ - ref: defender
+ team: BLUE
+ type: proxy-agent
+ observation_space:
+ type: custom
+ options:
+ components:
+ - type: nodes
+ label: NODES
+ options:
+ hosts:
+ # TAP001 Potential Starting Note | ST_PROJ-A-PRV-PC-1
+ - hostname: ST_PROJ-A-PRV-PC-1
+ services:
+ - service_name: ftp-client
+ applications:
+ - application_name: ransomware-script
+ - application_name: database-client
+ folders:
+ - folder_name: downloads
+ files:
+ - file_name: malware_dropper.ps1
+ - folder_name: exfiltration_folder
+ files:
+ - file_name: database.db
+ # TAP001 Potential Starting Note | ST_PROJ-B-PRV-PC-2
+ - hostname: ST_PROJ-B-PRV-PC-2
+ services:
+ - service_name: ftp-client
+ applications:
+ - application_name: ransomware-script
+ - application_name: database-client
+ folders:
+ - folder_name: downloads
+ files:
+ - file_name: malware_dropper.ps1
+ - folder_name: exfiltration_folder
+ files:
+ - file_name: database.db
+ # TAP001 Potential Starting Note | ST_PROJ-C-PRV-PC-3
+ - hostname: ST_PROJ-C-PRV-PC-3
+ services:
+ - service_name: ftp-client
+ applications:
+ - application_name: ransomware-script
+ - application_name: database-client
+ folders:
+ - folder_name: downloads
+ files:
+ - file_name: malware_dropper.ps1
+ - folder_name: exfiltration_folder
+ files:
+ - file_name: database.db
+ # ST DATA Server Database
+ - hostname: ST_DATA-PRV-SRV-DB
+ folders:
+ - folder_name: database
+ files:
+ - file_name: database.db
+ routers:
+ - hostname: ST_INTRA-PRV-RT-CR # TAP003 Malicious ACL Target | ROUTER0
+ - hostname: ST_INTRA-PRV-RT-DR-1 # TAP003 Malicious ACL Target | ROUTER1
+ - hostname: REM-PUB-RT-DR # TAP003 Malicious ACL Target | ROUTER2
+ num_ports: 5
+ num_services: 2
+ num_applications: 2
+ num_folders: 2
+ num_files: 1
+ num_nics: 1
+ ip_list:
+ # ip_list is indexed at 2:
+ # 0 reserved for padding to align with observations
+ # 1 reserved for ALL ips
+ *UC7_IP_LIST
+ wildcard_list:
+ - 0.0.0.1 # 0
+ - 0.0.0.255 # 1
+ - 0.0.255.255 # 2
+ port_list:
+ # 0 is a padding placeholder
+ # 1 means ALL ports
+ - FTP # 2
+ - DNS # 3
+ - HTTP # 4
+ - NTP # 5
+ - POSTGRES_SERVER # 6
+ - SSH # 7
+
+ protocol_list:
+ # 0 is padding placeholder
+ # 1 means ALL protocols
+ - ICMP # 2
+ - TCP # 3
+ - UDP # 4
+ num_rules: 5
+ include_num_access: true
+ include_nmne: true
+ monitored_traffic:
+ tcp:
+ - HTTP
+ - POSTGRES_SERVER
+ icmp:
+ - NONE
+ - type: links
+ label: LINKS
+ options:
+ link_references:
+ # HOME OFFICE SUBNET LINKS
+ - HOME-PUB-SW-AS:eth-1<->HOME-PUB-RT-DR:eth-1 # 1
+ - HOME-PUB-SW-AS:eth-1<->HOME-PUB-PC-1:eth-1 # 2
+ - HOME-PUB-SW-AS:eth-1<->HOME-PUB-PC-2:eth-1 # 3
+ - HOME-PUB-SW-AS:eth-1<->HOME-PUB-SRV:eth-1 # 4
+ # Internet LINKS
+ - ISP-PUB-RT-BR:eth-1<->HOME-PUB-RT-DR:eth-2 # 5
+ - ISP-PUB-RT-BR:eth-2<->ISP-PUB-SRV-DNS:eth-1 # 6
+ - ISP-PUB-RT-BR:eth-3<->REM-PUB-FW:eth-1 # 7
+ # Remote DMZ Links
+ - REM-PUB-FW:eth-2<->REM-PUB-RT-DR:eth-1 # 8
+ # Remote Site Links
+ - REM-PUB-RT-DR:eth-2<->REM-PUB-SW-AS:eth-1 # 9
+ - REM-PUB-SW-AS:eth-2<->REM-PUB-PC-1:eth-1 # 10
+ - REM-PUB-SW-AS:eth-3<->REM-PUB-PC-2:eth-1 # 11
+ - REM-PUB-SW-AS:eth-4<->REM-PUB-SRV:eth-1 # 12
+ # SOME_TECH DMZ
+ - ISP-PUB-RT-BR:eth-4<->ST_PUB-FW:eth-1 # 13
+ - ST_PUB-FW:eth-3<->ST_DMZ-PUB-SRV-WEB:eth-1 # 14
+ # SOME_TECH Intranet
+ - ST_INTRA-PRV-RT-CR:eth-1<->ST_PUB-FW:eth-2 # 15
+ - ST_INTRA-PRV-RT-CR:eth-2<->ST_INTRA-PRV-RT-DR-1:eth-1 # 16
+ - ST_INTRA-PRV-RT-CR:eth-3<->ST_INTRA-PRV-RT-DR-2:eth-1 # 17
+ - ST_INTRA-PRV-RT-CR:eth-4<->ST_DATA-PRV-SW-AS:eth-1 # 18
+ # SOME_TECH Head Office
+ - ST_HO-PRV-SW-AS:eth-1<->ST_INTRA-PRV-RT-DR-2:eth-2 # 19
+ - ST_HO-PRV-SW-AS:eth-2<->ST_HO-PRV-PC-1:eth-1 # 20
+ - ST_HO-PRV-SW-AS:eth-3<->ST_HO-PRV-PC-2:eth-1 # 21
+ - ST_HO-PRV-SW-AS:eth-4<->ST_HO-PRV-PC-3:eth-1 # 22
+ # SOME_TECH Human Resources
+ - ST_HR-PRV-SW-AS:eth-1<->ST_INTRA-PRV-RT-DR-2:eth-3 # 23
+ - ST_HR-PRV-SW-AS:eth-2<->ST_HR-PRV-PC-1:eth-1 # 24
+ - ST_HR-PRV-SW-AS:eth-3<->ST_HR-PRV-PC-2:eth-1 # 25
+ - ST_HR-PRV-SW-AS:eth-4<->ST_HR-PRV-PC-3:eth-1 # 26
+ # SOME_TECH Data Links
+ - ST_DATA-PRV-SW-AS:eth-2<->ST_DATA-PRV-SRV-STORAGE:eth-1 # 27
+ - ST_DATA-PRV-SW-AS:eth-3<->ST_DATA-PRV-SRV-DB:eth-1 # 28
+ # SOME_TECH Project A Links
+ - ST_INTRA-PRV-RT-DR-1:eth-2<->ST_PROJ-A-PRV-SW-AS:eth-1 # 29
+ - ST_PROJ-A-PRV-SW-AS:eth2<->ST_PROJ-A-PRV-PC-1:eth-1 # 31
+ - ST_PROJ-A-PRV-SW-AS:eth3<->ST_PROJ-A-PRV-PC-2:eth-1 # 32
+ - ST_PROJ-A-PRV-SW-AS:eth4<->ST_PROJ-A-PRV-PC-3:eth-1 # 33
+ # SOME_TECH Project B Links
+ - ST_INTRA-PRV-RT-DR-1:eth-3<->ST_PROJ-B-PRV-SW-AS:eth-1 # 34
+ - ST_PROJ-B-PRV-SW-AS:eth2<->ST_PROJ-B-PRV-PC-1:eth-1 # 35
+ - ST_PROJ-B-PRV-SW-AS:eth3<->ST_PROJ-B-PRV-PC-2:eth-1 # 36
+ - ST_PROJ-B-PRV-SW-AS:eth4<->ST_PROJ-B-PRV-PC-3:eth-1 # 37
+ # SOME_TECH Project C Links
+ - ST_INTRA-PRV-RT-DR-1:eth-4<->ST_PROJ-C-PRV-SW-AS:eth-1 # 38
+ - ST_PROJ-A-PRV-SW-AS:eth2<->ST_PROJ-C-PRV-PC-1:eth-1 # 39
+ - ST_PROJ-A-PRV-SW-AS:eth3<->ST_PROJ-C-PRV-PC-2:eth-1 # 40
+ - ST_PROJ-A-PRV-SW-AS:eth4<->ST_PROJ-C-PRV-PC-3:eth-1 # 41
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+
+ # |======================================|
+ # | ST_PROJ-A-PRV-PC-1 |
+ # |======================================|
+
+ # ST_PROJ-A-PRV-PC-1 | node-os-scan
+ 1:
+ action: node-os-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ # ST_PROJ-A-PRV-PC-1 | node-shutdown
+ 2:
+ action: node-shutdown
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ # ST_PROJ-A-PRV-PC-1 | node-startup
+ 3:
+ action: node-startup
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ # ST_PROJ-A-PRV-PC-1 | node-reset
+ 4:
+ action: node-reset
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ # ST_PROJ-A-PRV-PC-1 | host-nic-disable
+ 5:
+ action: host-nic-disable
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ nic_num: 0
+ # ST_PROJ-A-PRV-PC-1 | host-nic-enable
+ 6:
+ action: host-nic-enable
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ nic_num: 0
+ # ST_PROJ-A-PRV-PC-1 | node-application-close | database-client
+ 7:
+ action: node-application-close
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: database-client
+
+ # ST_PROJ-A-PRV-PC-1 | node-application-scan | database-client
+ 8:
+ action: node-application-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: database-client
+
+ # ST_PROJ-A-PRV-PC-1 | node-application-fix | database-client
+ 9:
+ action: node-application-fix
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: database-client
+
+ # ST_PROJ-A-PRV-PC-1 | node-application-remove | database-client
+ 10:
+ action: node-application-remove
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: database-client
+
+
+ # ST_PROJ-A-PRV-PC-1 | node-file-scan | downloads/malware_dropper.ps1
+ 11:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ folder_name: downloads
+ file_name: malware_dropper.ps1
+
+ # ST_PROJ-A-PRV-PC-1 | node-file-scan | exfiltration_folder/database.db
+ 12:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ folder_name: exfiltration_folder
+ file_name: database.db
+
+ # ST_PROJ-A-PRV-PC-1 | node-folder-scan | downloads/
+ 13:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ folder_name: downloads
+
+ # ST_PROJ-A-PRV-PC-1 | node-folder-scan | exfiltration_folder/
+ 14:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ folder_name: exfiltration_folder
+
+ # |======================================|
+ # | ST_PROJ-B-PRV-PC-2 |
+ # |======================================|
+
+ # ST_PROJ-B-PRV-PC-2 | node-os-scan
+ 15:
+ action: node-os-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+
+ # ST_PROJ-B-PRV-PC-2 | node-shutdown
+ 16:
+ action: node-shutdown
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+
+ # ST_PROJ-B-PRV-PC-2 | node-startup
+ 17:
+ action: node-startup
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+
+ # ST_PROJ-B-PRV-PC-2 | node-reset
+ 18:
+ action: node-reset
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+
+ # ST_PROJ-B-PRV-PC-2 | host-nic-disable
+ 19:
+ action: host-nic-disable
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ nic_num: 0
+
+ # ST_PROJ-B-PRV-PC-2 | host-nic-enable
+ 20:
+ action: host-nic-enable
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ nic_num: 0
+
+ # ST_PROJ-B-PRV-PC-2 | node-application-close | database-client
+ 21:
+ action: node-application-close
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: database-client
+
+ # ST_PROJ-B-PRV-PC-2 | node-application-scan | database-client
+ 22:
+ action: node-application-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: database-client
+
+ # ST_PROJ-B-PRV-PC-2 | node-application-fix | database-client
+ 23:
+ action: node-application-fix
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: database-client
+
+ # ST_PROJ-B-PRV-PC-2 | node-application-remove | database-client
+ 24:
+ action: node-application-remove
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: database-client
+
+ # ST_PROJ-B-PRV-PC-2 | node-file-scan | downloads/malware_dropper.ps1
+ 25:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ folder_name: downloads
+ file_name: malware_dropper.ps1
+
+ # ST_PROJ-B-PRV-PC-2 | node-file-scan | exfiltration_folder/database.db
+ 26:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ folder_name: exfiltration_folder
+ file_name: database.db
+
+ # ST_PROJ-B-PRV-PC-2 | node-folder-scan | downloads/
+ 27:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ folder_name: downloads
+
+ # ST_PROJ-B-PRV-PC-2 | node-folder-scan | exfiltration_folder/
+ 28:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ folder_name: exfiltration_folder
+
+ # |======================================|
+ # | ST_PROJ-C-PRV-PC-3 |
+ # |======================================|
+
+ # ST_PROJ-C-PRV-PC-3 | node-os-scan
+ 29:
+ action: node-os-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+
+ # ST_PROJ-C-PRV-PC-3 | node-shutdown
+ 30:
+ action: node-shutdown
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+
+ # ST_PROJ-C-PRV-PC-3 | node-startup
+ 31:
+ action: node-startup
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+
+ # ST_PROJ-C-PRV-PC-3 | node-reset
+ 32:
+ action: node-reset
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+
+ # ST_PROJ-C-PRV-PC-3 | host-nic-disable
+ 33:
+ action: host-nic-disable
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ nic_num: 0
+
+ # ST_PROJ-C-PRV-PC-3 | host-nic-enable
+ 34:
+ action: host-nic-enable
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ nic_num: 0
+
+ # ST_PROJ-C-PRV-PC-3 | node-application-close | database-client
+ 35:
+ action: node-application-close
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: database-client
+
+ # ST_PROJ-C-PRV-PC-3 | node-application-scan | database-client
+ 36:
+ action: node-application-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: database-client
+
+ # ST_PROJ-C-PRV-PC-3 | node-application-fix | database-client
+ 37:
+ action: node-application-fix
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: database-client
+
+ # ST_PROJ-C-PRV-PC-3 | node-application-remove | database-client
+ 38:
+ action: node-application-remove
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: database-client
+
+ # ST_PROJ-C-PRV-PC-3 | node-file-scan | downloads/malware_dropper.ps1
+ 39:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ folder_name: downloads
+ file_name: malware_dropper.ps1
+
+ # ST_PROJ-C-PRV-PC-3 | node-file-scan | exfiltration_folder/database.db
+ 40:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ folder_name: exfiltration_folder
+ file_name: database.db
+
+ # ST_PROJ-C-PRV-PC-3 | node-folder-scan | downloads/
+ 41:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ folder_name: downloads
+
+ # ST_PROJ-C-PRV-PC-3 | node-folder-scan | exfiltration_folder/
+ 42:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ folder_name: exfiltration_folder
+
+ # |======================================|
+ # | ST_INTRA-PRV-RT-CR |
+ # |======================================|
+
+ # ST_INTRA-PRV-RT-CR | router-acl-addrule | P2: ST_PROJ-A-PRV-PC-1 !==> ST_DATA-PRV-SRV-DB (TCP:POSTGRES_SERVER)
+ 43:
+ action: router-acl-addrule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 1
+ permission: DENY
+ src_ip: 192.168.230.2 # (ST_PROJ-A-PRV-PC-1)
+ src_wildcard: 0.0.255.255
+ src_port: POSTGRES_SERVER
+ dst_ip: 192.168.220.3 # (ST_DATA-PRV-SRV-DB)
+ dst_wildcard: 0.0.255.255
+ dst_port: POSTGRES_SERVER
+ protocol_name: TCP
+
+ # ST_INTRA-PRV-RT-CR | REMOVE_ACL_ADDRULE | Removes a given ACL at position 1
+ 44:
+ action: router-acl-remove-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 1
+
+ # ST_INTRA-PRV-RT-CR | router-acl-addrule | P3: ST_PROJ-B-PRV-PC-2 !==> ST_DATA-PRV-SRV-DB (TCP:POSTGRES_SERVER)
+ 45:
+ action: router-acl-addrule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 2
+ permission: DENY
+ src_ip: 192.168.240.3 # (ST_PROJ-B-PRV-PC-2)
+ src_wildcard: 0.0.255.255
+ src_port: POSTGRES_SERVER
+ dst_ip: 192.168.220.3 # (ST_DATA-PRV-SRV-DB)
+ dst_wildcard: 0.0.255.255
+ dst_port: POSTGRES_SERVER
+ protocol_name: TCP
+ # ST_INTRA-PRV-RT-CR | REMOVE_ACL_ADDRULE | Removes a given ACL at position 2
+ 46:
+ action: router-acl-remove-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 2
+
+ # ST_INTRA-PRV-RT-CR | router-acl-addrule | P4: ST_PROJ-C-PRV-PC-3 !==> ST_DATA-PRV-SRV-DB (TCP:POSTGRES_SERVER)
+ 47:
+ action: router-acl-addrule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 3
+ permission: DENY
+ src_ip: 192.168.250.4 # (ST_PROJ-C-PRV-PC-3)
+ src_wildcard: 0.0.255.255
+ src_port: POSTGRES_SERVER
+ dst_ip: 192.168.220.3 # (ST_DATA-PRV-SRV-DB)
+ dst_wildcard: 0.0.255.255
+ dst_port: POSTGRES_SERVER
+ protocol_name: TCP
+
+ # ST_INTRA-PRV-RT-CR | REMOVE_ACL_ADDRULE | Removes a given ACL at position 3
+ 48:
+ action: router-acl-remove-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 3
+
+ # |======================================|
+ # | ST_DATA-PRV-SRV-DB |
+ # |======================================|
+
+ # ST_DATA-PRV-SRV-DB | node-file-scan | Scans the database.db file (health status)
+ 49:
+ action: node-file-scan
+ options:
+ node_name: ST_DATA-PRV-SRV-DB
+ folder_name: database
+ file_name: database.db
+
+ # ST_DATA-PRV-SRV-DB | node-account-change-password | Changes the password of a user account
+ 50:
+ action: node-account-change-password
+ options:
+ node_name: ST_DATA-PRV-SRV-DB
+ username: admin # default account
+ current_password: admin # default password
+ new_password: thr33_alert_wolv3z # A more 'secure' password
+
+ # |======================================|
+ # | ST_INTRA-PRV-RT-DR-1 |
+ # |======================================|
+
+ # ST_INTRA-PRV-RT-DR-1 | router-acl-addrule | P1: ST_INTRA-PRV-RT-DR-1 !==> ANY (TCP:SSH)
+ 51:
+ action: router-acl-addrule
+ options:
+ target_router: ST_INTRA-PRV-RT-DR-1
+ position: 1
+ permission: DENY
+ src_ip: 192.168.230.2 # (ST_PROJ-A-PRV-PC-1)
+ src_wildcard: 0.0.255.255
+ src_port: SSH
+ dst_ip: ALL
+ dst_wildcard: 0.0.255.255
+ dst_port: SSH
+ protocol_name: TCP
+
+ # ST_INTRA-PRV-RT-DR-1 | node-account-change-password
+ 52:
+ action: node-account-change-password
+ options:
+ node_name: ST_INTRA-PRV-RT-DR-1
+ username: admin
+ current_password: admin
+ new_password: secure_password
+
+ # ST_INTRA-PRV-RT-DR-1 | router-acl-remove-rule | Removes the given ACL at position 1
+ 53:
+ action: router-acl-remove-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-DR-1
+ position: 1
+
+ # |======================================|
+ # | REM-PUB-RT-DR |
+ # |======================================|
+
+ # REM-PUB-RT-DR | node-account-change-password
+ 54:
+ action: node-account-change-password
+ options:
+ node_name: REM-PUB-RT-DR
+ username: admin
+ current_password: admin
+ new_password: secure_password
+
+ # REM-PUB-RT-DR | router-acl-remove-rule | Removes the given ACL at position 1
+ 55:
+ action: router-acl-remove-rule
+ options:
+ target_router: REM-PUB-RT-DR
+ position: 1
+
+ reward_function:
+ reward_components:
+ - type: database-file-integrity
+ weight: *HIGH_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_DATA-PRV-SRV-DB
+ folder_name: database
+ file_name: database.db
+
+ # Home Site Green Agents (32 Green Agents each contributing 0.03125 of blue reward)
+
+ # Blue Shared Reward | HOME_WORKER-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: HOME_WORKER-1-DB
+
+ # Blue Shared Reward | HOME_WORKER-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: HOME_WORKER-1-WEB
+
+ # Blue Shared Reward | HOME_WORKER-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: HOME_WORKER-2-DB
+
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: HOME_WORKER-2-WEB
+
+ # Remote Site Green Agents
+
+ # Blue Shared Reward | REMOTE_WORKER-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: REMOTE_WORKER-1-DB
+
+ # Blue Shared Reward | REMOTE_WORKER-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: REMOTE_WORKER-1-WEB
+
+ # Blue Shared Reward | REMOTE_WORKER-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: REMOTE_WORKER-2-DB
+
+ # Blue Shared Reward | REMOTE_WORKER-2-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: REMOTE_WORKER-2-WEB
+
+ # ST Project A Green Agents
+
+ # Blue Shared Reward | PROJ_A-SENIOR-DEV-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-SENIOR-DEV-DB
+
+ # Blue Shared Reward | PROJ_A-SENIOR-DEV-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-SENIOR-DEV-WEB
+
+ # Blue Shared Reward | PROJ_A-JUNIOR-DEV-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-JUNIOR-DEV-1-DB
+
+ # Blue Shared Reward | PROJ_A-JUNIOR-DEV-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-JUNIOR-DEV-1-WEB
+
+ # Blue Shared Reward | PROJ_A-JUNIOR-DEV-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-JUNIOR-DEV-2-DB
+
+ # Blue Shared Reward | PROJ_A-JUNIOR-DEV-2-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-JUNIOR-DEV-2-WEB
+
+ # ST Project B Green Agents
+
+ # Blue Shared Reward | PROJ_B-SENIOR-DEV-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-SENIOR-DEV-DB
+
+ # Blue Shared Reward | PROJ_B-SENIOR-DEV-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-SENIOR-DEV-WEB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-1-DB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-1-WEB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-2-DB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-2-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-2-WEB
+
+ # ST Project C Green Agents
+
+ # Blue Shared Reward | PROJ_B-SENIOR-DEV-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-SENIOR-DEV-DB
+
+ # Blue Shared Reward | PROJ_B-SENIOR-DEV-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-SENIOR-DEV-WEB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-1-DB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-1-WEB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-2-DB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-2-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-2-WEB
+
+ # ST Head Office Green Agents (CEO/CFO/CTO)
+
+ # Blue Shared Reward | CEO
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: CEO
+
+ # Blue Shared Reward | CFO
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: CFO
+
+ # Blue Shared Reward | CTO
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: CTO
+
+ # ST Human Resources Green Agents
+
+ # Blue Shared Reward | SENIOR_HR
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: SENIOR_HR
+
+ # Blue Shared Reward | SENIOR_HR
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: JUNIOR_HR-1
+
+ # Blue Shared Reward | SENIOR_HR
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: JUNIOR_HR-2
+
+ agent_settings:
+ flatten_obs: True
diff --git a/src/primaite/config/_package_data/uc7_multiple_attack_variants/TAP001_PC1.yaml b/src/primaite/config/_package_data/uc7_multiple_attack_variants/TAP001_PC1.yaml
new file mode 100644
index 00000000..721cec6e
--- /dev/null
+++ b/src/primaite/config/_package_data/uc7_multiple_attack_variants/TAP001_PC1.yaml
@@ -0,0 +1,40 @@
+red: &red
+ - ref: attacker
+ team: RED
+ type: tap-001
+ agent_settings:
+ start_step: 1
+ frequency: 5
+ variance: 0
+ repeat_kill_chain: false
+ repeat_kill_chain_stages: true
+ default_target_ip: 192.168.220.3
+ default_starting_node: "ST_PROJ-C-PRV-PC-1"
+ starting_nodes:
+ kill_chain:
+ ACTIVATE:
+ probability: 1
+ PROPAGATE:
+ probability: 1
+ scan_attempts: 20
+ repeat_scan: false
+ network_addresses:
+ - 192.168.230.0/29 # ST Project A
+ - 192.168.10.0/26 # Remote Site
+ - 192.168.20.0/30 # Remote DMZ
+ - 192.168.220.0/29 # ST Data (Contains Target)
+ COMMAND_AND_CONTROL:
+ probability: 1
+ keep_alive_frequency: 5
+ masquerade_port: HTTP
+ masquerade_protocol: TCP
+ c2_server_name: ISP-PUB-SRV-DNS
+ c2_server_ip: 8.8.8.8
+ PAYLOAD:
+ probability: 1
+ exfiltrate: true
+ corrupt: true
+ exfiltration_folder_name:
+ target_username: admin
+ target_password: admin
+ continue_on_failed_exfil: True
diff --git a/src/primaite/config/_package_data/uc7_multiple_attack_variants/TAP001_PC2.yaml b/src/primaite/config/_package_data/uc7_multiple_attack_variants/TAP001_PC2.yaml
new file mode 100644
index 00000000..382a2d40
--- /dev/null
+++ b/src/primaite/config/_package_data/uc7_multiple_attack_variants/TAP001_PC2.yaml
@@ -0,0 +1,40 @@
+red: &red
+ - ref: attacker
+ team: RED
+ type: tap-001
+ agent_settings:
+ start_step: 1
+ frequency: 5
+ variance: 0
+ repeat_kill_chain: false
+ repeat_kill_chain_stages: true
+ default_target_ip: 192.168.220.3
+ default_starting_node: "ST_PROJ-B-PRV-PC-2"
+ starting_nodes:
+ kill_chain:
+ ACTIVATE:
+ probability: 1
+ PROPAGATE:
+ probability: 1
+ scan_attempts: 20
+ repeat_scan: false
+ network_addresses:
+ - 192.168.240.0/29 # ST Project B
+ - 192.168.10.0/26 # Remote Site
+ - 192.168.20.0/30 # Remote DMZ
+ - 192.168.220.0/29 # ST Data (Contains Target)
+ COMMAND_AND_CONTROL:
+ probability: 1
+ keep_alive_frequency: 5
+ masquerade_port: HTTP
+ masquerade_protocol: TCP
+ c2_server_name: ISP-PUB-SRV-DNS
+ c2_server_ip: 8.8.8.8
+ PAYLOAD:
+ probability: 1
+ exfiltrate: true
+ corrupt: true
+ exfiltration_folder_name:
+ target_username: admin
+ target_password: admin
+ continue_on_failed_exfil: True
diff --git a/src/primaite/config/_package_data/uc7_multiple_attack_variants/TAP001_PC3.yaml b/src/primaite/config/_package_data/uc7_multiple_attack_variants/TAP001_PC3.yaml
new file mode 100644
index 00000000..ad418b32
--- /dev/null
+++ b/src/primaite/config/_package_data/uc7_multiple_attack_variants/TAP001_PC3.yaml
@@ -0,0 +1,40 @@
+red: &red
+ - ref: attacker
+ team: RED
+ type: tap-001
+ agent_settings:
+ start_step: 1
+ frequency: 5
+ variance: 0
+ repeat_kill_chain: false
+ repeat_kill_chain_stages: true
+ default_target_ip: 192.168.220.3
+ default_starting_node: "ST_PROJ-C-PRV-PC-3"
+ starting_nodes:
+ kill_chain:
+ ACTIVATE:
+ probability: 1
+ PROPAGATE:
+ probability: 1
+ scan_attempts: 20
+ repeat_scan: false
+ network_addresses:
+ - 192.168.250.0/29 # ST Project C
+ - 192.168.10.0/26 # Remote Site
+ - 192.168.20.0/30 # Remote DMZ
+ - 192.168.220.0/29 # ST Data (Contains Target)
+ COMMAND_AND_CONTROL:
+ probability: 1
+ keep_alive_frequency: 5
+ masquerade_port: HTTP
+ masquerade_protocol: TCP
+ c2_server_name: ISP-PUB-SRV-DNS
+ c2_server_ip: 8.8.8.8
+ PAYLOAD:
+ probability: 1
+ exfiltrate: true
+ corrupt: true
+ exfiltration_folder_name:
+ target_username: admin
+ target_password: admin
+ continue_on_failed_exfil: True
diff --git a/src/primaite/config/_package_data/uc7_multiple_attack_variants/TAP003.yaml b/src/primaite/config/_package_data/uc7_multiple_attack_variants/TAP003.yaml
new file mode 100644
index 00000000..aae7e9b4
--- /dev/null
+++ b/src/primaite/config/_package_data/uc7_multiple_attack_variants/TAP003.yaml
@@ -0,0 +1,94 @@
+red: &red
+ - ref: attacker
+ team: RED
+ type: tap-003
+ observation_space: {}
+ action_space: {}
+ agent_settings:
+ start_step: 1
+ frequency: 3
+ variance: 0
+ repeat_kill_chain: false
+ repeat_kill_chain_stages: true
+ default_starting_node: "ST_PROJ-A-PRV-PC-1"
+ starting_nodes:
+ # starting_nodes: ["ST_PROJ-A-PRV-PC-1", "ST_PROJ-B-PRV-PC-2", "ST_PROJ-C-PRV-PC-3"]
+ kill_chain:
+ PLANNING:
+ probability: 1
+ starting_network_knowledge:
+ credentials:
+ ST_PROJ-A-PRV-PC-1:
+ username: admin
+ password: admin
+ ST_PROJ-B-PRV-PC-2:
+ username: admin
+ password: admin
+ ST_PROJ-C-PRV-PC-3:
+ username: admin
+ password: admin
+ ST_INTRA-PRV-RT-DR-1:
+ ip_address: 192.168.230.1
+ username: admin
+ password: admin
+ ST_INTRA-PRV-RT-CR:
+ ip_address: 192.168.160.1
+ username: admin
+ password: admin
+ REM-PUB-RT-DR:
+ ip_address: 192.168.10.2
+ username: admin
+ password: admin
+ ACCESS:
+ probability: 1
+ MANIPULATION:
+ probability: 1
+ account_changes:
+ - host: ST_INTRA-PRV-RT-DR-1
+ ip_address: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1
+ action: change_password
+ username: admin
+ new_password: "red_pass"
+ - host: ST_INTRA-PRV-RT-CR
+ ip_address: 192.168.160.1 # ST_INTRA-PRV-RT-CR
+ action: change_password
+ username: "admin"
+ new_password: "red_pass"
+ - host: REM-PUB-RT-DR
+ ip_address: 192.168.10.2 # REM-PUB-RT-DR
+ action: change_password
+ username: "admin"
+ new_password: "red_pass"
+ EXPLOIT:
+ probability: 1
+ malicious_acls:
+ - target_router: ST_INTRA-PRV-RT-DR-1
+ position: 1
+ permission: DENY
+ src_ip: ALL
+ src_wildcard: 0.0.255.255
+ dst_ip: ALL
+ dst_wildcard: 0.0.255.255
+ src_port: POSTGRES_SERVER
+ dst_port: POSTGRES_SERVER
+ protocol_name: TCP
+ - target_router: ST_INTRA-PRV-RT-CR
+ position: 1
+ permission: DENY
+ src_ip: ALL
+ src_wildcard: 0.0.255.255
+ dst_ip: ALL
+ dst_wildcard: 0.0.255.255
+ src_port: HTTP
+ dst_port: HTTP
+ protocol_name: TCP
+ - target_router: REM-PUB-RT-DR
+ position: 1
+ permission: DENY
+ src_ip: ALL
+ src_wildcard: 0.0.255.255
+ dst_ip: ALL
+ dst_wildcard: 0.0.255.255
+ src_port: DNS
+ dst_port: DNS
+ protocol_name: TCP
diff --git a/src/primaite/config/_package_data/uc7_multiple_attack_variants/schedule.yaml b/src/primaite/config/_package_data/uc7_multiple_attack_variants/schedule.yaml
new file mode 100644
index 00000000..e11c2fbf
--- /dev/null
+++ b/src/primaite/config/_package_data/uc7_multiple_attack_variants/schedule.yaml
@@ -0,0 +1,42 @@
+base_scenario: uc7_config_no_red.yaml
+schedule:
+ 0:
+ - TAP001_PC1.yaml
+ 1:
+ - TAP001_PC2.yaml
+ 2:
+ - TAP001_PC3.yaml
+ 3:
+ - TAP001_PC1.yaml
+ 4:
+ - TAP001_PC2.yaml
+ 5:
+ - TAP003.yaml
+ 6:
+ - TAP003.yaml
+ 7:
+ - TAP003.yaml
+ 8:
+ - TAP003.yaml
+ 9:
+ - TAP003.yaml
+ 10:
+ - TAP001_PC1.yaml
+ 11:
+ - TAP003.yaml
+ 12:
+ - TAP001_PC1.yaml
+ 13:
+ - TAP003.yaml
+ 14:
+ - TAP001_PC2.yaml
+ 15:
+ - TAP003.yaml
+ 16:
+ - TAP001_PC3.yaml
+ 17:
+ - TAP003.yaml
+ 18:
+ - TAP001_PC1.yaml
+ 19:
+ - TAP003.yaml
diff --git a/src/primaite/config/_package_data/uc7_multiple_attack_variants/uc7_config_no_red.yaml b/src/primaite/config/_package_data/uc7_multiple_attack_variants/uc7_config_no_red.yaml
new file mode 100644
index 00000000..4a49175b
--- /dev/null
+++ b/src/primaite/config/_package_data/uc7_multiple_attack_variants/uc7_config_no_red.yaml
@@ -0,0 +1,2635 @@
+##########################################################
+# USE CASE 7 CONFIGURATION YAML FILE #
+##########################################################
+
+
+##########################################
+# PrimAITE Game and Logging Settings #
+##########################################
+
+
+# PrimAITE I/O Settings #
+
+io_settings:
+ save_agent_actions: True
+ save_step_metadata: True
+ save_pcap_logs: false
+ save_sys_logs: True
+ # save_sys_logs: true
+ write_sys_log_to_terminal: false
+
+
+# PrimAITE Game Settings #
+
+game:
+ max_episode_length: 128
+ ports:
+ - FTP
+ - DNS
+ - HTTP
+ - NTP
+ - POSTGRES_SERVER
+ - SSH
+ protocols:
+ - ICMP
+ - TCP
+ - UDP
+ thresholds:
+ nmne:
+ high: 10
+ medium: 5
+ low: 0
+
+############################################
+# PrimAITE Use Case 7 Simulation #
+############################################
+
+##########################################
+# Configuration Variables (Yaml Anchors) #
+##########################################
+
+# External Network Address List #
+
+DNS_SUBNET: &DNS_SUBNET 255.255.255.240 # | 8.8.8.0 / 28
+HOME_INTERNET_SUBNET: &HOME_INTERNET_SUBNET 255.255.255.252 # | 10.1.0.0 / 30
+REMOTE_INTERNET_SUBNET: &REMOTE_INTERNET_SUBNET 255.255.255.252 # | 10.1.10.0 / 30
+SOME_TECH_INTERNET_SUBNET: &ST_INTERNET_SUBNET 255.255.255.252 # | 10.1.100.0 / 30
+HOME_OFFICE_SUBNET: &HOME_SUBNET 255.255.255.0 # | 192.168.1.0 / 26
+REMOTE_SUBNET_DMZ: &REMOTE_SUBNET_DMZ 255.255.255.252 # | 192.168.10.0 / 30
+REMOTE_SUBNET: &REMOTE_SUBNET 255.255.255.240 # | 192.168.20.0 / 28
+
+# SOME_TECH (ST) Network Address List #
+
+SOME_TECH_DMZ_SUBNET: &ST_DMZ_SUBNET 255.255.255.252 # | 192.168.100.0 / 30
+SOME_TECH_INTRANET_RT_CR_SUBNET: &ST_INTRA_CR_SUBNET 255.255.255.240 # | 192.168.150.0 / 28
+SOME_TECH_INTRANET_RT_DR_ONE_SUBNET: &ST_INTRA_DR_ONE_SUBNET 255.255.255.252 # | 192.168.160.0 / 30
+SOME_TECH_INTRANET_RT_DR_TWO_SUBNET: &ST_INTRA_DR_TWO_SUBNET 255.255.255.252 # | 192.168.170.0 / 30
+SOME_TECH_HEAD_OFFICE_SUBNET: &ST_HO_SUBNET 255.255.255.248 # | 192.168.200.0 / 29
+SOME_TECH_HUMAN_RESOURCES_SUBNET: &ST_HR_SUBNET 255.255.255.248 # | 192.168.210.0 / 29
+SOME_TECH_DATA_SUBNET: &ST_DATA_SUBNET 255.255.255.248 # | 192.168.220.0 / 29
+SOME_TECH_PROJECT_A_SUBNET: &ST_PROJ_A_SUBNET 255.255.255.248 # | 192.168.230.0 / 29
+SOME_TECH_PROJECT_B_SUBNET: &ST_PROJ_B_SUBNET 255.255.255.248 # | 192.168.240.0 / 29
+SOME_TECH_PROJECT_C_SUBNET: &ST_PROJ_C_SUBNET 255.255.255.248 # | 192.168.250.0 / 29
+
+# Host & Server Configurations #
+
+# ST Public Web Server | web-server | ST_DMZ-PUB-SRV-WEB
+SOME_TECH_PUBLIC_SERVER_WEB_IP_ADDRESS: &ST_PUB_SRV_WEB_IP 192.168.100.2
+SOME_TECH_PUBLIC_SERVER_WEB_CONFIG: &ST_SRV_WEB_CONFIG #
+ - type: web-server
+
+# ISP Public DNS | dns-server | ISP-PUB-SRV-DNS
+PUBLIC_DNS_IP_ADDRESS: &PUBLIC_DNS_IP 8.8.8.8
+PUBLIC_DNS_CONFIG: &PUBLIC_DNS_CONFIG #
+ - type: dns-server
+ options:
+ domain_mapping:
+ some_tech.com: *ST_PUB_SRV_WEB_IP
+
+# ST Private Storage Server | ftp-server | ST_DATA-PRV-SRV-STORAGE
+SOME_TECH_PRIVATE_SERVER_STORAGE_IP: &ST_SRV_STORAGE_IP 192.168.220.2
+SOME_TECH_PRIVATE_SERVER_STORAGE_CONFIG: &ST_SRV_STORAGE_CONFIG
+ - type: ftp-server
+
+# ST Private Database Server | database-client & ftp-client | ST_DATA-PRV-SRV-DB
+SOME_TECH_PRIVATE_SERVER_DATABASE_IP: &ST_SRV_DB_IP 192.168.220.3
+SOME_TECH_PRIVATE_SERVER_DATABASE_CONFIG: &ST_SRV_DB_CONFIG
+ - type: database-service
+ options:
+ backup_server_ip: *ST_SRV_STORAGE_IP
+ - type: ftp-client
+
+# Default PC Configuration | Database Client & Web Server
+PERSONAL_COMPUTER_DEFAULT_CONFIG: &PC_DEFAULT_CONFIG
+ - type: database-client
+ options:
+ db_server_ip: *ST_SRV_DB_IP
+ - type: web-browser
+ options:
+ target_url: http://some_tech.com
+
+
+##############################
+# Simulation Configuration #
+##############################
+
+simulation:
+ defaults:
+ folder_scan_duration: 0
+ folder_restore_duration: 3
+ service_fix_duration: 2
+ service_restart_duration: 2
+ software_install_duration: 0
+ node_start_up_duration: 3
+ node_shut_down_duration: 3
+ node_scan_duration: 8
+ network:
+ nmne_config:
+ capture_nmne: true
+ nmne_capture_keywords:
+ - DELETE
+ - ENCRYPT
+ nodes:
+ ######################
+ # HOME OFFICE SUBNET #
+ ######################
+ - hostname: HOME-PUB-RT-DR
+ type: router
+ default_gateway: 10.1.0.1
+ ports:
+ 1:
+ ip_address: 192.168.1.1
+ subnet_mask: *HOME_SUBNET
+ 2:
+ ip_address: 10.1.0.2
+ subnet_mask: *HOME_INTERNET_SUBNET
+ default_route:
+ next_hop_ip_address: 10.1.0.1
+ acl:
+ 5:
+ action: PERMIT
+
+ - hostname: HOME-PUB-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: HOME-PUB-PC-1
+ type: computer
+ ip_address: 192.168.1.2
+ default_gateway: 192.168.1.1
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: HOME-PUB-PC-2
+ type: computer
+ ip_address: 192.168.1.3
+ default_gateway: 192.168.1.1
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: HOME-PUB-SRV
+ type: server
+ ip_address: 192.168.1.4
+ default_gateway: 192.168.1.1
+ dns_server: *PUBLIC_DNS_IP
+
+ ######################
+ # INTERNET SUBNET #
+ ######################
+ - hostname: ISP-PUB-RT-BR
+ type: router
+ ports:
+ 1:
+ ip_address: 10.1.0.1
+ subnet_mask: *HOME_INTERNET_SUBNET
+ 2:
+ ip_address: 8.8.8.1
+ subnet_mask: *DNS_SUBNET
+ 3:
+ ip_address: 10.1.10.1
+ subnet_mask: *REMOTE_INTERNET_SUBNET
+ 4:
+ ip_address: 10.1.100.1
+ subnet_mask: *ST_INTERNET_SUBNET
+ routes:
+ - address: 192.168.1.0
+ subnet_mask: *HOME_SUBNET
+ next_hop_ip_address: 10.1.0.2
+
+ - address: 8.8.8.0
+ subnet_mask: *DNS_SUBNET
+ next_hop_ip_address: 8.8.8.8
+
+ - address: 192.168.10.0
+ subnet_mask: *REMOTE_SUBNET_DMZ
+ next_hop_ip_address: 10.1.10.2
+
+ - address: 192.168.20.0
+ subnet_mask: *REMOTE_SUBNET
+ next_hop_ip_address: 10.1.10.2
+
+ default_route:
+ next_hop_ip_address: 10.1.100.2 # SOME_TECH Firewall
+
+ acl:
+ 5:
+ action: PERMIT
+
+ ################
+ # DNS SUBNET #
+ ################
+ - hostname: ISP-PUB-SRV-DNS
+ type: server
+ ip_address: 8.8.8.8
+ subnet_mask: *DNS_SUBNET
+ default_gateway: 8.8.8.1
+ services:
+ *PUBLIC_DNS_CONFIG
+ applications:
+ - type: c2-server # Represents the external internet.
+ options:
+ listen_on_ports:
+ - 80
+ - 53
+ - 21
+ ########################
+ # REMOTE SITE SUBNET #
+ ########################
+ - hostname: REM-PUB-FW
+ type: firewall
+ ports:
+ external_port: # Public Internet facing
+ ip_address: 10.1.10.2
+ subnet_mask: *REMOTE_INTERNET_SUBNET
+ internal_port: # Remote Site (DMZ Subnet) facing
+ ip_address: 192.168.10.1
+ subnet_mask: *REMOTE_SUBNET_DMZ
+ routes:
+ - address: 192.168.20.0 # Remote Site Network
+ subnet_mask: *REMOTE_SUBNET
+ next_hop_ip_address: 192.168.10.2
+ default_route:
+ next_hop_ip_address: 10.1.10.1 # Forward to internet router port 3
+ acl:
+ internal_inbound_acl:
+ 1:
+ action: PERMIT
+ internal_outbound_acl:
+ 1:
+ action: PERMIT
+ dmz_inbound_acl:
+ 1:
+ action: PERMIT
+ dmz_outbound_acl:
+ 1:
+ action: PERMIT
+ external_inbound_acl:
+ 1:
+ action: PERMIT
+ external_outbound_acl:
+ 1:
+ action: PERMIT
+
+ - hostname: REM-PUB-RT-DR
+ type: router
+ default_gateway: 192.168.10.1
+ ports:
+ 1:
+ ip_address: 192.168.10.2
+ subnet_mask: *REMOTE_SUBNET_DMZ
+ 2:
+ ip_address: 192.168.20.1
+ subnet_mask: *REMOTE_SUBNET
+ default_route:
+ next_hop_ip_address: 192.168.10.1
+ acl:
+ 5:
+ action: PERMIT
+
+ - hostname: REM-PUB-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: REM-PUB-PC-1
+ type: computer
+ ip_address: 192.168.20.2
+ default_gateway: 192.168.20.1
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: REM-PUB-PC-2
+ type: computer
+ ip_address: 192.168.20.3
+ default_gateway: 192.168.20.1
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: REM-PUB-SRV
+ type: server
+ ip_address: 192.168.20.4
+ default_gateway: 192.168.20.1
+ dns_server: *PUBLIC_DNS_IP
+
+
+ ########################
+ # SOME_TECH DMZ SUBNET #
+ ########################
+
+ - hostname: ST_PUB-FW
+ type: firewall
+ ports:
+ external_port: # Public Internet Facing Port
+ ip_address: 10.1.100.2
+ subnet_mask: *ST_INTERNET_SUBNET
+ internal_port: # SOME_TECH Intranet Port
+ ip_address: 192.168.150.1
+ subnet_mask: *ST_INTRA_CR_SUBNET
+ dmz_port: # SOME_TECH Port Facing Port
+ ip_address: 192.168.100.1
+ subnet_mask: *ST_DMZ_SUBNET
+ acl:
+ internal_inbound_acl:
+ 5:
+ action: PERMIT
+ internal_outbound_acl:
+ 5:
+ action: PERMIT
+ dmz_inbound_acl:
+ 5:
+ action: PERMIT
+ dmz_outbound_acl:
+ 5:
+ action: PERMIT
+ external_inbound_acl:
+ 5:
+ action: PERMIT
+ external_outbound_acl:
+ 5:
+ action: PERMIT
+ routes:
+ - address: 10.1.100.0
+ subnet_mask: *ST_INTERNET_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 10.1.10.0
+ subnet_mask: *REMOTE_INTERNET_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 10.1.0.0
+ subnet_mask: *HOME_INTERNET_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 192.168.1.0
+ subnet_mask: *HOME_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 192.168.10.0
+ subnet_mask: *REMOTE_SUBNET_DMZ
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 192.168.20.0
+ subnet_mask: *REMOTE_SUBNET
+ next_hop_ip_address: 10.1.100.1
+
+ - address: 8.8.8.0
+ subnet_mask: *DNS_SUBNET
+ next_hop_ip_address: 10.1.100.1
+ default_route:
+ next_hop_ip_address: 192.168.150.2
+
+ - hostname: ST_DMZ-PUB-SRV-WEB
+ type: server
+ ip_address: *ST_PUB_SRV_WEB_IP
+ subnet_mask: *ST_DMZ_SUBNET
+ default_gateway: 192.168.100.1
+ services:
+ *ST_SRV_WEB_CONFIG
+
+ #############################
+ # SOME_TECH INTRANET SUBNET #
+ #############################
+
+ - hostname: ST_INTRA-PRV-RT-CR
+ type: router
+ ports:
+ 1:
+ ip_address: 192.168.150.2
+ subnet_mask: *ST_INTRA_CR_SUBNET
+ 2:
+ ip_address: 192.168.160.1
+ subnet_mask: *ST_INTRA_DR_ONE_SUBNET
+ 3:
+ ip_address: 192.168.170.1
+ subnet_mask: *ST_INTRA_DR_TWO_SUBNET
+ 4:
+ ip_address: 192.168.220.1
+ subnet_mask: *ST_DATA_SUBNET
+
+ routes:
+ - address: 192.168.200.0
+ subnet_mask: *ST_HO_SUBNET
+ next_hop_ip_address: 192.168.170.2 # ST Intra Router Two
+ - address: 192.168.210.0
+ subnet_mask: *ST_HR_SUBNET
+ next_hop_ip_address: 192.168.170.2 # ST Intra Router Two
+ - address: 192.168.230.0
+ subnet_mask: *ST_PROJ_A_SUBNET
+ next_hop_ip_address: 192.168.160.2 # ST Intra Router One
+ - address: 192.168.240.0
+ subnet_mask: *ST_PROJ_B_SUBNET
+ next_hop_ip_address: 192.168.160.2 # ST Intra Router One
+ - address: 192.168.250.0
+ subnet_mask: *ST_PROJ_C_SUBNET
+ next_hop_ip_address: 192.168.160.2 # ST Intra Router One
+
+ default_route:
+ next_hop_ip_address: 192.168.150.1 # ST Public Firewall Internal Port
+ acl:
+ 5:
+ action: PERMIT
+
+ - hostname: ST_INTRA-PRV-RT-DR-1
+ type: router
+ ports:
+ 1:
+ ip_address: 192.168.160.2
+ subnet_mask: *ST_INTRA_DR_ONE_SUBNET
+ 2:
+ ip_address: 192.168.230.1
+ subnet_mask: *ST_PROJ_A_SUBNET
+ 3:
+ ip_address: 192.168.240.1
+ subnet_mask: *ST_PROJ_B_SUBNET
+ 4:
+ ip_address: 192.168.250.1
+ subnet_mask: *ST_PROJ_C_SUBNET
+ default_route:
+ next_hop_ip_address: 192.168.160.1 # ST Intranet CR Router Port 2
+ acl:
+ 5:
+ action: PERMIT
+
+ - hostname: ST_INTRA-PRV-RT-DR-2
+ type: router
+ default_gateway: 192.168.170.1
+ ports:
+ 1:
+ ip_address: 192.168.170.2
+ subnet_mask: *ST_INTRA_DR_TWO_SUBNET
+ 2:
+ ip_address: 192.168.200.1
+ subnet_mask: *ST_HO_SUBNET
+ 3:
+ ip_address: 192.168.210.1
+ subnet_mask: *ST_HR_SUBNET
+ default_route:
+ next_hop_ip_address: 192.168.170.1 # ST Intranet CR Router Port 3
+ acl:
+ 5:
+ action: PERMIT
+
+ ################################
+ # SOME_TECH HEAD OFFICE SUBNET #
+ ################################
+
+ - hostname: ST_HO-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_HO-PRV-PC-1
+ type: computer
+ ip_address: 192.168.200.2
+ default_gateway: 192.168.200.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_HO-PRV-PC-2
+ type: computer
+ ip_address: 192.168.200.3
+ default_gateway: 192.168.200.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_HO-PRV-PC-3
+ type: computer
+ ip_address: 192.168.200.4
+ default_gateway: 192.168.200.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ ####################################
+ # SOME_TECH HUMAN RESOURCES SUBNET #
+ ####################################
+
+ - hostname: ST_HR-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_HR-PRV-PC-1
+ type: computer
+ ip_address: 192.168.210.2
+ default_gateway: 192.168.210.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_HR-PRV-PC-2
+ type: computer
+ ip_address: 192.168.210.3
+ default_gateway: 192.168.210.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_HR-PRV-PC-3
+ type: computer
+ ip_address: 192.168.210.4
+ default_gateway: 192.168.210.1 # ST_INTRA-PRV-RT-DR-2 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ #########################
+ # SOME_TECH DATA SUBNET #
+ #########################
+
+ - hostname: ST_DATA-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_DATA-PRV-SRV-STORAGE
+ type: server
+ ip_address: *ST_SRV_STORAGE_IP
+ subnet_mask: *ST_DATA_SUBNET
+ default_gateway: 192.168.220.1
+ dns_server: *PUBLIC_DNS_IP
+ services:
+ *ST_SRV_STORAGE_CONFIG
+
+ - hostname: ST_DATA-PRV-SRV-DB
+ type: server
+ ip_address: *ST_SRV_DB_IP
+ subnet_mask: *ST_DATA_SUBNET
+ default_gateway: 192.168.220.1
+ dns_server: *PUBLIC_DNS_IP
+ services:
+ *ST_SRV_DB_CONFIG
+
+ #######################
+ # SOME_TECH PROJECT A #
+ #######################
+
+ - hostname: ST_PROJ-A-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_PROJ-A-PRV-PC-1
+ type: computer
+ ip_address: 192.168.230.2
+ default_gateway: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-A-PRV-PC-2
+ type: computer
+ ip_address: 192.168.230.3
+ default_gateway: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-A-PRV-PC-3
+ type: computer
+ ip_address: 192.168.230.4
+ default_gateway: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1 (Port 2)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ #######################
+ # SOME_TECH PROJECT B #
+ #######################
+
+ - hostname: ST_PROJ-B-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_PROJ-B-PRV-PC-1
+ type: computer
+ ip_address: 192.168.240.2
+ default_gateway: 192.168.240.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-B-PRV-PC-2
+ type: computer
+ ip_address: 192.168.240.3
+ default_gateway: 192.168.240.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-B-PRV-PC-3
+ type: computer
+ ip_address: 192.168.240.4
+ default_gateway: 192.168.240.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ #######################
+ # SOME_TECH PROJECT C #
+ #######################
+
+ - hostname: ST_PROJ-C-PRV-SW-AS
+ type: switch
+ num_ports: 5
+
+ - hostname: ST_PROJ-C-PRV-PC-1
+ type: computer
+ ip_address: 192.168.250.2
+ default_gateway: 192.168.250.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-C-PRV-PC-2
+ type: computer
+ ip_address: 192.168.250.3
+ default_gateway: 192.168.250.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+ - hostname: ST_PROJ-C-PRV-PC-3
+ type: computer
+ ip_address: 192.168.250.4
+ default_gateway: 192.168.250.1 # ST_INTRA-PRV-RT-DR-1 (Port 3)
+ dns_server: *PUBLIC_DNS_IP
+ applications:
+ *PC_DEFAULT_CONFIG
+
+
+ ##############################
+ # Simulation Network Links #
+ ##############################
+ links:
+
+ ############################
+ # HOME OFFICE SUBNET LINKS #
+ ############################
+
+ # Home Switch (Port 1) --> Home Router (Port 1)
+ - endpoint_a_hostname: HOME-PUB-SW-AS
+ endpoint_a_port: 1
+ endpoint_b_hostname: HOME-PUB-RT-DR
+ endpoint_b_port: 1
+
+ # Home Switch (Port 2) --> PC 1 (Port 1)
+ - endpoint_a_hostname: HOME-PUB-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: HOME-PUB-PC-1
+ endpoint_b_port: 1
+
+ # Home Switch (Port 3) --> PC 2 (Port 1)
+ - endpoint_a_hostname: HOME-PUB-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: HOME-PUB-PC-2
+ endpoint_b_port: 1
+
+ # Home Switch (Port 4) --> PC SRV (Port 1)
+ - endpoint_a_hostname: HOME-PUB-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: HOME-PUB-SRV
+ endpoint_b_port: 1
+
+ ##################
+ # Internet Links #
+ ##################
+
+ # Internet Router (Port 1) --> Home Router (Port 2)
+ - endpoint_a_hostname: ISP-PUB-RT-BR
+ endpoint_a_port: 1
+ endpoint_b_hostname: HOME-PUB-RT-DR
+ endpoint_b_port: 2
+
+ # Internet Router (Port 2) --> DNS Server (Port 1)
+ - endpoint_a_hostname: ISP-PUB-RT-BR
+ endpoint_a_port: 2
+ endpoint_b_hostname: ISP-PUB-SRV-DNS
+ endpoint_b_port: 1
+
+ # Internet Router (Port 3) --> Remote Firewall (External Port)
+ - endpoint_a_hostname: ISP-PUB-RT-BR
+ endpoint_a_port: 3
+ endpoint_b_hostname: REM-PUB-FW
+ endpoint_b_port: 1
+
+ ####################
+ # Remote DMZ Links #
+ ####################
+
+ # Remote Firewall (Internal Port) --> Remote Site Router (Port 1)
+ - endpoint_a_hostname: REM-PUB-FW
+ endpoint_a_port: 2
+ endpoint_b_hostname: REM-PUB-RT-DR
+ endpoint_b_port: 1
+
+ ####################
+ # Remote Site Link #
+ ####################
+
+ # Remote Site Router (Port 2) --> Remote Site Switch (Port 1)
+ - endpoint_a_hostname: REM-PUB-RT-DR
+ endpoint_a_port: 2
+ endpoint_b_hostname: REM-PUB-SW-AS
+ endpoint_b_port: 1
+
+ # Remote Site Switch (Port 2) --> Remote Site PC 1 (Port 1)
+ - endpoint_a_hostname: REM-PUB-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: REM-PUB-PC-1
+ endpoint_b_port: 1
+
+ # Remote Site Switch (Port 3) --> Remote Site PC 2 (Port 1)
+ - endpoint_a_hostname: REM-PUB-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: REM-PUB-PC-2
+ endpoint_b_port: 1
+
+ # Remote Site Switch (Port 4) --> Remote Site Server (Port 1)
+ - endpoint_a_hostname: REM-PUB-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: REM-PUB-SRV
+ endpoint_b_port: 1
+
+ #######################
+ # SOME_TECH DMZ Links #
+ #######################
+
+ # Internet Router (Port 4) --> Some Tech DMZ Firewall (External Port)
+ - endpoint_a_hostname: ISP-PUB-RT-BR
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PUB-FW
+ endpoint_b_port: 1
+
+ # Some Tech DMZ Firewall (DMZ Port) --> Some Tech Web Server (Port 1)
+ - endpoint_a_hostname: ST_PUB-FW
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_DMZ-PUB-SRV-WEB
+ endpoint_b_port: 1
+
+ ############################
+ # SOME_TECH INTRANET Links #
+ ############################
+
+ # Some Tech Intranet CR Router (Port 1) --> Some Tech DMZ Firewall (Internal Port)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-CR
+ endpoint_a_port: 1
+ endpoint_b_hostname: ST_PUB-FW
+ endpoint_b_port: 2
+
+ # Some Tech Intranet CR Router (Port 2) --> Some Tech Intranet DR Router 1 (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-CR
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_INTRA-PRV-RT-DR-1
+ endpoint_b_port: 1
+
+ # Some Tech Intranet CR Router (Port 3) --> Some Tech Intranet DR Router 2 (Port 2)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-CR
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_INTRA-PRV-RT-DR-2
+ endpoint_b_port: 1
+
+ # Some Tech Intranet Private Router CR (Port 4) --> Some Tech Data Private Switch (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-CR
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_DATA-PRV-SW-AS
+ endpoint_b_port: 1
+
+
+ ###############################
+ # SOME_TECH HEAD OFFICE Links #
+ ###############################
+
+ # Some Tech Head Office Switch (Port 1) --> Some Tech Intranet Private Router DR 2 (Port 2)
+ - endpoint_a_hostname: ST_HO-PRV-SW-AS
+ endpoint_a_port: 1
+ endpoint_b_hostname: ST_INTRA-PRV-RT-DR-2
+ endpoint_b_port: 2
+
+ # Some Tech Head Office Switch (Port 2) --> Some Tech Head Office PC 1 (Port 1)
+ - endpoint_a_hostname: ST_HO-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_HO-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Head Office Switch (Port 3) --> Some Tech Head Office PC 2 (Port 1)
+ - endpoint_a_hostname: ST_HO-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_HO-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Head Office Switch (Port 4) --> Some Tech Head Office PC 3 (Port 1)
+ - endpoint_a_hostname: ST_HO-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_HO-PRV-PC-3
+ endpoint_b_port: 1
+
+
+ ###################################
+ # SOME_TECH HUMAN RESOURCES Links #
+ ###################################
+
+ # Some Tech Human Resources Switch (Port 1) --> Some Tech Intranet Private Router DR 2 (Port 3)
+ - endpoint_a_hostname: ST_HR-PRV-SW-AS
+ endpoint_a_port: 1
+ endpoint_b_hostname: ST_INTRA-PRV-RT-DR-2
+ endpoint_b_port: 3
+
+ # Some Tech Human Resources Switch (Port 2) --> Some Tech Human Resources PC 1 (Port 1)
+ - endpoint_a_hostname: ST_HR-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_HR-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Human Resources Switch (Port 3) --> Some Tech Human Resources PC 2 (Port 1)
+ - endpoint_a_hostname: ST_HR-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_HR-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Human Resources Switch (Port 4) --> Some Tech Human Resources PC 3 (Port 1)
+ - endpoint_a_hostname: ST_HR-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_HR-PRV-PC-3
+ endpoint_b_port: 1
+
+ ########################
+ # SOME_TECH DATA Links #
+ ########################
+
+ # Some Tech Data Switch (Port 2) --> Some Tech Data Private Storage Server (Port 1)
+ - endpoint_a_hostname: ST_DATA-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_DATA-PRV-SRV-STORAGE
+ endpoint_b_port: 1
+
+ # Some Tech Data Switch (Port 3) --> Some Tech Data Private Database Server (Port 1)
+
+ - endpoint_a_hostname: ST_DATA-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_DATA-PRV-SRV-DB
+ endpoint_b_port: 1
+
+ #############################
+ # SOME_TECH PROJECT A Links #
+ #############################
+
+ # Some Tech Intranet Private Router DR 1 (Port 2) --> Some Tech Private Project A Switch (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-DR-1
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_PROJ-A-PRV-SW-AS
+ endpoint_b_port: 1
+
+ # Some Tech Private Project A Switch (Port 2) --> Some Tech Project A PC 1
+ - endpoint_a_hostname: ST_PROJ-A-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_PROJ-A-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Private Project A Switch (Port 3) --> Some Tech Project A PC 2
+ - endpoint_a_hostname: ST_PROJ-A-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_PROJ-A-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Private Project A Switch (Port 4) --> Some Tech Project A PC 3
+ - endpoint_a_hostname: ST_PROJ-A-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PROJ-A-PRV-PC-3
+ endpoint_b_port: 1
+
+ #############################
+ # SOME_TECH PROJECT B Links #
+ #############################
+
+ # Some Tech Intranet Private Router DR 1 (Port 3) --> Some Tech Private Project B Switch (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-DR-1
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_PROJ-B-PRV-SW-AS
+ endpoint_b_port: 1
+
+ # Some Tech Private Project B Switch (Port 2) --> Some Tech Project B PC 1
+ - endpoint_a_hostname: ST_PROJ-B-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_PROJ-B-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Private Project B Switch (Port 3) --> Some Tech Project B PC 2
+ - endpoint_a_hostname: ST_PROJ-B-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_PROJ-B-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Private Project B Switch (Port 4) --> Some Tech Project B PC 3
+ - endpoint_a_hostname: ST_PROJ-B-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PROJ-B-PRV-PC-3
+ endpoint_b_port: 1
+
+ #############################
+ # SOME_TECH PROJECT C Links #
+ #############################
+
+ # Some Tech Intranet Private Router DR 1 (Port 4) --> Some Tech Private Project C Switch (Port 1)
+ - endpoint_a_hostname: ST_INTRA-PRV-RT-DR-1
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PROJ-C-PRV-SW-AS
+ endpoint_b_port: 1
+
+ # Some Tech Private Project C Switch (Port 2) --> Some Tech Project C PC 1
+ - endpoint_a_hostname: ST_PROJ-C-PRV-SW-AS
+ endpoint_a_port: 2
+ endpoint_b_hostname: ST_PROJ-C-PRV-PC-1
+ endpoint_b_port: 1
+
+ # Some Tech Private Project C Switch (Port 3) --> Some Tech Project C PC 2
+ - endpoint_a_hostname: ST_PROJ-C-PRV-SW-AS
+ endpoint_a_port: 3
+ endpoint_b_hostname: ST_PROJ-C-PRV-PC-2
+ endpoint_b_port: 1
+
+ # Some Tech Private Project C Switch (Port 4) --> Some Tech Project C PC 3
+ - endpoint_a_hostname: ST_PROJ-C-PRV-SW-AS
+ endpoint_a_port: 4
+ endpoint_b_hostname: ST_PROJ-C-PRV-PC-3
+ endpoint_b_port: 1
+
+##################################
+# Use Case 7 Agent YAML Anchors #
+##################################
+
+##############################
+# Green Agent YAML Anchors #
+##############################
+
+# Green Agent Reward Impacts Values #
+
+LOW_WEIGHT_IMPACT: &LOW_WEIGHT_IMPACT 0.2
+MEDIUM_WEIGHT_IMPACT: &MEDIUM_WEIGHT_IMPACT 0.5
+HIGH_WEIGHT_IMPACT: &HIGH_WEIGHT_IMPACT 0.95
+
+LOW_WEIGHT_IMPACT_NEGATIVE: &LOW_WEIGHT_IMPACT_NEG -0.2
+MEDIUM_WEIGHT_IMPACT_NEGATIVE: &MEDIUM_WEIGHT_IMPACT_NEG -0.5
+HIGH_WEIGHT_IMPACT_NEGATIVE: &HIGH_WEIGHT_IMPACT_NEG -0.8
+
+# Default Green Agent Action Space Configuration Anchor #
+
+DEFAULT_GREEN_AGENT_MAX_EXECUTIONS: &DEFAULT_GREEN_AGENT_MAX_EXECUTIONS 1000 # Ensures green agent activity through-out an episode
+
+#################################################
+# Probabilistic Green Agent Config Yaml Anchors #
+#################################################
+
+# Probabilistic Green Agent | 20% node-application-execute | 80% do-nothing #
+PROBABILISTIC_CONFIG_20_PERCENTAGE_PROBABILITY: &GREEN_PROBABILISTIC_20
+ action_probabilities:
+ 0: 0.8
+ 1: 0.2
+
+# Probabilistic Green Agent | 40% node-application-execute | 60% do-nothing #
+PROBABILISTIC_CONFIG_40_PERCENTAGE_PROBABILITY: &GREEN_PROBABILISTIC_40
+ action_probabilities:
+ 0: 0.6
+ 1: 0.4
+
+# Probabilistic Green Agent | 60% node-application-execute | 40% do-nothing #
+PROBABILISTIC_CONFIG_60_PERCENTAGE_PROBABILITY: &GREEN_PROBABILISTIC_60
+ action_probabilities:
+ 0: 0.4
+ 1: 0.6
+
+
+# System Green Agent Config UC7 Network Wide Yaml Anchor #
+
+# Lists the IP_Address of all hosts that contain DNS and NTP Service Clients
+UC7_IP_LIST: &UC7_IP_LIST
+ # ====== Home Office ========
+ - 192.168.1.2 # HOME-PUB-PC-1 | ip_id: 2
+ - 192.168.1.3 # HOME-PUB-PC-2 | ip_id: 3
+ - 192.168.1.4 # HOME-PUB-PC-SRV | ip_id: 4
+ # ====== Remote Site ========
+ - 192.168.20.2 # REM-PUB-PC-1 | ip_id: 5
+ - 192.168.20.3 # REM-PUB-PC-2 | ip_id: 6
+ - 192.168.20.4 # REM-PUB-SRV | ip_id: 7
+ # ====== ST Public DMZ =======
+ - *ST_PUB_SRV_WEB_IP # 192.168.100.2 (ST_DMZ-PUB-SRV-WEB) | ip_id: 8
+ # ====== ST Head Office =======
+ - 192.168.200.2 # ST_HO-PRV-PC-1 | ip_id: 9
+ - 192.168.200.3 # ST_HO-PRV-PC-2 | ip_id: 10
+ - 192.168.200.4 # ST_HO-PRV-PC-3 | ip_id: 11
+ # ===== ST Human Resources ======
+ - 192.168.210.2 # ST_HR-PRV-PC-1 | ip_id: 12
+ - 192.168.210.3 # ST_HR-PRV-PC-2 | ip_id: 13
+ - 192.168.210.4 # ST_HR-PRV-PC-3 | ip_id: 14
+ # ====== ST DATA Servers =======
+ - *ST_SRV_STORAGE_IP # 192.168.220.2 (ST_DATA-PRV-SRV-STORAGE) | ip_id: 15
+ - *ST_SRV_DB_IP # 192.168.220.3 (ST_DATA-PRV-SRV-DB) | ip_id: 16
+ # ====== ST Project A =======
+ - 192.168.230.2 # PROJ-A-PRV-PC-1 | ip_id: 17
+ - 192.168.230.3 # PROJ-A-PRV-PC-2 | ip_id: 18
+ - 192.168.230.4 # PROJ-A-PRV-PC-3 | ip_id: 19
+ # ====== ST Project B =======
+ - 192.168.240.2 # PROJ-B-PRV-PC-1 | ip_id: 20
+ - 192.168.240.3 # PROJ-B-PRV-PC-2 | ip_id: 21
+ - 192.168.240.4 # PROJ-B-PRV-PC-3 | ip_id: 22
+ # ====== ST Project C =======
+ - 192.168.250.2 # PROJ-C-PRV-PC-1 | ip_id: 23
+ - 192.168.250.3 # PROJ-C-PRV-PC-2 | ip_id: 24
+ - 192.168.250.4 # PROJ-C-PRV-PC-3 | ip_id: 25
+
+############################################
+# Use Case 7 Agent Configuration Section #
+############################################
+
+agents:
+ #######################################################
+ # UC7 Green Agents Path of Life (POL) Configuration #
+ #######################################################
+
+
+ ####################################
+ # Home Office Network POL Config #
+ ####################################
+
+ # Home Office Green Agent Pattern Of Life
+ # ======================================
+ # 1. Three Home workers accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. Three Home workers accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: HOME_WORKER-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["HOME-PUB-PC-1"]
+ target_application: "database-client"
+ start_step: 4
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: HOME-PUB-PC-1
+
+ - ref: HOME_WORKER-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: HOME-PUB-PC-1
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: HOME-PUB-PC-1
+
+ - ref: HOME_WORKER-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["HOME-PUB-PC-2"]
+ target_application: "database-client"
+ start_step: 8
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: HOME-PUB-PC-2
+
+ - ref: HOME_WORKER-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: HOME-PUB-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: HOME-PUB-PC-2
+
+ ####################################
+ # Remote Site Network POL Config #
+ ####################################
+
+ # Remote Site Green Agent Pattern Of Life
+ # ======================================
+ # 1. Three Remote workers accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. Three Remote workers accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: REMOTE_WORKER-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["REM-PUB-PC-1"]
+ target_application: "database-client"
+ start_step: 12
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: REM-PUB-PC-1
+
+ - ref: REMOTE_WORKER-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: REM-PUB-PC-1
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: REM-PUB-PC-1
+
+ - ref: REMOTE_WORKER-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["REM-PUB-PC-2"]
+ target_application: "database-client"
+ start_step: 16
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: REM-PUB-PC-2
+
+ - ref: REMOTE_WORKER-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: REM-PUB-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: REM-PUB-PC-2
+
+ ####################################
+ # ST Project A Network POL Config #
+ ####################################
+
+ # ST Project A Green Agent Pattern Of Life
+ # ========================================
+ # 1. A Senior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. A Senior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 3. Two Junior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 4. Two Junior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+
+ - ref: PROJ_A-SENIOR-DEV-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-A-PRV-PC-1"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-1
+
+ - ref: PROJ_A-SENIOR-DEV-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_40
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-1
+
+ - ref: PROJ_A-JUNIOR-DEV-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-A-PRV-PC-2"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-2
+
+ - ref: PROJ_A-JUNIOR-DEV-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-A-PRV-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-2
+
+ - ref: PROJ_A-JUNIOR-DEV-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-A-PRV-PC-3"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-3
+
+ - ref: PROJ_A-JUNIOR-DEV-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-A-PRV-PC-3
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-A-PRV-PC-3
+
+ ####################################
+ # ST Project B Network POL Config #
+ ####################################
+
+ # ST Project B Green Agent Pattern Of Life
+ # ========================================
+ # 1. A Senior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. A Senior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 3. Two Junior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 4. Two Junior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: PROJ_B-SENIOR-DEV-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-B-PRV-PC-1"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-1
+
+ - ref: PROJ_B-SENIOR-DEV-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-B-PRV-PC-1
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_40
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-1
+
+ - ref: PROJ_B-JUNIOR-DEV-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-B-PRV-PC-2"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-2
+
+ - ref: PROJ_B-JUNIOR-DEV-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-2
+
+ - ref: PROJ_B-JUNIOR-DEV-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-B-PRV-PC-3"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-3
+
+ - ref: PROJ_B-JUNIOR-DEV-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-B-PRV-PC-3
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-B-PRV-PC-3
+
+ ####################################
+ # ST Project C Network POL Config #
+ ####################################
+
+ # ST Project C Green Agent Pattern Of Life
+ # ========================================
+ # 1. A Senior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 2. A Senior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 3. Two Junior Developer accessing the SOME_TECH Private Database (ST_DATA-PRV-SRV-DB)
+ # 4. Two Junior Developer accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: PROJ_C-SENIOR-DEV-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-C-PRV-PC-1"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-1
+
+ - ref: PROJ_C-SENIOR-DEV-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-C-PRV-PC-1
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_40
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-1
+
+ - ref: PROJ_C-JUNIOR-DEV-1-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-C-PRV-PC-2"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-2
+
+ - ref: PROJ_C-JUNIOR-DEV-1-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-C-PRV-PC-2
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-2
+
+ - ref: PROJ_C-JUNIOR-DEV-2-DB
+ team: GREEN
+ type: periodic-agent
+ observation_space: {}
+ agent_settings:
+ possible_start_nodes: ["ST_PROJ-C-PRV-PC-3"]
+ target_application: "database-client"
+ start_step: 1
+ start_variance: 1
+ max_executions: *DEFAULT_GREEN_AGENT_MAX_EXECUTIONS
+ frequency: 4
+ variance: 1
+ reward_function:
+ reward_components:
+ - type: green-admin-database-unreachable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-3
+
+ - ref: PROJ_C-JUNIOR-DEV-2-WEB
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: web-browser
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_20
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *LOW_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_PROJ-C-PRV-PC-3
+
+ ######################################
+ # ST Head Office Network POL Config #
+ ######################################
+
+ # ST Head Office Green Agent Pattern Of Life
+ # ==========================================
+ # 1. The ST CEO accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 2. The ST CTO accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 3. The ST CFO accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: CEO
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HO-PRV-PC-1
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *HIGH_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HO-PRV-PC-1
+
+ - ref: CTO
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HO-PRV-PC-2
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HO-PRV-PC-2
+
+ - ref: CFO
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HO-PRV-PC-3
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HO-PRV-PC-3
+
+ ##########################################
+ # ST Human Resources Network POL Config #
+ ##########################################
+
+ # ST Head Office Green Agent Pattern Of Life
+ # ==========================================
+ # 1. A senior HR staff accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+ # 2. Two junior HR staff accessing the SOME_TECH Public web-server (ST_DMZ-PUB-SRV-WEB)
+
+ - ref: SENIOR_HR
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HR-PRV-PC-1
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HR-PRV-PC-1
+
+ - ref: JUNIOR_HR-1
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HR-PRV-PC-2
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HR-PRV-PC-2
+
+ - ref: JUNIOR_HR-2
+ team: GREEN
+ type: probabilistic-agent
+ observation_space: {}
+ agent_settings:
+ <<: *GREEN_PROBABILISTIC_60
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+ 1:
+ action: node-application-execute
+ options:
+ node_name: ST_HR-PRV-PC-3
+ application_name: web-browser
+ reward_function:
+ reward_components:
+ - type: webpage-unavailable-penalty
+ weight: *MEDIUM_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_HR-PRV-PC-3
+
+ ##########################
+ # UC7 Red Agent Config #
+ ##########################
+
+ - *red
+###########################
+# UC7 Blue Agent Config #
+###########################
+
+ - ref: defender
+ team: BLUE
+ type: proxy-agent
+ observation_space:
+ type: custom
+ options:
+ components:
+ - type: nodes
+ label: NODES
+ options:
+ hosts:
+ # TAP001 Potential Starting Note | ST_PROJ-A-PRV-PC-1
+ - hostname: ST_PROJ-A-PRV-PC-1
+ services:
+ - service_name: ftp-client
+ applications:
+ - application_name: ransomware-script
+ - application_name: database-client
+ folders:
+ - folder_name: downloads
+ files:
+ - file_name: malware_dropper.ps1
+ - folder_name: exfiltration_folder
+ files:
+ - file_name: database.db
+ # TAP001 Potential Starting Note | ST_PROJ-B-PRV-PC-2
+ - hostname: ST_PROJ-B-PRV-PC-2
+ services:
+ - service_name: ftp-client
+ applications:
+ - application_name: ransomware-script
+ - application_name: database-client
+ folders:
+ - folder_name: downloads
+ files:
+ - file_name: malware_dropper.ps1
+ - folder_name: exfiltration_folder
+ files:
+ - file_name: database.db
+ # TAP001 Potential Starting Note | ST_PROJ-C-PRV-PC-3
+ - hostname: ST_PROJ-C-PRV-PC-3
+ services:
+ - service_name: ftp-client
+ applications:
+ - application_name: ransomware-script
+ - application_name: database-client
+ folders:
+ - folder_name: downloads
+ files:
+ - file_name: malware_dropper.ps1
+ - folder_name: exfiltration_folder
+ files:
+ - file_name: database.db
+ # ST DATA Server Database
+ - hostname: ST_DATA-PRV-SRV-DB
+ folders:
+ - folder_name: database
+ files:
+ - file_name: database.db
+ routers:
+ - hostname: ST_INTRA-PRV-RT-CR # TAP003 Malicious ACL Target | ROUTER0
+ - hostname: ST_INTRA-PRV-RT-DR-1 # TAP003 Malicious ACL Target | ROUTER1
+ - hostname: REM-PUB-RT-DR # TAP003 Malicious ACL Target | ROUTER2
+ num_ports: 5
+ num_services: 2
+ num_applications: 2
+ num_folders: 2
+ num_files: 1
+ num_nics: 1
+ ip_list:
+ # ip_list is indexed at 2:
+ # 0 reserved for padding to align with observations
+ # 1 reserved for ALL ips
+ *UC7_IP_LIST
+ wildcard_list:
+ - 0.0.0.1 # 0
+ - 0.0.0.255 # 1
+ - 0.0.255.255 # 2
+ port_list:
+ # 0 is a padding placeholder
+ # 1 means ALL ports
+ - FTP # 2
+ - DNS # 3
+ - HTTP # 4
+ - NTP # 5
+ - POSTGRES_SERVER # 6
+ - SSH # 7
+
+ protocol_list:
+ # 0 is padding placeholder
+ # 1 means ALL protocols
+ - ICMP # 2
+ - TCP # 3
+ - UDP # 4
+ num_rules: 5
+ include_num_access: true
+ include_nmne: true
+ monitored_traffic:
+ tcp:
+ - HTTP
+ - POSTGRES_SERVER
+ icmp:
+ - NONE
+ - type: links
+ label: LINKS
+ options:
+ link_references:
+ # HOME OFFICE SUBNET LINKS
+ - HOME-PUB-SW-AS:eth-1<->HOME-PUB-RT-DR:eth-1 # 1
+ - HOME-PUB-SW-AS:eth-1<->HOME-PUB-PC-1:eth-1 # 2
+ - HOME-PUB-SW-AS:eth-1<->HOME-PUB-PC-2:eth-1 # 3
+ - HOME-PUB-SW-AS:eth-1<->HOME-PUB-SRV:eth-1 # 4
+ # Internet LINKS
+ - ISP-PUB-RT-BR:eth-1<->HOME-PUB-RT-DR:eth-2 # 5
+ - ISP-PUB-RT-BR:eth-2<->ISP-PUB-SRV-DNS:eth-1 # 6
+ - ISP-PUB-RT-BR:eth-3<->REM-PUB-FW:eth-1 # 7
+ # Remote DMZ Links
+ - REM-PUB-FW:eth-2<->REM-PUB-RT-DR:eth-1 # 8
+ # Remote Site Links
+ - REM-PUB-RT-DR:eth-2<->REM-PUB-SW-AS:eth-1 # 9
+ - REM-PUB-SW-AS:eth-2<->REM-PUB-PC-1:eth-1 # 10
+ - REM-PUB-SW-AS:eth-3<->REM-PUB-PC-2:eth-1 # 11
+ - REM-PUB-SW-AS:eth-4<->REM-PUB-SRV:eth-1 # 12
+ # SOME_TECH DMZ
+ - ISP-PUB-RT-BR:eth-4<->ST_PUB-FW:eth-1 # 13
+ - ST_PUB-FW:eth-3<->ST_DMZ-PUB-SRV-WEB:eth-1 # 14
+ # SOME_TECH Intranet
+ - ST_INTRA-PRV-RT-CR:eth-1<->ST_PUB-FW:eth-2 # 15
+ - ST_INTRA-PRV-RT-CR:eth-2<->ST_INTRA-PRV-RT-DR-1:eth-1 # 16
+ - ST_INTRA-PRV-RT-CR:eth-3<->ST_INTRA-PRV-RT-DR-2:eth-1 # 17
+ - ST_INTRA-PRV-RT-CR:eth-4<->ST_DATA-PRV-SW-AS:eth-1 # 18
+ # SOME_TECH Head Office
+ - ST_HO-PRV-SW-AS:eth-1<->ST_INTRA-PRV-RT-DR-2:eth-2 # 19
+ - ST_HO-PRV-SW-AS:eth-2<->ST_HO-PRV-PC-1:eth-1 # 20
+ - ST_HO-PRV-SW-AS:eth-3<->ST_HO-PRV-PC-2:eth-1 # 21
+ - ST_HO-PRV-SW-AS:eth-4<->ST_HO-PRV-PC-3:eth-1 # 22
+ # SOME_TECH Human Resources
+ - ST_HR-PRV-SW-AS:eth-1<->ST_INTRA-PRV-RT-DR-2:eth-3 # 23
+ - ST_HR-PRV-SW-AS:eth-2<->ST_HR-PRV-PC-1:eth-1 # 24
+ - ST_HR-PRV-SW-AS:eth-3<->ST_HR-PRV-PC-2:eth-1 # 25
+ - ST_HR-PRV-SW-AS:eth-4<->ST_HR-PRV-PC-3:eth-1 # 26
+ # SOME_TECH Data Links
+ - ST_DATA-PRV-SW-AS:eth-2<->ST_DATA-PRV-SRV-STORAGE:eth-1 # 27
+ - ST_DATA-PRV-SW-AS:eth-3<->ST_DATA-PRV-SRV-DB:eth-1 # 28
+ # SOME_TECH Project A Links
+ - ST_INTRA-PRV-RT-DR-1:eth-2<->ST_PROJ-A-PRV-SW-AS:eth-1 # 29
+ - ST_PROJ-A-PRV-SW-AS:eth2<->ST_PROJ-A-PRV-PC-1:eth-1 # 31
+ - ST_PROJ-A-PRV-SW-AS:eth3<->ST_PROJ-A-PRV-PC-2:eth-1 # 32
+ - ST_PROJ-A-PRV-SW-AS:eth4<->ST_PROJ-A-PRV-PC-3:eth-1 # 33
+ # SOME_TECH Project B Links
+ - ST_INTRA-PRV-RT-DR-1:eth-3<->ST_PROJ-B-PRV-SW-AS:eth-1 # 34
+ - ST_PROJ-B-PRV-SW-AS:eth2<->ST_PROJ-B-PRV-PC-1:eth-1 # 35
+ - ST_PROJ-B-PRV-SW-AS:eth3<->ST_PROJ-B-PRV-PC-2:eth-1 # 36
+ - ST_PROJ-B-PRV-SW-AS:eth4<->ST_PROJ-B-PRV-PC-3:eth-1 # 37
+ # SOME_TECH Project C Links
+ - ST_INTRA-PRV-RT-DR-1:eth-4<->ST_PROJ-C-PRV-SW-AS:eth-1 # 38
+ - ST_PROJ-A-PRV-SW-AS:eth2<->ST_PROJ-C-PRV-PC-1:eth-1 # 39
+ - ST_PROJ-A-PRV-SW-AS:eth3<->ST_PROJ-C-PRV-PC-2:eth-1 # 40
+ - ST_PROJ-A-PRV-SW-AS:eth4<->ST_PROJ-C-PRV-PC-3:eth-1 # 41
+ action_space:
+ action_map:
+ 0:
+ action: do-nothing
+ options: {}
+
+ # |======================================|
+ # | ST_PROJ-A-PRV-PC-1 |
+ # |======================================|
+
+ # ST_PROJ-A-PRV-PC-1 | node-os-scan
+ 1:
+ action: node-os-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ # ST_PROJ-A-PRV-PC-1 | node-shutdown
+ 2:
+ action: node-shutdown
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ # ST_PROJ-A-PRV-PC-1 | node-startup
+ 3:
+ action: node-startup
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ # ST_PROJ-A-PRV-PC-1 | node-reset
+ 4:
+ action: node-reset
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ # ST_PROJ-A-PRV-PC-1 | host-nic-disable
+ 5:
+ action: host-nic-disable
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ nic_num: 0
+ # ST_PROJ-A-PRV-PC-1 | host-nic-enable
+ 6:
+ action: host-nic-enable
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ nic_num: 0
+ # ST_PROJ-A-PRV-PC-1 | node-application-close | database-client
+ 7:
+ action: node-application-close
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: database-client
+
+ # ST_PROJ-A-PRV-PC-1 | node-application-scan | database-client
+ 8:
+ action: node-application-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: database-client
+
+ # ST_PROJ-A-PRV-PC-1 | node-application-fix | database-client
+ 9:
+ action: node-application-fix
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: database-client
+
+ # ST_PROJ-A-PRV-PC-1 | node-application-remove | database-client
+ 10:
+ action: node-application-remove
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ application_name: database-client
+
+
+ # ST_PROJ-A-PRV-PC-1 | node-file-scan | downloads/malware_dropper.ps1
+ 11:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ folder_name: downloads
+ file_name: malware_dropper.ps1
+
+ # ST_PROJ-A-PRV-PC-1 | node-file-scan | exfiltration_folder/database.db
+ 12:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ folder_name: exfiltration_folder
+ file_name: database.db
+
+ # ST_PROJ-A-PRV-PC-1 | node-folder-scan | downloads/
+ 13:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ folder_name: downloads
+
+ # ST_PROJ-A-PRV-PC-1 | node-folder-scan | exfiltration_folder/
+ 14:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-A-PRV-PC-1
+ folder_name: exfiltration_folder
+
+ # |======================================|
+ # | ST_PROJ-B-PRV-PC-2 |
+ # |======================================|
+
+ # ST_PROJ-B-PRV-PC-2 | node-os-scan
+ 15:
+ action: node-os-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+
+ # ST_PROJ-B-PRV-PC-2 | node-shutdown
+ 16:
+ action: node-shutdown
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+
+ # ST_PROJ-B-PRV-PC-2 | node-startup
+ 17:
+ action: node-startup
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+
+ # ST_PROJ-B-PRV-PC-2 | node-reset
+ 18:
+ action: node-reset
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+
+ # ST_PROJ-B-PRV-PC-2 | host-nic-disable
+ 19:
+ action: host-nic-disable
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ nic_num: 0
+
+ # ST_PROJ-B-PRV-PC-2 | host-nic-enable
+ 20:
+ action: host-nic-enable
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ nic_num: 0
+
+ # ST_PROJ-B-PRV-PC-2 | node-application-close | database-client
+ 21:
+ action: node-application-close
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: database-client
+
+ # ST_PROJ-B-PRV-PC-2 | node-application-scan | database-client
+ 22:
+ action: node-application-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: database-client
+
+ # ST_PROJ-B-PRV-PC-2 | node-application-fix | database-client
+ 23:
+ action: node-application-fix
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: database-client
+
+ # ST_PROJ-B-PRV-PC-2 | node-application-remove | database-client
+ 24:
+ action: node-application-remove
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ application_name: database-client
+
+ # ST_PROJ-B-PRV-PC-2 | node-file-scan | downloads/malware_dropper.ps1
+ 25:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ folder_name: downloads
+ file_name: malware_dropper.ps1
+
+ # ST_PROJ-B-PRV-PC-2 | node-file-scan | exfiltration_folder/database.db
+ 26:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ folder_name: exfiltration_folder
+ file_name: database.db
+
+ # ST_PROJ-B-PRV-PC-2 | node-folder-scan | downloads/
+ 27:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ folder_name: downloads
+
+ # ST_PROJ-B-PRV-PC-2 | node-folder-scan | exfiltration_folder/
+ 28:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-B-PRV-PC-2
+ folder_name: exfiltration_folder
+
+ # |======================================|
+ # | ST_PROJ-C-PRV-PC-3 |
+ # |======================================|
+
+ # ST_PROJ-C-PRV-PC-3 | node-os-scan
+ 29:
+ action: node-os-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+
+ # ST_PROJ-C-PRV-PC-3 | node-shutdown
+ 30:
+ action: node-shutdown
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+
+ # ST_PROJ-C-PRV-PC-3 | node-startup
+ 31:
+ action: node-startup
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+
+ # ST_PROJ-C-PRV-PC-3 | node-reset
+ 32:
+ action: node-reset
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+
+ # ST_PROJ-C-PRV-PC-3 | host-nic-disable
+ 33:
+ action: host-nic-disable
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ nic_num: 0
+
+ # ST_PROJ-C-PRV-PC-3 | host-nic-enable
+ 34:
+ action: host-nic-enable
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ nic_num: 0
+
+ # ST_PROJ-C-PRV-PC-3 | node-application-close | database-client
+ 35:
+ action: node-application-close
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: database-client
+
+ # ST_PROJ-C-PRV-PC-3 | node-application-scan | database-client
+ 36:
+ action: node-application-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: database-client
+
+ # ST_PROJ-C-PRV-PC-3 | node-application-fix | database-client
+ 37:
+ action: node-application-fix
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: database-client
+
+ # ST_PROJ-C-PRV-PC-3 | node-application-remove | database-client
+ 38:
+ action: node-application-remove
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ application_name: database-client
+
+ # ST_PROJ-C-PRV-PC-3 | node-file-scan | downloads/malware_dropper.ps1
+ 39:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ folder_name: downloads
+ file_name: malware_dropper.ps1
+
+ # ST_PROJ-C-PRV-PC-3 | node-file-scan | exfiltration_folder/database.db
+ 40:
+ action: node-file-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ folder_name: exfiltration_folder
+ file_name: database.db
+
+ # ST_PROJ-C-PRV-PC-3 | node-folder-scan | downloads/
+ 41:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ folder_name: downloads
+
+ # ST_PROJ-C-PRV-PC-3 | node-folder-scan | exfiltration_folder/
+ 42:
+ action: node-folder-scan
+ options:
+ node_name: ST_PROJ-C-PRV-PC-3
+ folder_name: exfiltration_folder
+
+ # |======================================|
+ # | ST_INTRA-PRV-RT-CR |
+ # |======================================|
+
+ # ST_INTRA-PRV-RT-CR | router-acl-add-rule | P2: ST_PROJ-A-PRV-PC-1 !==> ST_DATA-PRV-SRV-DB (TCP:POSTGRES_SERVER)
+ 43:
+ action: router-acl-add-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 1
+ permission: DENY
+ src_ip: 192.168.230.2 # (ST_PROJ-A-PRV-PC-1)
+ src_wildcard: 0.0.255.255
+ src_port: POSTGRES_SERVER
+ dst_ip: 192.168.220.3 # (ST_DATA-PRV-SRV-DB)
+ dst_wildcard: 0.0.255.255
+ dst_port: POSTGRES_SERVER
+ protocol_name: TCP
+
+ # ST_INTRA-PRV-RT-CR | REMOVE_ACL_ADDRULE | Removes a given ACL at position 1
+ 44:
+ action: router-acl-remove-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 1
+
+ # ST_INTRA-PRV-RT-CR | router-acl-add-rule | P3: ST_PROJ-B-PRV-PC-2 !==> ST_DATA-PRV-SRV-DB (TCP:POSTGRES_SERVER)
+ 45:
+ action: router-acl-add-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 2
+ permission: DENY
+ src_ip: 192.168.240.3 # (ST_PROJ-B-PRV-PC-2)
+ src_wildcard: 0.0.255.255
+ src_port: POSTGRES_SERVER
+ dst_ip: 192.168.220.3 # (ST_DATA-PRV-SRV-DB)
+ dst_wildcard: 0.0.255.255
+ dst_port: POSTGRES_SERVER
+ protocol_name: TCP
+ # ST_INTRA-PRV-RT-CR | REMOVE_ACL_ADDRULE | Removes a given ACL at position 2
+ 46:
+ action: router-acl-remove-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 2
+
+ # ST_INTRA-PRV-RT-CR | router-acl-add-rule | P4: ST_PROJ-C-PRV-PC-3 !==> ST_DATA-PRV-SRV-DB (TCP:POSTGRES_SERVER)
+ 47:
+ action: router-acl-add-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 3
+ permission: DENY
+ src_ip: 192.168.250.4 # (ST_PROJ-C-PRV-PC-3)
+ src_wildcard: 0.0.255.255
+ src_port: POSTGRES_SERVER
+ dst_ip: 192.168.220.3 # (ST_DATA-PRV-SRV-DB)
+ dst_wildcard: 0.0.255.255
+ dst_port: POSTGRES_SERVER
+ protocol_name: TCP
+
+ # ST_INTRA-PRV-RT-CR | REMOVE_ACL_ADDRULE | Removes a given ACL at position 3
+ 48:
+ action: router-acl-remove-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-CR
+ position: 3
+
+ # |======================================|
+ # | ST_DATA-PRV-SRV-DB |
+ # |======================================|
+
+ # ST_DATA-PRV-SRV-DB | node-file-scan | Scans the database.db file (health status)
+ 49:
+ action: node-file-scan
+ options:
+ node_name: ST_DATA-PRV-SRV-DB
+ folder_name: database
+ file_name: database.db
+
+ # ST_DATA-PRV-SRV-DB | node-account-change-password | Changes the password of a user account
+ 50:
+ action: node-account-change-password
+ options:
+ node_name: ST_DATA-PRV-SRV-DB
+ username: admin # default account
+ current_password: admin # default password
+ new_password: thr33_alert_wolv3z # A more 'secure' password
+
+ # |======================================|
+ # | ST_INTRA-PRV-RT-DR-1 |
+ # |======================================|
+
+ # ST_INTRA-PRV-RT-DR-1 | router-acl-add-rule | P1: ST_INTRA-PRV-RT-DR-1 !==> ANY (TCP:SSH)
+ 51:
+ action: router-acl-add-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-DR-1
+ position: 1
+ permission: DENY
+ src_ip: 192.168.230.2 # (ST_PROJ-A-PRV-PC-1)
+ src_wildcard: 0.0.255.255
+ src_port: SSH
+ dst_ip: ALL
+ dst_wildcard: 0.0.255.255
+ dst_port: SSH
+ protocol_name: TCP
+
+ # ST_INTRA-PRV-RT-DR-1 | node-account-change-password
+ 52:
+ action: node-account-change-password
+ options:
+ node_name: ST_INTRA-PRV-RT-DR-1
+ username: admin
+ current_password: admin
+ new_password: secure_password
+
+ # ST_INTRA-PRV-RT-DR-1 | router-acl-remove-rule | Removes the given ACL at position 1
+ 53:
+ action: router-acl-remove-rule
+ options:
+ target_router: ST_INTRA-PRV-RT-DR-1
+ position: 1
+
+ # |======================================|
+ # | REM-PUB-RT-DR |
+ # |======================================|
+
+ # REM-PUB-RT-DR | node-account-change-password
+ 54:
+ action: node-account-change-password
+ options:
+ node_name: REM-PUB-RT-DR
+ username: admin
+ current_password: admin
+ new_password: secure_password
+
+ # REM-PUB-RT-DR | router-acl-remove-rule | Removes the given ACL at position 1
+ 55:
+ action: router-acl-remove-rule
+ options:
+ target_router: REM-PUB-RT-DR
+ position: 1
+
+ reward_function:
+ reward_components:
+ - type: database-file-integrity
+ weight: *HIGH_WEIGHT_IMPACT
+ options:
+ node_hostname: ST_DATA-PRV-SRV-DB
+ folder_name: database
+ file_name: database.db
+
+ # Home Site Green Agents (32 Green Agents each contributing 0.03125 of blue reward)
+
+ # Blue Shared Reward | HOME_WORKER-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: HOME_WORKER-1-DB
+
+ # Blue Shared Reward | HOME_WORKER-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: HOME_WORKER-1-WEB
+
+ # Blue Shared Reward | HOME_WORKER-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: HOME_WORKER-2-DB
+
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: HOME_WORKER-2-WEB
+
+ # Remote Site Green Agents
+
+ # Blue Shared Reward | REMOTE_WORKER-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: REMOTE_WORKER-1-DB
+
+ # Blue Shared Reward | REMOTE_WORKER-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: REMOTE_WORKER-1-WEB
+
+ # Blue Shared Reward | REMOTE_WORKER-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: REMOTE_WORKER-2-DB
+
+ # Blue Shared Reward | REMOTE_WORKER-2-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: REMOTE_WORKER-2-WEB
+
+ # ST Project A Green Agents
+
+ # Blue Shared Reward | PROJ_A-SENIOR-DEV-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-SENIOR-DEV-DB
+
+ # Blue Shared Reward | PROJ_A-SENIOR-DEV-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-SENIOR-DEV-WEB
+
+ # Blue Shared Reward | PROJ_A-JUNIOR-DEV-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-JUNIOR-DEV-1-DB
+
+ # Blue Shared Reward | PROJ_A-JUNIOR-DEV-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-JUNIOR-DEV-1-WEB
+
+ # Blue Shared Reward | PROJ_A-JUNIOR-DEV-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-JUNIOR-DEV-2-DB
+
+ # Blue Shared Reward | PROJ_A-JUNIOR-DEV-2-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_A-JUNIOR-DEV-2-WEB
+
+ # ST Project B Green Agents
+
+ # Blue Shared Reward | PROJ_B-SENIOR-DEV-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-SENIOR-DEV-DB
+
+ # Blue Shared Reward | PROJ_B-SENIOR-DEV-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-SENIOR-DEV-WEB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-1-DB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-1-WEB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-2-DB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-2-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-2-WEB
+
+ # ST Project C Green Agents
+
+ # Blue Shared Reward | PROJ_B-SENIOR-DEV-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-SENIOR-DEV-DB
+
+ # Blue Shared Reward | PROJ_B-SENIOR-DEV-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-SENIOR-DEV-WEB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-1-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-1-DB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-1-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-1-WEB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-2-DB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-2-DB
+
+ # Blue Shared Reward | PROJ_B-JUNIOR-DEV-2-WEB
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: PROJ_B-JUNIOR-DEV-2-WEB
+
+ # ST Head Office Green Agents (CEO/CFO/CTO)
+
+ # Blue Shared Reward | CEO
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: CEO
+
+ # Blue Shared Reward | CFO
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: CFO
+
+ # Blue Shared Reward | CTO
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: CTO
+
+ # ST Human Resources Green Agents
+
+ # Blue Shared Reward | SENIOR_HR
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: SENIOR_HR
+
+ # Blue Shared Reward | SENIOR_HR
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: JUNIOR_HR-1
+
+ # Blue Shared Reward | SENIOR_HR
+ - type: shared-reward
+ weight: 0.03125
+ options:
+ agent_name: JUNIOR_HR-2
+
+ agent_settings:
+ flatten_obs: False
diff --git a/src/primaite/game/agent/actions/node.py b/src/primaite/game/agent/actions/node.py
index b1b6ec12..5b62957a 100644
--- a/src/primaite/game/agent/actions/node.py
+++ b/src/primaite/game/agent/actions/node.py
@@ -37,15 +37,18 @@ class NodeAbstractAction(AbstractAction, ABC):
return ["network", "node", config.node_name, config.verb]
-class NodeOSScanAction(NodeAbstractAction, discriminator="node-os-scan"):
+class NodeOSScanAction(AbstractAction, discriminator="node-os-scan"):
"""Action which scans a node's OS."""
- config: "NodeOSScanAction.ConfigSchema"
+ class ConfigSchema(AbstractAction.ConfigSchema, ABC):
+ """Base Configuration schema for Node actions."""
- class ConfigSchema(NodeAbstractAction.ConfigSchema):
- """Configuration schema for NodeOSScanAction."""
+ node_name: str
- verb: ClassVar[str] = "scan"
+ @classmethod
+ def form_request(cls, config: ConfigSchema) -> RequestFormat:
+ """Return the action formatted as a request which can be ingested by the PrimAITE simulation."""
+ return ["network", "node", config.node_name, "os", "scan"]
class NodeShutdownAction(NodeAbstractAction, discriminator="node-shutdown"):
diff --git a/src/primaite/game/agent/interface.py b/src/primaite/game/agent/interface.py
index a6e9739f..b9a7fcc8 100644
--- a/src/primaite/game/agent/interface.py
+++ b/src/primaite/game/agent/interface.py
@@ -124,8 +124,8 @@ class AbstractAgent(BaseModel, ABC):
pass
else:
# format dict by putting each key-value entry on a separate line and putting a blank line on the end.
- param_string = "\n".join([*[f"{k}: {v:.30}" for k, v in item.parameters.items()], ""])
- data_string = "\n".join([*[f"{k}: {v:.30}" for k, v in item.response.data], ""])
+ param_string = "\n".join([*[f"{k}: {str(v):.80}" for k, v in item.parameters.items()], ""])
+ data_string = "\n".join([*[f"{k}: {str(v):.80}" for k, v in item.response.data.items()], ""])
table.add_row([item.timestep, item.action, param_string, item.response.status, data_string])
print(table)
diff --git a/src/primaite/game/agent/scripted_agents/TAP003.py b/src/primaite/game/agent/scripted_agents/TAP003.py
index 467c209a..1dcebe07 100644
--- a/src/primaite/game/agent/scripted_agents/TAP003.py
+++ b/src/primaite/game/agent/scripted_agents/TAP003.py
@@ -257,7 +257,7 @@ class TAP003(AbstractTAP, discriminator="tap-003"):
self.logger.debug(f"Updating network knowledge. Changed {username}'s password to {password} on {hostname}.")
self._change_password_target_host = ""
# local password change
- elif last_hist_item.action == "node-accounts-change-password" and last_hist_item.response.status == "success":
+ elif last_hist_item.action == "node-account-change-password" and last_hist_item.response.status == "success":
self.network_knowledge["current_session"] = {}
username = last_hist_item.request[6]
password = last_hist_item.request[8]
@@ -338,15 +338,17 @@ class TAP003(AbstractTAP, discriminator="tap-003"):
"""
if self.current_kill_chain_stage == self.selected_kill_chain.MANIPULATION:
if self._agent_trial_handler(self.config.agent_settings.kill_chain.MANIPULATION.probability):
- self.logger.info(f"TAP003 reached the {self.current_kill_chain_stage.name}")
+ if self.current_stage_progress == KillChainStageProgress.PENDING:
+ self.logger.info(f"TAP003 reached the {self.current_kill_chain_stage.name}.")
+ self.current_stage_progress = KillChainStageProgress.IN_PROGRESS
self.current_host = self.starting_node
account_changes = self.config.agent_settings.kill_chain.MANIPULATION.account_changes
- if len(account_changes) > 0:
+ if len(account_changes) > 0 or self._next_account_change:
if not self._next_account_change:
self._next_account_change = account_changes.pop(0)
if self._next_account_change["host"] == self.current_host:
# do a local password change
- self.chosen_action = "node-accounts-change-password", {
+ self.chosen_action = "node-account-change-password", {
"node_name": self.current_host,
"username": self._next_account_change["username"],
"current_password": self.network_knowledge["credentials"][self.current_host]["password"],
@@ -382,14 +384,15 @@ class TAP003(AbstractTAP, discriminator="tap-003"):
],
}
self.logger.info(f"Changing password on remote node {hostname}")
- self._next_account_change = account_changes.pop(0)
+ if len(account_changes) == 0:
+ self.logger.info("No further account changes required.")
+ self._next_account_change = None
+ else:
+ self._next_account_change = account_changes.pop(0)
self._change_password_target_host = hostname
- if len(account_changes) == 0:
- self._next_account_change = None
- self.logger.info("Finished changing passwords.")
+ if not self._next_account_change:
+ self.logger.info("Manipulation complete. Progressing to exploit...")
self._progress_kill_chain()
-
- self.current_stage_progress = KillChainStageProgress.PENDING
else:
if self.config.agent_settings.repeat_kill_chain_stages == False:
self.current_kill_chain_stage = self.selected_kill_chain.FAILED
diff --git a/src/primaite/game/game.py b/src/primaite/game/game.py
index a3b77ec3..a3a790cc 100644
--- a/src/primaite/game/game.py
+++ b/src/primaite/game/game.py
@@ -14,6 +14,7 @@ from primaite.simulator import SIM_OUTPUT
from primaite.simulator.network.creation import NetworkNodeAdder
from primaite.simulator.network.hardware.base import NetworkInterface, Node, NodeOperatingState, UserManager
from primaite.simulator.network.hardware.nodes.host.host_node import NIC
+from primaite.simulator.network.hardware.nodes.network.firewall import Firewall # noqa: F401
from primaite.simulator.network.hardware.nodes.network.switch import Switch
from primaite.simulator.network.hardware.nodes.network.wireless_router import WirelessRouter
from primaite.simulator.network.nmne import NMNEConfig
diff --git a/src/primaite/notebooks/Command-and-Control-E2E-Demonstration.ipynb b/src/primaite/notebooks/Command-and-Control-E2E-Demonstration.ipynb
index f187c8d5..f918c725 100644
--- a/src/primaite/notebooks/Command-and-Control-E2E-Demonstration.ipynb
+++ b/src/primaite/notebooks/Command-and-Control-E2E-Demonstration.ipynb
@@ -1041,7 +1041,7 @@
"outputs": [],
"source": [
"# Attempting to install the C2 RansomwareScript\n",
- "ransomware_install_command = {\"commands\":[[\"software_manager\", \"application\", \"install\", \"RansomwareScript\"]],\n",
+ "ransomware_install_command = {\"commands\":[[\"software_manager\", \"application\", \"install\", \"ransomware-script\"]],\n",
" \"username\": \"admin\",\n",
" \"password\": \"admin\"}\n",
"\n",
@@ -1129,7 +1129,7 @@
"outputs": [],
"source": [
"# Attempting to install the C2 RansomwareScript\n",
- "ransomware_install_command = {\"commands\":[\"software_manager\", \"application\", \"install\", \"RansomwareScript\"],\n",
+ "ransomware_install_command = {\"commands\":[\"software_manager\", \"application\", \"install\", \"ransomware-script\"],\n",
" \"username\": \"admin\",\n",
" \"password\": \"admin\"}\n",
"\n",
@@ -1254,7 +1254,7 @@
"metadata": {},
"outputs": [],
"source": [
- "database_server: Server = blue_env.game.simulation.network.get_node_by_hostname(\"database_server\")\n",
+ "database_server: Server = blue_env.game.simulation.network.get_node_by_hostname(\"database-server\")\n",
"database_server.software_manager.file_system.show(full=True)"
]
},
@@ -1670,6 +1670,16 @@
"\n",
"display_obs_diffs(tcp_c2_obs, udp_c2_obs, blue_config_env.game.step_counter)"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "env.game.agents[\"CustomC2Agent\"].show_history()"
+ ]
}
],
"metadata": {
diff --git a/src/primaite/notebooks/Data-Manipulation-E2E-Demonstration.ipynb b/src/primaite/notebooks/Data-Manipulation-E2E-Demonstration.ipynb
index 562f0f91..e7da2d15 100644
--- a/src/primaite/notebooks/Data-Manipulation-E2E-Demonstration.ipynb
+++ b/src/primaite/notebooks/Data-Manipulation-E2E-Demonstration.ipynb
@@ -380,18 +380,6 @@
"!primaite setup"
]
},
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "tags": []
- },
- "outputs": [],
- "source": [
- "%load_ext autoreload\n",
- "%autoreload 2"
- ]
- },
{
"cell_type": "code",
"execution_count": null,
@@ -712,7 +700,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python 3 (ipykernel)",
+ "display_name": ".venv",
"language": "python",
"name": "python3"
},
@@ -726,7 +714,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.10.11"
+ "version": "3.10.12"
}
},
"nbformat": 4,
diff --git a/src/primaite/notebooks/Terminal-Processing.ipynb b/src/primaite/notebooks/Terminal-Processing.ipynb
index 755b0184..55de6b1f 100644
--- a/src/primaite/notebooks/Terminal-Processing.ipynb
+++ b/src/primaite/notebooks/Terminal-Processing.ipynb
@@ -16,6 +16,13 @@
"## Simulation Layer Implementation."
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Simulation Layer Implementation."
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
diff --git a/src/primaite/notebooks/UC7-E2E-Demo.ipynb b/src/primaite/notebooks/UC7-E2E-Demo.ipynb
new file mode 100644
index 00000000..a1cbdd22
--- /dev/null
+++ b/src/primaite/notebooks/UC7-E2E-Demo.ipynb
@@ -0,0 +1,1619 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# UC7 Demonstration\n",
+ "\n",
+ "© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK\n",
+ "\n",
+ "\n",
+ "UC7 is a cybersecurity scenario set in a generic medium sized organisation, where multiple LAN networks which interconnect via the 'internet' to represent a corporate WAN. Comprising of four major networks; `Home Office (HOME)`, `INTERNET (ISP)`, `REMOTE SITE (REMOTE)` and the larger main site `SOME_TECH`. Each network is comprised of routers, switches, computers and servers which green agents use to represent a more real-world accurate pattern of life.\n",
+ "\n",
+ "Intended to be a step-up from the [smaller network of UC2](./Data-Manipulation-E2E-Demonstration.ipynb), UC7 introduces two new potential attacks (TAPS) that the blue agent must defend against. \n",
+ "\n",
+ "_This notebook acts as the starting point for any users unfamiliar with UC7 and will also sign post to any other UC7 relevant notebooks for further information._"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "!primaite setup"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from primaite.session.environment import PrimaiteGymEnv\n",
+ "from primaite.simulator.network.hardware.nodes.host.computer import Computer\n",
+ "from primaite.simulator.network.hardware.nodes.host.server import Server\n",
+ "from primaite.simulator.network.hardware.nodes.network.router import Router\n",
+ "from primaite.simulator.system.services.dns.dns_server import DNSServer\n",
+ "from primaite.simulator.system.software import SoftwareHealthState\n",
+ "from primaite.simulator.file_system.file_system_item_abc import FileSystemItemHealthStatus\n",
+ "from primaite.simulator.network.hardware.nodes.network.switch import Switch\n",
+ "from primaite.simulator.system.applications.web_browser import WebBrowser\n",
+ "from primaite.simulator.network.container import Network\n",
+ "from primaite.simulator.system.services.service import ServiceOperatingState\n",
+ "from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState\n",
+ "from primaite.simulator.system.services.database.database_service import DatabaseService\n",
+ "from primaite.simulator.system.applications.database_client import DatabaseClient\n",
+ "from primaite.simulator.network.hardware.nodes.network.firewall import Firewall\n",
+ "from primaite.game.game import PrimaiteGame\n",
+ "from primaite.simulator.sim_container import Simulation\n",
+ "import yaml\n",
+ "from pprint import pprint\n",
+ "from primaite.config.load import load, _EXAMPLE_CFG"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "use_case_7_config = load(_EXAMPLE_CFG/\"uc7_config.yaml\")\n",
+ "with open(file=_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as uc7_config:\n",
+ " cfg = yaml.safe_load(uc7_config)\n",
+ " cfg['io_settings']['save_sys_logs'] = True # Saving syslogs\n",
+ " cfg['io_settings']['save_agent_logs'] = True # Save agent logs\n",
+ "env = PrimaiteGymEnv(env_config=use_case_7_config)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Table of Contents\n",
+ "\n",
+ "- [Network Description](#network-description)\n",
+ " - [Home Office](#network--home-office)\n",
+ " - [Internet](#network--internet)\n",
+ " - [Remote Site](#network--remote-site)\n",
+ " - [ST DMZ](#network--some_tech-dmz)\n",
+ " - [ST Main Site](#network--some_tech-main-site)\n",
+ " - [ST Head Office](#network--some_tech-main-site--some_tech-head-office-st_ho)\n",
+ " - [ST Human Resources](#network--some_tech-main-site--some_tech-human-resources-st_hr)\n",
+ " - [ST Data](#network--some_tech-main-site--some_tech-data-st_data)\n",
+ " - [ST Project A](#network--some_tech-main-site--some_tech-project-a-st_proj_a)\n",
+ " - [ST Project B](#network--some_tech-main-site--some_tech-project-b-st_proj_b)\n",
+ " - [ST Project C](#network--some_tech-main-site--some_tech-project-c-st_proj_c)\n",
+ "- [Agents](#agent-description)\n",
+ " - [Green POL](#agents--green-pattern-of-life-pol)\n",
+ " - [DatabaseService](#agents--green-pattern-of-life-pol--database-service)\n",
+ " - [web-server](#agents--green-pattern-of-life-pol--web-server)\n",
+ " - [Red Agent](#agents--red-agent)\n",
+ " - [TAP001](#agents--red-agent--threat-actor-profile-001-tap001)\n",
+ " - [TAP003](#agents--red-agent--threat-actor-profile-003-tap003)\n",
+ " - [Blue Agent](#agents--blue-agent)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## NETWORK DESCRIPTION\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "uc7_network = env.game.simulation.network\n",
+ "uc7_network.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "| Default Computer Software |\n",
+ "|------------------|\n",
+ "| DNS Client (Service) | \n",
+ "| NTP Client (Service) | \n",
+ "| web-browser (Application) |\n",
+ "| database-client (Application) | "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "| Default Server Software |\n",
+ "|------------------|\n",
+ "| DNS Client (Service) | \n",
+ "| NTP Client (Service) | "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### NETWORK | HOME OFFICE \n",
+ "\n",
+ "The HOME OFFICE (HOME) network simulates a generic home office that consist of the following:\n",
+ "\n",
+ "- A main LAN with two computers (`HOME-PUB-PC-1`/`2`) and a server (`HOME-PUB-SRV`) using default configurations.\n",
+ "- A switch (`HOME-PUB-SW-AS`) which connects the above hosts.\n",
+ "- Lastly, a router (`HOME-PUB-RT-DR`) which connects the home office to the wider networks. \n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Home Office PC 1 (HOME-PUB-PC-1)\n",
+ "home_pub_pc_1: Computer = env.game.simulation.network.get_node_by_hostname(\"HOME-PUB-PC-1\")\n",
+ "home_pub_pc_1.show()\n",
+ "home_pub_pc_1.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Home Office Router (HOME-PUB-RT-DR)\n",
+ "home_pub_rt_dr: Router = env.game.simulation.network.get_node_by_hostname(\"HOME-PUB-RT-DR\")\n",
+ "home_pub_rt_dr.show_nic()\n",
+ "home_pub_rt_dr.show_open_ports()\n",
+ "home_pub_rt_dr.acl.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### NETWORK | INTERNET (ISP)\n",
+ "\n",
+ "The internet (ISP) network intends to represent the internet. Currently, it's not feasible or possible for PrimAITE to simulate an internet service provider as well as the internet as a whole to a high degree of fidelity. Thus, in UC7, the \"internet\" refers to the following:\n",
+ "\n",
+ "- A router (`ISP-PUB-RT-BR`) which connects the all other UC7 LANS together. \n",
+ "- A server (`ISP-PUB-SRV-DNS`) which acts as the public DNS server that all PC's use. (Default IP of this host is *8.8.8.8*) "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "isp_pub_rt_br: Router = env.game.simulation.network.get_node_by_hostname(\"ISP-PUB-RT-BR\")\n",
+ "isp_pub_rt_br.show_nic()\n",
+ "isp_pub_rt_br.show_open_ports()\n",
+ "isp_pub_rt_br.acl.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "isp_pub_srv_dns: Server = env.game.simulation.network.get_node_by_hostname(\"ISP-PUB-SRV-DNS\")\n",
+ "isp_pub_srv_dns.show_nic()\n",
+ "isp_pub_srv_dns_server: DNSServer = isp_pub_srv_dns.software_manager.software[\"dns-server\"]\n",
+ "isp_pub_srv_dns_server.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### NETWORK | REMOTE SITE \n",
+ "\n",
+ "The remote site (`REMOTE`) network is similar to the previously introduced `HOME` network but includes a firewall between the `ISP` and the `REMOTE` network:\n",
+ "\n",
+ "- A main LAN with two computers (`REM-PUB-PC-1`/`2`) and a server (`REM-PUB-SRV`) using default configurations.\n",
+ "- A switch (`REM-PUB-SW-AS`) which connects the above hosts.\n",
+ "- A router (`HOME-PUB-RT-DR`) which connects the home office to a firewall (`REM-PUB-FW`) which then connects back to the `INTERNET` network.\n",
+ "\n",
+ "By default the `REM-PUB-FW` will not block any traffic."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "rem_pub_fw: Firewall = uc7_network.get_node_by_hostname(hostname=\"REM-PUB-FW\")\n",
+ "rem_pub_fw.show_nic()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# By default all of the `REM_PUB_FW` acls are configured to permit all traffic\n",
+ "rem_pub_fw.acl.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### NETWORK | SOME_TECH DMZ (ST DMZ)\n",
+ "\n",
+ "The `ST_DMZ` network is a small but important segment which sits between the `INTERNET` network (and thus the `REMOTE` and `HOME` networks as well) and the wider `SOME_TECH` main site networks. Additionally, accessible through the `ST_DMZ` firewall (`ST-PUB-FW`)'s DMZ port is a server which hosts a `web-server` that is accessible to all hosts in the UC7 network."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST DMZ Public Firewall (Permits all traffic by default)\n",
+ "st_pub_fw: Firewall = uc7_network.get_node_by_hostname(hostname=\"ST_PUB-FW\")\n",
+ "st_pub_fw.show_nic()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST DMZ Public web-server\n",
+ "st_dmz_pub_srv_web: Server = uc7_network.get_node_by_hostname(hostname=\"ST_DMZ-PUB-SRV-WEB\")\n",
+ "st_dmz_pub_srv_web.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### NETWORK | SOME_TECH MAIN SITE\n",
+ "\n",
+ "SOME TECH's main site is comprised of 6 different networks:\n",
+ "\n",
+ "| ST Network | Purpose |\n",
+ "|------------|---------|\n",
+ "| `ST_HO` | Some Tech's Head Office. |\n",
+ "| `ST_HR` | Some Tech's Human Resourcing department |\n",
+ "| `ST_DATA` | Contains the ST database and backup server (FTP) |\n",
+ "| `ST_PROJ_A` | Development Network |\n",
+ "| `ST_PROJ_B` | Development Network |\n",
+ "| `ST_PROJ_C` | Development Network |\n",
+ "\n",
+ "In order for hosts to communicate between each network and the wider internet, the main site utilises three routers' `ST_INTRA-PRV-RT-DR-1`, `ST_INTRA-PRV-RT-DR-2` and `ST_INTRA-PRV-RT-CR`.\n",
+ "\n",
+ "The `ST_INTRA-PRV-RT-DR-1` router is responsible for routing all traffic from the `ST_PROJ_A`/`B`/`C` networks whereas the `ST_INTRA-PRV-RT-DR-2` router routes all traffic from the `ST_HO`/`HR` networks. Both of which then forward all traffic to the main `ST_INTRA-PRV-RT-CR` router. \n",
+ "\n",
+ "This central router connects to the `ST_DMZ` firewall (`ST-PUB-FW`) as well as any traffic that is headed to the `ST_DATA` (the ST database and database storage) network.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_intra_prv_rt_cr: Router = uc7_network.get_node_by_hostname(hostname=\"ST_INTRA-PRV-RT-CR\")\n",
+ "st_intra_prv_rt_cr.route_table.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_intra_prv_rt_dr_1: Router = uc7_network.get_node_by_hostname(hostname=\"ST_INTRA-PRV-RT-DR-1\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_intra_prv_rt_dr_2: Router = uc7_network.get_node_by_hostname(hostname=\"ST_INTRA-PRV-RT-DR-2\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### NETWORK | SOME_TECH MAIN SITE | SOME_TECH HEAD OFFICE (ST_HO)\n",
+ "\n",
+ "The some tech head office (`ST_HO`) is a simple LAN containing three computers with the default PC configuration."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_head_office_private_pc_1: Computer = uc7_network.get_node_by_hostname(\"ST_HO-PRV-PC-1\")\n",
+ "st_head_office_private_pc_1.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### NETWORK | SOME_TECH MAIN SITE | SOME_TECH HUMAN RESOURCES (ST_HR)\n",
+ "\n",
+ "Similarly, the some tech head human resources office (`ST_HR`) consisting of three default PC configurations computers."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_human_resources_private_pc_2: Computer = uc7_network.get_node_by_hostname(\"ST_HR-PRV-PC-2\")\n",
+ "st_human_resources_private_pc_2.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### NETWORK | SOME_TECH MAIN SITE | SOME_TECH DATA (ST_DATA)\n",
+ "\n",
+ "The `ST_DATA` networks contains two servers pivotal to the daily operation of SOME_TECH.\n",
+ "\n",
+ "| Server | Purpose |\n",
+ "|--------|---------|\n",
+ "| `ST_DATA-PRV-SRV-DB` | Hosts the `database-service` that all `database-client` are configured to use. | \n",
+ "| `ST_DATA-PRV-SRV-STORAGE`| Acts as a storage server for the `ST_DATA-PRV-SRV-DB`. |"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_data_private_server_database: Server = uc7_network.get_node_by_hostname(\"ST_DATA-PRV-SRV-DB\")\n",
+ "st_data_private_server_database_service: DatabaseService = st_data_private_server_database.software_manager.software[\"database-service\"]\n",
+ "st_data_private_server_database.software_manager.show()\n",
+ "st_data_private_server_database.software_manager.file_system.show(full=True)\n",
+ "st_data_private_server_database_service.backup_server_ip"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_data_private_server_storage: Server = uc7_network.get_node_by_hostname(\"ST_DATA-PRV-SRV-STORAGE\")\n",
+ "st_data_private_server_storage.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### NETWORK | SOME_TECH MAIN SITE | SOME_TECH PROJECT A (ST_PROJ_A)\n",
+ "\n",
+ "All of the `ST_PROJ_A`/`B`/`C` project networks contain three computers and a switch which connects to the `ST_INTRA-PRV-RT-DR-1` router (as described previously)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_a_private_pc_1: Computer = uc7_network.get_node_by_hostname(\"ST_PROJ-A-PRV-PC-1\")\n",
+ "st_project_a_private_pc_1.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### NETWORK | SOME_TECH MAIN SITE | SOME_TECH PROJECT B (ST_PROJ_B)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_b_private_pc_2: Computer = uc7_network.get_node_by_hostname(\"ST_PROJ-B-PRV-PC-2\")\n",
+ "st_project_b_private_pc_2.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### NETWORK | SOME_TECH MAIN SITE | SOME_TECH PROJECT C (ST_PROJ_C)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_c_private_pc_3: Computer = uc7_network.get_node_by_hostname(\"ST_PROJ-C-PRV-PC-3\")\n",
+ "st_project_c_private_pc_3.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Use Case 7 Agent Description / Demonstration"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### AGENTS | Green Pattern of Life (*PoL*)\n",
+ "\n",
+ "The UC7 green pattern of life refers to the traffic and behaviour generated by the default `32` different green agents. For each host on the UC7 network, two green agents will attempt to execute the `web-browser` and `database-client` applications and receive a positive or negative reward dependant on whenever they are successful or not.\n",
+ "\n",
+ "The table below gives a summary of the different green agent behaviour split between the different UC7 networks.\n",
+ "\n",
+ "| **Network** |**Agent Host** | **Application** | **Behaviour Type** | **Probabilities** | **Start Step** | **Start Variance** | **Frequency** | **Variance** | **Reward Impact** |\n",
+ "|:-----------:|:-------:|:---------------:|:------------------:|:-----------------:|:--------------:|:------------------:|:-------------:|:------------:|:------------------:|\n",
+ "| `HOME SITE` |`HOME-PUB-PC-1`| `database-client`| *Periodic* | |**4** |**1** |**4** |**1** |**MEDIUM** |\n",
+ "| `HOME SITE` |`HOME-PUB-PC-2`| `database-client`| *Periodic* | |**8** |**1** |**4** |**1** |**MEDIUM** |\n",
+ "| `HOME SITE` |`HOME-PUB-PC-1`/`2`| `web-browser` | *Probabilistic* |**20%** | | | | |**LOW** |\n",
+ "| `REMOTE SITE` |`REM-PUB-PC-1`| `database-client`| *Periodic* | |**12** |**1** |**4** |**1** |**MEDIUM** |\n",
+ "| `REMOTE SITE` |`REM-PUB-PC-2`| `database-client`| *Periodic* | |**16** |**1** |**4** |**1** |**MEDIUM** |\n",
+ "| `REMOTE SITE` |`REM-PUB-PC-1`/`2`| `web-browser` | *Probabilistic* |**20%** | | | | |**LOW** |\n",
+ "| `ST PROJECT A`/`B`/`C` |`ST_PROJ-*-PRV-PC-1`| `database-client`| *Periodic* | |**1** |**1** |**4** |**1** |**HIGH** |\n",
+ "| `ST PROJECT A`/`B`/`C` |`ST_PROJ-*-PRV-PC-1`| `web-browser` | *Probabilistic* |**40%** | | | | |**LOW** |\n",
+ "| `ST PROJECT A`/`B`/`C` |`ST_PROJ-*-PRV-PC-2`/`3`| `database-client`| *Periodic* | |**1** |**1** |**4** |**1** |**MEDIUM** |\n",
+ "| `ST PROJECT A`/`B`/`C` |`ST_PROJ-*-PRV-PC-2`/`3`| `web-browser` | *Probabilistic* |**20%** | | | | |**LOW** |\n",
+ "| `ST HEAD OFFICE` |`ST-HO-PRV-PC-1`| `web-browser` | *Probabilistic* |**60%** | | | | |**HIGH** |\n",
+ "| `ST HEAD OFFICE` |`ST-HO-PRV-PC-2`/`3`| `web-browser` | *Probabilistic* |**60%** | | | | |**MEDIUM** |\n",
+ "| `ST HUMAN RESOURCES` |`ST_HR-PRV-PC-1`| `web-browser` | *Probabilistic* |**60%** | | | | |**MEDIUM** |\n",
+ "| `ST HUMAN RESOURCES` |`ST_HR-PRV-PC-2`/`3`| `web-browser` | *Probabilistic* |**60%** | | | | |**LOW** |\n",
+ "\n",
+ "\n",
+ "For the full details on each green agent then please click on the drop-down menu below:\n",
+ "\n",
+ "\n",
+ " UC7 Green Agent Full Details \n",
+ "\n",
+ " **ID** | **PoL Type** | **Description of Activity** | **Agent Name** | **Source Node** | **Source App / Service** | **Destination Node** | **Destination App / Service** | **Transport Protocol** | **Application Protocol** | **Behaviour Type** | **Probabilities** | **Start Step** | **Start Variance** | **Max Executions** | **Frequency** | **Variance** | **Reward Impact** \n",
+ ":------:|:------------:|:---------------------------------------------------:|:-------------------:|:------------------:|:------------------------:|:-----------------------:|:-----------------------------:|:----------------------:|:------------------------:|:------------------:|:-----------------:|:--------------:|:------------------:|:------------------:|:-------------:|:------------:|:-----------------:\n",
+ " 1 | AGENT | Home Worker accessing Some Tech database | HOME_WORKER-1 | HOME-PUB-PC-1 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 4 | 1 | 1000 | 4 | 1 | MEDIUM \n",
+ " 2 | AGENT | Home Worker accessing Some Tech web pages | HOME_WORKER-1 | HOME-PUB-PC-1 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 20% chance | | | | | | LOW \n",
+ " 3 | AGENT | Home Worker accessing Some Tech database | HOME_WORKER-2 | HOME-PUB-PC-2 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 8 | 1 | 1000 | 4 | 1 | MEDIUM \n",
+ " 4 | AGENT | Home Worker accessing Some Tech web pages | HOME_WORKER-2 | HOME-PUB-PC-2 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 20% chance | | | | | | LOW \n",
+ " 5 | AGENT | Remote Worker accessing Some Tech database | REMOTE_WORKER-1 | REM-PUB-PC-1 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 12 | 1 | 1000 | 4 | 1 | MEDIUM \n",
+ " 6 | AGENT | Remote Worker accessing Some Tech web pages | REMOTE_WORKER-1 | REM-PUB-PC-1 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 20% chance | | | | | | LOW \n",
+ " 7 | AGENT | Remote Worker accessing Some Tech database | REMOTE_WORKER-2 | REM-PUB-PC-2 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 16 | 1 | 1000 | 4 | 1 | MEDIUM \n",
+ " 8 | AGENT | Remote Worker accessing Some Tech web pages | REMOTE_WORKER-2 | REM-PUB-PC-2 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 20% chance | | | | | | LOW \n",
+ " 9 | AGENT | Senior Developer accessing Some Tech database | PROJ_A-SENIOR_DEV | ST_PROJ_A-PRV-PC-1 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 1 | 1 | 1000 | 4 | 1 | HIGH \n",
+ " 10 | AGENT | Senior Developer accessing Some Tech web pages | PROJ_A-SENIOR_DEV | ST_PROJ_A-PRV-PC-1 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 40% chance | | | | | | LOW \n",
+ " 11 | AGENT | Junior Developer accessing Some Tech database | PROJ_A-JUNIOR_DEV-1 | ST_PROJ_A-PRV-PC-2 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 1 | 1 | 1000 | 4 | 1 | MEDIUM \n",
+ " 12 | AGENT | Junior Developer accessing Some Tech web pages | PROJ_A-JUNIOR_DEV-1 | ST_PROJ_A-PRV-PC-2 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 20% chance | | | | | | LOW \n",
+ " 13 | AGENT | Junior Developer accessing Some Tech database | PROJ_A-JUNIOR_DEV-2 | ST_PROJ_A-PRV-PC-3 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 1 | 1 | 1000 | 4 | 1 | MEDIUM \n",
+ " 14 | AGENT | Junior Developer accessing Some Tech web pages | PROJ_A-JUNIOR_DEV-2 | ST_PROJ_A-PRV-PC-3 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 20% chance | | | | | | LOW \n",
+ " 15 | AGENT | Senior Developer accessing Some Tech database | PROJ_B-SENIOR_DEV | ST_PROJ_B-PRV-PC-1 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 1 | 1 | 1000 | 4 | 1 | HIGH \n",
+ " 16 | AGENT | Senior Developer accessing Some Tech web pages | PROJ_B-SENIOR_DEV | ST_PROJ_B-PRV-PC-1 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 40% chance | | | | | | LOW \n",
+ " 17 | AGENT | Junior Developer accessing Some Tech database | PROJ_B-JUNIOR_DEV-1 | ST_PROJ_B-PRV-PC-2 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 1 | 1 | 1000 | 4 | 1 | MEDIUM \n",
+ " 18 | AGENT | Junior Developer accessing Some Tech web pages | PROJ_B-JUNIOR_DEV-1 | ST_PROJ_B-PRV-PC-2 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 20% chance | | | | | | LOW \n",
+ " 19 | AGENT | Junior Developer accessing Some Tech database | PROJ_B-JUNIOR_DEV-2 | ST_PROJ_B-PRV-PC-3 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 1 | 1 | 1000 | 4 | 1 | MEDIUM \n",
+ " 20 | AGENT | Junior Developer accessing Some Tech web pages | PROJ_B-JUNIOR_DEV-2 | ST_PROJ_B-PRV-PC-3 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 20% chance | | | | | | LOW \n",
+ " 21 | AGENT | Senior Developer accessing Some Tech database | PROJ_C-SENIOR_DEV | ST_PROJ_C-PRV-PC-1 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 1 | 1 | 1000 | 4 | 1 | HIGH \n",
+ " 22 | AGENT | Senior Developer accessing Some Tech web pages | PROJ_C-SENIOR_DEV | ST_PROJ_C-PRV-PC-1 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 40% chance | | | | | | LOW \n",
+ " 23 | AGENT | Junior Developer accessing Some Tech database | PROJ_C-JUNIOR_DEV-1 | ST_PROJ_C-PRV-PC-2 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 1 | 1 | 1000 | 4 | 1 | MEDIUM \n",
+ " 24 | AGENT | Junior Developer accessing Some Tech web pages | PROJ_C-JUNIOR_DEV-1 | ST_PROJ_C-PRV-PC-2 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 20% chance | | | | | | LOW \n",
+ " 25 | AGENT | Junior Developer accessing Some Tech database | PROJ_C-JUNIOR_DEV-2 | ST_PROJ_C-PRV-PC-3 | Database Client | ST_DATA-PRV-SRV-DB | Database Service | TCP | PostgreSQL | PERIODIC | | 1 | 1 | 1000 | 4 | 1 | MEDIUM \n",
+ " 26 | AGENT | Junior Developer accessing Some Tech web pages | PROJ_C-JUNIOR_DEV-2 | ST_PROJ_C-PRV-PC-3 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 20% chance | | | | | | LOW \n",
+ " 27 | AGENT | CEO accessing Some Tech web pages | CEO | ST_HO-PRV-PC-1 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 60% chance | | | | | | HIGH \n",
+ " 28 | AGENT | CTO accessing Some Tech web pages | CTO | ST_HO-PRV-PC-2 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 60% chance | | | | | | MEDIUM \n",
+ " 29 | AGENT | CFO accessing Some Tech web pages | CFO | ST_HO-PRV-PC-3 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 60% chance | | | | | | MEDIUM \n",
+ " 30 | AGENT | Senior HR accessing Some Tech web pages | SENIOR_HR | ST_HR-PRV-PC-1 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 60% chance | | | | | | MEDIUM \n",
+ " 31 | AGENT | Junior HR accessing Some Tech web pages | JUNIOR_HR-1 | ST_HR-PRV-PC-2 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | HTTPS | PROBABILISTIC | 60% chance | | | | | | LOW \n",
+ " 32 | AGENT | Junior HR accessing Some Tech web pages | JUNIOR_HR-2 | ST_HR-PRV-PC-3 | Web Browser | ST_DMZ-PUB-SRV-WEB | Web Server | TCP | \n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### AGENTS | Green *PoL* | database-client Agents Demo\n",
+ "\n",
+ "The `database-client` green agents will attempt to use their host's `database-client` application to make a simple connection to the `database-service` on the `ST_DATA-PRV-SRV-DB` host (these connections have no direct impact to the `database-service` or the `database.db` file itself).\n",
+ "\n",
+ "Additionally, `database-client` green agents are *Periodic* meaning they will attempt to use the database based on game time-steps. Specifically, these agents will begin on the time-step given in their `start step` setting and will then will reattempt on each subsequence timestep based on the `Frequency` setting. These settings are then randomised using the remaining `Start Variance` and `Variance` options (also given in timesteps). These values are used to *±* their respective base settings to ensure the green agents achieve a moderate amount of domain randomisation in each PrimAITE episode.\n",
+ "\n",
+ "For example, take a *Periodic* green agent set with a `start_step` of 4 and a `frequency` of **4** with a `start_variance` and a `variance` of **4** will cause a green agent to make it's first action on timestep $4 \\pm 1$ and then any subsequent actions every $4 \\pm 1$ timesteps afterwards.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset() # Resetting the simulation\n",
+ "home_pub_pc_1_database_green_agent = env.game.agents.get(\"HOME_WORKER-1-DB\")\n",
+ "for time_step in range(10):\n",
+ " env.step(0)\n",
+ " if not home_pub_pc_1_database_green_agent.history[time_step].action == 'DONOTHING':\n",
+ " print(home_pub_pc_1_database_green_agent.history[time_step])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "home_pub_pc_1.software_manager.software[\"database-client\"].sys_log.show(last_n=10)\n",
+ "st_data_private_server_database.software_manager.software[\"database-service\"].sys_log.show(last_n=5)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### AGENTS | Green *PoL* | web-browser Agents Demo\n",
+ "\n",
+ "Unlike the `database-client` green agents, the `web-browser` green agents are *probabilistic*. These agents are quite simple; on every timestep a probability roll is made to determine whenever the agent acts. On a successful outcome the agent will attempt to execute the `web-browser` application which will then attempt to connect to the `ST-DMZ-PUB-SRV-WEB` host (Some Tech's web-server). On a unsuccessful outcome then the green agent will simply perform not action on this timestep.\n",
+ "\n",
+ "For example, a `web-browser` green agent with a `20%` chance has a $\\frac{1}{5}$ chance of actioning it's host's `web-browser` to access the `ST-DMZ-PUB-SRV-WEB` web-server. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset() # Resetting the simulation\n",
+ "home_pub_pc_1_web_browser_green_agent = env.game.agents.get(\"HOME_WORKER-1-WEB\")\n",
+ "for time_step in range(10):\n",
+ " env.step(0)\n",
+ " if not home_pub_pc_1_web_browser_green_agent.history[time_step].action == 'DONOTHING':\n",
+ " print(home_pub_pc_1_web_browser_green_agent.history[time_step])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "home_pub_pc_1: Computer = env.game.simulation.network.get_node_by_hostname(\"HOME-PUB-PC-1\")\n",
+ "home_pub_pc_1_web_browser_green_agent.logger.show()\n",
+ "home_pub_pc_1_web_browser: WebBrowser = home_pub_pc_1.software_manager.software[\"web-browser\"]\n",
+ "home_pub_pc_1_web_browser.sys_log.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### AGENTS | Red Agent\n",
+ "\n",
+ "For UC7, two new red agents have been developed which introduce a much more complex and realistic attacks in comparison to UC2's [data manipulation red agent](./Data-Manipulation-Customising-Red-Agent.ipynb) for the blue agent to defend against. These new red agents, or more commonly referred to `Threat Actor Profiles` (_TAPS_), utilise a series of different green, blue and red actions to simulate the different steps of a real-world attack.\n",
+ "\n",
+ "This notebook does not cover the red agents in much detail, hence it is highly recommended that readers should check out the respective TAP notebooks for a much more in-depth look at each TAP and their impacts.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### AGENTS | RED AGENT | Threat Actor Profile 001 (TAP001)\n",
+ "\n",
+ "This TAP aims to exfiltrate and then encrypt the `database.db` file on `ST_DATA-PRV-SRV-DB` host, whilst leaving the functionality of the database intact. Configured by default to start on the `ST_PROJ-A-PRV-PC-1` host, `TAP001` must first embed itself on the host, locate the target (`ST_DATA-PRV-SRV-DB`) through a series of NMAP scans, establish a connection to it's `C2Server` (`ISP-PUB-SRV-DNS` by default) and then finally attempt to exfiltrate and encrypt. \n",
+ "\n",
+ "If successful, the blue agent is configured to receive a serve negative reward and thus must prevent `TAP001` from ever reaching the target database. This could be through blocking it's connection to the target or it's `C2Server` via a carefully crafted ACL or perhaps through more a forceful approach such as shutting down the starting host.\n",
+ "\n",
+ "For more information on `TAP001` and it's impacts, [please refer to the TAP001 E2E notebook](./UC7-TAP001-Kill-Chain-E2E.ipynb) or for more blue agent involved demonstration refer to the [UC7 attack variants notebook](./UC7-attack-variants.ipynb) "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# By default the `uc7_config.yaml` is setup to use TAP001\n",
+ "env.reset()\n",
+ "for _ in range(80):\n",
+ " env.step(action=0)\n",
+ "\n",
+ "uc7_tap001 = env.game.agents.get(\"attacker\")\n",
+ "uc7_tap001.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# TAP001 starting host\n",
+ "st_project_a_private_pc_1: Computer = env.game.simulation.network.get_node_by_hostname(\"ST_PROJ-A-PRV-PC-1\")\n",
+ "st_project_a_private_pc_1.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_a_private_pc_1.file_system.show(full=True)\n",
+ "isp_pub_srv_dns: Server = env.game.simulation.network.get_node_by_hostname(hostname=\"ISP-PUB-SRV-DNS\")\n",
+ "isp_pub_srv_dns.file_system.show(full=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Database Impact \n",
+ "st_data_private_server_database: Server = env.game.simulation.network.get_node_by_hostname(hostname=\"ST_DATA-PRV-SRV-DB\")\n",
+ "st_data_private_server_database.file_system.show(full=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### AGENTS | RED AGENT | Threat Actor Profile 003 (TAP003)\n",
+ "\n",
+ "Unlike `TAP001` more traditional representation of a threat actor, `TAP003` represents a malicious insider which leverages it's pre-existing knowledge to covertly add malicious access control lists (ACLs) to three different routers each of which affecting green agent traffic in a different way causing the blue agent to receive negative rewards. Thus, the blue agent must learn to leverage it's ability to remove rules and change credentials throughout the network to rectify the impacts of `TA003` and re-establish green POL and prevent TAP003 from accessing additional routers.\n",
+ "\n",
+ "The table below is a brief summary of the malicious acls added by `TAP003`\n",
+ "\n",
+ "|Target Router | Impact |\n",
+ "|----------------------|--------|\n",
+ "|`ST_INTRA-PRV-RT-DR-1`| Blocks all `POSTGRES_SERVER` that arrives at the `ST_INTRA-PRV-RT-DR-1` router. This rule will prevent all ST_PROJ_* hosts from accessing the database (`ST_DATA-PRV-SRV-DB`).|\n",
+ "|`ST_INTRA-PRV-RT-CR`| Blocks all `HTTP` traffic that arrives at the`ST_INTRA-PRV-RT-CR` router. This rule will prevent all SOME_TECH hosts from accessing the web-server (`ST-DMZ-PUB-SRV-WEB`)|\n",
+ "|`REM-PUB-RT-DR`| Blocks all `DNS` traffic that arrives at the `REM-PUB-RT-DR` router. This rule prevents any remote site works from accessing the DNS Server (`ISP-PUB-SRV-DNS`).|\n",
+ "\n",
+ "Lastly, it's highly recommended that users refer to the [TAP003 E2E notebook](./UC7-TAP003-Kill-Chain-E2E.ipynb) for further information or for the [UC7 attack variants notebook](./UC7-attack-variants.ipynb) demonstration of TAP003 defence."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Loading up the TAP003 UC7 config variant\n",
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as uc7_config:\n",
+ " cfg = yaml.safe_load(uc7_config)\n",
+ " cfg[\"agents\"][33][\"agent_settings\"][\"flatten_obs\"] = False\n",
+ " cfg['io_settings']['save_sys_logs'] = True # Saving syslogs\n",
+ " cfg['io_settings']['save_agent_logs'] = True # Saving agent logs\n",
+ "\n",
+ "env = PrimaiteGymEnv(env_config=cfg)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# By default the `uc7_config.yaml` is setup to use TAP001\n",
+ "env.reset()\n",
+ "for _ in range(128):\n",
+ " env.step(action=0)\n",
+ "\n",
+ "uc7_tap003 = env.game.agents.get(\"attacker\")\n",
+ "uc7_tap003.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-DR-1\").acl.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-CR\").acl.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.game.simulation.network.get_node_by_hostname(\"REM-PUB-RT-DR\").acl.show() "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## AGENTS | Blue Agent\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "In PrimAITE blue agent configuration is split into three separate sections, each responsible for a different part of the blue agent functionality.\n",
+ "\n",
+ "- `observation_space`\n",
+ "\n",
+ "The observation_space (or more commonly `OBS`) refers to the what simulation components the blue agent observes each `time_step`. A blue agent `OBS` can be configured to be as large the entire network or just an individual node. \n",
+ "\n",
+ "- `action_space`\n",
+ "\n",
+ "The action space configuration is used to set the actions available to the blue agent. The larger range of actions could be optimal for responding to a large set of different scenarios but could lead to longer training times. Crafting the perfect `action_space` is pivotal for creating an effective blue agent.\n",
+ "\n",
+ "- `reward_function`\n",
+ "\n",
+ "The `reward_function` section configures what type of reward (or penalisation) the blue agent will receive based on the current status of the simulation. A balanced and well crafted reward function is the path of success for any blue agent to learn what the best approach to scenario may be.\n",
+ "\n",
+ "\n",
+ "\n",
+ "_The remaining section of this notebook will cover the UC7 blue agent and the default aforementioned settings._"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset() # Resetting the env\n",
+ "defender = env.game.agents.get(\"defender\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## AGENTS | Blue Agent | Observation Space (OBS)\n",
+ "\n",
+ "## NETWORK DESCRIPTION\n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
\n",
+ "\n",
+ "_(Click to enlarge)_\n",
+ "\n",
+ "Represented as a hierarchy (i.e the same way as a dictionary) the blue agent OBS is separate into multiple sections.\n",
+ "\n",
+ "### Links\n",
+ "\n",
+ "The first section is Links, which is used to report the current network traffic load on every link in the network. Since the observation space is composed of categorical variables, the traffic values are converted from MBit/s to a category based on a percentage of the link's capacity.\n",
+ "\n",
+ " Link Values Mapping \n",
+ "\n",
+ "|load observation|percent utilisation|\n",
+ "|--|--|\n",
+ "|0|exactly 0%|\n",
+ "|1|0-11%|\n",
+ "|2|11-22%|\n",
+ "|3|22-33%|\n",
+ "|4|33-44%|\n",
+ "|5|44-55%|\n",
+ "|6|55-66%|\n",
+ "|7|66-77%|\n",
+ "|8|77-88%|\n",
+ "|9|88-99%|\n",
+ "|10|exactly 100%|\n",
+ "\n",
+ "\n",
+ " \n",
+ "\n",
+ "\n",
+ " Link List \n",
+ " \n",
+ "|Link number|Endpoint A|Endpoint B|\n",
+ "|---|---|---|\n",
+ "|1|HOME-PUB-SW-AS:eth-1|HOME-PUB-RT-DR:eth-1 |\n",
+ "|2|HOME-PUB-SW-AS:eth-1|HOME-PUB-PC-1:eth-1 |\n",
+ "|3|HOME-PUB-SW-AS:eth-1|HOME-PUB-PC-2:eth-1 |\n",
+ "|4|HOME-PUB-SW-AS:eth-1|HOME-PUB-SRV:eth-1 | \n",
+ "|5|ISP-PUB-RT-BR:eth-1|HOME-PUB-RT-DR:eth-2 |\n",
+ "|6|ISP-PUB-RT-BR:eth-2|ISP-PUB-SRV-DNS:eth-1 |\n",
+ "|7|ISP-PUB-RT-BR:eth-3|REM-PUB-FW:eth-1 |\n",
+ "|8|REM-PUB-FW:eth-2|REM-PUB-RT-DR:eth-1 |\n",
+ "|9|REM-PUB-RT-DR:eth-2|REM-PUB-SW-AS:eth-1 |\n",
+ "|10|REM-PUB-SW-AS:eth-2|REM-PUB-PC-1:eth-1 |\n",
+ "|11|REM-PUB-SW-AS:eth-3|REM-PUB-PC-2:eth-1 | \n",
+ "|12|REM-PUB-SW-AS:eth-4|REM-PUB-SRV:eth-1 |\n",
+ "|13|ISP-PUB-RT-BR:eth-4|ST_PUB-FW:eth-1 |\n",
+ "|14|ST_PUB-FW:eth-3|ST_DMZ-PUB-SRV-WEB:eth-1 |\n",
+ "|15|ST_INTRA-PRV-RT-CR:eth-1|ST_PUB-FW:eth-2 |\n",
+ "|16|ST_INTRA-PRV-RT-CR:eth-2|ST_INTRA-PRV-RT-DR-1:eth-1 |\n",
+ "|17|ST_INTRA-PRV-RT-CR:eth-3|ST_INTRA-PRV-RT-DR-2:eth-1 | \n",
+ "|18|ST_INTRA-PRV-RT-CR:eth-4|ST_DATA-PRV-SW-AS:eth-1 |\n",
+ "|19|ST_HO-PRV-SW-AS:eth-1|ST_INTRA-PRV-RT-DR-2:eth-2 |\n",
+ "|20|ST_HO-PRV-SW-AS:eth-2|ST_HO-PRV-PC-1:eth-1 |\n",
+ "|21|ST_HO-PRV-SW-AS:eth-3|ST_HO-PRV-PC-2:eth-1 |\n",
+ "|22|ST_HO-PRV-SW-AS:eth-4|ST_HO-PRV-PC-3:eth-1 |\n",
+ "|23|ST_HR-PRV-SW-AS:eth-1|ST_INTRA-PRV-RT-DR-2:eth-3 |\n",
+ "|24|ST_HR-PRV-SW-AS:eth-2|ST_HR-PRV-PC-1:eth-1 |\n",
+ "|25|ST_HR-PRV-SW-AS:eth-3|ST_HR-PRV-PC-2:eth-1 |\n",
+ "|26|ST_HR-PRV-SW-AS:eth-4|ST_HR-PRV-PC-3:eth-1 |\n",
+ "|27|ST_DATA-PRV-SW-AS:eth-2|ST_DATA-PRV-SRV-STORAGE:eth-1 |\n",
+ "|28|ST_DATA-PRV-SW-AS:eth-3|ST_DATA-PRV-SRV-DB:eth-1 | \n",
+ "|29|ST_INTRA-PRV-RT-DR-1:eth-2|ST_PROJ-A-PRV-SW-AS:eth-1 |\n",
+ "|30|ST_PROJ-A-PRV-SW-AS:eth2|ST_PROJ-A-PRV-PC-1:eth-1|\n",
+ "|31|ST_PROJ-A-PRV-SW-AS:eth3|ST_PROJ-A-PRV-PC-2:eth-1 |\n",
+ "|32|ST_PROJ-A-PRV-SW-AS:eth4|ST_PROJ-A-PRV-PC-3:eth-1 | \n",
+ "|33|ST_INTRA-PRV-RT-DR-1:eth-3|ST_PROJ-B-PRV-SW-AS:eth-1 |\n",
+ "|34|ST_PROJ-B-PRV-SW-AS:eth2|ST_PROJ-B-PRV-PC-1:eth-1 |\n",
+ "|35|ST_PROJ-B-PRV-SW-AS:eth3|ST_PROJ-B-PRV-PC-2:eth-1 |\n",
+ "|36|ST_PROJ-B-PRV-SW-AS:eth4|ST_PROJ-B-PRV-PC-3:eth-1 | \n",
+ "|37|ST_INTRA-PRV-RT-DR-1:eth-4|ST_PROJ-C-PRV-SW-AS:eth-1 |\n",
+ "|38|ST_PROJ-A-PRV-SW-AS:eth2|ST_PROJ-C-PRV-PC-1:eth-1 |\n",
+ "|39|ST_PROJ-A-PRV-SW-AS:eth3|ST_PROJ-C-PRV-PC-2:eth-1 |\n",
+ "|40|ST_PROJ-A-PRV-SW-AS:eth4|ST_PROJ-C-PRV-PC-3:eth-1 |\n",
+ "\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The code cell below prints out how the above link list table appears in the blue agent observation space"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset()\n",
+ "\n",
+ "obs, reward, _,_,info = env.step(0)\n",
+ "for i,x in obs['LINKS'].items():\n",
+ " print(i, x)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### HOSTS\n",
+ "\n",
+ "By default the blue agent is monitoring `3` different computers and `1` server:\n",
+ "\n",
+ "|Host label|hostname| services | applications | folders | files |\n",
+ "|:--:|:--:|:--:|:--:|:--:|:--:|\n",
+ "|HOST1|ST_PROJ-A-PRV-PC-1 | ftp-client | ransomware_script, database-client | downloads, exfiltration_folder | malware_dropper.ps1, database.db |\n",
+ "|HOST2|ST_PROJ-B-PRV-PC-2| ftp-client | ransomware-script, database-client | downloads, exfiltration_folder | malware_dropper.ps1, database.db |\n",
+ "|HOST3|ST_PROJ-C-PRV-PC-3| ftp-client | ransomware-script, database-client | downloads, exfiltration_folder | malware_dropper.ps1, database.db |\n",
+ "|HOST4|ST_DATA-PRV-SRV-DB||| database | database.db|\n",
+ "\n",
+ "\n",
+ "Each `time_step` these hosts report the following to the blue agent:\n",
+ "\n",
+ "- operating status \n",
+ "- number of file creations\n",
+ "- number of file deletions\n",
+ "- up to 4 installed services (operating status and health status)\n",
+ "- up to 2 installed applications (operating status, health status, and number of executions)\n",
+ "- up to 1 folder (health status)\n",
+ "- up to 1 file on the folders (health status and number of accesses)\n",
+ "- 1 network interface, including: \n",
+ " - operating status\n",
+ " - number of malicious network events detected\n",
+ " - amount of incoming and outgoing traffic on each protocol and port\n",
+ "\n",
+ "\n",
+ "\n",
+ "It's worth noting that for larger observation spaces, not every host will have the maximum number of files, folders, services, and applications configured for the observation space, so padding is used to ensure that the shape of each host observation is the same. The hosts appear in the order that they are defined in the config file."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset()\n",
+ "\n",
+ "obs, reward, _,_,info = env.step(0)\n",
+ "for node_id, node_obs in obs['NODES'].items():\n",
+ " if not \"ROUTER\" in node_id: # filter out router OBS for now\n",
+ " print(node_id)\n",
+ " pprint(node_obs)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "For any readers unfamiliar with the different enumeration values in any of the obs output (i.e what the `0`,`1`,`2`,`3` values represent) then please refer to the following tables for reference:\n",
+ "\n",
+ " Host operating state category table \n",
+ "\n",
+ "|value|meaning|\n",
+ "|-|-|\n",
+ "|0|UNUSED|\n",
+ "|1|ON|\n",
+ "|2|OFF|\n",
+ "|3|BOOTING|\n",
+ "|4|SHUTTING DOWN|\n",
+ "\n",
+ " \n",
+ "\n",
+ " No. file creations/deletions category table \n",
+ "\n",
+ "|value|meaning|\n",
+ "|-|-|\n",
+ "|0|0|\n",
+ "|1|1-5|\n",
+ "|2|6-10|\n",
+ "|3|>10|\n",
+ "\n",
+ " \n",
+ "\n",
+ " Service operating state category table \n",
+ "\n",
+ "|operating_state|label|\n",
+ "|--|--|\n",
+ "|0|UNUSED|\n",
+ "|1|RUNNING|\n",
+ "|2|STOPPED|\n",
+ "|3|PAUSED|\n",
+ "|4|DISABLED|\n",
+ "|5|INSTALLING|\n",
+ "|6|RESTARTING|\n",
+ "\n",
+ " \n",
+ "\n",
+ " Application operating state category table \n",
+ "\n",
+ "|operating_state|label|\n",
+ "|--|--|\n",
+ "|0|UNUSED|\n",
+ "|1|RUNNING|\n",
+ "|2|CLOSED|\n",
+ "|3|INSTALLING|\n",
+ "\n",
+ " \n",
+ "\n",
+ " Service/Application health state category table \n",
+ "\n",
+ "|health_state|label|\n",
+ "|--|--|\n",
+ "|0|UNUSED|\n",
+ "|1|GOOD|\n",
+ "|2|FIXING|\n",
+ "|3|COMPROMISED|\n",
+ "|4|OVERWHELMED|\n",
+ "\n",
+ " \n",
+ "\n",
+ " Application number of executions category table \n",
+ "\n",
+ "|num_executions label|meaning|\n",
+ "|-|-|\n",
+ "|0|0|\n",
+ "|1|1-5|\n",
+ "|2|6-10|\n",
+ "|3|>10|\n",
+ "\n",
+ " \n",
+ "\n",
+ " Folder/file health status table \n",
+ "\n",
+ "|health_status label|meaning|\n",
+ "|-|-|\n",
+ "|0|UNUSED|\n",
+ "|1|GOOD|\n",
+ "|2|COMPROMISED|\n",
+ "|3|CORRUPT|\n",
+ "|4|RESTORING|\n",
+ "|5|REPAIRING|\n",
+ "\n",
+ " \n",
+ "\n",
+ " File number of access category table \n",
+ "\n",
+ "|num_access label|meaning|\n",
+ "|-|-|\n",
+ "|0|0|\n",
+ "|1|1-5|\n",
+ "|2|6-10|\n",
+ "|3|>10|\n",
+ "\n",
+ " \n",
+ "\n",
+ " NICs' operating_status category table \n",
+ "\n",
+ "|operating_status|label|\n",
+ "|--|--|\n",
+ "|0|UNUSED|\n",
+ "|1|ENABLED|\n",
+ "|2|DISABLED|\n",
+ "\n",
+ " \n",
+ "\n",
+ " NIC monitored traffic utilisation category table \n",
+ "\n",
+ "|load observation|percent utilisation|\n",
+ "|--|--|\n",
+ "|0|exactly 0%|\n",
+ "|1|0-11%|\n",
+ "|2|11-22%|\n",
+ "|3|22-33%|\n",
+ "|4|33-44%|\n",
+ "|5|44-55%|\n",
+ "|6|55-66%|\n",
+ "|7|66-77%|\n",
+ "|8|77-88%|\n",
+ "|9|88-99%|\n",
+ "|10|exactly 100%|\n",
+ "\n",
+ "\n",
+ " \n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Routers and Firewalls\n",
+ "\n",
+ "In addition, the agent can observe the list of Access Control List rules present on routers and firewalls.\n",
+ "\n",
+ "Routers have one ACL and a list of network interfaces (ports)\n",
+ "\n",
+ "Firewalls have six ACLs and three ports (ports are Internal/External/DMZ, with an Inbound and Outbound ACL for each)\n",
+ "\n",
+ "by default, the UC7 agent is configured to observe `3` different routers:\n",
+ "\n",
+ "- `ST_INTRA-PRV-RT-CR`\n",
+ "- `ST_INTRA-PRV-RT-DR-1`\n",
+ "- `REM-PUB-RT-DR`\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ " Port operating status category table \n",
+ "\n",
+ "|operating_status|label|\n",
+ "|--|--|\n",
+ "|0|UNUSED|\n",
+ "|1|ENABLED|\n",
+ "|2|DISABLED|\n",
+ "\n",
+ " \n",
+ "\n",
+ " ACL Permission category table \n",
+ "\n",
+ "|permission|label|\n",
+ "|--|--|\n",
+ "|0|UNUSED|\n",
+ "|1|ALLOW|\n",
+ "|2|DENY|\n",
+ "\n",
+ " \n",
+ "\n",
+ "\n",
+ " ACL source/destination IP ID category table \n",
+ "\n",
+ "|IP ID|IP address| Associated node|\n",
+ "|--|--|--|\n",
+ "|0|UNUSED|\n",
+ "|1|ALL IPs|\n",
+ "|2|192.168.1.2 | HOME-PUB-PC-1 |\n",
+ "|3|192.168.1.3 | HOME-PUB-PC-2 |\n",
+ "|4|192.168.1.4 | HOME-PUB-PC-SRV |\n",
+ "|5|192.168.20.2 | REM-PUB-PC-1 |\n",
+ "|6|192.168.20.3 | REM-PUB-PC-2 |\n",
+ "|7|192.168.20.4 | REM-PUB-SRV |\n",
+ "|8|192.168.100.2| ST_PUB_SRV_WEB_IP |\n",
+ "|9|192.168.200.2 | ST_HO-PRV-PC-1 |\n",
+ "|10|192.168.200.3 | ST_HO-PRV-PC-2 |\n",
+ "|11|192.168.200.4 | ST_HO-PRV-PC-3 |\n",
+ "|12|192.168.210.2 | ST_HR-PRV-PC-1 |\n",
+ "|13|192.168.210.3 | ST_HR-PRV-PC-2 |\n",
+ "|14|192.168.210.4 | ST_HR-PRV-PC-3 |\n",
+ "|15|192.168.220.2 | ST_DATA-PRV-SRV-STORAGE | \n",
+ "|16|192.168.220.3 | ST_DATA-PRV-SRV-DB |\n",
+ "|17|192.168.230.2 | PROJ-A-PRV-PC-1 |\n",
+ "|18|192.168.230.3 | PROJ-A-PRV-PC-2 |\n",
+ "|19|192.168.230.4 | PROJ-A-PRV-PC-3 |\n",
+ "|20|192.168.240.2 | PROJ-B-PRV-PC-1 |\n",
+ "|21|192.168.240.3 | PROJ-B-PRV-PC-2 |\n",
+ "|22|192.168.240.4 | PROJ-B-PRV-PC-3 |\n",
+ "|23|192.168.250.2 | PROJ-C-PRV-PC-1 |\n",
+ "|24|192.168.250.3 | PROJ-C-PRV-PC-2 |\n",
+ "|25|192.168.250.4 | PROJ-C-PRV-PC-3 |\n",
+ "\n",
+ " \n",
+ "\n",
+ " ACL Rule IP Address Wildcard category table \n",
+ "\n",
+ "|wildcard|label|\n",
+ "|--|--|\n",
+ "|0|UNUSED|\n",
+ "|1|None|\n",
+ "|2|0.0.0.1|\n",
+ "|3|0.0.0.255|\n",
+ "|4|0.0.255.255|\n",
+ " \n",
+ "\n",
+ " ACL Rule Port category table \n",
+ "\n",
+ "|permission|label|used for|\n",
+ "|--|--|--|\n",
+ "|0|UNUSED|padding|\n",
+ "|1|ANY||\n",
+ "|2|21|FTP|\n",
+ "|3|53|DNS|\n",
+ "|4|80|HTTP|\n",
+ "|5|123|NTP|\n",
+ "|6|5432|POSTGRES SERVER|\n",
+ "|7|22|SSH|\n",
+ "\n",
+ " \n",
+ "\n",
+ " ACL Rule Protocol category table \n",
+ "\n",
+ "|permission|label|\n",
+ "|--|--|\n",
+ "|0|UNUSED|\n",
+ "|1|ANY|\n",
+ "|2|ICMP|\n",
+ "|3|TCP|\n",
+ "|4|UDP|\n",
+ "\n",
+ " \n",
+ "\n",
+ " Firewall ports \n",
+ "\n",
+ "|index|label|\n",
+ "|--|--|\n",
+ "|1|external|\n",
+ "|2|internal|\n",
+ "|3|DMZ|\n",
+ "\n",
+ " \n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "obs, reward, _,_,info = env.step(0)\n",
+ "for node_id, node_obs in obs['NODES'].items():\n",
+ " if not \"HOST\" in node_id: # filter out hosts OBS and focus on ROUTER\n",
+ " print(node_id)\n",
+ " pprint(node_obs)\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## AGENTS | Blue Agent | Action Space"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***\n",
+ "\n",
+ "#### `action_map`\n",
+ "\n",
+ "Numerically ordered, the `action_map` combines the options set out previously to define the actual details of what actions and the amount of actions that a blue agent can perform.\n",
+ "\n",
+ "For example, the snippet below details the first four actions the the default UC7 blue agent is setup with:\n",
+ "\n",
+ "```yaml\n",
+ " action_space:\n",
+ " action_map:\n",
+ " 0:\n",
+ " action: do-nothing\n",
+ " options: {}\n",
+ "\n",
+ " # |======================================|\n",
+ " # | ST_PROJ-A-PRV-PC-1 |\n",
+ " # |======================================|\n",
+ "\n",
+ " # ST_PROJ-A-PRV-PC-1 | node-os-scan\n",
+ " 1:\n",
+ " action: node-os-scan\n",
+ " options:\n",
+ " node_name: ST_PROJ-A-PRV-PC-1\n",
+ " # ST_PROJ-A-PRV-PC-1 | node-shutdown\n",
+ " 2:\n",
+ " action: node-shutdown\n",
+ " options:\n",
+ " node_name: ST_PROJ-A-PRV-PC-1\n",
+ " # ST_PROJ-A-PRV-PC-1 | node-startup\n",
+ " 3:\n",
+ " action: node-startup\n",
+ " options:\n",
+ " node_name: ST_PROJ-A-PRV-PC-1\n",
+ "```\n",
+ "\n",
+ "Converting the yaml snippet below we end up with the following:\n",
+ "\n",
+ "|Action Num | Action Type | Options|\n",
+ "|:---------:|:-----------:|:------:|\n",
+ "|0|**DONOTHING**|*n/a*|\n",
+ "|1|**NODE_OS_SCAN**|*node_name: ST_PROJ-A-PRV-PC-1*|\n",
+ "|2|**NODE_SHUTDOWN**|*node_name: ST_PROJ-A-PRV-PC-1*|\n",
+ "|3|**NODE_STARTUP**|*node_name: ST_PROJ-A-PRV-PC-1*|\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "`0: DONOTHING`:\n",
+ "\n",
+ "The first action, `DONOTHING` is a default standard that all agents are setup to use by default in primAITE. Quite simply this action makes no impact to the simulation - literally does nothing. Although this obviously does not seem all that useful, in practice an agent with a small yet impactful actions (such as adding or removing ACL's rules) may find that performing no action may be better than risking a potentially detrimental one.\n",
+ "\n",
+ "Additionally, you may spotted the code snippet below dotted around this notebook and many others.\n",
+ "\n",
+ "```py\n",
+ " env.step(0)\n",
+ "```\n",
+ "\n",
+ "This code snippet is used to step forward in an PrimAITE episode and force the blue agent into performing no action which is very useful for demonstrating default simulation behaviour as well as the different impacts that the green and red agents have upon the environment."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset()\n",
+ "env.step(0)\n",
+ "defender = env.game.rl_agents.get(\"defender\")\n",
+ "print(defender.history[0])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "`1: NODE_OS_SCAN`:\n",
+ "\n",
+ "The first actual action that the blue agent can perform is scanning action. A variety of different scanning type actions (such as `NODE_APPLICATION_SCAN` or `NODE_FILE/FOLDER_SCAN`) which can be used to by the blue agent to gain a deeper understanding of the simulation state. Specifically, these actions will cause the blue agent's observations to update to the \"true\" `HEALTH_STATUS` of a simulation component. The `NODE_OS_SCAN` acts a combined version of all these scan type actions.\n",
+ "\n",
+ "For example, if a red agent corrupts and alters the health status of a file, the blue agent's observation space will not reflect this until the agent performs a `NODE_FILE_SCAN` on the newly corrupted file. It's worth noting that blue agents can be configured to see the true `HEALTH_STATUS` of software and files without needing to scan in the yaml. Although this may make it easier for an train and create an effective blue agent it could be seen as reducing the fidelity of the simulation.\n",
+ "\n",
+ "The code snippet below demonstrates an example where the blue agent uses the `NODE_OS_SCAN` action to reveal the true health status `ST_PROJ-A-PRV-PC-1`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "obs, reward, term, trunc, info = env.step(0)\n",
+ "print(defender.history[1])\n",
+ "print(f\"ftp-client (Prior Scan) OBS: {defender.observation_manager.current_observation['NODES']['HOST0']['SERVICES'][1]}\")\n",
+ "print(f\"database-client (Prior Scan) OBS: {defender.observation_manager.current_observation['NODES']['HOST0']['APPLICATIONS'][2]}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_a_private_pc_1: Computer = env.game.simulation.network.get_node_by_hostname(\"ST_PROJ-A-PRV-PC-1\")\n",
+ "st_project_a_private_pc_1.software_manager.software[\"ftp-client\"].set_health_state(SoftwareHealthState.COMPROMISED)\n",
+ "st_project_a_private_pc_1.software_manager.software[\"database-client\"].set_health_state(SoftwareHealthState.COMPROMISED)\n",
+ "st_project_a_private_pc_1.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Set by the `node_scan_duration` option in the simulation `defaults` section, it takes **8** timesteps before the results of `node-os-scan` impact the blue agent's observation space."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(f'Node OS Scan time step duration: {cfg[\"simulation\"][\"defaults\"][\"node_scan_duration\"]}')\n",
+ "env.step(1)\n",
+ "print(defender.history[2])\n",
+ "for _ in range(9):\n",
+ " obs, reward, term, trunc, info = env.step(0)\n",
+ "\n",
+ "print(f\"Current Simulation Time Step: {env.game.step_counter}\")\n",
+ "print(f\"ftp-client (Post Scan) OBS: {defender.observation_manager.current_observation['NODES']['HOST0']['SERVICES'][1]}\")\n",
+ "print(f\"database-client (Post Scan) OBS: {defender.observation_manager.current_observation['NODES']['HOST0']['APPLICATIONS'][2]}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "`2: NODE_SHUTDOWN`:\n",
+ "\n",
+ "The next action available is the `NODE_SHUTDOWN` action. This action quite is quite simple in comparison and literally attempts to shut down the target host given in the `options` settings which is set to `ST_PROJ-A-PRV-PC-1`. Shutting a PC down affects the `operating_status` of the host machine which the following snippets demonstrate."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# `1` is equal to 'ON' in this case.\n",
+ "obs, reward, term, trunc, info = env.step(0)\n",
+ "print(f\"ST_PROJ-A-PRV-PC-1's (prior shutdown) operating state: {defender.observation_manager.current_observation['NODES']['HOST0']['operating_status']}\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "obs, reward, term, trunc, info = env.step(2)\n",
+ "for _ in range(3):\n",
+ " env.step(0) # 3 second shut down time.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "obs, reward, term, trunc, info = env.step(0)\n",
+ "print(f\"ST_PROJ-A-PRV-PC-1's (post shutdown) operating state: {defender.observation_manager.current_observation['NODES']['HOST0']['operating_status']}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "`3: NODE_STARTUP`:\n",
+ "\n",
+ "Luckily, the blue agent can use it's third action `NODE_STARTUP` has been configured to bring the `ST_PROJ-A-PRV-PC-1` back up and running. Although, with the a three timestep reboot time.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "obs, reward, term, trunc, info = env.step(3)\n",
+ "\n",
+ "for _ in range(3):\n",
+ " env.step(0) # 3 second reboot time.\n",
+ " \n",
+ "obs, reward, term, trunc, info = env.step(0)\n",
+ "print(f\"ST_PROJ-A-PRV-PC-1's (prior shutdown) operating state: {defender.observation_manager.current_observation['NODES']['HOST0']['operating_status']}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## AGENTS | Blue Agent | Reward Components\n",
+ "\n",
+ "In order to add context to the observation, the blue agent can be configured with different reward components. For any readers unfamiliar with PrimAITE rewards then user guide contains a good introduction as this notebook section will only cover the UC7 blue agent setup.\n",
+ "\n",
+ "For `UC7`, the blue agent is setup to receive a negative reward when the `database.db` file integrity is affected (i.e enters into a `COMPROMISED` state):\n",
+ "\n",
+ "```yaml\n",
+ " reward_function:\n",
+ " reward_components:\n",
+ " - type: DATABASE_FILE_INTEGRITY\n",
+ " weight: *HIGH_WEIGHT_IMPACT\n",
+ " options: \n",
+ " node_hostname: ST_DATA-PRV-SRV-DB \n",
+ " folder_name: database\n",
+ " file_name: database.db\n",
+ "```\n",
+ "\n",
+ "The blue agent's remaining reward function is comprised of **32** different ``SHARED_REWARD`` components. These rewards will grant the blue agent a positive or negative reward based on the current reward of the **32** green agents. The next code snippets The code snippets below demonstrate how the blue agent's reward is affected by simulation state."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for i in range(len(defender.reward_function.reward_components)):\n",
+ " try:\n",
+ " print(f\"Simulation State Reward: {defender.reward_function.reward_components[i][0].location_in_state}\")\n",
+ " except:\n",
+ " print(f\"Green Agent Shared Reward: {defender.reward_function.reward_components[i][0].config.agent_name}\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In a perfect episode, with no red agent interference, the blue agent can expect the following reward:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as uc7_config:\n",
+ " cfg = yaml.safe_load(uc7_config)\n",
+ " cfg[\"agents\"].pop(32) # removing red agent\n",
+ "env = PrimaiteGymEnv(env_config=cfg)\n",
+ "env.reset()\n",
+ "defender = env.game.rl_agents.get(\"defender\")\n",
+ "for _ in range(128):\n",
+ " env.step(0)\n",
+ "defender.reward_function.total_reward"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The below code snippet shows what you'd expect the defender's total reward to be after TAP001 is left unchallenged:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as uc7_config:\n",
+ " cfg = yaml.safe_load(uc7_config)\n",
+ "env = PrimaiteGymEnv(env_config=cfg)\n",
+ "env.reset()\n",
+ "defender = env.game.rl_agents.get(\"defender\")\n",
+ "for _ in range(128):\n",
+ " env.step(0)\n",
+ "print(f\"Successful TAP001 & Blue Agent Reward: {defender.reward_function.total_reward}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Next is what you'd expect the defender's total reward to be after TAP003 is left unchallenged:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as uc7_config:\n",
+ " cfg = yaml.safe_load(uc7_config)\n",
+ " cfg[\"agents\"][33][\"agent_settings\"][\"flatten_obs\"] = False\n",
+ " cfg['io_settings']['save_sys_logs'] = True # Saving syslogs\n",
+ " cfg['io_settings']['save_agent_actions'] = True # Saving syslogs\n",
+ " cfg['io_settings']['save_agent_logs'] = True # Saving agent logs\n",
+ "env = PrimaiteGymEnv(env_config=cfg)\n",
+ "env.reset()\n",
+ "defender = env.game.rl_agents.get(\"defender\")\n",
+ "for _ in range(128):\n",
+ " env.step(0)\n",
+ "print(f\"Successful TAP003 & Blue Agent Reward: {defender.reward_function.total_reward}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Lastly, if we completely block any green traffic and set the database.db to `COMPROMISED` we can simulate the potential worst case situation for the blue agent (based off the default `reward_components`)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env = PrimaiteGymEnv(env_config=cfg)\n",
+ "env.reset()\n",
+ "defender = env.game.rl_agents.get(\"defender\")\n",
+ "\n",
+ "# Corrupting and Disabling the database-service\n",
+ "st_data_private_server_database: Server = env.game.simulation.network.get_node_by_hostname(\"ST_DATA-PRV-SRV-DB\")\n",
+ "st_data_private_server_database_file = st_data_private_server_database.file_system.get_file(folder_name=\"database\", file_name=\"database.db\")\n",
+ "st_data_private_server_database_file.health_status = FileSystemItemHealthStatus.COMPROMISED\n",
+ "st_data_private_server_database.software_manager.software[\"database-service\"].operating_state = ServiceOperatingState.DISABLED\n",
+ "\n",
+ "# Shutting down the web-server\n",
+ "\n",
+ "st_dmz_pub_srv_web: Server = env.game.simulation.network.get_node_by_hostname(\"ST_DMZ-PUB-SRV-WEB\")\n",
+ "st_dmz_pub_srv_web.software_manager.software[\"web-server\"].operating_state = ServiceOperatingState.DISABLED\n",
+ "\n",
+ "# Shutting down the DNSServer\n",
+ "\n",
+ "isp_pub_srv_dns_server: Server = env.game.simulation.network.get_node_by_hostname(\"ISP-PUB-SRV-DNS\")\n",
+ "isp_pub_srv_dns_server.software_manager.software[\"dns-server\"].operating_state = ServiceOperatingState.DISABLED\n",
+ "\n",
+ "for _ in range(128):\n",
+ " env.step(0)\n",
+ "print(f\"Worst Case Episode Blue Agent Reward: {defender.reward_function.total_reward}\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": ".venv",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/src/primaite/notebooks/UC7-TAP001-Kill-Chain-E2E.ipynb b/src/primaite/notebooks/UC7-TAP001-Kill-Chain-E2E.ipynb
new file mode 100644
index 00000000..5ea67af3
--- /dev/null
+++ b/src/primaite/notebooks/UC7-TAP001-Kill-Chain-E2E.ipynb
@@ -0,0 +1,1844 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Mobile Malware Kill Chain - Ransomware Script Variant\n",
+ "\n",
+ "© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK\n",
+ "\n",
+ "**Threat Actor Profile (TAP):** 001 \n",
+ "**Kill Chain**: Mobile Malware - Ransomware Script Variant\n",
+ "\n",
+ "This notebook demonstrates TAP001 on the UC7 network infrastructure. In this scenario, a some_tech employee within the development project network plugs in his personal device. Whilst browsing, they encounter a ransomware virus which moves onto the host machine thus triggering the malware! \n",
+ " \n",
+ "\n",
+ "This ransomware variant targets the database service's file directly, rather than the disrupting the database service, hence why in this scenario the data service still functions after becoming corrupted.\n",
+ " \n",
+ "\n",
+ "The red attack intends to introduce realistic impacts to the observation space, such as files created/removed and applications installing mid-episode whilst still providing usable data for agent training."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "!primaite setup"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Importing the necessary PrimAITE libraries\n",
+ "from primaite.session.environment import PrimaiteGymEnv\n",
+ "import yaml\n",
+ "from primaite.game.agent.scripted_agents.TAP001 import TAP001, MobileMalwareKillChain\n",
+ "from primaite.config.load import load, _EXAMPLE_CFG\n",
+ "from deepdiff.diff import DeepDiff"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Utility functions\n",
+ "\n",
+ "def display_obs_diffs(old, new, step_counter):\n",
+ " \"\"\"\n",
+ " Use DeepDiff to extract and display differences in old and new instances of\n",
+ " the observation space.\n",
+ "\n",
+ " :param old: observation space instance.\n",
+ " :param new: observation space instance.\n",
+ " :param step_counter: current step counter.\n",
+ " \"\"\"\n",
+ " print(\"\\nObservation space differences\")\n",
+ " print(\"-----------------------------\")\n",
+ " diff = DeepDiff(old, new)\n",
+ " print(f\"Step {step_counter}\")\n",
+ " for d,v in diff.get('values_changed', {}).items():\n",
+ " print(f\"{d}: {v['old_value']} -> {v['new_value']}\")\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Notebook Sections:**\n",
+ "1. Notebook Intro\n",
+ "2. Notebook Setup\n",
+ "3. Initial States\n",
+ "4. Attack Trigger\n",
+ "5. Post Attack States\n",
+ "6. Configurations"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Notebook Intro** | **TAP001 - Mobile Malware Kill Chain** \n",
+ "\n",
+ "The TAP001 kill chain is comprised of 6 different stages. The table below describes the impact of the current TAP001 implementation as well as the attack stage order.\n",
+ "\n",
+ "_DOWNLOAD_\n",
+ "\n",
+ "|Index|Attack Stage|OBS Impact|Narrative|\n",
+ "|-----|------------|----------|---------|\n",
+ "|1|Download|**Starting Host** HOST:num_file_creations: HOST:FOLDER:FILES:* |The employee encounters a malicious payload through web browsing on his mobile phone, often disguised as legitimate content.|\n",
+ "\n",
+ "_INSTALL_\n",
+ "\n",
+ "|Index|Attack Stage|OBS Impact|Narrative|\n",
+ "|-----|------------|----------|---------|\n",
+ "|2|Install | **Starting Host** HOST:FOLDER:FILES:num_access:|The malware is activated, either by the employee opening the file or automatically upon download, initiating its malicious functions.|\n",
+ "\n",
+ "_ACTIVATE_\n",
+ "\n",
+ "|Index|Attack Stage|OBS Impact|Narrative|\n",
+ "|-----|------------|----------|---------|\n",
+ "|3|Activate | **Starting Host** HOST:APPLICATION:operating_status|The malware installs itself on the terminal, often seeking to gain persistence by embedding itself into system processes or startup routines.|\n",
+ "\n",
+ "_PROPAGATE_\n",
+ "\n",
+ "|Index|Attack Stage|OBS Impact|Narrative|\n",
+ "|-----|------------|----------|---------|\n",
+ "|4|Propagate| **Multiple Hosts** HOST:NICS:NIC:TRAFFIC:PROTOCOL:PORT:*|The malware attempts to spread to other systems or networks, looking for vulnerable services.|\n",
+ "\n",
+ "_COMMAND_AND_CONTROL_\n",
+ "\n",
+ "|Index|Attack Stage|OBS Impact|Narrative|\n",
+ "|-----|------------|----------|---------|\n",
+ "|5|Command and Control|**Starting Host** HOST:NICS:NIC:TRAFFIC:PROTOCOL:PORT:* HOST:APPLICATIONS:APPLICATION:*|The malware establishes a connection to an external command and control (C&C) server, receiving instructions and possibly exfiltrating data.|\n",
+ "\n",
+ "_PAYLOAD_\n",
+ "\n",
+ "|Index|Attack Stage|OBS Impact|Narrative|\n",
+ "|-----|------------|----------|---------|\n",
+ "|6A|Corruption| **Target Host** HOST:FOLDERS:FOLDER:FILES:FILE:num_access HOST:num_file_creations HOST:num_file_deletions HOST:FOLDERS:FOLDER:FILES:FILE:health_status | The attacker configures the ransomware script to target the IP address of the discovered database, then it performs its intended malicious activities, allowing it to corrupt the Database whilst leaving the database service operable|\n",
+ "|6B|Exfiltration| **Starting Host** HOST:FOLDER:FILES:FILE HOST:NICS:NIC:TRAFFIC:PROTOCOL:PORT:* HOST:APPLICATIONS:APPLICATION:* | The attacker remotely logins into the target host and exfiltrates the database.db file onto the starting host which then relays this file back to the C2 Server.|\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## **Notebook Setup** | **Network Configuration:**\n",
+ "\n",
+ "This notebook uses the same network setup as UC7. Please refer to the main [UC7-E2E-Demo notebook for further reference](./UC7-E2E-Demo.ipynb)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
\n",
+ " TAP001 Mobile Malware Kill Chain Demonstration - Ransomware Variant
\n",
+ "\n",
+ "_(Click to enlarge)_"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as uc7_config:\n",
+ " cfg = yaml.safe_load(uc7_config)\n",
+ " cfg[\"agents\"][33][\"agent_settings\"][\"flatten_obs\"] = False\n",
+ " cfg['io_settings']['save_sys_logs'] = True # Saving syslogs\n",
+ " cfg['io_settings']['save_agent_actions'] = True # Saving attacker logs\n",
+ "env = PrimaiteGymEnv(env_config=cfg)\n",
+ "env.game.simulation.network.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Notebook Setup** | Instantiating Relevant Simulation Objects\n",
+ "Simulation objects can be instantiated and called independently of agents via the environment.game.simulation (PrimAITE API).\n",
+ "\n",
+ "[Please refer to the main UC7 notebook for further details regarding agent implementations and the general UC7 scenario.](./example layout-E2E-Demo.ipynb)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset() # resetting the environment\n",
+ "# The TAP001 Agent\n",
+ "tap001 = env.game.agents.get(\"attacker\")\n",
+ "# A potential starting client\n",
+ "starting_host = env.game.simulation.network.get_node_by_hostname('ST_PROJ-A-PRV-PC-1')\n",
+ "\n",
+ "# The database server which acts as the initial target of the ransomware kill-chain\n",
+ "database_server = env.game.simulation.network.get_node_by_hostname('ST_DATA-PRV-SRV-DB')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## **Prior To Attack** | Initial States:"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The first section of this notebook displays the relevant default Observation Space (OBS)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Initial State** | Starting Client:\n",
+ "The starting point of the ransomware infection. This is where the kill chain attack originates from."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "starting_host.show()\n",
+ "starting_host.file_system.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "starting_host.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Initial State** | Database Server:\n",
+ "\n",
+ "TAP001 opts to attack the UC7 database server (`ST_DATA-PRV-SRV-DB`):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "database_server.software_manager.show()\n",
+ "database_server.file_system.show()\n",
+ "database_server.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## **Kill Chain** | Kill Chain Stage Demonstration"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | NOT STARTED\n",
+ "\n",
+ "This stage indicates that the TAP001 hasn't begun it's kill chain. \n",
+ "TAP001 will begin the Mobile Malware Kill chain on the next execution step."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset();\n",
+ "tap001 = env.game.agents.get(\"attacker\")\n",
+ "# The TAP001's Starting Client:\n",
+ "starting_host = env.game.simulation.network.get_node_by_hostname(tap001.starting_node)\n",
+ "# The TAP001's Database Server:\n",
+ "target_host = env.game.simulation.network.get_node_by_hostname('ST_DATA-PRV-SRV-DB')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap001.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap001.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap001.next_kill_chain_stage.name}\")\n",
+ "while(tap001.current_kill_chain_stage == MobileMalwareKillChain.NOT_STARTED):\n",
+ " default_obs, _, _, _, _ = env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | DOWNLOAD\n",
+ "\n",
+ "|Index|Action Stage|OBS Impact|Narrative|\n",
+ "|-----|------------|----------|---------|\n",
+ "|1|DOWNLOAD|HOST:FOLDER:FILE:*|The `some_tech` employee encounters a malicious payload through web browsing on his mobile phone, often disguised as legitimate content.|\n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ "
\n",
+ "\n",
+ "In this stage, TAP001 uses the **NODE_FOLDER_CREATE** and **NODE_FILE_CREATE** to create a file called ```\"malware_dropper.ps1\"``` within a ```\"Downloads\"``` folder. \n",
+ "These actions are intended to simulate the malicious payload creating a ```ps1``` (A windows powershell script) malware dropper on the `SOME_TECH` employee's phone. \n",
+ "\n",
+ "Currently, PrimAITE cannot simulate hosts joining the simulation mid-episode thus we must treat `ST_PROJ-A-PRV-PC-1`'s as also including the employee's phone. \n",
+ "From a narrative perspective, this could be explained as the employee plugging his phone into the `ST_PROJ-A-PRV-PC-1`.\n",
+ "\n",
+ "Additionally, it's worth noting that in the real world, malware droppers (small scripts or executables which download/install the malware after initially entering a host) use a variety of obfuscation methods to avoid detection. For example, some malware droppers are concealed within legitimate files such as word document macros in order to trick a user into running the dropper.\n",
+ "\n",
+ "Currently, PrimAITE's simulation does not operate a high enough fidelity to faithfully represent these techniques and their impacts to warrant their inclusion. Thus the file has been named as ```\"malware_dropper\"``` to prevent any potential confusion."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap001.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap001.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap001.next_kill_chain_stage.name}\")\n",
+ "while(tap001.current_kill_chain_stage == MobileMalwareKillChain.DOWNLOAD):\n",
+ " download_obs_impact, _, _, _, _ = env.step(0)\n",
+ "starting_host.file_system.show(full=True)\n",
+ "starting_host.file_system.show_num_files()\n",
+ "display_obs_diffs(default_obs, download_obs_impact, env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap001.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | INSTALL\n",
+ "|Index|Attack Stage|OBS Impact|Narrative|\n",
+ "|-----|------------|----------|---------|\n",
+ "|2|Install | HOST:FOLDER:FILES:num_access |The malware is activated, either by the employee opening the file or automatically upon download, initiating its malicious functions.|\n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
\n",
+ "\n",
+ "In this stage, TAP001 uses the **NODE_FILE_ACCESS** to increase the number of accesses of the ```\"malware_dropper.ps1\"```. \n",
+ "\n",
+ "These actions represent the employee executing malware dropper created in the previous stage. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap001.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap001.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap001.next_kill_chain_stage.name}\")\n",
+ "while(tap001.current_kill_chain_stage == MobileMalwareKillChain.INSTALL):\n",
+ " install_obs_impact, _, _, _, _ = env.step(0)\n",
+ "\n",
+ "malware_file = starting_host.file_system.get_file(\"downloads\",\"malware_dropper.ps1\")\n",
+ "malware_file.show()\n",
+ "\n",
+ "display_obs_diffs(download_obs_impact, install_obs_impact, env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap001.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | ACTIVATE\n",
+ "\n",
+ "|Index|Attack Stage|OBS Impact|Narrative|\n",
+ "|-----|------------|----------|---------|\n",
+ "|3|Activate | HOST:APPLICATION:operating_status |The malware installs itself on the terminal, often seeking to gain persistence by embedding itself into system processes or startup routines.|\n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
\n",
+ "\n",
+ "In this stage, TAP001 uses the **NODE_APPLICATION_INSTALL** to install the ransomware application onto the starting host. \n",
+ "\n",
+ "These actions represent the malware dropper successfully installing ransomware on the host machine. Similarly to the malware dropper, the ransomware currently implemented is intended to be a generic and OS agnostic ransomware which is not intended to represent any specific real world implementation. \n",
+ "\n",
+ "Please see the [Ransomware Notebook](./Ransomware-Kill-Chain-E2E.ipynb) for further information about the current implementation of the ransomware application.\n",
+ "\n",
+ "Future versions of PrimAITE intend to expand the capability of the ransomware application to more faithfully represent a real-world example; for example, a Trickbot variation such as Ryuk or Conti."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap001.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap001.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap001.next_kill_chain_stage.name}\")\n",
+ "while(tap001.current_kill_chain_stage == MobileMalwareKillChain.ACTIVATE):\n",
+ " activate_obs_impact, _, _, _, _ = env.step(0)\n",
+ "starting_host.software_manager.show()\n",
+ "display_obs_diffs(install_obs_impact, activate_obs_impact, env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap001.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | PROPAGATE\n",
+ "\n",
+ "|Index|Attack Stage|OBS Impact|Narrative|\n",
+ "|-----|------------|----------|---------|\n",
+ "|4|Propagate|HOST:NICS:NIC:TRAFFIC:PROTOCOL:PORT:*|The malware attempts to spread to other systems or networks, looking for vulnerable services.|\n",
+ "\n",
+ "In this stage, TAP001 uses **NODE_NMAP_PORT_SCAN**, **NODE_NMAP_PING_SCAN** and **NODE_NMAP_NETWORK_SERVICE_RECON** to scan the simulation in order to search for a valid database target.\n",
+ "\n",
+ "Unlike previous stages, the behaviour of this stage is dependant on the simulation and thus will perform differently dependant on the location of the target as well as the topology of the network. Specifically, the ```PROPAGATE``` stage uses three network enumeration actions and their action responses to populate its knowledge of the network. \n",
+ "These actions represent the now infected `ST_PROJ-A-PRV-PC-1` searching the UC7 network for valid targets ransomware. \n",
+ "\n",
+ "For more information around how agent requests and responses work then the [request-response notebook can provide some useful insights](./Requests-and-Responses.ipynb).\n",
+ "\n",
+ "It's worth noting that the implementation of the ```PROPAGATE``` stage does not class routers and switches as valid targets and thus will not scan them. \n",
+ "\n",
+ "_Currently, red agents have no way of probing the routing information of the simulation so must be provided the network addresses of the network. See the mobile malware configuration option section of this notebook for further information_"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Kill Chain** | PROPAGATE | Scan walkthrough\n",
+ "\n",
+ "The next juypter cells of this notebook will go through each individual CAOS action that the TAP001 leverages to reach the target host as well as the OBS each action impacts.\n",
+ "\n",
+ "This section uses the following ```PROPAGATE``` relevant TAP001 settings:\n",
+ "```yaml\n",
+ " kill chain:\n",
+ " PROPAGATE:\n",
+ " probability: 1\n",
+ " scan_attempts: 20\n",
+ " repeat_scan: false\n",
+ " network_addresses:\n",
+ " - 192.168.230.0/29 # ST Project A\n",
+ " - 192.168.10.0/26 # Remote Site\n",
+ " - 192.168.20.0/30 # Remote DMZ\n",
+ " # - 192.168.240.0/29 # ST Project B\n",
+ " # - 192.168.250.0/29 # ST Project C\n",
+ " - 192.168.220.0/29 # ST Data (Contains Target)\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap001.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap001.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap001.next_kill_chain_stage.name}\")\n",
+ "\n",
+ "def propagate_obs_and_show(tap001: TAP001, previous_obs, propagate_obs_impact, timestep):\n",
+ " tap001._show_scan()\n",
+ " display_obs_diffs(previous_obs, propagate_obs_impact, timestep)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap001.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Kill Chain** | PROPAGATE | ST_PROJ-A-PRV-PC-1\n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Ping Scan\n",
+ "for _ in range(5):\n",
+ " PROJ_A_SITE_ping, *_ = env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "propagate_obs_and_show(tap001, previous_obs=activate_obs_impact, propagate_obs_impact=PROJ_A_SITE_ping, timestep=env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Recon Scan\n",
+ "for _ in range(5):\n",
+ " PROJ_A_SITE_recon, *_ = env.step(0);"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "propagate_obs_and_show(tap001, PROJ_A_SITE_ping, PROJ_A_SITE_recon, env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Kill Chain** | PROPAGATE | REMOTE SITE\n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Ping Scan\n",
+ "for _ in range(5):\n",
+ " REMOTE_SITE_ping, *_ = env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "propagate_obs_and_show(tap001, previous_obs=activate_obs_impact, propagate_obs_impact=REMOTE_SITE_ping, timestep=env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Recon Scan\n",
+ "for _ in range(5):\n",
+ " REMOTE_SITE_recon, *_ = env.step(0);"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "propagate_obs_and_show(tap001, REMOTE_SITE_ping, REMOTE_SITE_recon, env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Kill Chain** | PROPAGATE | REMOTE DMZ\n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Ping Scan\n",
+ "for _ in range(5):\n",
+ " REMOTE_DMZ_ping, *_ = env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "propagate_obs_and_show(tap001, previous_obs=REMOTE_SITE_recon, propagate_obs_impact=REMOTE_DMZ_ping, timestep=env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Recon Scan\n",
+ "for _ in range(5):\n",
+ " REMOTE_DMZ_recon, *_ = env.step(0);"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "propagate_obs_and_show(tap001, previous_obs=REMOTE_DMZ_ping, propagate_obs_impact=REMOTE_DMZ_recon, timestep=env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Kill Chain** | PROPAGATE | SOME_TECH DATA \n",
+ "\n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Ping Scan\n",
+ "for _ in range(5):\n",
+ " ST_DATA_ping, *_ = env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "propagate_obs_and_show(tap001, previous_obs=REMOTE_DMZ_recon, propagate_obs_impact=ST_DATA_ping, timestep=env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Recon Scan\n",
+ "for _ in range(5):\n",
+ " ST_DATA_recon, *_ = env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "propagate_obs_and_show(tap001, previous_obs=ST_DATA_ping, propagate_obs_impact=ST_DATA_recon, timestep=env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for _ in range(5):\n",
+ " propagate_obs_impact, *_ = env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap001._show_scan()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap001.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | COMMAND_AND_CONTROL\n",
+ "|Index|Attack Stage|OBS Impact|Narrative|\n",
+ "|-----|------------|----------|---------|\n",
+ "|5|Command and Control| **Starting Host** HOST:NICS:NIC:TRAFFIC:PROTOCOL:PORT:* HOST:APPLICATIONS:APPLICATION:* |The malware establishes a connection to an external command and control (C&C) server, receiving instructions and possibly exfiltrating data.|\n",
+ "\n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
\n",
+ "\n",
+ "\n",
+ "For further details please refer to the ``Command-and-Control-E2E-Demonstration`` notebook.\n",
+ "\n",
+ "_Note: The referenced notebook above uses the UC2 scenario for demonstration purposes, however all the OBS impacts and C2 suite functionality is equally applicable to UC7._\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap001.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap001.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap001.next_kill_chain_stage.name}\")\n",
+ "while(tap001.current_kill_chain_stage == MobileMalwareKillChain.COMMAND_AND_CONTROL):\n",
+ " c_and_c_obs_impact, _, _, _, _ = env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "display_obs_diffs(propagate_obs_impact, c_and_c_obs_impact,env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap001.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | PAYLOAD - Corruption & Exfiltration\n",
+ "|Index|Attack Stage|OBS Impact|Narrative|\n",
+ "|-----|------------|----------|---------|\n",
+ "|6A|Corruption| **Target Host** HOST:FOLDERS:FOLDER:FILES:FILE:num_access HOST:num_file_creations HOST:num_file_deletions HOST:FOLDERS:FOLDER:FILES:FILE:health_status | The attacker configures the ransomware script to target the IP address of the discovered database, then it performs it's intended malicious activities, allowing it to corrupt the Database whilst leaving the database service operable|\n",
+ "|6B|Exfiltration| **Starting Host** HOST:FOLDER:FILES:FILE HOST:NICS:NIC:TRAFFIC:PROTOCOL:PORT:* HOST:APPLICATIONS:APPLICATION:* | The attacker remotely logins into the target host and exfiltrates the database.db file onto the starting host which then relays this file back to the C2 Server.|\n",
+ "\n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap001.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap001.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap001.next_kill_chain_stage.name}\")\n",
+ "while(tap001.current_kill_chain_stage == MobileMalwareKillChain.PAYLOAD):\n",
+ " payload_obs_impact, _, _, _, _ = env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "target_host.file_system.show(full=True)\n",
+ "display_obs_diffs(c_and_c_obs_impact, payload_obs_impact, env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap001.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can use the blue agent's NODE_FILE_SCAN action to scan the database file:\n",
+ "\n",
+ "```yaml\n",
+ "# ST_DATA-PRV-SRV-DB | node-file-scan | Scans the database.db file (health status)\n",
+ "49:\n",
+ " action: node-file-scan\n",
+ " options:\n",
+ " node_name: ST_DATA-PRV-SRV-DB\n",
+ " folder_name: database\n",
+ " file_name: database.db\n",
+ "```\n",
+ "\n",
+ "*You should notice a file `health_status` change to a value of 3*"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.step(0)\n",
+ "post_scan_payload_impact, _, _, _, _ = env.step(49) # \n",
+ "display_obs_diffs(payload_obs_impact, post_scan_payload_impact, env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "target_host.file_system.show(full=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can also see that the database.db file was successfully exfiltrated."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "c2_server = env.game.simulation.network.get_node_by_hostname(tap001.c2_settings['c2_server'])\n",
+ "starting_host.file_system.show(full=True)\n",
+ "c2_server.file_system.show(full=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap001.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## **Post Attack Impacts**\n",
+ "\n",
+ "Please refer to the [Ransomware E2E Notebook](./Ransomware-Kill-Chain-E2E.ipynb) for an in-depth look on the knock-on affects of the ransomware application."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Attack Configurations** | Threat Actor Profile Settings"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "All TAP's inherit the same general configurability shown in the following table:\n",
+ "\n",
+ " TAP Agent Config Options \n",
+ "\n",
+ "|Option Field|Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|start_step|The initial kill chain starting step.|Int|_Required_|\n",
+ "|frequency|The frequency of each kill chains starting steps.|Int|_Required_|\n",
+ "|variance| The timestep variance between frequency|Int|_Required_|\n",
+ "|repeat_kill_chain|Indicates whether the attack is repeated throughout the episode.|Bool|_Required_|\n",
+ "|repeat_kill_chain_stages|Indicates if the kill_chain stage should reset upon failure or retry.|Bool|_Required_|\n",
+ "|default_target_ip | The IP address of the target host |Str|_Required_|\n",
+ "|default_target_node|The Target Host|Str|_Required_|\n",
+ "|target_nodes|A list of Potential Target Hosts (database services) - Selected on per episode basis.|List|_Optional_|\n",
+ "|default_starting_node|The Starting Host|Str|_Required_|\n",
+ "|starting_nodes|A list of Potential Targets|List|_Optional_|\n",
+ "|kill_chain|TAP001 Specific Config (_See the next notebook section_)|Dict|_Required_|\n",
+ "|description|Free Text|Str|_Optional_|\n",
+ "\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```yaml\n",
+ "\n",
+ " - ref: attacker\n",
+ " team: RED\n",
+ " type: TAP001\n",
+ " agent_settings:\n",
+ " start_step: 1\n",
+ " frequency: 3\n",
+ " variance: 0\n",
+ " repeat_kill_chain: false\n",
+ " repeat_kill_chain_stages: true\n",
+ " default_target_ip: *ST_SRV_DB_IP\n",
+ " default_starting_node: \"ST_PROJ-A-PRV-PC-1\"\n",
+ " # starting_nodes: [\"ST_PROJ-A-PRV-PC-1\", \"ST_PROJ-B-PRV-PC-2\", \"ST_PROJ-C-PRV-PC-3\"]\n",
+ " kill_chain:\n",
+ " ... # Next notebook section will cover this configuration option\n",
+ "\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This notebook assumes the reader is already familiar with the below `agent_settings` and won't provide any code snippet examples. \n",
+ "\n",
+ "|Option Field|Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|start_step|The initial kill chain starting step.|Int|_Required_|\n",
+ "|frequency|The frequency of each kill chains starting steps.|Int|_Required_|\n",
+ "|variance| The timestep variance between frequency|Int|_Required_|\n",
+ "|repeat_kill_chain|Indicates whether the attack is repeated throughout the episode.|Bool|_Required_|\n",
+ "|repeat_kill_chain_stages|Indicates if the kill_chain stage should reset upon failure or retry.|Bool|_Required_|\n",
+ "|default_target_node|The Target Host|Str|_Required_|\n",
+ "|starting_nodes|A list of Potential Targets|List|_Optional_|\n",
+ "|kill_chain|_See the next notebook section_|Dict|_Required_||\n",
+ "\n",
+ "\n",
+ "If you're unfamiliar with the above then refer to the equivalent `agent_settings` section within the [TAP003 Kill Chain E2E Demonstration notebook](./TAP003-Kill-Chain-E2E.ipynb). "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap001 = env.game.agents.get(\"attacker\")\n",
+ "for key,value in tap001.config.agent_settings:\n",
+ " if key == 'kill_chain':\n",
+ " pass\n",
+ " else:\n",
+ " print(f\"{key} : {value}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Attack Configurations** | Kill Chain Settings\n",
+ "\n",
+ "Additionally, TAP001's Mobile Malware Kill Chain comes with some extra configuration options. \n",
+ "\n",
+ "These options can be configured to customise the behaviour of certain stages. \n",
+ "\n",
+ "The YAML snippet below is the current default configuration of the mobile malware kill chain:"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "``` YAML\n",
+ " - ref: attacker\n",
+ " team: RED\n",
+ " type: TAP001\n",
+ " agent_settings:\n",
+ " kill_chain:\n",
+ " ACTIVATE:\n",
+ " probability: 1\n",
+ " PROPAGATE:\n",
+ " probability: 1\n",
+ " scan_attempts: 20\n",
+ " repeat_scan: false\n",
+ " network_addresses:\n",
+ " - 192.168.230.0/29 # ST Project A\n",
+ " - 192.168.10.0/26 # Remote Site\n",
+ " - 192.168.20.0/30 # Remote DMZ\n",
+ " # - 192.168.240.0/29 # ST Project B\n",
+ " # - 192.168.250.0/29 # ST Project C\n",
+ " - 192.168.220.0/29 # ST Data (Contains Target)\n",
+ " COMMAND_AND_CONTROL:\n",
+ " probability: 1\n",
+ " keep_alive_frequency: 5\n",
+ " masquerade_port: HTTP\n",
+ " masquerade_protocol: TCP\n",
+ " c2_server_name: ISP-PUB-SRV-DNS\n",
+ " c2_server_ip: *PUBLIC_DNS_IP\n",
+ " PAYLOAD:\n",
+ " probability: 1\n",
+ " exfiltrate: true\n",
+ " corrupt: true\n",
+ " exfiltration_folder_name:\n",
+ " target_username: admin\n",
+ " target_password: admin\n",
+ " continue_on_failed_exfil: True\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | Mobile Malware Kill Chain | General Settings"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "TAP001's ``ACTIVATE``, ``PROPAGATE``, ``COMMAND_AND_CONTROL`` and ``PAYLOAD`` stages's probability of success can be configured.\n",
+ "\n",
+ "Similarly to other TAPs, the argument given to probability is the chance of action performing that stage of kill chain successfully. \n",
+ "The argument given is expected to be between **0** - **1**. \n",
+ "\n",
+ "_(With '1' equalling 100% chance of 'success')_\n",
+ "\n",
+ "It's important to note that the probabilities of success are calculated within the game layer meaning that if an TAP fails because of probability then the TAP will perform a ``DONOTHING`` action for that step. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "```yaml\n",
+ " kill_chain:\n",
+ " ACTIVATE:\n",
+ " probability: 1\n",
+ " PROPAGATE:\n",
+ " probability: 1\n",
+ " COMMAND_AND_CONTROL:\n",
+ " probability: 1\n",
+ " PAYLOAD:\n",
+ " probability: 1\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | Mobile Malware Kill Chain | Propagate Stage\n",
+ "\n",
+ "TAP001's propagate step leverages the NMAP application to scan the network. This kill chain stage is a considerably more complex than the other stages and thus has more configuration options.\n",
+ "\n",
+ " Propagate Configuration Settings \n",
+ "\n",
+ "|Option Field |Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|probability|Action Probability - This is only calculated on the initial scan.|int|_Required_|\n",
+ "|network_addresses|The network-addresses that are scanned during the propagate step. Scanned in the order they are defined.|list[str]|_Required_|\n",
+ "|scan_attempts|The amount of permitted scan attempts.|int|_Required_|\n",
+ "|repeat_scan|Should the scan repeat if the target is not found within the given network address|bool|_optional_|\n",
+ "\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Probability**\n",
+ "\n",
+ "***\n",
+ "\n",
+ "|Option Field |Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|probability|Action Probability |Int|_Required_|\n",
+ "\n",
+ "Similarly, to every other stage, probability is the chance of success of TAP001 has to successfully perform the Propagate Stage.\n",
+ "\n",
+ "However, it's important to note that the **probability of success is only calculated once**. \n",
+ "\n",
+ "After the first scan is performed, the TAP agent will perform the rest of the stage without trialing probability."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Network Addresses**\n",
+ "\n",
+ "***\n",
+ "\n",
+ "|Option Field |Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|network_addresses|The network-addresses that are scanned during the propagate step. Scanned in the order they are defined.|list[str]|_Required_|\n",
+ "\n",
+ "At present, TAPs cannot probe the simulation for routing information.\n",
+ "\n",
+ "Therefore, to scan multiple networks, the ``PROPAGATE`` stage must be provided a list of each network address.\n",
+ "\n",
+ "These network's are scanned in sequential order.\n",
+ "\n",
+ "For example; this notebook is configured with the following ``PROPAGATE`` network_address setting.\n",
+ "\n",
+ "| Network Address | Use Case 7 Subnet Name |\n",
+ "|-----------------|-------------------------|\n",
+ "| 192.168.10.0/26 | REMOTE-SITE |\n",
+ "| 192.168.20.0/30 | REMOTE-DMZ |\n",
+ "| 192.168.220.0/29 | SOME_TECH_DATA |\n",
+ "\n",
+ "\n",
+ "Which when represented in the yaml config is as follows:\n",
+ "\n",
+ "```yaml\n",
+ " kill_chain:\n",
+ " PROPAGATE:\n",
+ " probability: 1\n",
+ " scan_attempts: 20\n",
+ " repeat_scan: false\n",
+ " network_addresses:\n",
+ " - 192.168.230.0/29 # ST Project A\n",
+ " - 192.168.10.0/26 # Remote Site\n",
+ " - 192.168.20.0/30 # Remote DMZ\n",
+ " # - 192.168.240.0/29 # ST Project B\n",
+ " # - 192.168.250.0/29 # ST Project C\n",
+ " - 192.168.220.0/29 # ST Data (Contains Target)\n",
+ "```\n",
+ "Which is loaded into the TAP001 agent as the following list:\n",
+ "```Python\n",
+ "[\"192.168.230.0/29\", \"192.168.10.0/26\", \"192.168.20.0/30\", \"192.168.220.0/29\"]\n",
+ "```\n",
+ "\n",
+ "As PrimAITE expands and TAP agents are provided more ways of probing the simulation, then the ```PROPAGATE``` stage will be able to perform independently thus no longer requiring the network_address configuration option. "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Scan Attempts**\n",
+ "\n",
+ "***\n",
+ "|Option Field |Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|scan_attempts|The amount of permitted scan attempts.|int|_Required_|\n",
+ "\n",
+ "Simply, the ``scan_attempts`` configuration option indicates how many SCAN actions ``PROPAGATE`` stage is permitted to perform before the kill chain is considered to have failed. \n",
+ "\n",
+ "The ``scan_attempts`` option should mainly be kept higher than the length of the list provided in the previous ``network_address`` option.\n",
+ "\n",
+ "Currently, this setting is mainly used in conjunction with next setting: ```repeat_scan```.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Repeat Scan**\n",
+ "\n",
+ "***\n",
+ "|Option Field |Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|repeat_scan|Should the scan repeat if the target is not found within the given network address|bool|_optional_|\n",
+ "\n",
+ "This boolean flag controls whether the ```PROPAGATE``` stage should repeat if the target is not found within the given ```network_addresses```.\n",
+ "\n",
+ "This setting used in conjunction with the ```permitted_scan``` option allows the Red Agent to continue scanning even if the target is not found. \n",
+ "\n",
+ "The network addresses will be selected at random after the first sequential scan(s) of the given ```network_addresses``` for further domain randomisation. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Removing the target network address. (Thus the target will never be found)\n",
+ "network_addresses = [\"192.168.10.0/26\", \"192.168.20.0/30\"]\n",
+ "\n",
+ "with open(_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['io_settings']['save_sys_logs'] = True # Saving syslogs\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain_stages'] = True\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PROPAGATE']['network_addresses'] = network_addresses\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PROPAGATE']['probability'] = 1\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PROPAGATE']['scan_attempts'] = 30\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PROPAGATE']['repeat_scan'] = True\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "env.reset()\n",
+ "for _ in range (256):\n",
+ " env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "***\n",
+ "\n",
+ "[1] _PrimAITE does not actually enforce agent type (Red/Green/Blue) specific actions_\n",
+ "\n",
+ "_However, some actions such as ``APPLICATION_EXECUTE`` and ``NETWORK_RECON_SCAN`` require an understanding of the simulation that is beyond the blue agent's current observation and thus are not suitable for use by reinforcement algorithms._\n",
+ "\n",
+ "_These actions are usually only leveraged by Green or Red agents; hence why they are commonly referenced as such._\n",
+ "\n",
+ "***"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | Mobile Malware Kill Chain | Command and Control Stage\n",
+ "\n",
+ "TAP001's Command and Control stage leverages the C2 beacon which has it's own set of configuration options. In the case of TAP001 some of these settings are already pre-defined based on other settings such as ``target_node``. The table below details the currently available options.\n",
+ "\n",
+ " Command and Control Configuration Settings \n",
+ "\n",
+ "|Option Field | Meaning |Expected Type |Required/Optional|\n",
+ "|---------------------|------------------------------------------------------------------------------------|---------------|-----------------|\n",
+ "|probability | Action Probability - This is only calculated once at this stage. |Int | _Required_ |\n",
+ "|c2_server | What host should the C2 Beacon attempt to connect to as the chosen C2 Server |Str | _Required_ |\n",
+ "|keep_alive_frequency | How often should the C2 Beacon confirm its connection in timesteps. Defaults to 5 |Int | _Optional_ |\n",
+ "|masquerade_port | What port should the C2 traffic use? Defaults to TCP. |Str | _Optional_ |\n",
+ "|masquerade_protocol | What protocol should the C2 traffic masquerade as? Defaults to HTTP. |Str | _Optional_ |\n",
+ " \n",
+ "\n",
+ "For further information around the configuration of the C2 beacon please refer to the ``Command-&-Control-E2E-Demonstration`` last section on configurability."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " # Adding the C2 Server to a different node (REM-PUB-PC-1)\n",
+ " cfg['simulation']['network']['nodes'][10].update(\n",
+ " {\"applications\": [\n",
+ " {\"type\": \"database-client\", \"options\":{\"db_server_ip\":\"192.168.220.3\"}},\n",
+ " {\"type\": \"web-browser\", \"options\":{\"target_url\": \"http://some_tech.com\"}},\n",
+ " {\"type\": \"c2-server\", \"options\":{\"listen_on_ports\":[21]}}]\n",
+ " })\n",
+ "\n",
+ " # Configuring the C2 stage to use the REM-PUB-PC-1 as it's C2 Server and to use a different masquerade port.\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['COMMAND_AND_CONTROL'][\"c2_server_name\"] = \"REM-PUB-PC-1\"\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['COMMAND_AND_CONTROL'][\"c2_server_ip\"] = \"192.168.20.2\"\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['COMMAND_AND_CONTROL'][\"keep_alive_frequency\"] = 3\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['COMMAND_AND_CONTROL'][\"masquerade_port\"] = \"FTP\"\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['COMMAND_AND_CONTROL'][\"masquerade_protocol\"] = \"TCP\"\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "env.reset()\n",
+ "# TAP001 runs for exactly 110 timesteps using default TAP settings.\n",
+ "for _ in range(110):\n",
+ " env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The code cells below use .show() methods to show that the configuration options have successfully altered the C2's suite configuration. For example the C2 beacon's remote connection is now ``REM-PUB-PC-1``'s ip address which is ``192.168.20.2``."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "starting_host = env.game.simulation.network.get_node_by_hostname('ST_PROJ-A-PRV-PC-1')\n",
+ "c2_beacon = starting_host.software_manager.software[\"c2-beacon\"]\n",
+ "c2_beacon.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "c2_server_host = env.game.simulation.network.get_node_by_hostname('REM-PUB-PC-1')\n",
+ "c2_server = c2_server_host.software_manager.software[\"c2-server\"]\n",
+ "c2_server.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | Mobile Malware Kill Chain | Payload Stage\n",
+ "\n",
+ " Payload Settings \n",
+ "\n",
+ "|Option Field | Meaning |Expected Type |Required/Optional|\n",
+ "|---------------------|------------------------------------------------------------------------------------|---------------|-----------------|\n",
+ "|probability | Action Probability - This is only calculated once at this stage. |Int | _Required_ |\n",
+ "|corrupt | Should TAP001 launch the ransomware script against the target database? |Boolean | _Required_ |\n",
+ "|exfiltrate | Should TAP001 exfiltrate the target database.db file? |Boolean | _Required_ |\n",
+ "\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Probability**\n",
+ "\n",
+ "***\n",
+ "\n",
+ "|Option Field | Meaning |Expected Type |Required/Optional|\n",
+ "|---------------------|------------------------------------------------------------------------------------|---------------|-----------------|\n",
+ "|probability | Action Probability - This is only calculated once at this stage. |Int | _Required_ |\n",
+ "\n",
+ "Similarly, to every other stage, probability is the chance of success of TAP001 has to successfully perform the Payload Stage.\n",
+ "\n",
+ "However, it's important to note that the **probability of success is only calculated once**. \n",
+ "\n",
+ "After the agent is successful once then the TAP agent will perform the rest of the stage without trialing any further."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Corrupt**\n",
+ "\n",
+ "***\n",
+ "\n",
+ "|Option Field | Meaning |Expected Type |Required/Optional|\n",
+ "|---------------------|------------------------------------------------------------------------------------|---------------|-----------------|\n",
+ "|corrupt | Should TAP001 launch the ransomware script against the target database? |Boolean | _Required_ |\n",
+ "\n",
+ "This option is a boolean value which indicates if TAP001 should launch the ransomware script against the target database. \n",
+ "\n",
+ "By default this is enabled but if users wish to disable the ransomware attack for training purposes then this value can be set to ``False`` which will prevent the installed ``RansomwareScript`` from launching at the final step.\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Exfiltrate**\n",
+ "\n",
+ "***\n",
+ "\n",
+ "|Option Field | Meaning |Expected Type |Required/Optional|\n",
+ "|---------------------|------------------------------------------------------------------------------------|---------------|-----------------|\n",
+ "|exfiltrate | Should TAP001 exfiltrate the target database.db file? |Boolean | _Required_ |\n",
+ "\n",
+ "\n",
+ "Similar to ``corrupt``, this option is a boolean value which indicates if TAP001 should attempt to exfiltrate the database.db file.\n",
+ "\n",
+ "By default this is enabled but if users wish to disable the exfiltration for training purposes then this value can be set to ``False`` which will prevent the TAP001 agent from attempting to exfiltrate the database.db file."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "_If both ``exfiltrate`` and ``corrupt`` options are enabled then the TAP001 agent will exfiltrate the database.db and then launch the ``RansomwareScript`` against the target._"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Yaml Example:\n",
+ "\n",
+ "```yaml\n",
+ " kill_chain:\n",
+ " PAYLOAD:\n",
+ " probability: 1\n",
+ " exfiltrate: true\n",
+ " corrupt: true\n",
+ " exfiltration_folder_name:\n",
+ " target_username: admin\n",
+ " target_password: admin\n",
+ " continue_on_failed_exfil: True\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The following code cells demonstrate how ``corrupt`` and ``exfiltrate`` can be enabled/disabled and their effects on the environment. After each example the file systems of the target and starting hosts are displayed. If ``corrupt`` is enabled then the target database file will be encrypted and if the ``exfiltrate`` option is enabled then the target database.db will be present within the starting host's file system."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PAYLOAD'][\"corrupt\"] = True\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PAYLOAD'][\"exfiltrate\"] = False\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "env.reset()\n",
+ "for _ in range(110):\n",
+ " env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "starting_host = env.game.simulation.network.get_node_by_hostname('ST_PROJ-A-PRV-PC-1')\n",
+ "target_host = env.game.simulation.network.get_node_by_hostname('ST_DATA-PRV-SRV-DB')\n",
+ "target_host.file_system.show(full=True)\n",
+ "starting_host.file_system.show(full=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PAYLOAD'][\"corrupt\"] = False\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PAYLOAD'][\"exfiltrate\"] = True\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "env.reset()\n",
+ "for _ in range(110):\n",
+ " env.step(0)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "starting_host = env.game.simulation.network.get_node_by_hostname('ST_PROJ-A-PRV-PC-1')\n",
+ "target_host = env.game.simulation.network.get_node_by_hostname('ST_DATA-PRV-SRV-DB')\n",
+ "target_host.file_system.show(full=True)\n",
+ "starting_host.file_system.show(full=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PAYLOAD'][\"corrupt\"] = True\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PAYLOAD'][\"exfiltrate\"] = True\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "env.reset()\n",
+ "for _ in range(110):\n",
+ " env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "starting_host = env.game.simulation.network.get_node_by_hostname('ST_PROJ-A-PRV-PC-1')\n",
+ "target_host = env.game.simulation.network.get_node_by_hostname('ST_DATA-PRV-SRV-DB')\n",
+ "target_host.file_system.show(full=True)\n",
+ "starting_host.file_system.show(full=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Payload Stage | Exfiltration Settings\n",
+ "\n",
+ "If TAP001 is configured to exfiltrate the database.db file then the following configuration options are relevant.\n",
+ "\n",
+ " Exfiltration Settings \n",
+ "\n",
+ "|Option Field | Meaning |Expected Type |Required/Optional|\n",
+ "|-------------------------|------------------------------------------------------------------------------------|---------------|-----------------|\n",
+ "|exfiltration_folder_name | The folder used to store the database.db file. Defaults to ``exfiltration_folder`` |Str | _Optional_ |\n",
+ "|target_username | The username used to login into a target node. Defaults to ``admin`` |Str | _Required_ |\n",
+ "|target_password | The password used to login into a target node. Defaults to ``admin`` |Str | _Required_ |\n",
+ "|continue_on_failed_exfil | Indicates if the attacker should encrypt the target even if the exfiltration fails |Bool | _Required_ |\n",
+ "\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**exfiltration_folder_name**\n",
+ "\n",
+ "***\n",
+ "\n",
+ "|Option Field | Meaning |Expected Type |Required/Optional|\n",
+ "|-------------------------|------------------------------------------------------------------------------------|---------------|-----------------|\n",
+ "|exfiltration_folder_name | The folder used to store the database.db file. Defaults to ``exfiltration_folder``.|str | _Optional_ |\n",
+ "\n",
+ "Users are able to configure what folder the database.db is stored within after successful database exfiltration. For example, if this option was set to ``crown_jewels`` then the TAP001 agent would create a new folder on the starting node called ``crown_jewels`` and once the data-exfiltration is successful that folder will be populated with the ``database.db`` file from the target database. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PAYLOAD'][\"exfiltration_folder_name\"] = \"crown_jewels\"\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "env.reset()\n",
+ "for _ in range(110):\n",
+ " env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "starting_host = env.game.simulation.network.get_node_by_hostname('ST_PROJ-A-PRV-PC-1')\n",
+ "target_host = env.game.simulation.network.get_node_by_hostname('ST_DATA-PRV-SRV-DB')\n",
+ "target_host.file_system.show(full=True)\n",
+ "starting_host.file_system.show(full=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**target_username & target_password**\n",
+ "\n",
+ "***\n",
+ "\n",
+ "|Option Field | Meaning |Expected Type |Required/Optional|\n",
+ "|-------------------------|------------------------------------------------------------------------------------|---------------|-----------------|\n",
+ "|target_username | The username used to login into a target node. Defaults to ``admin`` |Str | _required_ |\n",
+ "|target_password | The password used to login into a target node. Defaults to ``admin`` |Str | _required_ |\n",
+ "\n",
+ "These fields indicate what user credentials the TAP001 agent will use when attempting to exfiltrate the `database.db` file from the target."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Creating a new user for the TAP001 to use.\n",
+ "users = [{\n",
+ " \"username\": \"example_user\",\n",
+ " \"password\": \"example_pass\",\n",
+ " \"is_admin\": \"False\",\n",
+ "}]\n",
+ "with open(_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['simulation']['network']['nodes'][28].update({\"users\":users}) # Adding this new user to the target\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PAYLOAD'][\"target_username\"] = \"example_user\" # Setting TAP001 to use the new user credentials.\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PAYLOAD'][\"target_password\"] = \"example_pass\"\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "env.reset()\n",
+ "for _ in range(110):\n",
+ " env.step(0)\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "target_host = env.game.simulation.network.get_node_by_hostname('ST_DATA-PRV-SRV-DB')\n",
+ "target_host.user_manager.show()\n",
+ "target_host.file_system.show()\n",
+ "tap001.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**continue_on_failed_exfil**\n",
+ "\n",
+ "***\n",
+ "|Option Field | Meaning |Expected Type |Required/Optional|\n",
+ "|-------------------------|------------------------------------------------------------------------------------|---------------|-----------------|\n",
+ "|continue_on_failed_exfil | Indicates if the attacker should encrypt the target even if the exfiltration fails |Bool | _Required_ |\n",
+ "\n",
+ "\n",
+ "This option will affect how the TAP001 agent responds to failing the exfiltration. If this option is set to `True` then the TAP001 agent will attempt the final attack against the database even if the `database.db` exfiltration attempt is unsuccessful. Likewise, if this option is set to `False` then the TAP001 agent will consider it's attack failed if it cannot complete the exfiltration.\n",
+ "\n",
+ "The code cells below demonstrate the differences by using the blue agent to change the user account details on the target database before the exfiltration occurs using action 50\n",
+ "\n",
+ "```yaml\n",
+ " # ST_DATA-PRV-SRV-DB | node-account-change-password | Changes the password of a user account\n",
+ " 50:\n",
+ " action: node-account-change-password\n",
+ " options:\n",
+ " node_name: ST_DATA-PRV-SRV-DB\n",
+ " username: admin # default account\n",
+ " current_password: admin # default password\n",
+ " new_password: thr33_alert_wolv3z # A more 'secure' password\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "If we set the `continue_on_failed_exfil` to true we can see that the despite the exfiltration failing the `database.db` still ends up corrupted by the end of the attack."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PAYLOAD'][\"continue_on_failed_exfil\"] = True\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain'] = False\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "env.reset()\n",
+ "\n",
+ "# Changing the target database credentials:\n",
+ "env.step(50)\n",
+ "\n",
+ "# Finishing the episode:\n",
+ "for _ in range(127):\n",
+ " env.step(0)\n",
+ " \n",
+ "tap001.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The exfiltration was not successful\n",
+ "starting_host = env.game.simulation.network.get_node_by_hostname(tap001.starting_node)\n",
+ "\n",
+ "starting_host.file_system.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Yet the target database.db is still corrupt.\n",
+ "\n",
+ "target_host = env.game.simulation.network.get_node_by_hostname('ST_DATA-PRV-SRV-DB')\n",
+ "target_host.file_system.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Whereas now if we set `continue_on_failed_exfil` to false we can see that the attack failed and the database health status remains `GOOD`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PAYLOAD'][\"continue_on_failed_exfil\"] = False\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain'] = False\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "env.reset()\n",
+ "\n",
+ "# Changing the target database credentials:\n",
+ "env.step(50)\n",
+ "\n",
+ "# Finishing the episode:\n",
+ "for _ in range(127):\n",
+ " env.step(0)\n",
+ " \n",
+ "tap001.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# The exfiltration was not successful\n",
+ "starting_host = env.game.simulation.network.get_node_by_hostname(tap001.starting_node)\n",
+ "\n",
+ "starting_host.file_system.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# And the target database.db remains healthy.\n",
+ "\n",
+ "target_host = env.game.simulation.network.get_node_by_hostname('ST_DATA-PRV-SRV-DB')\n",
+ "target_host.file_system.show()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": ".venv",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/src/primaite/notebooks/UC7-TAP003-Kill-Chain-E2E.ipynb b/src/primaite/notebooks/UC7-TAP003-Kill-Chain-E2E.ipynb
new file mode 100644
index 00000000..306e070a
--- /dev/null
+++ b/src/primaite/notebooks/UC7-TAP003-Kill-Chain-E2E.ipynb
@@ -0,0 +1,1714 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Backdoor & Vulnerability Creation Kill Chain\n",
+ "\n",
+ "© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK\n",
+ "\n",
+ "**Threat Actor Profile (TAP):** 003 \n",
+ "**Kill Chain**: Backdoor & Vulnerability Creation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "This notebook demonstrates a new UC7 Kill Chain which aims to represent a different style of attack in comparison to the mobile malware kill chain (TAP001).\n",
+ "Kill chains aim to represent a potential real world cyber attack. In this scenario an malicious `SOME_TECH` admin (TAP003) leverages his legitimate credentials and permissions to create purposeful backdoors, establish footholds and use other legitimate features in malicious ways.\n",
+ " \n",
+ "\n",
+ "In this version - this scenario is limited in scope. TAP003 opts to alter user accounts and implement malicious ACL rule by using the ``terminal`` service to SSH into target routers. These ACLs block green traffic which trigger a negative reward.\n",
+ " \n",
+ "\n",
+ "This kill chain intends to introduce a new UC7 attack which is both realistic but also dissimilar to other kill chains."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "!primaite setup"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "# Importing the necessary primAITE libraries\n",
+ "from primaite.session.environment import PrimaiteGymEnv\n",
+ "from primaite.simulator.system.applications.database_client import DatabaseClient\n",
+ "from primaite.simulator.system.services.dns.dns_client import DNSClient\n",
+ "from primaite.simulator.network.hardware.nodes.host.computer import Computer\n",
+ "from primaite.simulator.system.applications.web_browser import WebBrowser\n",
+ "from primaite.simulator.network.hardware.nodes.network.router import Router\n",
+ "from primaite.game.agent.scripted_agents.TAP003 import TAP003, InsiderKillChain, InsiderKillChainOptions\n",
+ "from primaite.config.load import load, _EXAMPLE_CFG\n",
+ "from pprint import pprint\n",
+ "from deepdiff.diff import DeepDiff\n",
+ "from prettytable import PrettyTable\n",
+ "import yaml"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Utility functions.\n",
+ "\n",
+ "def print_agent_actions_except_do_nothing(agent_name):\n",
+ " \"\"\"Get the agent's action history, filter out `do-nothing` actions, print relevant data in a table.\"\"\"\n",
+ " table = PrettyTable()\n",
+ " table.field_names = [\"Step\", \"Action\", \"Node\", \"Application\", \"Target IP\", \"Response\"]\n",
+ " print(f\"Episode: {env.episode_counter}, Actions for '{agent_name}':\")\n",
+ " for item in env.game.agents[agent_name].history:\n",
+ " if item.action == \"do-nothing\":\n",
+ " continue\n",
+ "\n",
+ " node, application, target_ip = \"N/A\", \"N/A\", \"N/A\",\n",
+ "\n",
+ " if item.action.startswith(\"node-nmap\"):\n",
+ " node = item.parameters['source_node']\n",
+ " application = \"nmap\"\n",
+ " target_ip = str(item.parameters['target_ip_address'])\n",
+ " target_ip = (target_ip[:25]+'...') if len(target_ip)>25 else target_ip # truncate long string\n",
+ "\n",
+ " elif item.action == \"router-acl-add-rule\":\n",
+ " node = item.parameters.get(\"router_name\")\n",
+ " elif item.action == \"node-send-remote-command\":\n",
+ " node = item.parameters.get(\"node_name\")\n",
+ " target_ip = item.parameters.get(\"remote_ip\")\n",
+ " application = item.parameters.get(\"command\")\n",
+ " elif item.action == \"node-session-remote-login\":\n",
+ " node = item.parameters.get(\"node_name\")\n",
+ " target_ip = item.parameters.get(\"remote_ip\")\n",
+ " application = \"user-manager\"\n",
+ " elif item.action.startswith(\"c2-server\"):\n",
+ " application = \"c2-server\"\n",
+ " node = item.parameters.get('node_name')\n",
+ " elif item.action == \"configure-c2-beacon\":\n",
+ " application = \"c2-beacon\"\n",
+ " node = item.parameters.get('node_name')\n",
+ "\n",
+ " else:\n",
+ " if (node_id := item.parameters.get('node_id')) is not None:\n",
+ " node = env.game.agents[agent_name].action_manager.node_names[node_id]\n",
+ " if (application_id := item.parameters.get('application_id')) is not None:\n",
+ " application = env.game.agents[agent_name].action_manager.application_names[node_id][application_id]\n",
+ " if (application_name := item.parameters.get('application_name')) is not None:\n",
+ " application = application_name\n",
+ "\n",
+ " table.add_row([item.timestep, item.action, node, application, target_ip, item.response.status])\n",
+ "\n",
+ " print(table)\n",
+ " print(\"(Any do-nothing actions are omitted)\")\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def display_obs_diffs(old, new, step_counter):\n",
+ " \"\"\"\n",
+ " Use DeepDiff to extract and display differences in old and new instances of\n",
+ " the observation space.\n",
+ "\n",
+ " :param old: observation space instance.\n",
+ " :param new: observation space instance.\n",
+ " :param step_counter: current step counter.\n",
+ " \"\"\"\n",
+ " print(\"\\nObservation space differences\")\n",
+ " print(\"-----------------------------\")\n",
+ " diff = DeepDiff(old, new)\n",
+ " print(f\"Step {step_counter}\")\n",
+ " for d,v in diff.get('values_changed', {}).items():\n",
+ " print(f\"{d}: {v['old_value']} -> {v['new_value']}\")\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Notebook Sections:**\n",
+ "1. Notebook Intro\n",
+ "2. Notebook Setup\n",
+ "3. Prior To Attack\n",
+ "4. Kill Chain Stage Demonstration\n",
+ "5. Attack Configurations"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Notebook Intro** | **Backdoor & Vulnerability Creation Kill Chain Intro** \n",
+ "\n",
+ "TAP003's kill chain is comprised of a variety of blue actions which are leveraged in unusual ways. This includes introducing malicious ACL's which block green traffic and installing and execute green applications in order to simulate unusual green pattern of life. The rest of this notebook will go through each step in more detail whilst demonstrating the impacts that each step has on both observation and simulation behaviour.\n",
+ "\n",
+ "_Reconnaissance - DONOTHING CAOS Action_\n",
+ "\n",
+ "|Index | Action Stage| OBS Impact | Narrative |\n",
+ "|-----|-------------|-------------|-----------|\n",
+ "|1|Reconnaissance|*No Direct Impact*|TAP003 is passively investigating sensitive systems, data and access control mechanisms.|\n",
+ "\n",
+ "_Planning - DONOTHING CAOS Action_\n",
+ "\n",
+ "|Index| Action Stage| OBS Impact | Narrative |\n",
+ "|-----|-------------|------------|-----------|\n",
+ "|2|Planning| **No current impact**|TAP003 is devising a plan to exploit their elevated privileges.|\n",
+ "\n",
+ " _Access - DONOTHING CAOS Action__\n",
+ "\n",
+ "|Index| Action Stage| OBS Impact | Narrative |\n",
+ "|-----|-------------|------------|-----------|\n",
+ "|3|Access|**No current impact** |TAP003 uses their legitimate credentials to access the access control settings.|\n",
+ "\n",
+ " _Manipulation - HOST:SESSIONS_SEND_REMOTE_COMMAND -> HOST:ACCOUNTS:CHANGE:PASSWORD CAOS ACTION_\n",
+ " \n",
+ "|Index| Action Stage| OBS Impact | Narrative |\n",
+ "|-----|-------------|------------|-----------|\n",
+ "|4|Manipulation| **Target Host(s)** HOST::SESSIONS:REMOTE |TAP003 exploits their insider knowledge/privilege to implement changes for sabotage.|\n",
+ "\n",
+ " _Exploit - FIREWALL:ACL:add_rule CAOS ACTION_\n",
+ "\n",
+ "|Index| Action Stage| OBS Impact | Narrative |\n",
+ "|-----|-------------|------------|-----------|\n",
+ "|5|Exploit| **Target Host(s)** FIREWALL:ACL:INTERNAL/EXTERNAL:*|TAP003 exploits their insider knowledge/privilege to implement changes for sabotage.|\n",
+ "\n",
+ "_Only the initial five steps are represented in the this version of this kill-chain._ \n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## **Notebook Setup** | **Network Configuration:**\n",
+ "\n",
+ "This notebook uses the same network setup as UC7. \n",
+ "\n",
+ "Please refer to the main [UC7-E2E-Demo notebook for further reference](./UC7-E2E-Demo.ipynb)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
\n",
+ "\n",
+ "_(Click to enlarge)_"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as uc7_config:\n",
+ " cfg = yaml.safe_load(uc7_config)\n",
+ " cfg[\"agents\"][33][\"agent_settings\"][\"flatten_obs\"] = False\n",
+ " cfg['io_settings']['save_agent_logs'] = True\n",
+ " cfg['io_settings']['save_sys_logs'] = True # Saving syslogs\n",
+ "env = PrimaiteGymEnv(env_config=cfg)\n",
+ "env.game.simulation.network.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Notebook Setup** | Instantiating Relevant Simulation Objects\n",
+ "The cell below sets up the relevant simulation and agent objects for the kill chain demonstration.\n",
+ "\n",
+ "\n",
+ "The following cell resets the environment, instantiates TAP003 and it's selected starting/target hosts."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "env.reset() # resetting the environment\n",
+ "# The TAP003 Agent\n",
+ "tap003 = env.game.agents['attacker']\n",
+ "tap003.logger.logger.setLevel(\"INFO\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## **Prior To Attack** | Initial States:"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The first section of this notebook displays the initial simulation state of TAP003's starting and target nodes."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Initial State** | Starting Host:\n",
+ "TAP003's initial starting point.\n",
+ "\n",
+ "TAP003's starting host does not cause any MNE (Malicious Network Events) in it's current implementation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "# TAP003's Starting Client:\n",
+ "starting_host = env.game.simulation.network.get_node_by_hostname(tap003.starting_node)\n",
+ "print(f\"Starting host:\")\n",
+ "starting_host.show()\n",
+ "starting_host.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Initial State** | Target Hosts\n",
+ "\n",
+ "TAP003's selected target hosts at current the only valid targets for TAP003 are Router/Firewall type nodes\n",
+ "\n",
+ "Code snippet below shows the default OBS of the target routers"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "# TAP003's target routers\n",
+ "\n",
+ "st_intra_prv_rt_cr: Router = env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-CR\")\n",
+ "st_intra_prv_rt_dr_1: Router = env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-DR-1\")\n",
+ "rem_pub_rt_dr: Router = env.game.simulation.network.get_node_by_hostname(\"REM-PUB-RT-DR\")\n",
+ "\n",
+ "st_intra_prv_rt_cr.acl.show()\n",
+ "st_intra_prv_rt_dr_1.acl.show()\n",
+ "rem_pub_rt_dr.acl.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## **Kill Chain** | Kill Chain Stage Demonstration \n",
+ "\n",
+ "For the initial kill chain demonstration, TAP003 is configured with the following yaml snippet:\n",
+ "\n",
+ "```yaml\n",
+ " - ref: attacker\n",
+ " team: RED\n",
+ " type: tap-003\n",
+ " observation_space: {}\n",
+ " action_space: {}\n",
+ " agent_settings:\n",
+ " start_step: 1\n",
+ " frequency: 3\n",
+ " variance: 0\n",
+ " repeat_kill_chain: false\n",
+ " repeat_kill_chain_stages: true\n",
+ " default_starting_node: \"ST_PROJ-A-PRV-PC-1\"\n",
+ " starting_nodes:\n",
+ " # starting_nodes: [\"ST_PROJ-A-PRV-PC-1\", \"ST_PROJ-B-PRV-PC-2\", \"ST_PROJ-C-PRV-PC-3\"]\n",
+ " kill_chain:\n",
+ " PLANNING:\n",
+ " probability: 1\n",
+ " starting_network_knowledge:\n",
+ " credentials:\n",
+ " ST_PROJ-A-PRV-PC-1:\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ST_PROJ-B-PRV-PC-2:\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ST_PROJ-C-PRV-PC-3:\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ST_INTRA-PRV-RT-DR-1:\n",
+ " ip_address: 192.168.230.1\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ST_INTRA-PRV-RT-CR:\n",
+ " ip_address: 192.168.160.1\n",
+ " username: admin\n",
+ " password: admin\n",
+ " REM-PUB-RT-DR:\n",
+ " ip_address: 192.168.10.2\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ACCESS:\n",
+ " probability: 1\n",
+ " MANIPULATION:\n",
+ " probability: 1\n",
+ " account_changes:\n",
+ " - host: ST_INTRA-PRV-RT-DR-1\n",
+ " ip_address: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1\n",
+ " action: change_password\n",
+ " username: admin\n",
+ " new_password: \"red_pass\"\n",
+ " - host: ST_INTRA-PRV-RT-CR\n",
+ " ip_address: 192.168.160.1 # ST_INTRA-PRV-RT-CR\n",
+ " action: change_password\n",
+ " username: \"admin\"\n",
+ " new_password: \"red_pass\"\n",
+ " - host: REM-PUB-RT-DR\n",
+ " ip_address: 192.168.10.2 # REM-PUB-RT-DR\n",
+ " action: change_password\n",
+ " username: \"admin\"\n",
+ " new_password: \"red_pass\"\n",
+ " EXPLOIT:\n",
+ " probability: 1\n",
+ " malicious_acls:\n",
+ " - target_router: ST_INTRA-PRV-RT-DR-1\n",
+ " position: 1\n",
+ " permission: DENY\n",
+ " src_ip: ALL\n",
+ " src_wildcard: 0.0.255.255\n",
+ " dst_ip: ALL\n",
+ " dst_wildcard: 0.0.255.255\n",
+ " src_port: POSTGRES_SERVER\n",
+ " dst_port: POSTGRES_SERVER\n",
+ " protocol_name_name: TCP\n",
+ " - target_router: ST_INTRA-PRV-RT-CR\n",
+ " position: 1\n",
+ " permission: DENY\n",
+ " src_ip: ALL\n",
+ " src_wildcard: 0.0.255.255\n",
+ " dst_ip: ALL\n",
+ " dst_wildcard: 0.0.255.255\n",
+ " src_port: HTTP\n",
+ " dst_port: HTTP\n",
+ " protocol_name_name: TCP\n",
+ " - target_router: REM-PUB-RT-DR\n",
+ " position: 1\n",
+ " permission: DENY\n",
+ " src_ip: ALL\n",
+ " src_wildcard: 0.0.255.255\n",
+ " dst_ip: ALL\n",
+ " dst_wildcard: 0.0.255.255\n",
+ " src_port: DNS\n",
+ " dst_port: DNS\n",
+ " protocol_name_name: TCP\n",
+ "\n",
+ "```\n",
+ "_Further information & guidance around configuring TAP003 can be found within the last section of this notebook._"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | NOT STARTED\n",
+ "This is the default state of the TAP003 Agent. This stage indicates that the TAP003 agent has not begun it's kill chain.\n",
+ "If TAP003 is in this stage then on the next execution step the kill chain will begin."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap003 = env.game.agents['attacker']\n",
+ "\n",
+ "\n",
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap003.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap003.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap003.next_kill_chain_stage.name}\")\n",
+ "while(tap003.current_kill_chain_stage == InsiderKillChain.NOT_STARTED):\n",
+ " default_obs, _, _, _, _ = env.step(0)\n",
+ "starting_host.software_manager.show()\n",
+ "\n",
+ "env.step(0);"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap003.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | RECONNAISSANCE\n",
+ "\n",
+ "|Index| Action Stage| OBS Impact | Narrative |\n",
+ "|-----|-------------|------------|-----------|\n",
+ "|1|RECONNAISSANCE|*No Direct Impact*|TAP003 is identifying Sensitive systems, data and access control mechanisms in legitimate ways.|\n",
+ "\n",
+ "Currently, this stage in the kill chain is implemented via the 'DONOTHING' CAOS action."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap003.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap003.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap003.next_kill_chain_stage.name}\")\n",
+ "\n",
+ "while(tap003.current_kill_chain_stage == InsiderKillChain.RECONNAISSANCE):\n",
+ " reconnaissance_obs_impact, _, _, _, _ = env.step(0)\n",
+ "\n",
+ "current_host = env.game.simulation.network.get_node_by_hostname(tap003.current_host)\n",
+ "current_host.software_manager.show()\n",
+ "display_obs_diffs(default_obs, reconnaissance_obs_impact, env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap003.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | PLANNING\n",
+ "\n",
+ "|Index| Action Stage| OBS Impact | Narrative |\n",
+ "|-----|-------------|------------|-----------|\n",
+ "|2|PLANNING| *No Direct Impact*| HOST:APPLICATION|TAP003 is devising a plan to exploit their elevated privileges.|\n",
+ "\n",
+ "Currently, the TAP003 agent does not perform any actions at this stage of the kill chain."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "pprint(\"---TAP003's Current State---\")\n",
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap003.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap003.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap003.next_kill_chain_stage.name}\")\n",
+ "pprint(\"---Starting Client State----\")\n",
+ "while(tap003.current_kill_chain_stage == InsiderKillChain.PLANNING):\n",
+ " planning_obs_impact, _, _, _, info = env.step(0);\n",
+ "current_host.software_manager.show()\n",
+ "display_obs_diffs(reconnaissance_obs_impact, planning_obs_impact, env.game.step_counter)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap003.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | ACCESS\n",
+ "\n",
+ "|Index| Action Stage| OBS Impact | Narrative |\n",
+ "|-----|-------------|------------|-----------|\n",
+ "|3|Access|_DONOTHING CAOS Action_|TAP003 uses their legitimate credentials to access the access control settings.|\n",
+ "\n",
+ "Currently, at this point of the kill chain stage the TAP003 does not perform any simulations actions. Future versions of TAP003 aim to leverage more of the simulation to create and remove accounts at this stage."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "pprint(\"---TAP003's Current State---\")\n",
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap003.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap003.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap003.next_kill_chain_stage.name}\")\n",
+ "pprint(\"---Starting Client State----\")\n",
+ "while(tap003.current_kill_chain_stage == InsiderKillChain.ACCESS):\n",
+ " access_obs_impact, _, _, _, info = env.step(0)\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\n",
+ "# Compare observation space before and after ACCESS stage.\n",
+ "display_obs_diffs(planning_obs_impact, access_obs_impact, env.game.step_counter)\n",
+ "\n",
+ "starting_host.software_manager.show()\n",
+ "print_agent_actions_except_do_nothing(tap003.config.ref)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap003.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | MANIPULATION\n",
+ "\n",
+ "|Index| Action Stage| OBS Impact | Narrative |\n",
+ "|-----|-------------|------------|-----------|\n",
+ "|4|Manipulation| **Target Host(s)** HOST::SESSIONS:REMOTE |TAP003 exploits their insider knowledge/privilege to implement changes for sabotage.|\n",
+ "\n",
+ "In the ``MANIPULATION`` kill chain stage the TAP003 agent creates new and alters pre-existing user accounts based on user given settings. \n",
+ "\n",
+ "_For more information please refer to the later TAP003 customisation section of the notebook._"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "access_obs_impact, _, _, _, _ = env.step(0)\n",
+ "pprint(f\"Agent action: {info['agent_actions']['attacker']}\")\n",
+ "\n",
+ "pprint(\"---TAP003's Current State---\")\n",
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap003.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap003.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap003.next_kill_chain_stage.name}\")\n",
+ "pprint(\"---Target Client State----\")\n",
+ "while(tap003.current_kill_chain_stage == InsiderKillChain.MANIPULATION):\n",
+ " manipulation_obs_impact, _, _, _, info = env.step(0)\n",
+ "\n",
+ "\n",
+ "# Example host\n",
+ "rem_pub_rt_dr.user_manager.show()\n",
+ "# rem_pub_rt_dr.user_session_manager.show()\n",
+ "\n",
+ "# Compare observation space before and after MANIPULATION stage.\n",
+ "display_obs_diffs(access_obs_impact, manipulation_obs_impact, env.game.step_counter)\n",
+ "print_agent_actions_except_do_nothing(tap003.config.ref)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap003.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Kill Chain** | EXPLOITATION\n",
+ "\n",
+ "|Index| Action Stage| OBS Impact | Narrative |\n",
+ "|-----|-------------|------------|-----------|\n",
+ "|5|EXPLOITATION| **Target Host(s)** ROUTER_ACL_ADDRULE |TAP003 exploiting their insider knowledge/privilege to implement changes for sabotage|\n",
+ "\n",
+ "In the final attack stage the TAP003 agent insert a malicious ACL rule(s) which blocks specific traffic, therefore triggering negative rewards for the green agents.\n",
+ "\n",
+ "The table below shows the impacts:\n",
+ "\n",
+ "|Target Router | Impact |\n",
+ "|----------------------|--------|\n",
+ "|`ST_INTRA-PRV-RT-DR-1`| Blocks all `POSTGRES_SERVER` that arrives at the `ST_INTRA-PRV-RT-DR-1` router. This rule will prevent all ST_PROJ_* hosts from accessing the database (`ST_DATA-PRV-SRV-DB`).|\n",
+ "|`ST_INTRA-PRV-RT-CR`| Blocks all `HTTP` traffic that arrives at the`ST_INTRA-PRV-RT-CR` router. This rule will prevent all SOME_TECH hosts from accessing the webserver (`ST_DMZ-PUB-SRV-WEB`)|\n",
+ "|`REM-PUB-RT-DR`| Blocks all `DNS` traffic that arrives at the `REM-PUB-RT-DR` router. This rule prevents any remote site works from accessing the DNS Server (`ISP-PUB-SRV-DNS`).|\n",
+ "\n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
\n",
+ "\n",
+ "_(Click to enlarge)_"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "manipulation_obs_impact, _, _, _, _ = env.step(0)\n",
+ "pprint(f\"Agent action: {info['agent_actions']['attacker']}\")\n",
+ "\n",
+ "pprint(\"---TAP003's Current State---\")\n",
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap003.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap003.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap003.next_kill_chain_stage.name}\")\n",
+ "pprint(\"---Target Client State----\")\n",
+ "while(tap003.current_kill_chain_stage == InsiderKillChain.EXPLOIT):\n",
+ " exploit_obs_impact, _, _, _, info = env.step(0)\n",
+ " \n",
+ "st_intra_prv_rt_cr.acl.show()\n",
+ "st_intra_prv_rt_dr_1.acl.show()\n",
+ "rem_pub_rt_dr.acl.show()\n",
+ "\n",
+ "# Stepping once more to allow the malicious acl to appear in the simulation.\n",
+ "exploit_obs_impact, _, _, _, _ = env.step(0)\n",
+ "\n",
+ "# Compare observation space before and after MANIPULATION stage.\n",
+ "display_obs_diffs(manipulation_obs_impact, exploit_obs_impact, env.game.step_counter)\n",
+ "print_agent_actions_except_do_nothing(tap003.config.ref)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tap003.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Demonstration of the ACL Rule blocking traffic\n",
+ "\n",
+ "As an example of the malicious ACL Rule affecting traffic across the network, attempting to query the database server (ST_DATA-PRV-SRV-DB) from any of the `ST_PROJECT_*` networks should fail because it is must route through the `ST_INTRA-PRV-RT-DR-1` router which TAP003 has configured to block all `POSTGRES_SERVER` traffic."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "affected_node = env.game.simulation.network.get_node_by_hostname(\"ST_PROJ-A-PRV-PC-1\")\n",
+ "database_server = env.game.simulation.network.get_node_by_hostname(\"ST_DATA-PRV-SRV-DB\")\n",
+ "\n",
+ "st_intra_prv_rt_dr_1 = env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-DR-1\")\n",
+ "\n",
+ "database_client: DatabaseClient = affected_node.software_manager.software.get(\"database-client\")\n",
+ "st_intra_prv_rt_dr_1.acl.show()\n",
+ "\n",
+ "# should be False\n",
+ "print(database_client.query(sql=\"SELECT\"))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "However, ACL rules will not stop ICMP traffic, allowing us to still ping the target nodes as shown below."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# should be true\n",
+ "print(affected_node.ping(database_server.network_interface[1].ip_address))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Additionally, by default, TAP003 is configured to add two more ACLs on the UC7 network as shown in the table previously."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# This ACL blocks all web_server traffic from within the main `SOME_TECH` office. Thus leading to every SOME_TECH host unable to access the web-server\n",
+ "st_intra_prv_rt_cr = env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-CR\")\n",
+ "st_intra_prv_rt_cr.acl.show()\n",
+ "\n",
+ "st_head_office_private_pc_1: Computer = env.game.simulation.network.get_node_by_hostname(\"ST_HO-PRV-PC-1\")\n",
+ "st_head_office_private_pc_1_web_browser: WebBrowser = st_head_office_private_pc_1.software_manager.software[\"web-browser\"]\n",
+ "st_head_office_private_pc_1_web_browser.get_webpage(url=\"http://some_tech.com\")\n",
+ "st_head_office_private_pc_1_web_browser.sys_log.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# This ACL blocks all DNS traffic from exiting the SOME_TECH remote site.\n",
+ "rem_pub_pc_1: Computer = env.game.simulation.network.get_node_by_hostname(hostname=\"REM-PUB-PC-1\")\n",
+ "rem_pub_rt_dr = env.game.simulation.network.get_node_by_hostname(\"REM-PUB-RT-DR\")\n",
+ "dns_client: DNSClient = rem_pub_pc_1.software_manager.software[\"dns-client\"]\n",
+ "dns_client.dns_cache.clear()\n",
+ "dns_client.check_domain_exists(target_domain=\"some_tech.com\")\n",
+ "rem_pub_rt_dr.acl.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## **Kill Chain Configurations** | Overview:"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The following sections cover the TAP003's settings & configurations. \n",
+ "Each section contains code cells which directly demonstrate each option and it's effect on TAP003."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Attack Configurations** | Threat Actor Profile (TAP) wide Agent Settings\n",
+ "\n",
+ " Threat Actor Profile Agent Settings \n",
+ "\n",
+ "\n",
+ "\n",
+ "|Option Field|Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|start_step|The initial kill chain starting step.|Int|_Required_|\n",
+ "|frequency|The frequency of each kill chains starting steps.|Int|_Required_|\n",
+ "|variance| The timestep variance between frequency|Int|_Required_|\n",
+ "|repeat_kill_chain|Indicates whether the attack is repeated throughout the episode.|Bool|_Required_|\n",
+ "|repeat_kill_chain_stages|Indicates if the kill_chain stage should reset upon failure or retry.|Bool|_Required_|\n",
+ "|default_target_node|The Target Host|Str|_Required_|\n",
+ "|starting_nodes|A list of Potential Targets|List|_Optional_|\n",
+ "|kill_chain|_See the next notebook section_|Dict|_Required_||\n",
+ "\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "_Example kill chain setting configuration_\n",
+ "```yaml\n",
+ " start_step: 1\n",
+ " frequency: 3\n",
+ " variance: 0\n",
+ " repeat_kill_chain: false\n",
+ " repeat_kill_chain_stages: true\n",
+ " default_starting_node: \"ST_PROJ-A-PRV-PC-1\"\n",
+ " starting_nodes:\n",
+ " # starting_nodes: [\"ST_PROJ-A-PRV-PC-1\", \"ST_PROJ-B-PRV-PC-2\", \"ST_PROJ-C-PRV-PC-3\"]\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Attack Configurations** | Kill Chain Settings Overview\n",
+ "Currently, each kill chain stage has a probability of success option.\n",
+ "Additionally the manipulation kill stage offers an additional configuration of the malicious ACL.\n",
+ "\n",
+ " TAP003's Kill Chain Settings \n",
+ "\n",
+ " \n",
+ "\n",
+ "Kill Chain Stage 1 - _PLANNING_\n",
+ "\n",
+ "|Option Field|Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|probability|Probability Of Success - The chance of successfully carrying out this stage in the kill_chain.|float|_Required_|\n",
+ "|starting_network_knowledge| User Account details | dict |_required_|\n",
+ "\n",
+ "Kill Chain Stage 2 - _ACCESS_\n",
+ "\n",
+ "|Option Field|Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|probability|Probability Of Success - The chance of successfully carrying out this stage in the kill_chain.|float|_Required_|\n",
+ "\n",
+ "Kill Chain Stage 3 - _MANIPULATION_\n",
+ "\n",
+ "|Option Field|Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|probability|Probability Of Success - The chance of successfully carrying out this stage in the kill_chain.|float|_Required_|\n",
+ "|account_changes| User Accounts hijacked - Must be the same targets as `malicious_acl` used in next kill chain stage | dict | _Required_|\n",
+ "\n",
+ "Kill Chain Stage 4 - _EXPLOIT_\n",
+ "\n",
+ "|Option Field|Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|malicious_acl|The configurable ACL that the TAP003 agent adds to the target node.|dict|_Required_|\n",
+ "\n",
+ " "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "_An example of a kill chain setting configuration_ \n",
+ "```yaml\n",
+ " kill_chain:\n",
+ " PLANNING:\n",
+ " probability: 1\n",
+ " starting_network_knowledge:\n",
+ " credentials:\n",
+ " ST_PROJ-A-PRV-PC-1:\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ST_PROJ-B-PRV-PC-2:\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ST_PROJ-C-PRV-PC-3:\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ST_INTRA-PRV-RT-DR-1:\n",
+ " ip_address: 192.168.230.1\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ST_INTRA-PRV-RT-CR:\n",
+ " ip_address: 192.168.160.1\n",
+ " username: admin\n",
+ " password: admin\n",
+ " REM-PUB-RT-DR:\n",
+ " ip_address: 192.168.10.2\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ACCESS:\n",
+ " probability: 1\n",
+ " MANIPULATION:\n",
+ " probability: 1\n",
+ " account_changes:\n",
+ " - host: ST_INTRA-PRV-RT-DR-1\n",
+ " ip_address: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1\n",
+ " action: change_password\n",
+ " username: admin\n",
+ " new_password: \"red_pass\"\n",
+ " - host: ST_INTRA-PRV-RT-CR\n",
+ " ip_address: 192.168.160.1 # ST_INTRA-PRV-RT-CR\n",
+ " action: change_password\n",
+ " username: \"admin\"\n",
+ " new_password: \"red_pass\"\n",
+ " - host: REM-PUB-RT-DR\n",
+ " ip_address: 192.168.10.2 # REM-PUB-RT-DR\n",
+ " action: change_password\n",
+ " username: \"admin\"\n",
+ " new_password: \"red_pass\"\n",
+ " EXPLOIT:\n",
+ " probability: 1\n",
+ " malicious_acls:\n",
+ " - target_router: ST_INTRA-PRV-RT-DR-1\n",
+ " ip_address: 192.168.230.1 \n",
+ " position: 1\n",
+ " permission: DENY\n",
+ " src_ip: ALL\n",
+ " src_wildcard_mask: 0.0.255.255\n",
+ " dst_ip: ALL\n",
+ " dst_wildcard_mask: 0.0.255.255\n",
+ " src_port: POSTGRES_SERVER\n",
+ " dst_port: POSTGRES_SERVER\n",
+ " protocol_name: TCP\n",
+ "\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### **Attack Configurations** | Configuration Examples \n",
+ "The following notebook section demonstrates a few potential examples of different TAP003 configurations and their expected behaviour within an episode."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "tap003 = env.game.agents['attacker']\n",
+ "for key,value in tap003.config.agent_settings:\n",
+ " if key == 'kill_chain':\n",
+ " pass\n",
+ " else:\n",
+ " print(f\"{key} : {value}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | Start Step, Frequency & Variance\n",
+ "\n",
+ "In this section, the code cells below demonstrate the following options:\n",
+ "\n",
+ "|Option Field|Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|start_step|The initial kill chain starting step.|Int|_Required_|\n",
+ "|frequency|The frequency of each kill chains starting steps.|Str|_Required_|\n",
+ "|variance|The timestep variance between frequency.|Str|_Required_|\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The code cell below alters the start_step, frequency and variance to 20, 10 and 5 respectively.\n",
+ "Additionally, the probability of the kill chain stages are set to guarantee success. "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as uc7_config:\n",
+ " cfg = yaml.safe_load(uc7_config)\n",
+ " cfg[\"agents\"][33][\"agent_settings\"][\"flatten_obs\"] = False\n",
+ " cfg['io_settings']['save_sys_logs'] = True # Saving syslogs\n",
+ " cfg['agents'][32]['agent_settings']['start_step'] = 20\n",
+ " cfg['agents'][32]['agent_settings']['frequency'] = 10\n",
+ " cfg['agents'][32]['agent_settings']['variance'] = 5\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['MANIPULATION']['probability'] = 1\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['ACCESS']['probability'] = 1\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PLANNING']['probability'] = 1\n",
+ "env = PrimaiteGymEnv(env_config = cfg)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The cell below demonstrates how the frequency & variance options affect TAP003's next execution step."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "tap003 = env.game.agents['attacker']\n",
+ "print(\"---TAP003's Current State---\")\n",
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap003.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap003.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap003.next_kill_chain_stage.name}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | repeat_kill_chain & repeat_kill_chain_stages\n",
+ "\n",
+ "This section demonstrate how the different repeat options may affect a 100 step length episode.\n",
+ "\n",
+ "|Option Field|Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|repeat_kill_chain|Indicates whether the attack is repeated throughout the episode.|Str|_Required_|\n",
+ "|repeat_kill_chain_stages|Indicates if the kill_chain stage should reset upon failure or retry.|Str|_Required_|\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['io_settings']['save_sys_logs'] = True # Saving syslogs\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain'] = False\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain_stages'] = False\n",
+ "env = PrimaiteGymEnv(env_config = cfg)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain'] = True\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain_stages'] = True\n",
+ "env = PrimaiteGymEnv(env_config = cfg)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "while(env.game.step_counter != 100):\n",
+ " env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | Starting Node\n",
+ "\n",
+ "The code cells below demonstrate how to configure TAP003's different options for selecting starting hosts.\n",
+ "\n",
+ "|Option Field|Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|default_starting_node|The default starting host.|Str|_Required_|\n",
+ "|starting_nodes|A list of potential targets|List|_Optional_|\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg[\"agents\"][32][\"agent_settings\"][\"default_starting_node\"] = \"ST_PROJ-A-PRV-PC-1\"\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "tap003 = env.game.agents[\"attacker\"]\n",
+ "print(f\"TA003's Selected Starting Host: {tap003.starting_node}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The code cell below demonstrates how starting node lists overrule the default start node options:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg[\"agents\"][32][\"agent_settings\"][\"default_starting_node\"] = \"ST_PROJ-A-PRV-PC-1\"\n",
+ " cfg[\"agents\"][32][\"agent_settings\"][\"starting_nodes\"] = [\"ST_PROJ-A-PRV-PC-1\",\"ST_PROJ-B-PRV-PC-2\"]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "tap003 = env.game.agents[\"attacker\"]\n",
+ "print(f\"TA003's Selected Starting Host: {tap003.starting_node}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | kill_chain_settings | probability\n",
+ "\n",
+ "The code cells below configure each kill chain's probability of success. \n",
+ "The cells also demonstrate how TAP003 handles failure within an episode.\n",
+ "\n",
+ "|Option Field|Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|probability | The chance of successfully carrying out this stage in the kill chain.|float|_Required_|\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The code cell below directly sets each probability of success to 0.25. \n",
+ "Additionally the repeat kill chain and kill chain stage configuration options are set to false."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['io_settings']['save_sys_logs'] = True # Saving syslogs\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain'] = False\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain_stages'] = False\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['EXPLOIT']['probability'] = 0.25\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['ACCESS']['probability'] = 0.25\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PLANNING']['probability'] = 0.25\n",
+ "env = PrimaiteGymEnv(env_config = cfg)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "while(env.game.step_counter != 100):\n",
+ " env.step(0)\n",
+ "tap003 = env.game.agents['attacker']\n",
+ "pprint(\"---TAP003's Current State---\")\n",
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap003.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap003.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap003.next_kill_chain_stage.name}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The code cell below performs the same episode but with the repeat_kill_chain and repeat_kill_chain_stages to true."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain'] = True\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain_stages'] = True\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['MANIPULATION']['probability'] = 0.25\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['ACCESS']['probability'] = 0.25\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PLANNING']['probability'] = 0.25\n",
+ "env = PrimaiteGymEnv(env_config = cfg)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "while(env.game.step_counter != 100):\n",
+ " env.step(0)\n",
+ "tap003 = env.game.agents['attacker']\n",
+ "pprint(\"---TAP003's Current State---\")\n",
+ "print(f\"Current Environment Step: {env.game.step_counter}\")\n",
+ "print(f\"Current Kill Chain Stage: {tap003.current_kill_chain_stage.name}\")\n",
+ "print(f\"Next Execution Step: {tap003.next_execution_timestep}\")\n",
+ "print(f\"Next Kill Chain Stage {tap003.next_kill_chain_stage.name}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | kill_chain_settings | ACCESS - Starting Network Knowledge\n",
+ "\n",
+ "|Option Field |Meaning|Expected Type|Required/Optional|\n",
+ "|-------------|-------|-------------|-----------------|\n",
+ "|probability |Action Probability - The chance of successfully carrying out this stage in the kill_chain.|str|_Required_|\n",
+ "|starting_network_knowledge|TAP003's starting knowledge. Used to login into the target accounts in the ``MANIPULATION`` stage.|dict|_Required_|"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "``starting_network_knowledge``\n",
+ "\n",
+ "***\n",
+ "\n",
+ "The ``starting_network_knowledge`` options uses the following schema:\n",
+ "\n",
+ "|Option Field |Meaning|Expected Type|Required/Optional|\n",
+ "|-------------|-------|-------------|-----------------|\n",
+ "|credentials|The credential knowledge does TAP003 starts the episode with.|dict|_Required_|\n",
+ "\n",
+ "```yaml\n",
+ " kill_chain:\n",
+ " PLANNING:\n",
+ " probability: 1\n",
+ " starting_network_knowledge:\n",
+ " credentials:\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "``credentials``\n",
+ "\n",
+ "***\n",
+ "\n",
+ "The ``credentials`` options uses the following schema:\n",
+ "\n",
+ "|Option Field |Meaning|Expected Type|Required/Optional|\n",
+ "|-------------|-------|-------------|-----------------|\n",
+ "|ip_address |The IP Address of the target host.|str|_Required_|\n",
+ "|username |A username of a valid user account. Defaults to ``Admin``.|str|_Optional_|\n",
+ "|password |The corresponding valid password of the given username. Defaults to ``Admin``.|str|_Optional_|\n",
+ "\n",
+ "These credentials will are used in the ``MANIPULATION`` kill chain stage to login into the target accounts. Therefore the ``credentials`` options needs contain the same hosts that the the ``ACCOUNT_CHANGES`` option\n",
+ "\n",
+ "```yaml\n",
+ "\n",
+ " kill_chain:\n",
+ " PLANNING:\n",
+ " probability: 1\n",
+ " starting_network_knowledge:\n",
+ " credentials:\n",
+ " ST_PROJ-A-PRV-PC-1:\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ST_PROJ-B-PRV-PC-2:\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ST_PROJ-C-PRV-PC-3:\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ST_INTRA-PRV-RT-DR-1:\n",
+ " ip_address: 192.168.230.1\n",
+ " username: admin\n",
+ " password: admin\n",
+ " ST_INTRA-PRV-RT-CR:\n",
+ " ip_address: 192.168.160.1\n",
+ " username: admin\n",
+ " password: admin\n",
+ " REM-PUB-RT-DR:\n",
+ " ip_address: 192.168.10.2\n",
+ " username: admin\n",
+ " password: admin\n",
+ "\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset()\n",
+ "tap003 = env.game.agents['attacker']\n",
+ "# This while loop will run TAP003 until it hits TAP003 reaches ``ACCESS`` (Therefore passing PLANNING)\n",
+ "while(tap003.current_kill_chain_stage != InsiderKillChain.ACCESS):\n",
+ " env.step(0)\n",
+ "for account in tap003.network_knowledge['credentials']:\n",
+ " print(f\"----{account}---\")\n",
+ " for key in tap003.network_knowledge['credentials'][account]:\n",
+ " pprint(f\"{key}: {tap003.network_knowledge['credentials'][account][key]}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | kill_chain_settings | Manipulation - Account Changes\n",
+ "\n",
+ "|Option Field |Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|probability|Action Probability - The chance of successfully carrying out this stage in the kill_chain.|str|_Required_|\n",
+ "|account_changes|List of dictionaries containing the target hostnames, ip and account configuration changes.|list[dict]|_Required_|\n",
+ "\n",
+ "```yaml\n",
+ " kill_chain:\n",
+ " MANIPULATION:\n",
+ " probability: 1\n",
+ " account_changes:\n",
+ " - host: ST_INTRA-PRV-RT-DR-1\n",
+ " ip_address: 192.168.230.1 # ST_INTRA-PRV-RT-DR-1\n",
+ " action: change_password\n",
+ " username: admin\n",
+ " new_password: \"red_pass\"\n",
+ " - host: ST_INTRA-PRV-RT-CR\n",
+ " ip_address: 192.168.160.1 # ST_INTRA-PRV-RT-CR\n",
+ " action: change_password\n",
+ " username: \"admin\"\n",
+ " new_password: \"red_pass\"\n",
+ " - host: REM-PUB-RT-DR\n",
+ " ip_address: 192.168.10.2 # REM-PUB-RT-DR\n",
+ " action: change_password\n",
+ " username: \"admin\"\n",
+ " new_password: \"red_pass\"\n",
+ "\n",
+ "```\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "``account_changes``\n",
+ "\n",
+ "***\n",
+ "\n",
+ "The ``account_changes`` options uses the following schema:\n",
+ "\n",
+ "|Option Field |Meaning|Expected Type|Required/Optional|\n",
+ "|-------------|-------|-------------|-----------------|\n",
+ "|host|The hostname of the target host.|str|_Required_|\n",
+ "|ip_address|The IP Address of the target host.|str|_Required_|\n",
+ "|action|The user account manager action. Currently only ``change_password`` is available.|str|_Required_|\n",
+ "|username|The username of the account that TAP003 will target.|str|_Required_|\n",
+ "|new_password|The new password that TAP003 will set.|str|_Required_|\n",
+ "\n",
+ "_For further information around the simulation implementation of user sessions please consult the ``user_session_manager`` primAITE API documentation page within PrimAITE's user guide documentation._"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | kill_chain_settings | Manipulation - Sandbox \n",
+ "\n",
+ "The code cells below can be used as a sandbox to trial out different configuration options and their impact on the simulation. Additionally, if users wish to alter an account other than admin on this sandbox they can alter the ``new_users`` dictionary in the code cell below."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# New ST_PROJ-B-PRV-PC-2 user account\n",
+ "user_username = \"example_user_1\"\n",
+ "user_password = \"example_pass_1\"\n",
+ "user_admin = \"False\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "new_users = {\"username\": user_username, \"password\": user_password, \"is_admin\": user_admin }"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Changing the password\n",
+ "tap003_new_password = \"tap003_password\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "account_changes = [{\"host\":\"ST_PROJ-A-PRV-PC-2\", \"ip_address\": \"192.168.230.2\", \"username\": user_username, \"old_password\": user_password, \"new_password\": tap003_new_password}]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now we update the UC7 config and implement the new user accounts and run through an episode."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain'] = False\n",
+ " cfg['simulation']['network']['nodes'][31].update({'users':[]})\n",
+ " cfg['simulation']['network']['nodes'][31]['users'].append(new_users)\n",
+ " cfg['agents'][32]['agent_settings']['start_step'] = 1\n",
+ " cfg['agents'][32]['agent_settings']['frequency'] = 3\n",
+ " cfg['agents'][32]['agent_settings']['variance'] = 0\n",
+ " starting_creds = {\"username\": \"admin\",\"password\":\"admin\", \"ip_address\":\"192.168.230.2\"} # Adding \"ST_PROJ-A-PRV-PC-2\" to TAP003's starting_network_knowledge\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PLANNING']['starting_network_knowledge']['credentials'].update({\"ST_PROJ-A-PRV-PC-2\": starting_creds})\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['MANIPULATION']['account_changes'] = account_changes\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "env.reset()\n",
+ "while(env.game.step_counter != 90): # 20 Red Actions (frequency of 3)\n",
+ " env.step(0)\n",
+ "tap003 = env.game.agents['attacker']\n",
+ "target_host = env.game.simulation.network.get_node_by_hostname(\"ST_PROJ-A-PRV-PC-2\")\n",
+ "target_host.user_manager.show()\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | kill_chain_settings | Exploit - Malicious ACL\n",
+ "\n",
+ "|Option Field |Meaning|Expected Type|Required/Optional|\n",
+ "|------------|-------|-------------|-----------------|\n",
+ "|probability|Action Probability - The chance of successfully carrying out this stage in the kill_chain.|str|_Required_|\n",
+ "|malicious_acls|The configurable ACL that the TAP003 agent adds to the target node.|dict|_Required_|\n",
+ "\n",
+ "The malicious ACL is configured identically to the other ACLs. except from the target router/firewall. \n",
+ "This option is set to the TAP003's configured target host automatically.\n",
+ "\n",
+ "TAP003 intends to leverage these ACL's for malicious purposes. The default configuration is to deny all traffic from and towards the 0.0.0.255 subnet. \n",
+ "The configurability of the malicious ACL will allow for future releases of TAP type agents itself to perform more complex attacks. Currently, the TAP003 aims to block green agent traffic."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "``malicious_acl``\n",
+ "\n",
+ "***\n",
+ "\n",
+ "The ``malicious_acl`` options uses the following schema:\n",
+ "\n",
+ "|Option Field |Meaning|Expected Type|Required/Optional|\n",
+ "|-------------|-------|-------------|-----------------|\n",
+ "|target_router|The hostname of target router.|str|_Required_|\n",
+ "|ip_address|The ip_address of target router.|str|_Required_|\n",
+ "|position|The position that the malicious ACL is placed.|str|_Required_|\n",
+ "|permission|The implicit action. Should the ACL ``DENY`` or ``PERMIT``.|str|_Required_|\n",
+ "|src_ip|The source IP address to be targeted by the ``ACL``.|str|_Required_|\n",
+ "|src_wildcard_mask|The wildcard mask for the source ip address.|str|_Required_|\n",
+ "|dst_ip|The destination IP address to be targeted by the ``ACL``.|str|_Required_|\n",
+ "|dst_wildcard_mask|The wildcard mask for the destination ip address.|str|_Required_|\n",
+ "|src_port|The source port to be targeted by the ``ACL``.|str|_Required_|\n",
+ "|dst_port|The destination port to be targeted by the ``ACL``.|str|_Required_|\n",
+ "|protocol_name|The transport layer protocol_name to be targeted.|str|_Required_|\n",
+ "\n",
+ "_For further information please consult the simulation ACL documentation within PrimAITE's Sphinx documentation._"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The code cell below demonstrates the default ACL's added by TAP003:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['agents'][32]['agent_settings']['start_step'] = 1\n",
+ " cfg['agents'][32]['agent_settings']['frequency'] = 3 # Install action takes multiple timesteps.\n",
+ " cfg['agents'][32]['agent_settings']['variance'] = 0\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['EXPLOIT']['probability'] = 1\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['MANIPULATION']['probability'] = 1\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['ACCESS']['probability'] = 1\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['PLANNING']['probability'] = 1\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "while(env.game.step_counter != 70):\n",
+ " env.step(0)\n",
+ "tap003 = env.game.agents['attacker']\n",
+ "for key,value in tap003.config.agent_settings:\n",
+ " if key != 'kill_chain':\n",
+ " pass\n",
+ " else:\n",
+ " for kill_chain_setting_key in value:\n",
+ " if kill_chain_setting_key == 'EXPLOIT':\n",
+ " pprint(value[kill_chain_setting_key]['malicious_acls'][0])\n",
+ " pprint(value[kill_chain_setting_key]['malicious_acls'][1])\n",
+ " pprint(value[kill_chain_setting_key]['malicious_acls'][2])\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_intra_prv_rt_dr_1 = env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-DR-1\")\n",
+ "st_intra_prv_rt_dr_1.acl.show()\n",
+ "\n",
+ "rem_pub_rt_dr = env.game.simulation.network.get_node_by_hostname(\"REM-PUB-RT-DR\")\n",
+ "rem_pub_rt_dr.acl.show()\n",
+ "\n",
+ "st_intra_prv_rt_cr = env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-CR\")\n",
+ "st_intra_prv_rt_cr.acl.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Unlike the blue agent, TAP003 does not need to use it's action space options for indexing different options, meaning that ACL's are a lot easier to configure.\n",
+ "\n",
+ "The sandbox below can be used to try out different configuration options and their impact on the simulation."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### **Attack Configurations** | kill_chain_settings | Exploit - Sandbox "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "metadata": {}
+ },
+ "outputs": [],
+ "source": [
+ "# please ensure that the source/dest ip_addresses are within the blue agent's observation space ip_list option.\n",
+ "with open(_EXAMPLE_CFG/\"uc7_config_tap003.yaml\", mode=\"r\") as f:\n",
+ " cfg = yaml.safe_load(f)\n",
+ " cfg['agents'][32]['agent_settings']['repeat_kill_chain'] = False\n",
+ " cfg['agents'][32]['agent_settings']['start_step'] = 1\n",
+ " cfg['agents'][32]['agent_settings']['frequency'] = 3\n",
+ " cfg['agents'][32]['agent_settings']['variance'] = 0\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['EXPLOIT']['malicious_acls'][0]['position'] = 1\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['EXPLOIT']['malicious_acls'][0]['permission'] = \"DENY\"\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['EXPLOIT']['malicious_acls'][0]['src_ip'] = \"ALL\"\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['EXPLOIT']['malicious_acls'][0]['src_wildcard'] = '0.0.255.255'\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['EXPLOIT']['malicious_acls'][0]['dst_ip'] = 'ALL'\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['EXPLOIT']['malicious_acls'][0]['dst_wildcard'] = \"0.0.255.255\"\n",
+ " # Please refer to the ``PORT`` class in the primAITE API for more information around the different supported ports\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['EXPLOIT']['malicious_acls'][0]['src_port'] = 'POSTGRES_SERVER'\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['EXPLOIT']['malicious_acls'][0]['dst_port'] = \"POSTGRES_SERVER\"\n",
+ " cfg['agents'][32]['agent_settings']['kill_chain']['EXPLOIT']['malicious_acls'][0]['protocol_name'] = 'ALL'\n",
+ "env = PrimaiteGymEnv(env_config = cfg)\n",
+ "while(env.game.step_counter != 50):\n",
+ " env.step(0)\n",
+ "tap003 = env.game.agents['attacker']\n",
+ "target_host = env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-DR-1\")\n",
+ "target_host.acl.show()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": ".venv",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/src/primaite/notebooks/UC7-Training.ipynb b/src/primaite/notebooks/UC7-Training.ipynb
new file mode 100644
index 00000000..ddaa6844
--- /dev/null
+++ b/src/primaite/notebooks/UC7-Training.ipynb
@@ -0,0 +1,147 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "vscode": {
+ "languageId": "plaintext"
+ }
+ },
+ "source": [
+ "# Training an SB3 Agent\n",
+ "\n",
+ "© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK\n",
+ "\n",
+ "This notebook will demonstrate how to use primaite to create and train a PPO agent, using a pre-defined configuration file."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### First, we import the inital packages and read in our configuration file."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "!primaite setup"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import yaml\n",
+ "from primaite.session.environment import PrimaiteGymEnv\n",
+ "from primaite import PRIMAITE_PATHS\n",
+ "from prettytable import PrettyTable\n",
+ "from deepdiff.diff import DeepDiff\n",
+ "from primaite.simulator.network.hardware.nodes.host.server import Server\n",
+ "from primaite.simulator.network.hardware.nodes.network.router import Router\n",
+ "from primaite.simulator.network.hardware.nodes.host.computer import Computer\n",
+ "\n",
+ "scenario_path = PRIMAITE_PATHS.user_config_path / \"example_config/uc7_config.yaml\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "gym = PrimaiteGymEnv(env_config=scenario_path)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from stable_baselines3 import PPO\n",
+ "\n",
+ "# EPISODE_LEN = 128\n",
+ "EPISODE_LEN = 128\n",
+ "NUM_EPISODES = 10\n",
+ "NO_STEPS = EPISODE_LEN * NUM_EPISODES\n",
+ "BATCH_SIZE = 32\n",
+ "LEARNING_RATE = 3e-4"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model = PPO('MlpPolicy', gym, learning_rate=LEARNING_RATE, n_steps=NO_STEPS, batch_size=BATCH_SIZE, verbose=0, tensorboard_log=\"./PPO_UC7/\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model.learn(total_timesteps=NO_STEPS)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "model.save(\"PrimAITE-PPO-UC7-example-agent\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "eval_model = PPO(\"MlpPolicy\", gym)\n",
+ "eval_model = PPO.load(\"PrimAITE-PPO-UC7-example-agent\", gym)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from stable_baselines3.common.evaluation import evaluate_policy\n",
+ "\n",
+ "evaluate_policy(eval_model, gym, n_eval_episodes=1)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": ".venv",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/src/primaite/notebooks/UC7-attack-variants.ipynb b/src/primaite/notebooks/UC7-attack-variants.ipynb
new file mode 100644
index 00000000..14742796
--- /dev/null
+++ b/src/primaite/notebooks/UC7-attack-variants.ipynb
@@ -0,0 +1,586 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# UC7 with Attack Variability\n",
+ "\n",
+ "© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "vscode": {
+ "languageId": "plaintext"
+ }
+ },
+ "source": [
+ "This notebook demonstrates the PrimAITE environment with the UC7 network laydown and multiple attack personas. The first attack persona is TAP001 which performs a ransomware attack against the database. The other one is TAP003 which is able to maliciously add ACL rules that block green pattern of life.\n",
+ "\n",
+ "The environment switches between these two attacks on a pre-defined schedule which is defined in the schedule.yaml file of the scenario folder."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Setup and Imports"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "!primaite setup"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import yaml\n",
+ "from primaite.session.environment import PrimaiteGymEnv\n",
+ "from primaite import PRIMAITE_PATHS\n",
+ "from prettytable import PrettyTable\n",
+ "from deepdiff.diff import DeepDiff\n",
+ "from primaite.session.environment import PrimaiteGymEnv\n",
+ "from primaite.simulator.network.hardware.nodes.host.computer import Computer\n",
+ "from primaite.simulator.network.hardware.nodes.host.server import Server\n",
+ "from primaite.simulator.network.hardware.nodes.network.router import Router\n",
+ "from primaite.simulator.system.services.dns.dns_server import DNSServer\n",
+ "from primaite.simulator.system.software import SoftwareHealthState\n",
+ "from primaite.simulator.file_system.file_system_item_abc import FileSystemItemHealthStatus\n",
+ "from primaite.simulator.network.hardware.nodes.network.switch import Switch\n",
+ "from primaite.simulator.system.applications.web_browser import WebBrowser\n",
+ "from primaite.simulator.network.container import Network\n",
+ "from primaite.simulator.system.services.service import ServiceOperatingState\n",
+ "from primaite.simulator.network.hardware.node_operating_state import NodeOperatingState\n",
+ "from primaite.simulator.system.services.database.database_service import DatabaseService\n",
+ "from primaite.simulator.system.applications.database_client import DatabaseClient\n",
+ "from primaite.simulator.network.hardware.nodes.network.firewall import Firewall\n",
+ "from primaite.game.game import PrimaiteGame\n",
+ "from primaite.simulator.sim_container import Simulation\n",
+ "from primaite.config.load import load, _EXAMPLE_CFG\n",
+ "from primaite.simulator.network.hardware.nodes.host.server import Server\n",
+ "from primaite.simulator.network.hardware.nodes.network.router import Router\n",
+ "from primaite.simulator.network.hardware.nodes.host.computer import Computer\n",
+ "\n",
+ "scenario_path = PRIMAITE_PATHS.user_config_path / \"example_config/uc7_multiple_attack_variants\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env = PrimaiteGymEnv(env_config=scenario_path)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Schedule\n",
+ "\n",
+ "Let's print the schedule so that we can see which attack we can expect on each episode.\n",
+ "\n",
+ "On episodes 0-4, the TAP001 agent will be used, and on episodes 5-9, the TAP003 agent will be used. Then, the environment will alternate between the two. Furthermore, the TAP001 agent will alternate between starting at `ST_PROJ-A-PRV-PC-1`, `ST_PROJ-B-PRV-PC-2`, `ST_PROJ-C-PRV-PC-3`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(scenario_path / \"schedule.yaml\",'r') as f:\n",
+ " print(f.read())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## TAP001 attack\n",
+ "\n",
+ "Let's first demonstrate the TAP001 attack. We will let the environment run for 30 steps and print out the red agent's actions.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#utils\n",
+ "def run_green_and_red_pol(num_steps):\n",
+ " for i in range(num_steps): # perform steps\n",
+ " env.step(0)\n",
+ "\n",
+ "def print_agent_actions_except_do_nothing(agent_name):\n",
+ " \"\"\"Get the agent's action history, filter out `do-nothing` actions, print relevant data in a table.\"\"\"\n",
+ " table = PrettyTable()\n",
+ " table.field_names = [\"Step\", \"Action\", \"Node\", \"Application\", \"Target IP\", \"Response\"]\n",
+ " print(f\"Episode: {env.episode_counter}, Actions for '{agent_name}':\")\n",
+ " for item in env.game.agents[agent_name].history:\n",
+ " if item.action == \"do-nothing\":\n",
+ " continue\n",
+ "\n",
+ " node, application, target_ip = \"N/A\", \"N/A\", \"N/A\",\n",
+ "\n",
+ " if item.action.startswith(\"node-nmap\"):\n",
+ " node = item.parameters['source_node']\n",
+ " application = \"nmap\"\n",
+ " target_ip = str(item.parameters['target_ip_address'])\n",
+ " target_ip = (target_ip[:25]+'...') if len(target_ip)>25 else target_ip # truncate long string\n",
+ "\n",
+ " elif item.action == \"router-acl-add-rule\":\n",
+ " node = item.parameters.get(\"router_name\")\n",
+ " elif item.action == \"node-send-remote-command\":\n",
+ " node = item.parameters.get(\"node_name\")\n",
+ " target_ip = item.parameters.get(\"remote_ip\")\n",
+ " application = item.parameters.get(\"command\")\n",
+ " elif item.action == \"node-session-remote-login\":\n",
+ " node = item.parameters.get(\"node_name\")\n",
+ " target_ip = item.parameters.get(\"remote_ip\")\n",
+ " application = \"user-manager\"\n",
+ " elif item.action.startswith(\"c2-server\"):\n",
+ " application = \"c2-server\"\n",
+ " node = item.parameters.get('node_name')\n",
+ " elif item.action == \"configure-c2-beacon\":\n",
+ " application = \"c2-beacon\"\n",
+ " node = item.parameters.get('node_name')\n",
+ "\n",
+ " else:\n",
+ " if (node_id := item.parameters.get('node_id')) is not None:\n",
+ " node = env.game.agents[agent_name].action_manager.node_names[node_id]\n",
+ " if (application_id := item.parameters.get('application_id')) is not None:\n",
+ " application = env.game.agents[agent_name].action_manager.application_names[node_id][application_id]\n",
+ " if (application_name := item.parameters.get('application_name')) is not None:\n",
+ " application = application_name\n",
+ "\n",
+ " table.add_row([item.timestep, item.action, node, application, target_ip, item.response.status])\n",
+ "\n",
+ " print(table)\n",
+ " print(\"(Any do-nothing actions are omitted)\")\n",
+ "\n",
+ "def finish_episode_and_print_reward():\n",
+ " while env.game.step_counter < 128:\n",
+ " env.step(0)\n",
+ " print(f\"Total reward this episode: {env.agent.reward_function.total_reward:2f}\")\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "run_green_and_red_pol(110)\n",
+ "print_agent_actions_except_do_nothing(\"attacker\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_data_prv_srv_db: Server = env.game.simulation.network.get_node_by_hostname(\"ST_DATA-PRV-SRV-DB\")\n",
+ "st_data_prv_srv_db.file_system.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "finish_episode_and_print_reward()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## TAP001 Prevention"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The blue agent should be able to prevent the ransomware attack by blocking the red agent's access to the database. Let's run the environment until the observation space shows symptoms of the attack starting.\n",
+ "\n",
+ "Because we are in episode index 1, the red agent will use `ST-PROJ-A-PRV-PC-1` to start the attack. On step 25, the red agent installs `RansomwareScript`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset()\n",
+ "obs, reward, term, trunc, info = env.step(0)\n",
+ "for i in range(25): # we know that the ransomware install happens at step 25\n",
+ " old = obs\n",
+ " obs, reward, term, trunc, info = env.step(0)\n",
+ " new = obs\n",
+ "\n",
+ "diff = DeepDiff(old,new)\n",
+ "print(f\"Step {env.game.step_counter}\") # it's step 26 now because the step counter is incremented after the step\n",
+ "for d,v in diff.get('values_changed', {}).items():\n",
+ " print(f\"{d}: {v['old_value']} -> {v['new_value']}\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can see that on HOST0, application index 1 has gone from `operating_status` 0 to 3, meaning there wasn't an application before, but now there is an application in the `INSTALLING` state. The blue agent should be able to detect this and block the red agent's access to the database. Action 43 will block `ST-PROJ-A-PRV-PC-1` from sending POSTGRES traffic to the DB server.\n",
+ "\n",
+ "If this were a different episode, it could have been `ST-PROJ-B-PRV-PC-2` or `ST-PROJ-C-PRV-PC-3` that are affected, and a different defensive action would be required."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.step(43)\n",
+ "env.step(45)\n",
+ "env.step(47)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_intra_prv_rt_cr: Router = env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-CR\")\n",
+ "st_intra_prv_rt_cr.acl.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "finish_episode_and_print_reward()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_intra_prv_rt_cr.acl.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now TAP001 is unable to locate the database!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print_agent_actions_except_do_nothing(\"attacker\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## TAP003 attack\n",
+ "\n",
+ "Let's skip until episode 5 and demonstrate the TAP003 attack. We will let the environment run and print out the red agent's actions.\n",
+ "\n",
+ "By default, TAP003 will add the following rules:\n",
+ "\n",
+ "|Target Router | Impact |\n",
+ "|----------------------|--------|\n",
+ "|`ST_INTRA-PRV-RT-DR-1`| Blocks all `POSTGRES_SERVER` that arrives at the `ST_INTRA-PRV-RT-DR-1` router. This rule will prevent all ST_PROJ_* hosts from accessing the database (`ST_DATA-PRV-SRV-DB`).|\n",
+ "|`ST_INTRA-PRV-RT-CR`| Blocks all `HTTP` traffic that arrives at the`ST_INTRA-PRV-RT-CR` router. This rule will prevent all SOME_TECH hosts from accessing the webserver (`ST-DMZ-PUB-SRV-WEB`)|\n",
+ "|`REM-PUB-RT-DR`| Blocks all `DNS` traffic that arrives at the `REM-PUB-RT-DR` router. This rule prevents any remote site works from accessing the DNS Server (`ISP-PUB-SRV-DNS`).|"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "while env.episode_counter < 5:\n",
+ " env.reset()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "run_green_and_red_pol(128)\n",
+ "print_agent_actions_except_do_nothing(\"attacker\")\n",
+ "obs, reward, term, trunc, info = env.step(0); # one more step so we can capture the value of `obs`"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The agent selected to add ACL rules that will prevent green pattern of life by blocking a variety of different traffic. This has a negative impact on reward. Let's view the ACL list on the affected router."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-DR-1\").acl.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-CR\").acl.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.game.simulation.network.get_node_by_hostname(\"REM-PUB-RT-DR\").acl.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can see that at indices 1-5, there are ACL rules that block all traffic. The blue agent can see this rule in the `ROUTERS` part of the observation space.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "obs['NODES']['ROUTER0']['ACL'][1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "obs['NODES']['ROUTER1']['ACL'][1]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "obs['NODES']['ROUTER2']['ACL'][1]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Preventing TAP003 attack\n",
+ "\n",
+ "The blue agent can prevent the red agent from adding ACL rules. TAP003 relies on connecting to the router via SSH, and sending remote ACL_ADDRULE requests. The blue agent can prevent this by pre-emptively changing the admin password on the affected routers or by blocking SSH traffic between the red agent's starting node and the target routers."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset()\n",
+ "obs, reward, term, trunc, info = env.step(0)\n",
+ "old = obs\n",
+ "for i in range(128): \n",
+ " obs, reward, term, trunc, info = env.step(0)\n",
+ " new = obs\n",
+ "\n",
+ "diff = DeepDiff(old,new)\n",
+ "print(f\"Step {env.game.step_counter}\") # it's the next step now because the step counter is incremented after the step\n",
+ "for d,v in diff.get('values_changed', {}).items():\n",
+ " print(f\"{d}: {v['old_value']} -> {v['new_value']}\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "By printing the reward of each individual agent, we will see what green agents are affected the most. Of course, these green rewards count towards the blue reward so ultimately the blue agent should learn to remove the ACL rule."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "finish_episode_and_print_reward()\n",
+ "\n",
+ "for ag in env.game.agents.values():\n",
+ " print(ag.config.ref, ag.reward_function.total_reward)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The most effective option that the blue agent has against TAP003 is to prevent the red agent from ever adding the ACLs in the first place through blocking the SSH connection."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset()\n",
+ "env.step(51) # SSH Blocking ACL on ST-INRA-PRV-RT-R1\n",
+ "finish_episode_and_print_reward()\n",
+ "\n",
+ "for ag in env.game.agents.values():\n",
+ " print(ag.config.ref, ag.reward_function.total_reward)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Additionally, another option the blue agent can take is to change the passwords of the different target routers that TAP003 will attack through the `NODE_ACCOUNTS_CHANGE_PASSWORD` action."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset()\n",
+ "env.step(50) # NODE_ACCOUNTS_CHANGE_PASSWORD | ST_INTRA-prv-rt-cr\n",
+ "env.step(52) # NODE_ACCOUNTS_CHANGE_PASSWORD | ST_INTRA-prv-rt-dr-1\n",
+ "env.step(54) # NODE_ACCOUNTS_CHANGE_PASSWORD | rem-pub-rt-dr\n",
+ "finish_episode_and_print_reward()\n",
+ "\n",
+ "for ag in env.game.agents.values():\n",
+ " print(ag.config.ref, ag.reward_function.total_reward)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Lastly, the blue agent can remedy the impacts of TAP003 through removing the malicious ACLs that TAP003 adds."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.reset()\n",
+ "\n",
+ "# Allow TAP003 to add it's malicious rules\n",
+ "for _ in range(45):\n",
+ " env.step(0)\n",
+ "\n",
+ "env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-CR\").acl.show()\n",
+ "env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-DR-1\").acl.show()\n",
+ "env.game.simulation.network.get_node_by_hostname(\"REM-PUB-RT-DR\").acl.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.step(44) # ROUTER_ACL_REMOVERULE | ST_INTRA-prv-rt-cr\n",
+ "env.step(53) # ROUTER_ACL_REMOVERULE | ST_INTRA-prv-rt-dr-1\n",
+ "env.step(55) # ROUTER_ACL_REMOVERULE | rem-pub-rt-dr"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-CR\").acl.show()\n",
+ "env.game.simulation.network.get_node_by_hostname(\"ST_INTRA-PRV-RT-DR-1\").acl.show()\n",
+ "env.game.simulation.network.get_node_by_hostname(\"REM-PUB-RT-DR\").acl.show()\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "finish_episode_and_print_reward()\n",
+ "\n",
+ "for ag in env.game.agents.values():\n",
+ " print(ag.config.ref, ag.reward_function.total_reward)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": ".venv",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/src/primaite/notebooks/UC7-network_connectivity.ipynb b/src/primaite/notebooks/UC7-network_connectivity.ipynb
new file mode 100644
index 00000000..8aef5465
--- /dev/null
+++ b/src/primaite/notebooks/UC7-network_connectivity.ipynb
@@ -0,0 +1,1126 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# UC7 Demonstration\n",
+ "\n",
+ "© Crown-owned copyright 2025, Defence Science and Technology Laboratory UK\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Network Description\n",
+ "\n",
+ "\n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "
\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "!primaite setup"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from primaite.session.environment import PrimaiteGymEnv\n",
+ "from primaite.simulator.network.hardware.nodes.host.computer import Computer\n",
+ "from primaite.simulator.network.hardware.nodes.host.server import Server\n",
+ "from primaite.simulator.network.hardware.nodes.network.router import Router\n",
+ "from primaite.simulator.network.hardware.nodes.network.switch import Switch\n",
+ "from primaite.simulator.network.container import Network\n",
+ "from primaite.simulator.network.hardware.nodes.network.firewall import Firewall\n",
+ "from primaite.game.game import PrimaiteGame\n",
+ "from primaite.simulator.sim_container import Simulation\n",
+ "import yaml\n",
+ "from pprint import pprint\n",
+ "from primaite.config.load import load, _EXAMPLE_CFG"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open(file=_EXAMPLE_CFG/\"uc7_config.yaml\", mode=\"r\") as uc7_config:\n",
+ " cfg = yaml.safe_load(uc7_config)\n",
+ " cfg['io_settings']['save_sys_logs'] = True # Saving syslogs\n",
+ " cfg['io_settings']['save_agent_logs'] = True # Save agent logs\n",
+ "env = PrimaiteGymEnv(env_config=cfg)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "uc7_network = env.game.simulation.network\n",
+ "uc7_network.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## UC7 Network | Home Office Subnet"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "home_pub_pc_1: Computer = env.game.simulation.network.get_node_by_hostname(\"HOME-PUB-PC-1\")\n",
+ "home_pub_pc_2: Computer = env.game.simulation.network.get_node_by_hostname(\"HOME-PUB-PC-2\")\n",
+ "home_pub_pc_srv: Server = env.game.simulation.network.get_node_by_hostname(\"HOME-PUB-SRV\")\n",
+ "home_pub_rt_dr: Router = env.game.simulation.network.get_node_by_hostname(\"HOME-PUB-RT-DR\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# HOME PC 1 --> HOME PC 2\n",
+ "home_pub_pc_1.ping(home_pub_pc_2.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# HOME PC 2 --> HOME SERVER\n",
+ "home_pub_pc_2.ping(home_pub_pc_srv.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# HOME SERVER --> HOME ROUTER\n",
+ "home_pub_pc_srv.ping(home_pub_rt_dr.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## UC7 Network | Internet"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "isp_pub_rt_br: Router = env.game.simulation.network.get_node_by_hostname(\"ISP-PUB-RT-BR\")\n",
+ "isp_pub_srv_dns: Server = env.game.simulation.network.get_node_by_hostname(\"ISP-PUB-SRV-DNS\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "home_pub_pc_1.ping(isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# HOME ROUTER --> INTERNET ROUTER\n",
+ "home_pub_rt_dr.ping(isp_pub_rt_br.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "home_pub_rt_dr.route_table.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# HOME ROUTER --> INTERNET ISP\n",
+ "home_pub_rt_dr.ping(isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# INTERNET ROUTER --> INTERNET DNS\n",
+ "isp_pub_rt_br.ping(target_ip_address=isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# HOME ROUTER --> INTERNET DNS\n",
+ "home_pub_rt_dr.ping(target_ip_address=isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# PC 1 --> INTERNET DNS\n",
+ "\n",
+ "home_pub_pc_1.ping(target_ip_address=isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "isp_pub_rt_br.show_nic()\n",
+ "isp_pub_rt_br.ping(\"192.168.1.2\")\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## UC7 Network | Remote Site Subnet"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "network: Network = env.game.simulation.network\n",
+ "\n",
+ "\n",
+ "rem_pub_fw: Firewall = network.get_node_by_hostname(hostname=\"REM-PUB-FW\")\n",
+ "rem_pub_rt_dr: Router = network.get_node_by_hostname(hostname=\"REM-PUB-RT-DR\")\n",
+ "rem_pub_sw_as: Switch = network.get_node_by_hostname(hostname=\"REM-PUB-SW-AS\")\n",
+ "rem_pub_pc_1: Computer = network.get_node_by_hostname(hostname=\"REM-PUB-PC-1\")\n",
+ "rem_pub_pc_2: Computer = network.get_node_by_hostname(hostname=\"REM-PUB-PC-2\")\n",
+ "rem_pub_srv: Computer = network.get_node_by_hostname(hostname=\"REM-PUB-SRV\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Remote PC 1 --> Remote PC_2\n",
+ "\n",
+ "rem_pub_pc_1.ping(rem_pub_pc_2.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Remote PC 2 --> Remote Server\n",
+ "\n",
+ "rem_pub_pc_2.ping(rem_pub_srv.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Remote Server --> Remote Site Router\n",
+ "\n",
+ "rem_pub_srv.ping(rem_pub_rt_dr.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Remote Site Router --> Remote Pub Firewall (Internal)\n",
+ "\n",
+ "rem_pub_rt_dr.ping(rem_pub_fw.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Remote Site Router --> Remote Pub Firewall (External)\n",
+ "\n",
+ "rem_pub_rt_dr.ping(rem_pub_fw.network_interface[2].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Remote Pub Firewall (external) --> Public Internet\n",
+ "\n",
+ "rem_pub_fw.ping(isp_pub_rt_br.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Remote Site PC 1 --> Public DNS\n",
+ "\n",
+ "rem_pub_pc_1.ping(target_ip_address=isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Remote Site PC 1 --> Home Office PC 1\n",
+ "\n",
+ "rem_pub_pc_1.ping(target_ip_address=home_pub_pc_1.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## UC7 Network | SOME_TECH_DMZ"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_pub_fw: Firewall = network.get_node_by_hostname(hostname=\"ST_PUB-FW\")\n",
+ "st_dmz_pub_srv_web: Server = network.get_node_by_hostname(hostname=\"ST_DMZ-PUB-SRV-WEB\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some Tech Firewall --> Some Tech DMZ public web server\n",
+ "\n",
+ "st_pub_fw.ping(st_dmz_pub_srv_web.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some Tech Firewall --> Public DNS Server\n",
+ "\n",
+ "st_pub_fw.ping(isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some Tech DMZ public web serv"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some Tech Firewall --> Internet Router (Port 4)\n",
+ "\n",
+ "st_pub_fw.ping(isp_pub_rt_br.network_interface[4].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## UC7 Network | SOME_TECH_INTRANET"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_intra_prv_rt_cr: Router = network.get_node_by_hostname(hostname=\"ST_INTRA-PRV-RT-CR\")\n",
+ "st_intra_prv_rt_dr_1: Router = network.get_node_by_hostname(hostname=\"ST_INTRA-PRV-RT-DR-1\")\n",
+ "st_intra_prv_rt_dr_2: Router = network.get_node_by_hostname(hostname=\"ST_INTRA-PRV-RT-DR-2\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some Tech Intranet Private Router CR --> Some Tech Public Firewall\n",
+ "\n",
+ "st_intra_prv_rt_cr.ping(st_pub_fw.network_interface[3].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some tech intranet router DR 1 --> Some Tech Intranet Router CR\n",
+ "\n",
+ "st_intra_prv_rt_dr_1.ping(st_intra_prv_rt_cr.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some tech intranet router DR 2 --> Some Tech Intranet Router CR\n",
+ "\n",
+ "st_intra_prv_rt_dr_2.ping(st_intra_prv_rt_cr.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some tech intranet router DR 1 --> Some tech intranet router DR 2\n",
+ "\n",
+ "st_intra_prv_rt_dr_1.ping(st_intra_prv_rt_dr_2.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some tech intranet router DR 1 --> Some Tech Firewall (Internal Port)\n",
+ "\n",
+ "st_intra_prv_rt_dr_1.ping(st_pub_fw.network_interface[3].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some tech intranet router DR 1 --> Some Tech Firewall (DMZ Port)\n",
+ "\n",
+ "st_intra_prv_rt_dr_1.ping(st_pub_fw.network_interface[2].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some tech intranet router DR 1 --> Some Tech Firewall (External Port)\n",
+ "\n",
+ "st_intra_prv_rt_dr_1.ping(st_pub_fw.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some Tech Intranet Router DR 1 --> Some Tech DMZ web-server\n",
+ "\n",
+ "st_intra_prv_rt_dr_1.ping(target_ip_address=st_dmz_pub_srv_web.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some tech intranet router DR 1 --> Public Internet\n",
+ "\n",
+ "st_intra_prv_rt_dr_1.ping(isp_pub_rt_br.network_interface[3].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some tech intranet router DR 1 --> Public DNS \n",
+ "\n",
+ "st_intra_prv_rt_dr_1.ping(isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some Tech Intranet Router DR 1 --> Home Office PC 1\n",
+ "\n",
+ "st_intra_prv_rt_dr_1.ping(target_ip_address=home_pub_pc_1.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Some Tech Intranet Router DR 1 --> Remote Site PC 1\n",
+ "\n",
+ "st_intra_prv_rt_dr_1.ping(target_ip_address=rem_pub_pc_1.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## UC7 Network | Some Tech Head Office"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_head_office_private_pc_1: Computer = network.get_node_by_hostname(\"ST_HO-PRV-PC-1\")\n",
+ "st_head_office_private_pc_2: Computer = network.get_node_by_hostname(\"ST_HO-PRV-PC-2\")\n",
+ "st_head_office_private_pc_3: Computer = network.get_node_by_hostname(\"ST_HO-PRV-PC-3\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Home office PC 1 --> ST Home Office PC 2\n",
+ "\n",
+ "st_head_office_private_pc_1.ping(st_head_office_private_pc_1.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Home office PC 3 --> ST Router DR 2 \n",
+ "\n",
+ "st_head_office_private_pc_1.ping(st_intra_prv_rt_dr_2.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Home office PC 1 --> Public DNS\n",
+ "\n",
+ "st_head_office_private_pc_1.ping(isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## UC7 Network | Some Tech Human Resources"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_human_resources_private_pc_1: Computer = network.get_node_by_hostname(\"ST_HR-PRV-PC-1\")\n",
+ "st_human_resources_private_pc_2: Computer = network.get_node_by_hostname(\"ST_HR-PRV-PC-2\")\n",
+ "st_human_resources_private_pc_3: Computer = network.get_node_by_hostname(\"ST_HR-PRV-PC-3\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Human Resources PC 1 --> ST Human Resources PC 2 \n",
+ "\n",
+ "st_human_resources_private_pc_1.ping(st_human_resources_private_pc_2.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Human Resources PC 2 --> # ST Human Resources PC 3\n",
+ "\n",
+ "st_human_resources_private_pc_2.ping(st_human_resources_private_pc_3.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Human Resources PC 1 --> ST Intranet Router DR 2 \n",
+ "\n",
+ "st_human_resources_private_pc_1.ping(st_intra_prv_rt_dr_2.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Human Resources PC 1 --> Public DNS \n",
+ "\n",
+ "st_human_resources_private_pc_1.ping(isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## UC7 Network | Some Tech Data (Database / Database Backup)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_data_private_server_database: Server = network.get_node_by_hostname(\"ST_DATA-PRV-SRV-DB\")\n",
+ "st_data_private_server_storage: Server = network.get_node_by_hostname(\"ST_DATA-PRV-SRV-STORAGE\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Data Private Database --> ST Data Private Storage\n",
+ "\n",
+ "st_data_private_server_database.ping(st_data_private_server_storage.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Data Private Storage --> Public DNS\n",
+ "\n",
+ "st_data_private_server_storage.ping(isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## UC7 Network | Some Tech Project A "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_a_private_pc_1: Computer = network.get_node_by_hostname(\"ST_PROJ-A-PRV-PC-1\")\n",
+ "st_project_a_private_pc_2: Computer = network.get_node_by_hostname(\"ST_PROJ-A-PRV-PC-2\")\n",
+ "st_project_a_private_pc_3: Computer = network.get_node_by_hostname(\"ST_PROJ-A-PRV-PC-3\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Private Project A PC 1 --> ST Private Project A PC 2\n",
+ "\n",
+ "st_project_a_private_pc_1.ping(st_project_a_private_pc_2.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Private Project A PC 2 --> ST Private Project A PC 3\n",
+ "\n",
+ "st_project_a_private_pc_3.ping(st_project_a_private_pc_3.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Private Project A PC 3 --> Public DNS\n",
+ "\n",
+ "st_project_a_private_pc_3.ping(isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Private Project A PC 1 --> ST_INTRA-PRV-RT-CR\n",
+ "\n",
+ "st_project_a_private_pc_1.ping(st_intra_prv_rt_cr.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Private Project A PC 1 --> ST_INTRA-PRV-RT-DR-2\n",
+ "\n",
+ "st_project_a_private_pc_1.ping(\"192.168.170.2\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## UC7 Network | Some Tech Project B"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_b_private_pc_1: Computer = network.get_node_by_hostname(\"ST_PROJ-B-PRV-PC-1\")\n",
+ "st_project_b_private_pc_2: Computer = network.get_node_by_hostname(\"ST_PROJ-B-PRV-PC-2\")\n",
+ "st_project_b_private_pc_3: Computer = network.get_node_by_hostname(\"ST_PROJ-B-PRV-PC-3\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Private Project B PC 1 --> ST Private Project B PC 2\n",
+ "\n",
+ "st_project_b_private_pc_1.ping(st_project_b_private_pc_2.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Private Project B PC 2 --> ST Private Project B PC 3\n",
+ "\n",
+ "st_project_b_private_pc_2.ping(st_project_b_private_pc_3.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Private Project B PC 3 --> Public DNS\n",
+ "\n",
+ "st_project_b_private_pc_3.ping(isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## UC7 Network | Some Tech Project C"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_c_private_pc_1: Computer = network.get_node_by_hostname(\"ST_PROJ-C-PRV-PC-1\")\n",
+ "st_project_c_private_pc_2: Computer = network.get_node_by_hostname(\"ST_PROJ-C-PRV-PC-2\")\n",
+ "st_project_c_private_pc_3: Computer = network.get_node_by_hostname(\"ST_PROJ-C-PRV-PC-3\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Private Project C PC 1 --> ST Private Project C PC 2\n",
+ "\n",
+ "st_project_c_private_pc_1.ping(st_project_c_private_pc_2.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Private Project C PC 2 --> ST Private Project C PC 3\n",
+ "\n",
+ "st_project_c_private_pc_2.ping(st_project_c_private_pc_3.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# ST Private Project c PC 3 --> Public DNS\n",
+ "\n",
+ "st_project_c_private_pc_3.ping(isp_pub_srv_dns.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_c_private_pc_1.ping(st_project_b_private_pc_1.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_b_private_pc_1.ping(st_project_a_private_pc_1.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_a_private_pc_1.ping(st_head_office_private_pc_1.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_a_private_pc_1.ping(st_human_resources_private_pc_1.network_interface[1].ip_address)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## UC7 Network | Applications & Services"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# DNS Server\n",
+ "\n",
+ "isp_pub_srv_dns.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Web Server & Web Browser\n",
+ "\n",
+ "st_project_a_web_browser = st_project_a_private_pc_1.software_manager.software[\"web-browser\"]\n",
+ "st_project_a_web_browser.get_webpage()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_web_server = st_dmz_pub_srv_web.software_manager.software[\"web-server\"]\n",
+ "st_web_server.sys_log.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_database_client = st_project_a_private_pc_1.software_manager.software[\"database-client\"]\n",
+ "st_database_client.connect()\n",
+ "\n",
+ "st_database = st_data_private_server_database.software_manager.software[\"database-service\"]\n",
+ "st_database.sys_log.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_ftp_server = st_data_private_server_storage.software_manager.software[\"ftp-server\"]\n",
+ "\n",
+ "st_ftp_server.sys_log.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from primaite.simulator.system.services.dns.dns_client import DNSClient\n",
+ "home_pub_rt_dr.acl.show()\n",
+ "\n",
+ "home_pub_pc_1: Computer = network.get_node_by_hostname(\"HOME-PUB-PC-1\")\n",
+ "dns_client: DNSClient = home_pub_pc_1.software_manager.software[\"dns-client\"]\n",
+ "\n",
+ "dns_client.check_domain_exists(target_domain=\"some_tech.com\")\n",
+ "dns_client.dns_cache.get(\"some_tech.com\", None) is not None\n",
+ "len(dns_client.dns_cache) == 1\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for _ in range(80):\n",
+ " env.step(0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def print_agent_actions_except_do_nothing(agent_name):\n",
+ " print(f\"\\n{agent_name} actions this episode:\")\n",
+ " for item in env.game.agents[agent_name].history:\n",
+ " if item.action != \"DONOTHING\":\n",
+ " node, application = 'unknown', 'unknown'\n",
+ " if (node_id := item.parameters.get('node_id')) is not None:\n",
+ " node = env.game.agents[agent_name].action_manager.node_names[node_id]\n",
+ " if (application_id := item.parameters.get('application_id')) is not None:\n",
+ " application = env.game.agents[agent_name].action_manager.application_names[node_id][application_id]\n",
+ " print(f\"Step: {item.timestep}, action: {item.action}, {node}, {application}, response: {item.response.status}\")\n",
+ "\n",
+ "print_agent_actions_except_do_nothing(\"HOME_WORKER-1-DB\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "green_agent = env.game.agents.get(\"HOME_WORKER-1-DB\")\n",
+ "green_agent.reward_function.total_reward"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print_agent_actions_except_do_nothing(\"HOME_WORKER-1-WEB\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "green_agent = env.game.agents.get(\"HOME_WORKER-1-WEB\")\n",
+ "green_agent.reward_function.total_reward"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "red_agent = env.game.agents.get(\"attacker\")\n",
+ "red_agent.logger.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_project_a_private_pc_1.file_system.show()\n",
+ "\n",
+ "# # st_project_a_private_pc_1.file_system.folders[\"exfiltration\"].show()\n",
+ "\n",
+ "# st_project_a_private_pc_1.software_manager.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "st_intra_prv_rt_cr.acl.show()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": ".venv",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/src/primaite/notebooks/_package_data/uc7/blue_agent_action_and_obs.png b/src/primaite/notebooks/_package_data/uc7/blue_agent_action_and_obs.png
new file mode 100644
index 00000000..85d5537d
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/blue_agent_action_and_obs.png differ
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_network.png b/src/primaite/notebooks/_package_data/uc7/uc7_network.png
new file mode 100644
index 00000000..32cecb6a
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/uc7_network.png differ
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_network_detailed.png b/src/primaite/notebooks/_package_data/uc7/uc7_network_detailed.png
new file mode 100644
index 00000000..c6d15435
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/uc7_network_detailed.png differ
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_network_detailed_svg.svg b/src/primaite/notebooks/_package_data/uc7/uc7_network_detailed_svg.svg
new file mode 100644
index 00000000..dfa8cb3c
--- /dev/null
+++ b/src/primaite/notebooks/_package_data/uc7/uc7_network_detailed_svg.svg
@@ -0,0 +1,4 @@
+
+
+
+ST_PROJ_A-... SOME TECH PROJECT A (ST_PROJ_A)
SOME TECH PROJECT A (ST_PROJ_A) 192.168.240.0/29 3 2 1 9 ST_INTRA-PRV-... ST_INTRA-PRV-... ST_INTRA-PRV-... Port 1: 192.168.170.2 Port 3: 192.168.170.1 Port 2: 192.168.160.1 Port 1: 192.168.160.2 SOME_TECH HUMAN RESOURCES (ST_HR)
SOME_TECH HUMAN RESOURCES... ST_PROJ_C-... ST_PROJ_C-... 3 2 1 9 Port 1: 192.168.250.4 Port 4 ST_PROJ_C-... 3 2 1 9 Port 1: 192.168.250.2 Port 2 ST_PROJ_C-... 3 2 1 9 Port 1: 192.168.250.3 Port 3 SOME TECH PROJECT C (ST_PROJ_C)
SOME TECH PROJECT C (ST_PROJ_C) 192.168.250.0/29 192.168.160.0/30 192.168.170.0/30 192.168.210.0/29 Port 4: 10.1.100.1 External Port: 10.1.100.2
External Port: 10.1.100.2 ST_HO-PRV-PC-2 3 2 1 9 ST_HO-PRV-PC-1 3 2 1 9 Port 2 Port 1: 192.168.20.2 Port 3 Port 1: 192.168.20.3 Port 4 Port 1: 192.168.20.4 ST_PUB-FW DMZ Port: 192.168.100.1 Port 1: 192.168.100.2 Internal Port: 192.168.150.1
Internal Port: 192.168.150.1 Port 1: 192.168.150.2 ST_HO-PRV-... ST_DATA-PRV-SRV-DB 7 9 3 6 Port 1: 192.168.220.3 Port 3 Port 1: 192.168.220.2 Port 2 ST_PROJ_B-... 3 2 1 9 ST_PROJ_B-... Port 1: 192.168.240.3 Port 3 SOME_TECH DMZ (ST_DMZ)
ST_DMZ-PUB-SRV-WEB ST_DMZ-PUB-SRV-WEB 9 3 5 Port 1 Port 2: 192.168.200.1 Port 1 Port 3: 192.168.210.1 ST_HO-PRV-PC-1 3 2 1 9 Port 2 Port 1: 192.168.200.2 ST_HO-PRV-... ST_HO-PRV-PC-3 3 2 1 9 Port 4 Port 1: 192.168.200.4 SOME_TECH HEAD OFFICE (ST_HO)
SOME_TECH HEAD OFFICE... ST_HO-PRV-PC-2 3 2 1 9 Port 3 Port 1: 192.168.200.3 Port 4: 192.168.220.1 Port 1 Port 1 Port 4: 192.168.250.1 Port 2: 192.168.230.1 Port 1 Port 1 Port 3: 192.168.240.1 ST_PROJ_A-... ST_PROJ_A-... 3 2 1 9 ST_PROJ_A-... 3 2 1 9 Port 1: 192.168.230.2 Port 2 Port 1: 192.168.230.3 Port 3 Port 1: 192.168.230.4 Port 4 SOME TECH PROJECT B (ST_PROJ_ B)
SOME TECH PROJECT B... ST_PROJ_B-... 3 2 1 9 Port 1: 192.168.240.2 Port 2 Port 1: 192.168.240.4 Port 4 ST_PROJ_B-... 3 2 1 9 ST_HO-PRV-PC-3 3 2 1 9 SOME_TECH Main Site Network
SOME_TECH Main Site Network SOME TECH DATA (ST_DATA) HOME OFFICE (HOME) HOME-PUB-PC-1 3 2 1 9 192.168.1.0/26 HOME-PUB-PC-2 3 2 1 9 HOME-PUB-SRV 3 9 HOME-PUB-... Port 1: 192.168.1.2/26 Port 2 Port 1: 192.168.1.3/26 Port 3 Port 1 Port 1: 192.168.1.1 HOME-PUB-... ISP-PUB-RT-BR ISP-PUB-... 8.8.8.0/28 10.1.10.0/30 INTERNET (ISP) REM-PUB-FW Port 1: 192.168.1.4/26 Port 4 REM-PUB-RT-DR Port 3: 10.1.10.1 External Port: 10.1.10.1 Port 2: 10.1.0.2 Port 1: 10.1.0.1 Internal Port: 192.168.10.1
Internal Port: 192.168.10.1 Port 1: 192.168.10.2 Port 1: 8.8.8.8 Port 2: 8.8.8.1 4 10 Remote Site (REMOTE) REM-PUB-PC-2 3 2 1 9 REM-PUB-PC-1 3 2 1 9 Port 2 Port 1: 192.168.20.2 Port 3 Port 1: 192.168.20.3 Port 3 Port 2: 192.168.20.1 Port 1 REM-PUB-... REM-PUB-SRV 3 9 Port 1: 192.168.20.4 Port 4 192.168.10.0/30 192.168.10.0/30 192.168.250.0/29 ST_DATA-PRV-SW-AS
ST_DATA-PRV-SRV-STOR... 3 8 9 192.168.220.0/29 192.168.200.0/29 192.168.50.0/28 10.1.100.0/30 192.168.100.0/30 10.1.0.0/30 Node Software... SERVICES APPLICATIONS 1 2 DatabaseClient Webbrowser 3 DNSClient 4 Web Server 5 WebServer 6 DatabaseService 7 FTP Client 8 FTP Server 9 NTP Client 10 NTP Server
UC7 Detailed Network Diagram UC7 Detailed Network Diagram Node Type Colour Key ROUTER... SERVER... FIREWALL... SWITCH... COMPUTER... Text is not SVG - cannot display
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_activate.png b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_activate.png
new file mode 100644
index 00000000..b8f283e4
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_activate.png differ
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_c2.png b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_c2.png
new file mode 100644
index 00000000..b8ab98e6
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_c2.png differ
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_download_install.png b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_download_install.png
new file mode 100644
index 00000000..4d7a5f20
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_download_install.png differ
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_main.png b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_main.png
new file mode 100644
index 00000000..4d86d0a7
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_main.png differ
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_payload.png b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_payload.png
new file mode 100644
index 00000000..bf9f07ae
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_payload.png differ
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_propagate_1.png b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_propagate_1.png
new file mode 100644
index 00000000..1b6b6a1d
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_propagate_1.png differ
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_propagate_2.png b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_propagate_2.png
new file mode 100644
index 00000000..4faa8eb4
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_propagate_2.png differ
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_propagate_3.png b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_propagate_3.png
new file mode 100644
index 00000000..1f00d3a8
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_propagate_3.png differ
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_propagate_4.png b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_propagate_4.png
new file mode 100644
index 00000000..01cddf5c
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/uc7_tap001/uc7_tap001_propagate_4.png differ
diff --git a/src/primaite/notebooks/_package_data/uc7/uc7_tap003/uc7_tap003_main.png b/src/primaite/notebooks/_package_data/uc7/uc7_tap003/uc7_tap003_main.png
new file mode 100644
index 00000000..2882fd3b
Binary files /dev/null and b/src/primaite/notebooks/_package_data/uc7/uc7_tap003/uc7_tap003_main.png differ
diff --git a/src/primaite/simulator/network/hardware/base.py b/src/primaite/simulator/network/hardware/base.py
index 9cc39848..2adb9ff5 100644
--- a/src/primaite/simulator/network/hardware/base.py
+++ b/src/primaite/simulator/network/hardware/base.py
@@ -1534,6 +1534,12 @@ class Node(SimComponent, ABC):
_registry: ClassVar[Dict[str, Type["Node"]]] = {}
"""Registry of application types. Automatically populated when subclasses are defined."""
+ red_scan_countdown: int = 0
+ "Time steps until reveal to red scan is complete."
+
+ node_scan_countdown: int = 0
+ "Time steps until scan is complete"
+
# TODO: this should not be set for abstract classes.
_discriminator: ClassVar[str]
"""discriminator for this particular class, used for printing and logging. Each subclass redefines this."""
@@ -1570,12 +1576,6 @@ class Node(SimComponent, ABC):
node_scan_duration: int = 10
"How many timesteps until the whole node is scanned. Default 10 time steps."
- node_scan_countdown: int = 0
- "Time steps until scan is complete"
-
- red_scan_countdown: int = 0
- "Time steps until reveal to red scan is complete."
-
dns_server: Optional[IPv4Address] = None
"List of IP addresses of DNS servers used for name resolution."
@@ -2019,10 +2019,10 @@ class Node(SimComponent, ABC):
# time steps which require the node to be on
if self.operating_state == NodeOperatingState.ON:
# node scanning
- if self.config.node_scan_countdown > 0:
- self.config.node_scan_countdown -= 1
+ if self.node_scan_countdown > 0:
+ self.node_scan_countdown -= 1
- if self.config.node_scan_countdown == 0:
+ if self.node_scan_countdown == 0:
# scan everything!
for process_id in self.processes:
self.processes[process_id].scan()
@@ -2038,10 +2038,10 @@ class Node(SimComponent, ABC):
# scan file system
self.file_system.scan(instant_scan=True)
- if self.config.red_scan_countdown > 0:
- self.config.red_scan_countdown -= 1
+ if self.red_scan_countdown > 0:
+ self.red_scan_countdown -= 1
- if self.config.red_scan_countdown == 0:
+ if self.red_scan_countdown == 0:
# scan processes
for process_id in self.processes:
self.processes[process_id].reveal_to_red()
@@ -2098,7 +2098,7 @@ class Node(SimComponent, ABC):
to the red agent.
"""
- self.config.node_scan_countdown = self.config.node_scan_duration
+ self.node_scan_countdown = self.config.node_scan_duration
return True
def reveal_to_red(self) -> bool:
@@ -2114,7 +2114,7 @@ class Node(SimComponent, ABC):
`revealed_to_red` to `True`.
"""
- self.config.red_scan_countdown = self.config.node_scan_duration
+ self.red_scan_countdown = self.config.node_scan_duration
return True
def power_on(self) -> bool:
diff --git a/tests/e2e_integration_tests/test_uc7_agents.py b/tests/e2e_integration_tests/test_uc7_agents.py
new file mode 100644
index 00000000..d54bf6d2
--- /dev/null
+++ b/tests/e2e_integration_tests/test_uc7_agents.py
@@ -0,0 +1,172 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+
+import pytest
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG, load
+from primaite.game.game import PrimaiteGame
+from primaite.session.environment import PrimaiteGymEnv
+from primaite.simulator.file_system.file import File
+from primaite.simulator.file_system.file_system_item_abc import FileSystemItemHealthStatus
+from primaite.simulator.network.container import Network
+from primaite.simulator.network.hardware.nodes.host.computer import Computer
+from primaite.simulator.network.hardware.nodes.host.server import Server
+from primaite.simulator.network.hardware.nodes.network.firewall import Firewall
+from primaite.simulator.system.applications.application import ApplicationOperatingState
+from primaite.simulator.system.applications.database_client import DatabaseClient
+from primaite.simulator.system.applications.red_applications.c2.c2_beacon import C2Beacon
+from primaite.simulator.system.applications.red_applications.ransomware_script import RansomwareScript
+from primaite.simulator.system.applications.web_browser import WebBrowser
+from primaite.simulator.system.services.database.database_service import DatabaseService
+from primaite.simulator.system.services.dns.dns_client import DNSClient
+from primaite.simulator.system.services.dns.dns_server import DNSServer
+from primaite.simulator.system.services.ftp.ftp_client import FTPClient
+from primaite.simulator.system.services.ftp.ftp_server import FTPServer
+from primaite.simulator.system.services.ntp.ntp_client import NTPClient
+from primaite.simulator.system.services.ntp.ntp_server import NTPServer
+from primaite.simulator.system.services.service import ServiceOperatingState
+from primaite.simulator.system.software import SoftwareHealthState
+
+CONFIG_FILE = _EXAMPLE_CFG / "uc7_config.yaml"
+ATTACK_AGENT_INDEX = 32
+
+
+@pytest.fixture(scope="function")
+def uc7_environment() -> PrimaiteGymEnv:
+ with open(_EXAMPLE_CFG / "uc7_config.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ env = PrimaiteGymEnv(env_config=cfg)
+ return env
+
+
+def assert_agent_reward(env: PrimaiteGymEnv, agent_name: str, positive: bool):
+ """Asserts that a given agent has a reward that is below/above or equal to 0 dependant on arguments."""
+ agent_reward = env.game.agents[agent_name].reward_function.total_reward
+ if agent_name == "defender":
+ return # ignore blue agent
+ if positive is True:
+ assert agent_reward >= 0 # Asserts that no agents are below a total reward of 0
+ elif positive is False:
+ assert agent_reward <= 0 # Asserts that no agents are above a total reward of 0
+
+
+def test_green_agent_positive_reward(uc7_environment):
+ """Confirms that the UC7 Green Agents receive a positive reward (Default Behaviour)."""
+ env: PrimaiteGymEnv = uc7_environment
+
+ # Performing no changes to the environment. Default Behaviour
+
+ # Stepping 60 times in the environment
+ for _ in range(60):
+ env.step(0)
+
+ for agent in env.game.agents:
+ assert_agent_reward(env=env, agent_name=env.game.agents[agent].config.ref, positive=True)
+
+
+def test_green_agent_negative_reward(uc7_environment):
+ """Confirms that the UC7 Green Agents receive a negative reward. (Disabled web-server and database-service)"""
+
+ env: PrimaiteGymEnv = uc7_environment
+
+ # Purposefully disabling the following services:
+
+ # 1. Disabling the web-server
+ st_dmz_pub_srv_web: Server = env.game.simulation.network.get_node_by_hostname("ST_DMZ-PUB-SRV-WEB")
+ st_web_server = st_dmz_pub_srv_web.software_manager.software["web-server"]
+ st_web_server.operating_state = ServiceOperatingState.DISABLED
+ assert st_web_server.operating_state == ServiceOperatingState.DISABLED
+
+ # 2. Disabling the DatabaseServer
+ st_data_database_server: Server = env.game.simulation.network.get_node_by_hostname("ST_DATA-PRV-SRV-DB")
+ database_service: DatabaseService = st_data_database_server.software_manager.software["database-service"]
+ database_service.operating_state = ServiceOperatingState.DISABLED
+ assert database_service.operating_state == ServiceOperatingState.DISABLED
+
+ # Stepping 100 times in the environment
+ for _ in range(100):
+ env.step(0)
+
+ for agent in env.game.agents:
+ assert_agent_reward(env=env, agent_name=env.game.agents[agent].config.ref, positive=False)
+
+
+def test_tap001_default_behaviour(uc7_environment):
+ """Confirms that the TAP001 expected simulation impacts works as expected in the UC7 environment."""
+ env: PrimaiteGymEnv = uc7_environment
+ env.reset()
+ network = env.game.simulation.network
+
+ # Running for 128 episodes
+ for _ in range(128):
+ env.step(0)
+
+ some_tech_proj_a_pc_1: Computer = network.get_node_by_hostname("ST_PROJ-A-PRV-PC-1")
+
+ # Asserting that the `malware_dropper.ps1` was created.
+
+ malware_dropper_file: File = some_tech_proj_a_pc_1.file_system.get_file("downloads", "malware_dropper.ps1")
+ assert malware_dropper_file.health_status == FileSystemItemHealthStatus.GOOD
+
+ # Asserting that the `RansomwareScript` launched successfully.
+
+ ransomware_script: RansomwareScript = some_tech_proj_a_pc_1.software_manager.software["ransomware-script"]
+ assert ransomware_script.health_state_actual == SoftwareHealthState.GOOD
+ assert ransomware_script.operating_state == ApplicationOperatingState.RUNNING
+
+ # Asserting that the `C2Beacon` connected to the `C2Server`.
+
+ c2_beacon: C2Beacon = some_tech_proj_a_pc_1.software_manager.software["c2-beacon"]
+ assert c2_beacon.health_state_actual == SoftwareHealthState.GOOD
+ assert c2_beacon.operating_state == ApplicationOperatingState.RUNNING
+ assert c2_beacon.c2_connection_active == True
+
+ # Asserting that the target database was successfully corrupted.
+ some_tech_data_server_database: Server = network.get_node_by_hostname("ST_DATA-PRV-SRV-DB")
+ database_file: File = some_tech_data_server_database.file_system.get_file(
+ folder_name="database", file_name="database.db"
+ )
+ assert database_file.health_status == FileSystemItemHealthStatus.CORRUPT
+
+
+def test_tap003_default_behaviour(uc7_environment):
+ """Confirms that the TAP003 expected simulation impacts works as expected in the UC7 environment."""
+ from primaite.simulator.network.hardware.nodes.network.router import ACLAction, Router
+ from primaite.simulator.network.transmission.network_layer import IPPacket, IPProtocol
+ from primaite.utils.validation.port import PORT_LOOKUP
+
+ def uc7_environment_tap003() -> PrimaiteGymEnv:
+ with open(_EXAMPLE_CFG / "uc7_config_tap003.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["starting_nodes"] = ["ST_PROJ-A-PRV-PC-1"]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["default_starting_node"] = "ST_PROJ-A-PRV-PC-1"
+ env = PrimaiteGymEnv(env_config=cfg)
+ return env
+
+ env: PrimaiteGymEnv = uc7_environment_tap003()
+ env.reset()
+ # Running for 128 episodes
+ for _ in range(128):
+ env.step(0)
+ network = env.game.simulation.network
+
+ # Asserting that a malicious ACL has been added to ST_INTRA-PRV-RT-DR-1
+ st_intra_prv_rt_dr_1: Router = network.get_node_by_hostname(hostname="ST_INTRA-PRV-RT-DR-1")
+ assert st_intra_prv_rt_dr_1.acl.acl[1].action == ACLAction.DENY
+ assert st_intra_prv_rt_dr_1.acl.acl[1].protocol == "tcp"
+ assert st_intra_prv_rt_dr_1.acl.acl[1].src_port == PORT_LOOKUP.get("POSTGRES_SERVER")
+ assert st_intra_prv_rt_dr_1.acl.acl[1].dst_port == PORT_LOOKUP.get("POSTGRES_SERVER")
+
+ # Asserting that a malicious ACL has been added to ST_INTRA-PRV-RT-CR
+ st_intra_prv_rt_cr: Router = network.get_node_by_hostname(hostname="ST_INTRA-PRV-RT-CR")
+ assert st_intra_prv_rt_cr.acl.acl[1].action == ACLAction.DENY
+ assert st_intra_prv_rt_cr.acl.acl[1].protocol == "tcp"
+ assert st_intra_prv_rt_cr.acl.acl[1].src_port == PORT_LOOKUP.get("HTTP")
+ assert st_intra_prv_rt_cr.acl.acl[1].dst_port == PORT_LOOKUP.get("HTTP")
+
+ # Asserting that a malicious ACL has been added to REM-PUB-RT-DR
+ rem_pub_rt_dr: Router = network.get_node_by_hostname(hostname="REM-PUB-RT-DR")
+ assert rem_pub_rt_dr.acl.acl[1].action == ACLAction.DENY
+ assert rem_pub_rt_dr.acl.acl[1].protocol == "tcp"
+ assert rem_pub_rt_dr.acl.acl[1].src_port == PORT_LOOKUP.get("DNS")
+ assert rem_pub_rt_dr.acl.acl[1].dst_port == PORT_LOOKUP.get("DNS")
diff --git a/tests/e2e_integration_tests/test_uc7_route_connectivity.py b/tests/e2e_integration_tests/test_uc7_route_connectivity.py
new file mode 100644
index 00000000..af5f3cd2
--- /dev/null
+++ b/tests/e2e_integration_tests/test_uc7_route_connectivity.py
@@ -0,0 +1,237 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+import pytest
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG
+from primaite.game.game import PrimaiteGame
+from primaite.session.environment import PrimaiteGymEnv
+from primaite.simulator.network.container import Network
+from primaite.simulator.network.hardware.nodes.host.computer import Computer
+from primaite.simulator.network.hardware.nodes.host.server import Server
+from primaite.simulator.network.hardware.nodes.network.firewall import Firewall
+from primaite.simulator.network.hardware.nodes.network.router import Router
+from primaite.simulator.network.hardware.nodes.network.switch import Switch
+
+CONFIG_FILE = _EXAMPLE_CFG / "uc7_config.yaml"
+
+
+@pytest.fixture(scope="function")
+def uc7_network() -> Network:
+ with open(file=CONFIG_FILE, mode="r") as f:
+ cfg = yaml.safe_load(stream=f)
+
+ game = PrimaiteGame.from_config(cfg=cfg)
+ return game.simulation.network
+
+
+def test_ping_home_office(uc7_network):
+ """Asserts that all home_pub_* can ping each-other and the public dns (isp_pub_srv_dns)"""
+ network = uc7_network
+ home_pub_pc_1: Computer = network.get_node_by_hostname("HOME-PUB-PC-1")
+ home_pub_pc_2: Computer = network.get_node_by_hostname("HOME-PUB-PC-2")
+ home_pub_pc_srv: Server = network.get_node_by_hostname("HOME-PUB-SRV")
+ home_pub_rt_dr: Router = network.get_node_by_hostname("HOME-PUB-RT-DR")
+ isp_pub_srv_dns: Server = network.get_node_by_hostname("ISP-PUB-SRV-DNS")
+
+ assert home_pub_pc_1.ping(isp_pub_srv_dns.network_interface[1].ip_address)
+
+ def ping_all_home_office(host):
+ assert host.ping(home_pub_pc_1.network_interface[1].ip_address)
+ assert host.ping(home_pub_pc_2.network_interface[1].ip_address)
+ assert host.ping(home_pub_pc_srv.network_interface[1].ip_address)
+ assert host.ping(home_pub_rt_dr.network_interface[1].ip_address)
+ assert host.ping(isp_pub_srv_dns.network_interface[1].ip_address)
+
+ ping_all_home_office(home_pub_pc_1)
+ ping_all_home_office(home_pub_pc_2)
+ ping_all_home_office(home_pub_pc_srv)
+ ping_all_home_office(isp_pub_srv_dns)
+
+
+def test_ping_remote_site(uc7_network):
+ """Asserts that all remote_pub_* hosts can ping each-other and the public dns server (isp_pub_srv_dns)"""
+ network = uc7_network
+ rem_pub_fw: Firewall = network.get_node_by_hostname(hostname="REM-PUB-FW")
+ rem_pub_rt_dr: Router = network.get_node_by_hostname(hostname="REM-PUB-RT-DR")
+ rem_pub_pc_1: Computer = network.get_node_by_hostname(hostname="REM-PUB-PC-1")
+ rem_pub_pc_2: Computer = network.get_node_by_hostname(hostname="REM-PUB-PC-2")
+ rem_pub_srv: Computer = network.get_node_by_hostname(hostname="REM-PUB-SRV")
+
+ def ping_all_remote_site(host):
+ assert host.ping(rem_pub_fw.network_interface[1].ip_address)
+ assert host.ping(rem_pub_rt_dr.network_interface[1].ip_address)
+ assert host.ping(rem_pub_pc_1.network_interface[1].ip_address)
+ assert host.ping(rem_pub_pc_2.network_interface[1].ip_address)
+ assert host.ping(rem_pub_srv.network_interface[1].ip_address)
+
+ ping_all_remote_site(host=rem_pub_fw)
+ ping_all_remote_site(host=rem_pub_rt_dr)
+ ping_all_remote_site(host=rem_pub_pc_1)
+ ping_all_remote_site(host=rem_pub_pc_2)
+ ping_all_remote_site(host=rem_pub_srv)
+
+
+def test_ping_some_tech_dmz(uc7_network):
+ """Asserts that the st_dmz_pub_srv_web and the st_public_firewall can ping each other and remote site and home office."""
+ network = uc7_network
+ st_pub_fw: Firewall = network.get_node_by_hostname(hostname="ST_PUB-FW")
+ st_dmz_pub_srv_web: Server = network.get_node_by_hostname(hostname="ST_DMZ-PUB-SRV-WEB")
+ isp_pub_srv_dns: Server = network.get_node_by_hostname("ISP-PUB-SRV-DNS")
+ home_pub_pc_1: Computer = network.get_node_by_hostname("HOME-PUB-PC-1")
+
+ def ping_all_some_tech_dmz(host):
+ assert host.ping(st_dmz_pub_srv_web.network_interface[1].ip_address)
+ assert host.ping(isp_pub_srv_dns.network_interface[1].ip_address)
+
+ ping_all_some_tech_dmz(host=st_pub_fw)
+ ping_all_some_tech_dmz(host=isp_pub_srv_dns)
+ ping_all_some_tech_dmz(host=home_pub_pc_1)
+
+
+def test_ping_some_tech_head_office(uc7_network):
+ """Asserts that all the some_tech_* PCs can ping each other and the public dns"""
+ network = uc7_network
+ st_home_office_private_pc_1: Computer = network.get_node_by_hostname("ST_HO-PRV-PC-1")
+ st_home_office_private_pc_2: Computer = network.get_node_by_hostname("ST_HO-PRV-PC-2")
+ st_home_office_private_pc_3: Computer = network.get_node_by_hostname("ST_HO-PRV-PC-3")
+ isp_pub_srv_dns: Server = network.get_node_by_hostname("ISP-PUB-SRV-DNS")
+
+ def ping_all_some_tech_head_office(host):
+ assert host.ping(st_home_office_private_pc_1.network_interface[1].ip_address)
+ assert host.ping(st_home_office_private_pc_2.network_interface[1].ip_address)
+ assert host.ping(st_home_office_private_pc_3.network_interface[1].ip_address)
+ assert host.ping(isp_pub_srv_dns.network_interface[1].ip_address)
+
+ ping_all_some_tech_head_office(host=st_home_office_private_pc_1)
+ ping_all_some_tech_head_office(host=st_home_office_private_pc_2)
+ ping_all_some_tech_head_office(host=st_home_office_private_pc_3)
+
+
+def test_ping_some_tech_hr(uc7_network):
+ """Assert that all some_tech_hr_* PCs can ping each other and the public dns"""
+ network = uc7_network
+ some_tech_hr_pc_1: Computer = network.get_node_by_hostname("ST_HR-PRV-PC-1")
+ some_tech_hr_pc_2: Computer = network.get_node_by_hostname("ST_HR-PRV-PC-2")
+ some_tech_hr_pc_3: Computer = network.get_node_by_hostname("ST_HR-PRV-PC-3")
+ isp_pub_srv_dns: Server = network.get_node_by_hostname("ISP-PUB-SRV-DNS")
+
+ def ping_all_some_tech_hr(host):
+ assert host.ping(some_tech_hr_pc_1.network_interface[1].ip_address)
+ assert host.ping(some_tech_hr_pc_2.network_interface[1].ip_address)
+ assert host.ping(some_tech_hr_pc_3.network_interface[1].ip_address)
+ assert host.ping(isp_pub_srv_dns.network_interface[1].ip_address)
+
+ ping_all_some_tech_hr(some_tech_hr_pc_1)
+ ping_all_some_tech_hr(some_tech_hr_pc_2)
+ ping_all_some_tech_hr(some_tech_hr_pc_3)
+
+
+def test_some_tech_data_hr(uc7_network):
+ """Assert that all some_tech_data_* servers can ping each other and the public dns."""
+ network = uc7_network
+ some_tech_data_server_storage: Server = network.get_node_by_hostname("ST_DATA-PRV-SRV-STORAGE")
+ some_tech_data_server_database: Server = network.get_node_by_hostname("ST_DATA-PRV-SRV-DB")
+ isp_pub_srv_dns: Server = network.get_node_by_hostname("ISP-PUB-SRV-DNS")
+
+ def ping_all_some_tech_hr(host):
+ assert host.ping(some_tech_data_server_storage.network_interface[1].ip_address)
+ assert host.ping(some_tech_data_server_database.network_interface[1].ip_address)
+ assert host.ping(isp_pub_srv_dns.network_interface[1].ip_address)
+
+ ping_all_some_tech_hr(some_tech_data_server_storage)
+ ping_all_some_tech_hr(some_tech_data_server_database)
+
+
+def test_some_tech_project_a(uc7_network):
+ """Asserts that all some_tech project A's PCs can ping each other and the public dns."""
+ network = uc7_network
+ some_tech_proj_a_pc_1: Computer = network.get_node_by_hostname("ST_PROJ-A-PRV-PC-1")
+ some_tech_proj_a_pc_2: Computer = network.get_node_by_hostname("ST_PROJ-A-PRV-PC-2")
+ some_tech_proj_a_pc_3: Computer = network.get_node_by_hostname("ST_PROJ-A-PRV-PC-3")
+ isp_pub_srv_dns: Server = network.get_node_by_hostname("ISP-PUB-SRV-DNS")
+
+ def ping_all_some_tech_proj_a(host):
+ assert host.ping(some_tech_proj_a_pc_1.network_interface[1].ip_address)
+ assert host.ping(some_tech_proj_a_pc_2.network_interface[1].ip_address)
+ assert host.ping(some_tech_proj_a_pc_3.network_interface[1].ip_address)
+ assert host.ping(isp_pub_srv_dns.network_interface[1].ip_address)
+
+ ping_all_some_tech_proj_a(some_tech_proj_a_pc_1)
+ ping_all_some_tech_proj_a(some_tech_proj_a_pc_2)
+ ping_all_some_tech_proj_a(some_tech_proj_a_pc_3)
+
+
+def test_some_tech_project_b(uc7_network):
+ """Asserts that all some_tech_project_b PC's can ping each other and the public dps."""
+ network = uc7_network
+ some_tech_proj_b_pc_1: Computer = network.get_node_by_hostname("ST_PROJ-B-PRV-PC-1")
+ some_tech_proj_b_pc_2: Computer = network.get_node_by_hostname("ST_PROJ-B-PRV-PC-2")
+ some_tech_proj_b_pc_3: Computer = network.get_node_by_hostname("ST_PROJ-B-PRV-PC-3")
+ isp_pub_srv_dns: Server = network.get_node_by_hostname("ISP-PUB-SRV-DNS")
+
+ def ping_all_some_tech_proj_b(host):
+ assert host.ping(some_tech_proj_b_pc_1.network_interface[1].ip_address)
+ assert host.ping(some_tech_proj_b_pc_2.network_interface[1].ip_address)
+ assert host.ping(some_tech_proj_b_pc_3.network_interface[1].ip_address)
+ assert host.ping(isp_pub_srv_dns.network_interface[1].ip_address)
+
+ ping_all_some_tech_proj_b(some_tech_proj_b_pc_1)
+ ping_all_some_tech_proj_b(some_tech_proj_b_pc_2)
+ ping_all_some_tech_proj_b(some_tech_proj_b_pc_3)
+
+
+def test_some_tech_project_a(uc7_network):
+ """Asserts that all some_tech_project_c PC's can ping each other and the public dps."""
+ network = uc7_network
+ some_tech_proj_c_pc_1: Computer = network.get_node_by_hostname("ST_PROJ-C-PRV-PC-1")
+ some_tech_proj_c_pc_2: Computer = network.get_node_by_hostname("ST_PROJ-C-PRV-PC-2")
+ some_tech_proj_c_pc_3: Computer = network.get_node_by_hostname("ST_PROJ-C-PRV-PC-3")
+ isp_pub_srv_dns: Server = network.get_node_by_hostname("ISP-PUB-SRV-DNS")
+
+ def ping_all_some_tech_proj_c(host):
+ assert host.ping(some_tech_proj_c_pc_1.network_interface[1].ip_address)
+ assert host.ping(some_tech_proj_c_pc_2.network_interface[1].ip_address)
+ assert host.ping(some_tech_proj_c_pc_3.network_interface[1].ip_address)
+ assert host.ping(isp_pub_srv_dns.network_interface[1].ip_address)
+
+ ping_all_some_tech_proj_c(some_tech_proj_c_pc_1)
+ ping_all_some_tech_proj_c(some_tech_proj_c_pc_2)
+ ping_all_some_tech_proj_c(some_tech_proj_c_pc_3)
+
+
+def test_ping_all_networks(uc7_network):
+ """Asserts that one machine from each network is able to ping all others."""
+ network = uc7_network
+ home_office_pc_1: Computer = network.get_node_by_hostname("HOME-PUB-PC-1")
+ isp_pub_srv_dns: Server = network.get_node_by_hostname("ISP-PUB-SRV-DNS")
+ remote_office_pc_1: Computer = network.get_node_by_hostname("REM-PUB-PC-1")
+ st_head_office_pc_1: Computer = network.get_node_by_hostname("ST_HO-PRV-PC-1")
+ st_human_resources_pc_1: Computer = network.get_node_by_hostname("ST_HR-PRV-PC-1")
+ st_data_storage_server: Server = network.get_node_by_hostname("ST_DATA-PRV-SRV-STORAGE")
+ st_data_database_server: Server = network.get_node_by_hostname("ST_DATA-PRV-SRV-DB")
+ st_proj_a_pc_1: Computer = network.get_node_by_hostname("ST_PROJ-A-PRV-PC-1")
+ st_proj_b_pc_1: Computer = network.get_node_by_hostname("ST_PROJ-B-PRV-PC-1")
+ st_proj_c_pc_1: Computer = network.get_node_by_hostname("ST_PROJ-C-PRV-PC-1")
+
+ def ping_network_wide(host):
+ assert host.ping(home_office_pc_1.network_interface[1].ip_address)
+ assert host.ping(isp_pub_srv_dns.network_interface[1].ip_address)
+ assert host.ping(remote_office_pc_1.network_interface[1].ip_address)
+ assert host.ping(st_head_office_pc_1.network_interface[1].ip_address)
+ assert host.ping(st_human_resources_pc_1.network_interface[1].ip_address)
+ assert host.ping(st_data_storage_server.network_interface[1].ip_address)
+ assert host.ping(st_data_database_server.network_interface[1].ip_address)
+ assert host.ping(st_proj_a_pc_1.network_interface[1].ip_address)
+ assert host.ping(st_proj_b_pc_1.network_interface[1].ip_address)
+ assert host.ping(st_proj_c_pc_1.network_interface[1].ip_address)
+
+ ping_network_wide(host=home_office_pc_1)
+ ping_network_wide(host=isp_pub_srv_dns)
+ ping_network_wide(host=remote_office_pc_1)
+ ping_network_wide(host=st_head_office_pc_1)
+ ping_network_wide(host=st_human_resources_pc_1)
+ ping_network_wide(host=st_data_storage_server)
+ ping_network_wide(host=st_data_database_server)
+ ping_network_wide(host=st_proj_a_pc_1)
+ ping_network_wide(host=st_proj_b_pc_1)
+ ping_network_wide(host=st_proj_c_pc_1)
diff --git a/tests/e2e_integration_tests/test_uc7_services_and_applications.py b/tests/e2e_integration_tests/test_uc7_services_and_applications.py
new file mode 100644
index 00000000..0bcfcfca
--- /dev/null
+++ b/tests/e2e_integration_tests/test_uc7_services_and_applications.py
@@ -0,0 +1,338 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+
+import pytest
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG
+from primaite.game.game import PrimaiteGame
+from primaite.session.environment import PrimaiteGymEnv
+from primaite.simulator.network.container import Network
+from primaite.simulator.network.hardware.nodes.host.computer import Computer
+from primaite.simulator.network.hardware.nodes.host.server import Server
+from primaite.simulator.system.applications.application import ApplicationOperatingState
+from primaite.simulator.system.applications.database_client import DatabaseClient
+from primaite.simulator.system.applications.web_browser import WebBrowser
+from primaite.simulator.system.services.database.database_service import DatabaseService
+from primaite.simulator.system.services.dns.dns_client import DNSClient
+from primaite.simulator.system.services.dns.dns_server import DNSServer
+from primaite.simulator.system.services.ftp.ftp_client import FTPClient
+from primaite.simulator.system.services.ftp.ftp_server import FTPServer
+from primaite.simulator.system.services.ntp.ntp_client import NTPClient
+from primaite.simulator.system.services.ntp.ntp_server import NTPServer
+from primaite.simulator.system.services.service import ServiceOperatingState
+from primaite.simulator.system.software import SoftwareHealthState
+
+CONFIG_FILE = _EXAMPLE_CFG / "uc7_config.yaml"
+
+
+@pytest.fixture(scope="function")
+def uc7_network() -> Network:
+ with open(file=CONFIG_FILE, mode="r") as f:
+ cfg = yaml.safe_load(stream=f)
+
+ game = PrimaiteGame.from_config(cfg=cfg)
+ return game.simulation.network
+
+
+def assert_ntp_client(host):
+ """Confirms that the ntp_client service is present and functioning."""
+ ntp_client: NTPClient = host.software_manager.software["ntp-client"]
+ assert ntp_client is not None
+ assert ntp_client.operating_state == ServiceOperatingState.RUNNING
+ assert ntp_client.health_state_actual == SoftwareHealthState.GOOD
+
+
+def assert_dns_client(host):
+ """Confirms that the dns_client service is present and functioning."""
+ dns_client: DNSClient = host.software_manager.software["dns-client"]
+ assert dns_client is not None
+ assert dns_client.operating_state == ServiceOperatingState.RUNNING
+ assert dns_client.health_state_actual == SoftwareHealthState.GOOD
+
+
+def assert_web_browser(host: Computer):
+ """Asserts that the web_browser application is present and functioning."""
+ web_browser: WebBrowser = host.software_manager.software["web-browser"]
+ assert web_browser is not None
+ assert web_browser.operating_state == ApplicationOperatingState.RUNNING
+ assert web_browser.health_state_actual == SoftwareHealthState.GOOD
+
+
+def assert_database_client(host: Computer):
+ """Asserts that the database_client application is present and functioning."""
+ database_client = host.software_manager.software["database-client"]
+ assert database_client is not None
+ assert database_client.operating_state == ApplicationOperatingState.RUNNING
+ assert database_client.health_state_actual == SoftwareHealthState.GOOD
+
+
+def test_home_office_software(uc7_network):
+ """Asserts that each host in the home_office network contains the expected software."""
+ network: Network = uc7_network
+ home_pub_pc_1: Computer = network.get_node_by_hostname("HOME-PUB-PC-1")
+ home_pub_pc_2: Computer = network.get_node_by_hostname("HOME-PUB-PC-1")
+ home_pub_srv: Server = network.get_node_by_hostname("HOME-PUB-SRV")
+
+ # Home Office PC 1
+ assert_web_browser(home_pub_pc_1)
+ assert_database_client(home_pub_pc_1)
+ assert_dns_client(home_pub_pc_1)
+ assert_ntp_client(home_pub_pc_1)
+
+ # Home Office PC 2
+ assert_web_browser(home_pub_pc_2)
+ assert_database_client(home_pub_pc_2)
+ assert_dns_client(home_pub_pc_2)
+ assert_ntp_client(home_pub_pc_2)
+
+ # Home Office Server
+ assert_dns_client(home_pub_srv)
+ assert_ntp_client(home_pub_srv)
+
+
+def test_internet_dns_server(uc7_network):
+ """Asserts that `ISP-PUB-SRV-DNS` host's DNSServer application is operating and functioning as expected."""
+ network: Network = uc7_network
+ isp_pub_srv_dns: Server = network.get_node_by_hostname("ISP-PUB-SRV-DNS")
+
+ # Confirming that the DNSServer is up and running:
+
+ dns_server: DNSServer = isp_pub_srv_dns.software_manager.software["dns-server"]
+ assert dns_server is not None
+ assert dns_server.operating_state == ServiceOperatingState.RUNNING
+ assert dns_server.health_state_actual == SoftwareHealthState.GOOD
+
+ # Confirming that the DNSServer is performing as expected by performing a request from a client
+
+ home_pub_pc_1: Computer = network.get_node_by_hostname("HOME-PUB-PC-1")
+ dns_client: DNSClient = home_pub_pc_1.software_manager.software["dns-client"]
+
+ assert dns_client.check_domain_exists(target_domain="some_tech.com")
+ assert dns_client.dns_cache.get("some_tech.com", None) is not None
+ assert len(dns_client.dns_cache) == 1
+
+
+def test_remote_office_software(uc7_network):
+ """Asserts that each host on the remote_office network has the expected services & applications which are operating as expected."""
+ network = uc7_network
+ rem_pub_pc_1: Computer = network.get_node_by_hostname(hostname="REM-PUB-PC-1")
+ rem_pub_pc_2: Computer = network.get_node_by_hostname(hostname="REM-PUB-PC-2")
+ rem_pub_srv: Server = network.get_node_by_hostname(hostname="REM-PUB-SRV")
+
+ # Remote Site PC 1
+ assert_web_browser(rem_pub_pc_1)
+ assert_database_client(rem_pub_pc_1)
+ assert_dns_client(rem_pub_pc_1)
+ assert_ntp_client(rem_pub_pc_1)
+
+ # Remote Site PC 2
+ assert_web_browser(rem_pub_pc_2)
+ assert_database_client(rem_pub_pc_2)
+ assert_dns_client(rem_pub_pc_2)
+ assert_ntp_client(rem_pub_pc_2)
+
+ # Remote Site Server
+ assert_dns_client(rem_pub_srv)
+ assert_ntp_client(rem_pub_srv)
+
+
+def test_dmz_web_server(uc7_network):
+ """Asserts that the DMZ WebServer functions as expected"""
+ network: Network = uc7_network
+ st_dmz_pub_srv_web: Server = network.get_node_by_hostname("ST_DMZ-PUB-SRV-WEB")
+
+ # Asserting the ST Web Server is working as expected
+ st_web_server = st_dmz_pub_srv_web.software_manager.software["web-server"]
+ assert st_web_server is not None
+ assert st_web_server.operating_state == ServiceOperatingState.RUNNING
+ assert st_web_server.health_state_actual == SoftwareHealthState.GOOD
+
+ # Asserting that WebBrowser can actually connect to the WebServer
+
+ # SOME TECH Human Resources --> DMZ Web Server
+ st_hr_pc_1: Computer = network.get_node_by_hostname("ST_HR-PRV-PC-1")
+ st_hr_pc_1_web_browser: WebBrowser = st_hr_pc_1.software_manager.software["web-browser"]
+ assert st_hr_pc_1_web_browser.get_webpage("http://some_tech.com")
+
+ # Remote Site --> DMZ Web Server
+ rem_pub_pc_1: Computer = network.get_node_by_hostname("REM-PUB-PC-1")
+ rem_pub_pc_1_web_browser: WebBrowser = rem_pub_pc_1.software_manager.software["web-browser"]
+ assert rem_pub_pc_1_web_browser.get_webpage("http://some_tech.com")
+
+ # Home Office --> DMZ Web Server
+ home_pub_pc_1: Computer = network.get_node_by_hostname("HOME-PUB-PC-1")
+ home_pub_pc_1_web_browser: WebBrowser = home_pub_pc_1.software_manager.software["web-browser"]
+ assert home_pub_pc_1_web_browser.get_webpage("http://some_tech.com")
+
+
+def test_tech_head_office_software(uc7_network):
+ """Asserts that each host on the some_tech_head_office network has the expected services & applications which are operating as expected."""
+ network: Network = uc7_network
+
+ st_head_office_private_pc_1: Computer = network.get_node_by_hostname("ST_HO-PRV-PC-1")
+ st_head_office_private_pc_2: Computer = network.get_node_by_hostname("ST_HO-PRV-PC-2")
+ st_head_office_private_pc_3: Computer = network.get_node_by_hostname("ST_HO-PRV-PC-3")
+
+ # ST Head Office One
+
+ assert_web_browser(st_head_office_private_pc_1)
+ assert_database_client(st_head_office_private_pc_1)
+ assert_dns_client(st_head_office_private_pc_1)
+ assert_ntp_client(st_head_office_private_pc_1)
+
+ # ST Head Office Two
+
+ assert_web_browser(st_head_office_private_pc_2)
+ assert_database_client(st_head_office_private_pc_2)
+ assert_dns_client(st_head_office_private_pc_2)
+ assert_ntp_client(st_head_office_private_pc_2)
+
+ # ST Head Office Three
+
+ assert_web_browser(st_head_office_private_pc_3)
+ assert_database_client(st_head_office_private_pc_3)
+ assert_dns_client(st_head_office_private_pc_3)
+ assert_ntp_client(st_head_office_private_pc_3)
+
+
+def test_tech_human_resources_office_software(uc7_network):
+ """Asserts that each host on the some_tech human_resources network has the expected services & applications which are operating as expected."""
+ network: Network = uc7_network
+
+ st_hr_pc_1: Computer = network.get_node_by_hostname("ST_HR-PRV-PC-1")
+ st_hr_pc_2: Computer = network.get_node_by_hostname("ST_HR-PRV-PC-2")
+ st_hr_pc_3: Computer = network.get_node_by_hostname("ST_HR-PRV-PC-3")
+
+ # ST Human Resource PC 1
+
+ assert_web_browser(st_hr_pc_1)
+ assert_database_client(st_hr_pc_1)
+ assert_dns_client(st_hr_pc_1)
+ assert_ntp_client(st_hr_pc_1)
+
+ # ST Human Resource PC 2
+
+ assert_web_browser(st_hr_pc_2)
+ assert_database_client(st_hr_pc_2)
+ assert_dns_client(st_hr_pc_2)
+ assert_ntp_client(st_hr_pc_2)
+
+ # ST Human Resource PC 3
+
+ assert_web_browser(st_hr_pc_3)
+ assert_database_client(st_hr_pc_3)
+ assert_dns_client(st_hr_pc_3)
+ assert_ntp_client(st_hr_pc_3)
+
+
+def test_tech_data_software(uc7_network):
+ """Asserts the database and database storage servers on the some_tech data network are operating as expected."""
+ network: Network = uc7_network
+ st_data_database_server: Server = network.get_node_by_hostname("ST_DATA-PRV-SRV-DB")
+ st_data_database_storage: Server = network.get_node_by_hostname("ST_DATA-PRV-SRV-STORAGE")
+ st_proj_a_pc_1: Computer = network.get_node_by_hostname("ST_PROJ-A-PRV-PC-1")
+
+ # Asserting that the database_service is working as expected
+ database_service: DatabaseService = st_data_database_server.software_manager.software["database-service"]
+
+ assert database_service is not None
+ assert database_service.operating_state == ServiceOperatingState.RUNNING
+ assert database_service.health_state_actual == SoftwareHealthState.GOOD
+
+ # Asserting that the database_client can connect to the database
+ database_client: DatabaseClient = st_proj_a_pc_1.software_manager.software["database-client"]
+
+ assert database_client.server_ip_address is not None
+ assert database_client.server_ip_address == st_data_database_server.network_interface[1].ip_address
+ assert database_client.connect()
+
+ # Asserting that the database storage works as expected.
+ assert database_service.backup_server_ip == st_data_database_storage.network_interface[1].ip_address
+ assert database_service.backup_database()
+
+
+def test_tech_proj_a_software(uc7_network):
+ """Asserts that each host on the some_tech project A network has the expected services & applications which are operating as expected."""
+ network: Network = uc7_network
+ st_proj_a_pc_1: Computer = network.get_node_by_hostname("ST_PROJ-A-PRV-PC-1")
+ st_proj_a_pc_2: Computer = network.get_node_by_hostname("ST_PROJ-A-PRV-PC-2")
+ st_proj_a_pc_3: Computer = network.get_node_by_hostname("ST_PROJ-A-PRV-PC-3")
+
+ # ST Project A - PC 1
+
+ assert_web_browser(st_proj_a_pc_1)
+ assert_database_client(st_proj_a_pc_1)
+ assert_dns_client(st_proj_a_pc_1)
+ assert_ntp_client(st_proj_a_pc_1)
+
+ # ST Project A - PC 2
+
+ assert_web_browser(st_proj_a_pc_2)
+ assert_database_client(st_proj_a_pc_2)
+ assert_dns_client(st_proj_a_pc_2)
+ assert_ntp_client(st_proj_a_pc_2)
+
+ # ST Project A - PC 3
+
+ assert_web_browser(st_proj_a_pc_3)
+ assert_database_client(st_proj_a_pc_3)
+ assert_dns_client(st_proj_a_pc_3)
+ assert_ntp_client(st_proj_a_pc_3)
+
+
+def test_tech_proj_b_software(uc7_network):
+ """Asserts that each host on the some_tech project A network has the expected services & applications which are operating as expected."""
+ network: Network = uc7_network
+ st_proj_b_pc_1: Computer = network.get_node_by_hostname("ST_PROJ-B-PRV-PC-1")
+ st_proj_b_pc_2: Computer = network.get_node_by_hostname("ST_PROJ-B-PRV-PC-2")
+ st_proj_b_pc_3: Computer = network.get_node_by_hostname("ST_PROJ-B-PRV-PC-3")
+
+ # ST Project B - PC 1
+
+ assert_web_browser(st_proj_b_pc_1)
+ assert_database_client(st_proj_b_pc_1)
+ assert_dns_client(st_proj_b_pc_1)
+ assert_ntp_client(st_proj_b_pc_1)
+
+ # ST Project B - PC2
+
+ assert_web_browser(st_proj_b_pc_2)
+ assert_database_client(st_proj_b_pc_2)
+ assert_dns_client(st_proj_b_pc_2)
+ assert_ntp_client(st_proj_b_pc_2)
+
+ # ST Project B - PC3
+
+ assert_web_browser(st_proj_b_pc_3)
+ assert_database_client(st_proj_b_pc_3)
+ assert_dns_client(st_proj_b_pc_3)
+ assert_ntp_client(st_proj_b_pc_3)
+
+
+def test_tech_proj_c_software(uc7_network):
+ """Asserts that each host on the some_tech project A network has the expected services & applications which are operating as expected."""
+ network: Network = uc7_network
+ st_proj_c_pc_1: Computer = network.get_node_by_hostname("ST_PROJ-C-PRV-PC-1")
+ st_proj_c_pc_2: Computer = network.get_node_by_hostname("ST_PROJ-C-PRV-PC-2")
+ st_proj_c_pc_3: Computer = network.get_node_by_hostname("ST_PROJ-C-PRV-PC-3")
+
+ # ST Project C - PC 1
+
+ assert_web_browser(st_proj_c_pc_1)
+ assert_database_client(st_proj_c_pc_1)
+ assert_dns_client(st_proj_c_pc_1)
+ assert_ntp_client(st_proj_c_pc_1)
+
+ # ST Project C - PC2
+
+ assert_web_browser(st_proj_c_pc_2)
+ assert_database_client(st_proj_c_pc_2)
+ assert_dns_client(st_proj_c_pc_2)
+ assert_ntp_client(st_proj_c_pc_2)
+
+ # ST Project C - PC3
+
+ assert_web_browser(st_proj_c_pc_3)
+ assert_database_client(st_proj_c_pc_3)
+ assert_dns_client(st_proj_c_pc_3)
+ assert_ntp_client(st_proj_c_pc_3)
diff --git a/tests/e2e_integration_tests/threat_actor_profiles/__init__.py b/tests/e2e_integration_tests/threat_actor_profiles/__init__.py
new file mode 100644
index 00000000..836b79af
--- /dev/null
+++ b/tests/e2e_integration_tests/threat_actor_profiles/__init__.py
@@ -0,0 +1 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
diff --git a/tests/e2e_integration_tests/threat_actor_profiles/test_abstract_tap.py b/tests/e2e_integration_tests/threat_actor_profiles/test_abstract_tap.py
new file mode 100644
index 00000000..cecfa880
--- /dev/null
+++ b/tests/e2e_integration_tests/threat_actor_profiles/test_abstract_tap.py
@@ -0,0 +1,142 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+import pytest
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG
+from primaite.game.agent.scripted_agents.abstract_tap import (
+ AbstractTAP,
+ BaseKillChain,
+ KillChainOptions,
+ KillChainStageOptions,
+ KillChainStageProgress,
+)
+from primaite.game.agent.scripted_agents.TAP001 import MobileMalwareKillChain, TAP001
+from primaite.game.agent.scripted_agents.TAP003 import InsiderKillChain, TAP003
+from primaite.session.environment import PrimaiteGymEnv
+
+START_STEP = 1 # The starting step of the agent.
+FREQUENCY = 5 # The frequency of kill chain stage progression (E.g it's next attempt at "attacking").
+VARIANCE = 0 # The timestep variance between kill chain progression (E.g Next timestep = Frequency +/- variance)
+ATTACK_AGENT_INDEX = 32
+
+
+def uc7_tap001_env() -> PrimaiteGymEnv:
+ with open(_EXAMPLE_CFG / "uc7_config.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["start_step"] = START_STEP
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["frequency"] = FREQUENCY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["variance"] = VARIANCE
+
+ env = PrimaiteGymEnv(env_config=cfg)
+
+ return env
+
+
+def uc7_tap003_env(**kwargs) -> PrimaiteGymEnv:
+ """Setups the UC7 TAP003 Game with the following settings:
+
+ start_step = Start on Step 1
+ frequency = Attack Every 5 Steps
+
+ Each PyTest will define the rest of the TAP & Kill Chain settings via **Kwargs
+ """
+ with open(_EXAMPLE_CFG / "uc7_config_tap003.yaml", "r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["start_step"] = START_STEP
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["frequency"] = FREQUENCY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["variance"] = VARIANCE
+
+ if "repeat_kill_chain" in kwargs:
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["repeat_kill_chain"] = kwargs["repeat_kill_chain"]
+ if "repeat_kill_chain_stages" in kwargs:
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["repeat_kill_chain_stages"] = kwargs[
+ "repeat_kill_chain_stages"
+ ]
+ if "planning_probability" in kwargs:
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["PLANNING"]["probability"] = kwargs[
+ "planning_probability"
+ ]
+ if "custom_kill_chain" in kwargs:
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"] = kwargs["custom_kill_chain"]
+ if "starting_nodes" in kwargs:
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["starting_nodes"] = kwargs["starting_nodes"]
+ if "target_nodes" in kwargs:
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["target_nodes"] = kwargs["target_nodes"]
+
+ env = PrimaiteGymEnv(env_config=cfg)
+ return env
+
+
+def test_tap001_setup():
+ """Tests abstract TAP's following methods:
+ 1. _setup_kill_chain
+ 2. _setup_agent_kill_chain
+ 3. _setup_tap_applications
+ """
+ env = uc7_tap001_env() # Using TAP001 for PyTests.
+ tap: TAP001 = env.game.agents["attacker"]
+
+ # check the kill chain loaded correctly
+ assert tap.selected_kill_chain is MobileMalwareKillChain
+ assert tap.selected_kill_chain.FAILED == BaseKillChain.FAILED
+ assert tap.selected_kill_chain.SUCCEEDED == BaseKillChain.SUCCEEDED
+ assert tap.selected_kill_chain.NOT_STARTED == BaseKillChain.NOT_STARTED
+
+ if sn := tap.config.agent_settings.default_starting_node:
+ assert tap.starting_node == sn
+ else:
+ assert tap.starting_node in tap.config.agent_settings.starting_nodes
+
+ if ti := tap.config.agent_settings.default_target_ip:
+ assert tap.target_ip == ti
+ else:
+ assert tap.target_ip in tap.config.agent_settings.target_ips
+
+ assert tap.next_execution_timestep == tap.config.agent_settings.start_step
+
+ assert tap.current_host == tap.starting_node
+
+
+def test_abstract_tap_select_start_node():
+ """Tests that Abstract TAP's _select_start_node"""
+ env = uc7_tap003_env(repeat_kill_chain=True, repeat_kill_chain_stages=True) # Using TAP003 for PyTests.
+ tap: TAP003 = env.game.agents["attacker"]
+
+ assert tap.starting_node == "ST_PROJ-A-PRV-PC-1"
+ assert tap.current_host == tap.starting_node
+
+
+def test_outcome_handler():
+ """Tests Abstract Tap's outcome handler concludes the episode when the kill chain fails."""
+ env = uc7_tap003_env(repeat_kill_chain=False, repeat_kill_chain_stages=False) # Using TAP003 for PyTests.
+ tap: TAP003 = env.game.agents["attacker"]
+ tap.current_kill_chain_stage = BaseKillChain.FAILED
+ # 6 Iterations as the attacker frequency is set to 5. Therefore, after 6 timesteps we expect the agent to realise it's failed the kill chain.
+ for _ in range(6):
+ env.step(0)
+ assert tap.actions_concluded == True
+
+
+def test_abstract_tap_kill_chain_repeat():
+ """Tests that the kill chain repeats from the beginning upon failure."""
+ env = uc7_tap003_env(repeat_kill_chain=True, repeat_kill_chain_stages=False) # Using TAP003 for PyTests.
+ tap: TAP003 = env.game.agents["attacker"]
+ for _ in range(15):
+ env.step(0) # Steps directly to the Access Stage
+ assert tap.current_kill_chain_stage == InsiderKillChain.ACCESS
+ tap.current_kill_chain_stage = BaseKillChain.FAILED
+ for _ in range(5):
+ env.step(0) # Steps to manipulation - but failure causes the kill chain to restart.
+ assert tap.actions_concluded == False
+ assert tap.current_kill_chain_stage == InsiderKillChain.RECONNAISSANCE
+
+ """Tests that kill chain stages repeat when expected"""
+ env = uc7_tap003_env(
+ repeat_kill_chain=True, repeat_kill_chain_stages=True, planning_probability=0
+ ) # Using TAP003 for PyTests.
+ tap: TAP003 = env.game.agents["attacker"]
+ tap.current_kill_chain_stage = InsiderKillChain.PLANNING
+ for _ in range(15):
+ env.step(0) # Attempts to progress past the PLANNING stage multiple times.
+ assert tap.actions_concluded == False
+ assert tap.current_kill_chain_stage == InsiderKillChain.PLANNING
diff --git a/tests/e2e_integration_tests/threat_actor_profiles/test_kill_chain_methods.py b/tests/e2e_integration_tests/threat_actor_profiles/test_kill_chain_methods.py
new file mode 100644
index 00000000..e9a40e45
--- /dev/null
+++ b/tests/e2e_integration_tests/threat_actor_profiles/test_kill_chain_methods.py
@@ -0,0 +1,72 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+import pytest
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG
+from primaite.game.agent.scripted_agents.abstract_tap import (
+ AbstractTAP,
+ BaseKillChain,
+ KillChainOptions,
+ KillChainStageOptions,
+ KillChainStageProgress,
+)
+from primaite.game.agent.scripted_agents.TAP001 import MobileMalwareKillChain, TAP001
+from primaite.game.agent.scripted_agents.TAP003 import InsiderKillChain, TAP003
+from primaite.session.environment import PrimaiteGymEnv
+
+# Defining constants.
+
+START_STEP = 1 # The starting step of the agent.
+FREQUENCY = 2 # The frequency of kill chain stage progression (E.g it's next attempt at "attacking").
+VARIANCE = 0 # The timestep variance between kill chain progression (E.g Next timestep = Frequency +/- variance)
+ATTACK_AGENT_INDEX = 32
+
+
+def uc7_tap003_env() -> PrimaiteGymEnv:
+ """Setups the UC7 TAP003 Game with a 1 timestep start_step, frequency of 2 and probabilities set to 1 as well"""
+ with open(_EXAMPLE_CFG / "uc7_config_tap003.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ cfg["io_settings"]["save_sys_logs"] = False
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["start_step"] = START_STEP
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["frequency"] = FREQUENCY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["variance"] = VARIANCE
+ env = PrimaiteGymEnv(env_config=cfg)
+ return env
+
+
+def uc7_tap001_env() -> PrimaiteGymEnv:
+ """Setup the UC7 TAP001 Game with the start_step & frequency set to 1 & 2 respectively. Probabilities are set to 1"""
+ with open(_EXAMPLE_CFG / "uc7_config.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ cfg["io_settings"]["save_sys_logs"] = False
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["start_step"] = START_STEP
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["frequency"] = FREQUENCY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["variance"] = VARIANCE
+ env = PrimaiteGymEnv(env_config=cfg)
+ return env
+
+
+def test_tap003_insider_kill_chain_load():
+ """Tests that tap003's insider kill chain is successfully loaded into the tap.selected_kill_chain attribute."""
+ env = uc7_tap003_env() # Using TAP003 for PyTests.
+ tap: TAP003 = env.game.agents["attacker"]
+ # Asserting that the Base Kill Chain intEnum stages are loaded
+ kill_chain_enums = [enums for enums in tap.selected_kill_chain]
+ assert BaseKillChain.FAILED in kill_chain_enums
+ assert BaseKillChain.SUCCEEDED in kill_chain_enums
+ assert BaseKillChain.NOT_STARTED in kill_chain_enums
+ # Asserting that the Insider Kill Chain intenum stages are loaded.
+ assert len(InsiderKillChain.__members__) == len(tap.selected_kill_chain.__members__)
+
+
+def test_tap001_mobile_malware_kill_chain_load():
+ """Tests that tap001's mobile malware is successfully loaded into the tap.selected_kill_chain attribute."""
+ env = uc7_tap001_env() # Using TAP003 for PyTests.
+ tap: TAP001 = env.game.agents["attacker"]
+ # Asserting that the Base Kill Chain intEnum stages are loaded.
+ kill_chain_enums = [enums for enums in tap.selected_kill_chain]
+ assert BaseKillChain.FAILED in kill_chain_enums
+ assert BaseKillChain.SUCCEEDED in kill_chain_enums
+ assert BaseKillChain.NOT_STARTED in kill_chain_enums
+ # Asserting that the Insider Kill Chain intEnum stages are loaded.
+ assert len(MobileMalwareKillChain.__members__) == len(tap.selected_kill_chain.__members__)
diff --git a/tests/e2e_integration_tests/threat_actor_profiles/test_tap001_kill_chain_repeat.py b/tests/e2e_integration_tests/threat_actor_profiles/test_tap001_kill_chain_repeat.py
new file mode 100644
index 00000000..94832ed0
--- /dev/null
+++ b/tests/e2e_integration_tests/threat_actor_profiles/test_tap001_kill_chain_repeat.py
@@ -0,0 +1,116 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+import pytest
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG
+from primaite.game.agent.scripted_agents.abstract_tap import (
+ AbstractTAP,
+ BaseKillChain,
+ KillChainOptions,
+ KillChainStageOptions,
+ KillChainStageProgress,
+)
+from primaite.game.agent.scripted_agents.TAP001 import MobileMalwareKillChain, TAP001
+from primaite.game.agent.scripted_agents.TAP003 import InsiderKillChain, TAP003
+from primaite.session.environment import PrimaiteGymEnv
+
+# Defining constants.
+
+START_STEP = 1 # The starting step of the agent.
+FREQUENCY = 2 # The frequency of kill chain stage progression (E.g it's next attempt at "attacking").
+VARIANCE = 0 # The timestep variance between kill chain progression (E.g Next timestep = Frequency +/- variance)
+ATTACK_AGENT_INDEX = 32
+
+
+def uc7_tap001_env(**kwargs) -> PrimaiteGymEnv:
+ """Setups the UC7 tap001 game with a 1 timestep start_step, frequency of 2 and probabilities set to 1 as well"""
+ with open(_EXAMPLE_CFG / "uc7_config.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ cfg["io_settings"]["save_sys_logs"] = False
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["start_step"] = START_STEP
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["frequency"] = FREQUENCY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["variance"] = VARIANCE
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["repeat_kill_chain"] = kwargs["repeat_kill_chain"]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["repeat_kill_chain_stages"] = kwargs[
+ "repeat_kill_chain_stages"
+ ]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["PROPAGATE"]["probability"] = kwargs[
+ "propagate_probability"
+ ]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["PAYLOAD"]["probability"] = kwargs[
+ "payload_probability"
+ ]
+ env = PrimaiteGymEnv(env_config=cfg)
+ return env
+
+
+def test_tap001_repeating_kill_chain():
+ """Tests to check that tap001 repeats it's kill chain after success"""
+ env = uc7_tap001_env(
+ repeat_kill_chain=True,
+ repeat_kill_chain_stages=True,
+ payload_probability=1,
+ propagate_probability=1,
+ )
+ tap001: TAP001 = env.game.agents["attacker"]
+ # Looping for 50 timesteps - As the agent is set to execute an action every 2 timesteps
+ # This is the equivalent of the agent taking 25 actions.
+ for _ in range(50): # This for loop should never actually fully complete.
+ if tap001.current_kill_chain_stage == BaseKillChain.SUCCEEDED:
+ break
+ env.step(0)
+
+ # Catches if the above for loop fully completes.
+ # This test uses a probability of 1 for all stages and a frequency of 2 timesteps
+ # Thus the for loop above should never complete it's full 50 iterations.
+ # If this occurs then there is an error somewhere in either:
+ # 1. The TAP Logic
+ # 2. Failing Agent Actions are causing the TAP to fail. (See tap_return_handler).
+ if tap001.current_kill_chain_stage != BaseKillChain.SUCCEEDED:
+ pytest.fail("Attacker Never Reached SUCCEEDED - Please evaluate current TAP Logic.")
+
+ # Stepping four timesteps (2 TAP001 steps) for the succeeded logic to kick in:
+ env.step(0)
+ env.step(0)
+ env.step(0)
+ env.step(0)
+
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.DOWNLOAD.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.INSTALL.name
+
+
+def test_tap001_repeating_kill_chain_stages():
+ """Tests to check that tap001 repeats it's kill chain after failing a kill chain stage."""
+ env = uc7_tap001_env(
+ repeat_kill_chain=True,
+ repeat_kill_chain_stages=True,
+ payload_probability=1,
+ propagate_probability=0,
+ # Probability 0 = Will never be able to perform the access stage and progress to Manipulation.
+ )
+ tap001: TAP001 = env.game.agents["attacker"]
+ env.step(0) # Skipping not started
+ env.step(0) # Successful on the first stage
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.DOWNLOAD.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.INSTALL.name
+ env.step(0) # Successful progression to the second stage
+ env.step(0)
+ env.step(0)
+ env.step(0)
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.INSTALL.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.ACTIVATE.name
+ env.step(0) # Successful progression to the third stage
+ env.step(0)
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.ACTIVATE.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.PROPAGATE.name
+ env.step(0) # Successful progression to the Fourth stage
+ env.step(0)
+ env.step(0)
+ env.step(0)
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.PROPAGATE.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.COMMAND_AND_CONTROL.name
+ env.step(0) # FAILURE -- Unsuccessful progression to the Fourth stage
+ env.step(0)
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.PROPAGATE.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.COMMAND_AND_CONTROL.name
+ assert tap001.current_stage_progress == KillChainStageProgress.PENDING
diff --git a/tests/e2e_integration_tests/threat_actor_profiles/test_tap001_kill_chain_stages.py b/tests/e2e_integration_tests/threat_actor_profiles/test_tap001_kill_chain_stages.py
new file mode 100644
index 00000000..851910d1
--- /dev/null
+++ b/tests/e2e_integration_tests/threat_actor_profiles/test_tap001_kill_chain_stages.py
@@ -0,0 +1,215 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+import pytest
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG
+from primaite.game.agent.scripted_agents.abstract_tap import (
+ AbstractTAP,
+ BaseKillChain,
+ KillChainOptions,
+ KillChainStageOptions,
+ KillChainStageProgress,
+)
+from primaite.game.agent.scripted_agents.TAP001 import MobileMalwareKillChain, TAP001
+from primaite.game.agent.scripted_agents.TAP003 import InsiderKillChain, TAP003
+from primaite.session.environment import PrimaiteGymEnv
+from primaite.simulator.file_system.file_system_item_abc import FileSystemItemHealthStatus
+from primaite.simulator.system.applications.red_applications.c2.c2_beacon import C2Beacon
+from primaite.simulator.system.services.database.database_service import DatabaseService
+
+# Defining constants.
+
+START_STEP = 1 # The starting step of the agent.
+FREQUENCY = 2 # The frequency of kill chain stage progression (E.g it's next attempt at "attacking").
+VARIANCE = 0 # The timestep variance between kill chain progression (E.g Next timestep = Frequency +/- variance)
+REPEAT_KILL_CHAIN = False # Should the TAP repeat the kill chain after success/failure?
+REPEAT_KILL_CHAIN_STAGES = False # Should the TAP restart from it's previous stage on failure?
+KILL_CHAIN_PROBABILITY = 1 # Blank probability for agent 'success'
+DATA_EXFIL = True # Data exfiltration on the payload stage is enabled.
+ATTACK_AGENT_INDEX = 32
+
+
+def uc7_tap001_env() -> PrimaiteGymEnv:
+ """Setups the UC7 tap001 Game with the start_step & frequency set to 1 with probabilities set to 1 as well"""
+ with open(_EXAMPLE_CFG / "uc7_config.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ cfg["io_settings"]["save_sys_logs"] = False
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["start_step"] = START_STEP
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["frequency"] = FREQUENCY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["variance"] = VARIANCE
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["repeat_kill_chain"] = REPEAT_KILL_CHAIN_STAGES
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["repeat_kill_chain_stages"] = REPEAT_KILL_CHAIN_STAGES
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["PAYLOAD"][
+ "probability"
+ ] = KILL_CHAIN_PROBABILITY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["PROPAGATE"][
+ "probability"
+ ] = KILL_CHAIN_PROBABILITY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["PAYLOAD"]["exfiltrate"] = DATA_EXFIL
+ env = PrimaiteGymEnv(env_config=cfg)
+ return env
+
+
+def test_tap001_kill_chain_stage_DOWNLOAD():
+ """Tests that the DOWNLOAD Mobile Malware step works as expected and the expected impacts are made in the simulation."""
+
+ # Instantiating the relevant simulation/game objects:
+ env = uc7_tap001_env()
+ tap001: TAP001 = env.game.agents["attacker"]
+ starting_host = env.game.simulation.network.get_node_by_hostname(tap001.starting_node)
+ assert tap001.current_kill_chain_stage == BaseKillChain.NOT_STARTED
+
+ # Frequency is set to two steps so we need to step through the environment a couple of times
+ # In order for TAP001 to move onto the next kill chain stage.
+ env.step(0)
+ env.step(0)
+
+ env.step(0)
+ env.step(0)
+
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.DOWNLOAD.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.INSTALL.name
+ assert tap001.current_stage_progress == KillChainStageProgress.IN_PROGRESS
+
+ # Creating the "downloads" folder
+ env.step(0)
+ env.step(0)
+
+ assert starting_host.software_manager.file_system.get_folder(folder_name="downloads")
+ assert starting_host.software_manager.file_system.get_file(folder_name="downloads", file_name="malware_dropper.ps1")
+
+ # Testing that the num_file_increase works
+
+ assert starting_host.file_system.num_file_creations == 1
+
+
+def test_tap001_kill_chain_stage_INSTALL():
+ """Tests that the INSTALL Mobile Malware step works as expected and the expected impacts are made in the simulation."""
+ env = uc7_tap001_env()
+ tap001: TAP001 = env.game.agents["attacker"]
+ # The tap001's Starting Client:
+ starting_host = env.game.simulation.network.get_node_by_hostname(tap001.starting_node)
+
+ # Skipping directly to the activate stage
+ for _ in range(6):
+ env.step(0)
+
+ # Testing that tap001 Enters into the expected kill chain stages
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.INSTALL.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.ACTIVATE.name
+
+ env.step(0) # Allows the agent action to resolve.
+ env.step(0)
+
+ ransomware_dropper_file = starting_host.software_manager.file_system.get_file(
+ folder_name="downloads", file_name="malware_dropper.ps1"
+ )
+ assert ransomware_dropper_file.num_access == 1
+
+
+def test_tap001_kill_chain_stage_ACTIVATE():
+ """Tests that the ACTIVATE Mobile Malware step works as expected and the current impacts are made in the simulation."""
+ env = uc7_tap001_env()
+ tap001: TAP001 = env.game.agents["attacker"]
+ # The tap001's Starting Client:
+ starting_host = env.game.simulation.network.get_node_by_hostname(tap001.starting_node)
+
+ # Skipping directly to the activate stage
+ for _ in range(8):
+ env.step(0)
+
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.ACTIVATE.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.PROPAGATE.name
+
+ # Installing ransomware-script Application
+ env.step(0)
+ env.step(0)
+
+ # Installing NMAP Application
+ env.step(0)
+ env.step(0)
+
+ # These asserts will fail if the applications are not present in the software_manager
+ assert starting_host.software_manager.software["ransomware-script"]
+ assert starting_host.software_manager.software["nmap"]
+
+
+def test_tap001_kill_chain_stage_PROPAGATE():
+ """Tests that the ACTIVATE Mobile Malware step works as expected and the current impacts are made in the simulation."""
+ env = uc7_tap001_env()
+ tap001: TAP001 = env.game.agents["attacker"]
+
+ for _ in range(12):
+ env.step(0)
+
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.PROPAGATE.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.COMMAND_AND_CONTROL.name
+
+ # Specific Stage by Stage Propagate Testing is done in test_tap001_propagate.
+ fail_safe_var = 0
+ while tap001.current_kill_chain_stage.name == MobileMalwareKillChain.PROPAGATE:
+ env.step(0)
+ assert tap001.current_stage_progress == KillChainStageProgress.IN_PROGRESS
+ fail_safe_var += 1
+ if fail_safe_var == 100:
+ pytest.fail("Fail Safe Variable was hit! -- Propagate step is running indefinitely")
+
+
+def test_tap001_kill_chain_stage_COMMAND_AND_CONTROL():
+ """Tests that the Command And Control Mobile Malware step works as expected and the current impacts are made in the simulation."""
+ env = uc7_tap001_env()
+ tap001: TAP001 = env.game.agents["attacker"]
+ fail_safe_var = 0
+
+ for _ in range(28):
+ env.step(0)
+
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.COMMAND_AND_CONTROL.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.PAYLOAD.name
+
+ while tap001.current_kill_chain_stage == MobileMalwareKillChain.COMMAND_AND_CONTROL:
+ env.step(0)
+ fail_safe_var += 1
+ env.game.simulation.network.airspace.show()
+ if fail_safe_var == 100:
+ pytest.fail(reason="Fail Safe Variable was hit! -- Propagate step is running indefinitely")
+
+ starting_host = env.game.simulation.network.get_node_by_hostname(tap001.starting_node)
+
+ c2_beacon: C2Beacon = starting_host.software_manager.software["c2-beacon"]
+
+ assert c2_beacon.c2_connection_active is True
+
+
+def test_tap001_kill_chain_stage_PAYLOAD():
+ """Tests that the PAYLOAD Mobile Malware step works as expected and the current impacts are made in the simulation."""
+
+ env = uc7_tap001_env()
+ tap001: TAP001 = env.game.agents["attacker"]
+
+ # The tap001's Target Database
+ target_host = env.game.simulation.network.get_node_by_hostname("ST_DATA-PRV-SRV-DB")
+ db_server_service: DatabaseService = target_host.software_manager.software.get("database-service")
+
+ # Green agent status requests are tested within the ransomware application tests.
+ # See test_ransomware_disrupts_green_agent_connection for further reference.
+ assert db_server_service.db_file.health_status is FileSystemItemHealthStatus.GOOD
+
+ fail_safe_var = 0
+ while tap001.current_kill_chain_stage != MobileMalwareKillChain.PAYLOAD:
+ env.step(0)
+ fail_safe_var += 1
+ if fail_safe_var == 100:
+ pytest.fail(reason="Fail Safe Variable was hit! -- a step is running indefinitely")
+
+ for _ in range(12):
+ env.step(0)
+
+ assert db_server_service.db_file.health_status is FileSystemItemHealthStatus.CORRUPT
+
+ # Asserting we've managed to the database.db file onto the starting node & server
+ starting_host = env.game.simulation.network.get_node_by_hostname(tap001.starting_node)
+ c2_host = env.game.simulation.network.get_node_by_hostname(tap001.c2_settings["c2_server"])
+
+ assert starting_host.file_system.access_file(folder_name="exfiltration_folder", file_name="database.db")
+ assert c2_host.file_system.access_file(folder_name="exfiltration_folder", file_name="database.db")
diff --git a/tests/e2e_integration_tests/threat_actor_profiles/test_tap001_propagate_stage.py b/tests/e2e_integration_tests/threat_actor_profiles/test_tap001_propagate_stage.py
new file mode 100644
index 00000000..24fbaa23
--- /dev/null
+++ b/tests/e2e_integration_tests/threat_actor_profiles/test_tap001_propagate_stage.py
@@ -0,0 +1,141 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+import pytest
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG
+from primaite.game.agent.scripted_agents.abstract_tap import (
+ AbstractTAP,
+ BaseKillChain,
+ KillChainOptions,
+ KillChainStageOptions,
+ KillChainStageProgress,
+)
+from primaite.game.agent.scripted_agents.TAP001 import MobileMalwareKillChain, TAP001
+from primaite.game.agent.scripted_agents.TAP003 import InsiderKillChain, TAP003
+from primaite.session.environment import PrimaiteGymEnv
+from primaite.simulator.file_system.file_system_item_abc import FileSystemItemHealthStatus
+from primaite.simulator.system.applications.red_applications.c2.c2_beacon import C2Beacon
+from primaite.simulator.system.services.database.database_service import DatabaseService
+
+# Defining generic tap constants.
+
+START_STEP = 1 # The starting step of the agent.
+FREQUENCY = 2 # The frequency of kill chain stage progression (E.g it's next attempt at "attacking").
+VARIANCE = 0 # The timestep variance between kill chain progression (E.g Next timestep = Frequency +/- variance)
+REPEAT_KILL_CHAIN = False # Should the TAP repeat the kill chain after success/failure?
+REPEAT_KILL_CHAIN_STAGES = False # Should the TAP restart from it's previous stage on failure?
+KILL_CHAIN_PROBABILITY = 1 # Blank probability for agent 'success's.
+ATTACK_AGENT_INDEX = 32
+
+
+def uc7_tap001_env(**kwargs) -> PrimaiteGymEnv:
+ """Setups the UC7 tap001 Game with the start_step & frequency set to 1 with probabilities set to 1 as well"""
+ with open(_EXAMPLE_CFG / "uc7_config.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ cfg["io_settings"]["save_sys_logs"] = False
+ agent_cfg = cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]
+ agent_cfg["start_step"] = START_STEP
+ agent_cfg["frequency"] = FREQUENCY
+ agent_cfg["variance"] = VARIANCE
+ agent_cfg["repeat_kill_chain"] = REPEAT_KILL_CHAIN_STAGES
+ agent_cfg["repeat_kill_chain_stages"] = REPEAT_KILL_CHAIN_STAGES
+ agent_cfg["kill_chain"]["PAYLOAD"]["probability"] = KILL_CHAIN_PROBABILITY
+ agent_cfg["kill_chain"]["PROPAGATE"]["probability"] = KILL_CHAIN_PROBABILITY
+ agent_cfg["kill_chain"]["PROPAGATE"]["scan_attempts"] = kwargs["scan_attempts"]
+ agent_cfg["kill_chain"]["PAYLOAD"]["payload"] = kwargs["payload"]
+ agent_cfg["kill_chain"]["PROPAGATE"]["network_addresses"] = kwargs["network_addresses"]
+ if "repeat_scan" in kwargs:
+ agent_cfg["kill_chain"]["PROPAGATE"]["repeat_scan"] = kwargs["repeat_scan"]
+ if "starting_nodes" in kwargs:
+ agent_cfg["starting_nodes"] = kwargs["starting_nodes"]
+ agent_cfg["default_starting_node"] = kwargs["starting_nodes"][0]
+ if "target_ips" in kwargs:
+ agent_cfg["target_ips"] = kwargs["target_ips"]
+ env = PrimaiteGymEnv(env_config=cfg)
+ return env
+
+
+def test_tap001_kill_chain_stage_PROPAGATE_default():
+ """Tests that the PROPAGATE Mobile Malware step works as expected and the current impacts are made in the simulation."""
+ payload = "ENCRYPT"
+ scan_attempts = 10
+ network_addresses = [
+ "192.168.230.0/29",
+ "192.168.10.0/26",
+ "192.168.20.0/30",
+ "192.168.240.0/29",
+ "192.168.220.0/29",
+ ]
+ env = uc7_tap001_env(payload=payload, scan_attempts=scan_attempts, network_addresses=network_addresses)
+ tap001: TAP001 = env.game.agents["attacker"]
+
+ # First Kill Chain Stages
+ for _ in range(12):
+ env.step(0)
+
+ # Assert that we're about to enter into the propagate stage.
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.PROPAGATE.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.COMMAND_AND_CONTROL.name
+
+ # Move into the propagate stage.
+ while tap001.current_kill_chain_stage == MobileMalwareKillChain.PROPAGATE:
+ env.step(0)
+
+ # Assert that we've successfully moved into the command and control stage.
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.COMMAND_AND_CONTROL.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.PAYLOAD.name
+
+
+def test_tap001_kill_chain_stage_PROPAGATE_different_starting_node():
+ """Tests that the PROPAGATE Mobile Malware step works as expected and the current impacts are made in the simulation from a different starting node."""
+ payload = "ENCRYPT"
+ scan_attempts = 10
+ network_addresses = [
+ "192.168.230.0/29",
+ "192.168.10.0/26",
+ "192.168.20.0/30",
+ "192.168.240.0/29",
+ "192.168.220.0/29",
+ ]
+ starting_nodes = ["ST_PROJ-B-PRV-PC-2", "ST_PROJ-C-PRV-PC-3"]
+
+ env = uc7_tap001_env(
+ payload=payload, scan_attempts=scan_attempts, network_addresses=network_addresses, starting_nodes=starting_nodes
+ )
+
+ tap001: TAP001 = env.game.agents["attacker"]
+
+ for _ in range(12):
+ env.step(0)
+
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.PROPAGATE.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.COMMAND_AND_CONTROL.name
+
+ # Specific Stage by Stage Propagate Testing is done in test_tap001_propagate.
+ while tap001.current_kill_chain_stage == MobileMalwareKillChain.PROPAGATE:
+ env.step(0)
+
+ assert tap001.current_kill_chain_stage.name == MobileMalwareKillChain.COMMAND_AND_CONTROL.name
+ assert tap001.next_kill_chain_stage.name == MobileMalwareKillChain.PAYLOAD.name
+
+
+def test_tap001_kill_chain_stage_PROPAGATE_repeat_scan():
+ """Tests that the PROPAGATE Mobile Malware step will fail when the target is unable to be located."""
+ payload = "ENCRYPT"
+ scan_attempts = 20
+ repeat_scan = True
+ network_addresses = ["192.168.1.0/24", "192.168.0.0/28", "100.64.0.0/30", "172.168.0.0/28"]
+ env = uc7_tap001_env(
+ payload=payload, scan_attempts=scan_attempts, network_addresses=network_addresses, repeat_scan=repeat_scan
+ )
+ for _ in range(12):
+ env.step(0)
+
+ tap001: TAP001 = env.game.agents["attacker"]
+
+ while tap001.current_kill_chain_stage == MobileMalwareKillChain.PROPAGATE:
+ env.step(0)
+
+ # As the given network_address does not contain the target, we should fail because the maximum amount of scan attempts has been reached
+ assert tap001.scans_complete == scan_attempts
+ assert tap001.current_kill_chain_stage == MobileMalwareKillChain.FAILED
diff --git a/tests/e2e_integration_tests/threat_actor_profiles/test_tap003_kill_chain_repeat.py b/tests/e2e_integration_tests/threat_actor_profiles/test_tap003_kill_chain_repeat.py
new file mode 100644
index 00000000..7df846b1
--- /dev/null
+++ b/tests/e2e_integration_tests/threat_actor_profiles/test_tap003_kill_chain_repeat.py
@@ -0,0 +1,108 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+import pytest
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG
+from primaite.game.agent.scripted_agents.abstract_tap import (
+ AbstractTAP,
+ BaseKillChain,
+ KillChainOptions,
+ KillChainStageOptions,
+ KillChainStageProgress,
+)
+from primaite.game.agent.scripted_agents.TAP001 import MobileMalwareKillChain, TAP001
+from primaite.game.agent.scripted_agents.TAP003 import InsiderKillChain, TAP003
+from primaite.session.environment import PrimaiteGymEnv
+
+# Defining constants.
+
+START_STEP = 1 # The starting step of the agent.
+FREQUENCY = 2 # The frequency of kill chain stage progression (E.g it's next attempt at "attacking").
+VARIANCE = 0 # The timestep variance between kill chain progression (E.g Next timestep = Frequency +/- variance)
+ATTACK_AGENT_INDEX = 32
+
+
+def uc7_tap003_env(**kwargs) -> PrimaiteGymEnv:
+ """Setups the UC7 TAP003 Game with a 1 timestep start_step, frequency of 2 and probabilities set to 1 as well"""
+ with open(_EXAMPLE_CFG / "uc7_config_tap003.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ cfg["io_settings"]["save_sys_logs"] = False
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["start_step"] = START_STEP
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["frequency"] = FREQUENCY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["variance"] = VARIANCE
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["repeat_kill_chain"] = kwargs["repeat_kill_chain"]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["repeat_kill_chain_stages"] = kwargs[
+ "repeat_kill_chain_stages"
+ ]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["MANIPULATION"]["probability"] = kwargs[
+ "manipulation_probability"
+ ]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["ACCESS"]["probability"] = kwargs[
+ "access_probability"
+ ]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["PLANNING"]["probability"] = kwargs[
+ "planning_probability"
+ ]
+ env = PrimaiteGymEnv(env_config=cfg)
+ return env
+
+
+def test_tap003_repeating_kill_chain():
+ """Tests to check that TAP003 repeats it's kill chain after success"""
+ env = uc7_tap003_env(
+ repeat_kill_chain=True,
+ repeat_kill_chain_stages=True,
+ manipulation_probability=1,
+ access_probability=1,
+ planning_probability=1,
+ )
+ tap003: TAP003 = env.game.agents["attacker"]
+ for _ in range(40): # This for loop should never actually fully complete.
+ if tap003.current_kill_chain_stage == BaseKillChain.SUCCEEDED:
+ break
+ env.step(0)
+
+ # Catches if the above for loop fully completes.
+ # This test uses a probability of 1 for all stages and a variance of 2 timesteps
+ # Thus the for loop above should never fail.
+ # If this occurs then there is an error somewhere in either:
+ # 1. The TAP Logic
+ # 2. Failing Agent Actions are causing the TAP to fail. (See tap_return_handler).
+ if tap003.current_kill_chain_stage != BaseKillChain.SUCCEEDED:
+ pytest.fail("Attacker Never Reached SUCCEEDED - Please evaluate current TAP Logic.")
+
+ # Stepping twice for the succeeded logic to kick in:
+ env.step(0)
+ env.step(0)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.RECONNAISSANCE.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.PLANNING.name
+
+
+def test_tap003_repeating_kill_chain_stages():
+ """Tests to check that TAP003 repeats it's kill chain after failing a kill chain stage."""
+ env = uc7_tap003_env(
+ repeat_kill_chain=True,
+ repeat_kill_chain_stages=True,
+ manipulation_probability=1,
+ # access_probability 0 = Will never be able to perform the access stage and progress to Manipulation.
+ access_probability=0,
+ planning_probability=1,
+ )
+ tap003: TAP003 = env.game.agents["attacker"]
+ env.step(0) # Skipping not started
+ env.step(0) # Successful on the first stage
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.RECONNAISSANCE.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.PLANNING.name
+ env.step(0) # Successful progression to the second stage
+ env.step(0)
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.PLANNING.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.ACCESS.name
+ env.step(0) # Successfully moved onto access.
+ env.step(0)
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.ACCESS.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.MANIPULATION.name
+ env.step(0) # Failure to progress past the third stage.
+ env.step(0)
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.ACCESS.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.MANIPULATION.name
diff --git a/tests/e2e_integration_tests/threat_actor_profiles/test_tap003_kill_chain_stages.py b/tests/e2e_integration_tests/threat_actor_profiles/test_tap003_kill_chain_stages.py
new file mode 100644
index 00000000..bea4ed26
--- /dev/null
+++ b/tests/e2e_integration_tests/threat_actor_profiles/test_tap003_kill_chain_stages.py
@@ -0,0 +1,218 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+import pytest
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG
+from primaite.game.agent.scripted_agents.abstract_tap import (
+ AbstractTAP,
+ BaseKillChain,
+ KillChainOptions,
+ KillChainStageOptions,
+ KillChainStageProgress,
+)
+from primaite.game.agent.scripted_agents.TAP003 import InsiderKillChain, TAP003
+from primaite.session.environment import PrimaiteGymEnv
+from primaite.simulator.network.hardware.nodes.network.firewall import Firewall
+from primaite.simulator.network.hardware.nodes.network.router import ACLAction, Router
+
+# Defining constants.
+
+START_STEP = 1 # The starting step of the agent.
+FREQUENCY = 2 # The frequency of kill chain stage progression (E.g it's next attempt at "attacking").
+VARIANCE = 0 # The timestep variance between kill chain progression (E.g Next timestep = Frequency +/- variance)
+REPEAT_KILL_CHAIN = False # Should the TAP repeat the kill chain after success/failure?
+REPEAT_KILL_CHAIN_STAGES = False # Should the TAP restart from it's previous stage on failure?
+KILL_CHAIN_PROBABILITY = 1 # Blank probability for agent 'success'
+ATTACK_AGENT_INDEX = 32
+
+
+def uc7_tap003_env() -> PrimaiteGymEnv:
+ """Setups the UC7 TAP003 Game with a 1 timestep start_step, frequency of 2 and probabilities set to 1 as well"""
+ with open(_EXAMPLE_CFG / "uc7_config_tap003.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ cfg["io_settings"]["save_sys_logs"] = False
+ cfg["io_settings"]["save_agent_logs"] = True
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["start_step"] = START_STEP
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["frequency"] = FREQUENCY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["variance"] = VARIANCE
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["repeat_kill_chain"] = REPEAT_KILL_CHAIN_STAGES
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["repeat_kill_chain_stages"] = REPEAT_KILL_CHAIN_STAGES
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["MANIPULATION"][
+ "probability"
+ ] = KILL_CHAIN_PROBABILITY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["ACCESS"][
+ "probability"
+ ] = KILL_CHAIN_PROBABILITY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["PLANNING"][
+ "probability"
+ ] = KILL_CHAIN_PROBABILITY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["EXPLOIT"][
+ "probability"
+ ] = KILL_CHAIN_PROBABILITY
+ env = PrimaiteGymEnv(env_config=cfg)
+ return env
+
+
+def environment_step(i: int, env: PrimaiteGymEnv) -> PrimaiteGymEnv:
+ """Carries out i (given parameter) steps in the environment.."""
+ for x in range(i):
+ env.step(0)
+ return env
+
+
+def test_tap003_kill_chain_stage_reconnaissance():
+ """Tests the successful/failed handlers in the reconnaissance stage in the Insider Kill Chain InsiderKillChain"""
+
+ # Instantiating the relevant simulation/game objects:
+ env = uc7_tap003_env()
+ tap003: TAP003 = env.game.agents["attacker"]
+ assert tap003.current_kill_chain_stage == BaseKillChain.NOT_STARTED
+
+ # Frequency is set to two steps
+ env = environment_step(i=2, env=env)
+
+ # Testing that TAP003 Enters into the expected kill chain stages
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.RECONNAISSANCE.name
+
+
+def test_tap003_kill_chain_stage_planning():
+ """Tests the successful/failed handlers in the planning stage in the Insider Kill Chain (TAP003)"""
+ env = uc7_tap003_env()
+ tap003: TAP003 = env.game.agents["attacker"]
+
+ assert tap003.current_kill_chain_stage == BaseKillChain.NOT_STARTED
+
+ env = environment_step(i=2, env=env)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.RECONNAISSANCE.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.PLANNING.name
+
+ env = environment_step(i=2, env=env)
+
+ # Testing that TAP003 Enters into the expected kill chain stages
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.PLANNING.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.ACCESS.name
+
+ env = environment_step(i=2, env=env)
+
+ # Testing that the stage successful - TAP003 has loaded it's starting network knowledge into it's network knowledge.
+
+ # At this point TAP003 will parse it's starting network knowledge config into it's a private attribute (`network_knowledge`)
+ assert (
+ tap003.network_knowledge["credentials"]
+ == tap003.config.agent_settings.kill_chain.PLANNING.starting_network_knowledge["credentials"]
+ )
+
+
+def test_tap003_kill_chain_stage_access():
+ """Tests the successful/failed handlers in the access stage in the InsiderKillChain"""
+ env = uc7_tap003_env()
+ tap003: TAP003 = env.game.agents["attacker"]
+
+ assert tap003.current_kill_chain_stage == BaseKillChain.NOT_STARTED
+
+ env = environment_step(i=2, env=env)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.RECONNAISSANCE.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.PLANNING.name
+
+ env = environment_step(i=2, env=env)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.PLANNING.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.ACCESS.name
+
+ env = environment_step(i=2, env=env)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.ACCESS.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.MANIPULATION.name
+
+
+def test_tap003_kill_chain_stage_manipulation():
+ """Tests the successful/failed handlers in the manipulation stage in the InsiderKillChain"""
+ env = uc7_tap003_env()
+ tap003: TAP003 = env.game.agents["attacker"]
+
+ assert tap003.current_kill_chain_stage == BaseKillChain.NOT_STARTED
+
+ env = environment_step(i=2, env=env)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.RECONNAISSANCE.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.PLANNING.name
+
+ env = environment_step(i=2, env=env)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.PLANNING.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.ACCESS.name
+
+ env = environment_step(i=2, env=env)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.ACCESS.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.MANIPULATION.name
+
+ env = environment_step(i=2, env=env)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.MANIPULATION.name
+
+ # Testing that the stage successfully impacted the simulation - Accounts Altered
+ env = environment_step(i=5, env=env)
+ st_intra_prv_rt_dr_1: Router = env.game.simulation.network.get_node_by_hostname("ST_INTRA-PRV-RT-DR-1")
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.MANIPULATION.name
+ assert st_intra_prv_rt_dr_1.user_manager.admins["admin"].password == "red_pass"
+
+ env = environment_step(i=5, env=env)
+ st_intra_prv_rt_cr: Router = env.game.simulation.network.get_node_by_hostname("ST_INTRA-PRV-RT-CR")
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.MANIPULATION.name
+ assert st_intra_prv_rt_cr.user_manager.admins["admin"].password == "red_pass"
+
+ env = environment_step(i=5, env=env)
+ rem_pub_rt_dr: Router = env.game.simulation.network.get_node_by_hostname("REM-PUB-RT-DR")
+ assert rem_pub_rt_dr.user_manager.admins["admin"].password == "red_pass"
+
+
+def test_tap003_kill_chain_stage_exploit():
+ """Tests the successful/failed handlers in the exploit stage in the InsiderKillChain"""
+
+ env = uc7_tap003_env()
+ tap003: TAP003 = env.game.agents["attacker"]
+ # The TAP003's Target Router/Firewall
+ st_intra_prv_rt_dr_1: Router = env.game.simulation.network.get_node_by_hostname("ST_INTRA-PRV-RT-DR-1")
+ st_intra_prv_rt_cr: Router = env.game.simulation.network.get_node_by_hostname("ST_INTRA-PRV-RT-CR")
+ rem_pub_rt_dr: Router = env.game.simulation.network.get_node_by_hostname("REM-PUB-RT-DR")
+
+ assert tap003.current_kill_chain_stage == BaseKillChain.NOT_STARTED
+
+ env = environment_step(i=2, env=env)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.RECONNAISSANCE.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.PLANNING.name
+
+ env = environment_step(i=2, env=env)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.PLANNING.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.ACCESS.name
+
+ env = environment_step(i=2, env=env)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.ACCESS.name
+ assert tap003.next_kill_chain_stage.name == InsiderKillChain.MANIPULATION.name
+
+ env = environment_step(i=16, env=env)
+
+ assert tap003.current_kill_chain_stage.name == InsiderKillChain.EXPLOIT.name
+
+ # Testing that the stage successfully impacted the simulation - Malicious ACL Added:
+ for _ in range(14):
+ env.step(0)
+
+ # Tests that the ACL has been added and that the action is deny.
+ st_intra_prv_rt_dr_1_acl_list = st_intra_prv_rt_dr_1.acl
+ assert st_intra_prv_rt_dr_1_acl_list.acl[1].action != None
+ assert st_intra_prv_rt_dr_1_acl_list.acl[1].action == ACLAction.DENY
+
+ st_intra_prv_rt_cr_acl_list = st_intra_prv_rt_cr.acl
+ assert st_intra_prv_rt_cr_acl_list.acl[1].action != None
+ assert st_intra_prv_rt_cr_acl_list.acl[1].action == ACLAction.DENY
+
+ rem_pub_rt_dr_acl_list = rem_pub_rt_dr.acl
+ assert rem_pub_rt_dr_acl_list.acl[1].action != None
+ assert rem_pub_rt_dr_acl_list.acl[1].action == ACLAction.DENY
diff --git a/tests/e2e_integration_tests/threat_actor_profiles/test_tap003_multiple_rules.py b/tests/e2e_integration_tests/threat_actor_profiles/test_tap003_multiple_rules.py
new file mode 100644
index 00000000..0db318a7
--- /dev/null
+++ b/tests/e2e_integration_tests/threat_actor_profiles/test_tap003_multiple_rules.py
@@ -0,0 +1,203 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+from typing import Protocol
+
+import pytest
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG
+from primaite.game.agent.scripted_agents.abstract_tap import (
+ AbstractTAP,
+ BaseKillChain,
+ KillChainOptions,
+ KillChainStageOptions,
+ KillChainStageProgress,
+)
+from primaite.game.agent.scripted_agents.TAP001 import MobileMalwareKillChain, TAP001
+from primaite.game.agent.scripted_agents.TAP003 import InsiderKillChain, TAP003
+from primaite.session.environment import PrimaiteGymEnv
+from primaite.simulator.network.hardware.nodes.network.router import ACLAction, Router
+from primaite.utils.validation.ip_protocol import PROTOCOL_LOOKUP
+from primaite.utils.validation.ipv4_address import IPV4Address
+from primaite.utils.validation.port import PORT_LOOKUP
+
+# Defining constants.
+ATTACK_AGENT_INDEX = 32
+START_STEP = 1 # The starting step of the agent.
+FREQUENCY = 2 # The frequency of kill chain stage progression (E.g it's next attempt at "attacking").
+VARIANCE = 0 # The timestep variance between kill chain progression (E.g Next timestep = Frequency +/- variance)
+REPEAT_KILL_CHAIN = False # Should the TAP repeat the kill chain after success/failure?
+REPEAT_KILL_CHAIN_STAGES = False # Should the TAP restart from it's previous stage on failure?
+KILL_CHAIN_PROBABILITY = 1 # Blank probability for agent 'success'
+RULES = [
+ {
+ "target_router": "ST_INTRA-PRV-RT-DR-1",
+ "position": 1,
+ "permission": "DENY",
+ "src_ip": "192.168.220.3",
+ "src_wildcard": "NONE",
+ "dst_ip": "192.168.220.3",
+ "dst_wildcard": "NONE",
+ "src_port": "ALL",
+ "dst_port": "ALL",
+ "protocol_name": "ALL",
+ },
+ {
+ "target_router": "ST_INTRA-PRV-RT-DR-2",
+ "position": 5,
+ "permission": "DENY",
+ "src_ip": "192.168.220.3",
+ "src_wildcard": "NONE",
+ "dst_ip": "ALL",
+ "dst_wildcard": "NONE",
+ "src_port": "ALL",
+ "dst_port": "ALL",
+ "protocol_name": "ALL",
+ },
+ {
+ "target_router": "ST_INTRA-PRV-RT-CR",
+ "position": 6,
+ "permission": "PERMIT",
+ "src_ip": "192.168.220.3",
+ "src_wildcard": "NONE",
+ "dst_ip": "ALL",
+ "dst_wildcard": "NONE",
+ "src_port": "ALL",
+ "dst_port": "ALL",
+ "protocol_name": "ALL",
+ },
+ {
+ "target_router": "REM-PUB-RT-DR",
+ "position": 3,
+ "permission": "PERMIT",
+ "src_ip": "192.168.220.3",
+ "src_wildcard": "0.0.0.1",
+ "dst_ip": "192.168.220.3",
+ "dst_wildcard": "0.0.0.1",
+ "src_port": "FTP",
+ "dst_port": "FTP",
+ "protocol_name": "TCP",
+ },
+ #
+]
+
+
+def uc7_tap003_env(**kwargs) -> PrimaiteGymEnv:
+ """Setups the UC7 TAP003 Game with a 1 timestep start_step, frequency of 2 and probabilities set to 1 as well"""
+ with open(_EXAMPLE_CFG / "uc7_config_tap003.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ cfg["io_settings"]["save_sys_logs"] = False
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["start_step"] = START_STEP
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["frequency"] = FREQUENCY
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["variance"] = VARIANCE
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["repeat_kill_chain"] = kwargs["repeat_kill_chain"]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["repeat_kill_chain_stages"] = kwargs[
+ "repeat_kill_chain_stages"
+ ]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["MANIPULATION"]["probability"] = kwargs[
+ "manipulation_probability"
+ ]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["ACCESS"]["probability"] = kwargs[
+ "access_probability"
+ ]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["PLANNING"]["probability"] = kwargs[
+ "planning_probability"
+ ]
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["EXPLOIT"]["malicious_acls"] = RULES
+ # Adding the new test target to TAP003's starting knowledge:
+ new_target_dict = {
+ "ST_INTRA-PRV-RT-DR-2": {
+ "ip_address": "192.168.170.2",
+ "username": "admin",
+ "password": "admin",
+ }
+ }
+ new_target_manipulation = {
+ "host": "ST_INTRA-PRV-RT-DR-2",
+ "ip_address": "192.168.170.2",
+ "action": "change_password",
+ "username": "admin",
+ "new_password": "red_pass",
+ }
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["PLANNING"]["starting_network_knowledge"][
+ "credentials"
+ ].update(new_target_dict)
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["MANIPULATION"]["account_changes"].append(
+ new_target_manipulation
+ )
+ env = PrimaiteGymEnv(env_config=cfg)
+ return env
+
+
+def test_tap003_cycling_rules():
+ """Tests to check that TAP003 repeats it's kill chain after success"""
+
+ env = uc7_tap003_env(
+ repeat_kill_chain=True,
+ repeat_kill_chain_stages=True,
+ manipulation_probability=1,
+ access_probability=1,
+ planning_probability=1,
+ )
+ tap003: TAP003 = env.game.agents["attacker"]
+
+ def wait_until_attack():
+ # 120 environment steps to ensure that TAP003 reaches manipulate.
+ # If this loop finishes 120 iterations before the test finishes then TAP003 is struggling to
+ # reach or finish the manipulation kill chain stage correctly.
+ for _ in range(120):
+ # check if the agent has executed and therefore moved onto the next rule index
+ env.step(0)
+ if tap003.history[-1].action == "node-send-remote-command":
+ if tap003.history[-1].parameters["command"][0] == "acl":
+ return
+ pytest.fail("While testing the cycling of TAP003 rules, the agent unexpectedly didn't execute its attack.")
+
+ wait_until_attack()
+ target_node: Router = env.game.simulation.network.get_node_by_hostname("ST_INTRA-PRV-RT-DR-1")
+ assert (rule_0 := target_node.acl.acl[1]) is not None
+ assert rule_0.action == ACLAction.DENY
+ assert rule_0.protocol == None
+ assert rule_0.src_ip_address == IPV4Address("192.168.220.3")
+ assert rule_0.src_wildcard_mask == None
+ assert rule_0.dst_ip_address == IPV4Address("192.168.220.3")
+ assert rule_0.dst_wildcard_mask == None
+ assert rule_0.src_port == None
+ assert rule_0.dst_port == None
+
+ target_node: Router = env.game.simulation.network.get_node_by_hostname("ST_INTRA-PRV-RT-DR-2")
+ wait_until_attack()
+ assert (rule_1 := target_node.acl.acl[5]) is not None
+ assert rule_1.action == ACLAction.DENY
+ assert rule_1.protocol == None
+ assert rule_1.src_ip_address == IPV4Address("192.168.220.3")
+ assert rule_1.src_wildcard_mask == None
+ assert rule_1.dst_ip_address == None
+ assert rule_1.dst_wildcard_mask == None
+ assert rule_1.src_port == None
+ assert rule_1.dst_port == None
+
+ wait_until_attack()
+ target_node: Router = env.game.simulation.network.get_node_by_hostname("ST_INTRA-PRV-RT-CR")
+ assert (rule_2 := target_node.acl.acl[6]) is not None
+ assert rule_2.action == ACLAction.PERMIT
+ assert rule_2.protocol == None
+ assert rule_2.src_ip_address == IPV4Address("192.168.220.3")
+ assert rule_2.src_wildcard_mask == None # default
+ assert rule_2.dst_ip_address == None
+ assert rule_2.dst_wildcard_mask == None # default
+ assert rule_2.src_port == None
+ assert rule_2.dst_port == None
+
+ wait_until_attack()
+ target_node: Router = env.game.simulation.network.get_node_by_hostname("REM-PUB-RT-DR")
+ assert (rule_3 := target_node.acl.acl[3]) is not None
+ assert rule_3.action == ACLAction.PERMIT
+ assert rule_3.protocol == PROTOCOL_LOOKUP["TCP"]
+ assert rule_3.src_ip_address == IPV4Address("192.168.220.3")
+ assert rule_3.src_wildcard_mask == IPV4Address("0.0.0.1")
+ assert rule_3.dst_ip_address == IPV4Address("192.168.220.3")
+ assert rule_3.dst_wildcard_mask == IPV4Address("0.0.0.1")
+ assert rule_3.src_port == PORT_LOOKUP["FTP"]
+ assert rule_3.dst_port == PORT_LOOKUP["FTP"]
+
+ # If we've gotten this fair then we can pass the test :)
diff --git a/tests/integration_tests/configuration_file_parsing/threat_actor_profile_settings/__init__.py b/tests/integration_tests/configuration_file_parsing/threat_actor_profile_settings/__init__.py
new file mode 100644
index 00000000..836b79af
--- /dev/null
+++ b/tests/integration_tests/configuration_file_parsing/threat_actor_profile_settings/__init__.py
@@ -0,0 +1 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
diff --git a/tests/integration_tests/configuration_file_parsing/threat_actor_profile_settings/test_kill_chain_settings.py b/tests/integration_tests/configuration_file_parsing/threat_actor_profile_settings/test_kill_chain_settings.py
new file mode 100644
index 00000000..59fd9d86
--- /dev/null
+++ b/tests/integration_tests/configuration_file_parsing/threat_actor_profile_settings/test_kill_chain_settings.py
@@ -0,0 +1,25 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+from pathlib import Path
+from typing import Union
+
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG
+from primaite.game.agent.scripted_agents.TAP003 import TAP003
+from primaite.game.game import PrimaiteGame
+
+ATTACK_AGENT_INDEX = 32
+
+
+def test_tap003_kill_chain_settings_load_config():
+ with open(_EXAMPLE_CFG / "uc7_config_tap003.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["MANIPULATION"]["probability"] = 0.5
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["ACCESS"]["probability"] = 0.5
+ cfg["agents"][ATTACK_AGENT_INDEX]["agent_settings"]["kill_chain"]["PLANNING"]["probability"] = 0.5
+ game = PrimaiteGame.from_config(cfg)
+ tap: TAP003 = game.agents["attacker"]
+ kill_chain = tap.config.agent_settings.kill_chain
+ assert kill_chain.MANIPULATION.probability == 0.5
+ assert kill_chain.ACCESS.probability == 0.5
+ assert kill_chain.PLANNING.probability == 0.5
diff --git a/tests/integration_tests/configuration_file_parsing/threat_actor_profile_settings/test_threat_actor_profile_settings.py b/tests/integration_tests/configuration_file_parsing/threat_actor_profile_settings/test_threat_actor_profile_settings.py
new file mode 100644
index 00000000..03216865
--- /dev/null
+++ b/tests/integration_tests/configuration_file_parsing/threat_actor_profile_settings/test_threat_actor_profile_settings.py
@@ -0,0 +1,35 @@
+# © Crown-owned copyright 2025, Defence Science and Technology Laboratory UK
+from pathlib import Path
+from typing import Union
+
+import yaml
+
+from primaite.config.load import _EXAMPLE_CFG
+from primaite.game.agent.scripted_agents.TAP003 import TAP003
+from primaite.game.game import PrimaiteGame
+
+
+def test_threat_actor_profile_load_config():
+ """Test to check that threat actor profiles are able to be loaded."""
+ with open(_EXAMPLE_CFG / "uc7_config_tap003.yaml", mode="r") as uc7_config:
+ cfg = yaml.safe_load(uc7_config)
+
+ game = PrimaiteGame.from_config(cfg)
+ # tap003 is found and loaded TODO: Once tuple digestion is implemented, change to hardcoded 'tap003' test.
+ assert "attacker" in game.agents
+ assert isinstance(game.agents["attacker"], TAP003)
+ agent: TAP003 = game.agents["attacker"]
+ assert agent.config.agent_settings.start_step == 1
+ assert agent.config.agent_settings.frequency == 3
+ assert agent.config.agent_settings.variance == 0
+ assert not agent.config.agent_settings.repeat_kill_chain
+ assert agent.config.agent_settings.repeat_kill_chain_stages
+ assert agent.config.agent_settings.default_starting_node == "ST_PROJ-A-PRV-PC-1"
+ assert not agent.config.agent_settings.starting_nodes
+ assert agent.config.agent_settings.kill_chain.PLANNING.probability == 1
+ assert len(agent.config.agent_settings.kill_chain.PLANNING.starting_network_knowledge["credentials"]) == 6
+ assert agent.config.agent_settings.kill_chain.ACCESS.probability == 1
+ assert agent.config.agent_settings.kill_chain.MANIPULATION.probability == 1
+ assert len(agent.config.agent_settings.kill_chain.MANIPULATION.account_changes) == 3
+ assert agent.config.agent_settings.kill_chain.EXPLOIT.probability == 1
+ assert len(agent.config.agent_settings.kill_chain.EXPLOIT.malicious_acls) == 3