893 - added new tests to test action space size and node is completing both sets of actions in a single episode and created new main config
This commit is contained in:
@@ -1273,5 +1273,6 @@ class Primaite(Env):
|
|||||||
|
|
||||||
# Combine the Node dict and ACL dict
|
# Combine the Node dict and ACL dict
|
||||||
combined_action_dict = {**acl_action_dict, **new_node_action_dict}
|
combined_action_dict = {**acl_action_dict, **new_node_action_dict}
|
||||||
|
print("combined_action_dict entry", combined_action_dict.items())
|
||||||
# print(len(list(combined_action_dict.values())))
|
# print(len(list(combined_action_dict.values())))
|
||||||
return combined_action_dict
|
return combined_action_dict
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# Main Config File
|
||||||
|
|
||||||
|
# Generic config values
|
||||||
|
# Choose one of these (dependent on Agent being trained)
|
||||||
|
# "STABLE_BASELINES3_PPO"
|
||||||
|
# "STABLE_BASELINES3_A2C"
|
||||||
|
# "GENERIC"
|
||||||
|
agentIdentifier: GENERIC_TEST
|
||||||
|
# Number of episodes to run per session
|
||||||
|
numEpisodes: 1
|
||||||
|
# Time delay between steps (for generic agents)
|
||||||
|
timeDelay: 1
|
||||||
|
# Filename of the scenario / laydown
|
||||||
|
configFilename: single_action_space_lay_down_config.yaml
|
||||||
|
# Type of session to be run (TRAINING or EVALUATION)
|
||||||
|
sessionType: TRAINING
|
||||||
|
# Determine whether to load an agent from file
|
||||||
|
loadAgent: False
|
||||||
|
# File path and file name of agent if you're loading one in
|
||||||
|
agentLoadFile: C:\[Path]\[agent_saved_filename.zip]
|
||||||
|
|
||||||
|
# Environment config values
|
||||||
|
# The high value for the observation space
|
||||||
|
observationSpaceHighValue: 1000000000
|
||||||
|
|
||||||
|
# Reward values
|
||||||
|
# Generic
|
||||||
|
allOk: 0
|
||||||
|
# Node Operating State
|
||||||
|
offShouldBeOn: -10
|
||||||
|
offShouldBeResetting: -5
|
||||||
|
onShouldBeOff: -2
|
||||||
|
onShouldBeResetting: -5
|
||||||
|
resettingShouldBeOn: -5
|
||||||
|
resettingShouldBeOff: -2
|
||||||
|
resetting: -3
|
||||||
|
# Node O/S or Service State
|
||||||
|
goodShouldBePatching: 2
|
||||||
|
goodShouldBeCompromised: 5
|
||||||
|
goodShouldBeOverwhelmed: 5
|
||||||
|
patchingShouldBeGood: -5
|
||||||
|
patchingShouldBeCompromised: 2
|
||||||
|
patchingShouldBeOverwhelmed: 2
|
||||||
|
patching: -3
|
||||||
|
compromisedShouldBeGood: -20
|
||||||
|
compromisedShouldBePatching: -20
|
||||||
|
compromisedShouldBeOverwhelmed: -20
|
||||||
|
compromised: -20
|
||||||
|
overwhelmedShouldBeGood: -20
|
||||||
|
overwhelmedShouldBePatching: -20
|
||||||
|
overwhelmedShouldBeCompromised: -20
|
||||||
|
overwhelmed: -20
|
||||||
|
# Node File System State
|
||||||
|
goodShouldBeRepairing: 2
|
||||||
|
goodShouldBeRestoring: 2
|
||||||
|
goodShouldBeCorrupt: 5
|
||||||
|
goodShouldBeDestroyed: 10
|
||||||
|
repairingShouldBeGood: -5
|
||||||
|
repairingShouldBeRestoring: 2
|
||||||
|
repairingShouldBeCorrupt: 2
|
||||||
|
repairingShouldBeDestroyed: 0
|
||||||
|
repairing: -3
|
||||||
|
restoringShouldBeGood: -10
|
||||||
|
restoringShouldBeRepairing: -2
|
||||||
|
restoringShouldBeCorrupt: 1
|
||||||
|
restoringShouldBeDestroyed: 2
|
||||||
|
restoring: -6
|
||||||
|
corruptShouldBeGood: -10
|
||||||
|
corruptShouldBeRepairing: -10
|
||||||
|
corruptShouldBeRestoring: -10
|
||||||
|
corruptShouldBeDestroyed: 2
|
||||||
|
corrupt: -10
|
||||||
|
destroyedShouldBeGood: -20
|
||||||
|
destroyedShouldBeRepairing: -20
|
||||||
|
destroyedShouldBeRestoring: -20
|
||||||
|
destroyedShouldBeCorrupt: -20
|
||||||
|
destroyed: -20
|
||||||
|
scanning: -2
|
||||||
|
# IER status
|
||||||
|
redIerRunning: -5
|
||||||
|
greenIerBlocked: -10
|
||||||
|
|
||||||
|
# Patching / Reset durations
|
||||||
|
osPatchingDuration: 5 # The time taken to patch the OS
|
||||||
|
nodeResetDuration: 5 # The time taken to reset a node (hardware)
|
||||||
|
servicePatchingDuration: 5 # The time taken to patch a service
|
||||||
|
fileSystemRepairingLimit: 5 # The time take to repair the file system
|
||||||
|
fileSystemRestoringLimit: 5 # The time take to restore the file system
|
||||||
|
fileSystemScanningLimit: 5 # The time taken to scan the file system
|
||||||
@@ -15,39 +15,41 @@
|
|||||||
node_type: COMPUTER
|
node_type: COMPUTER
|
||||||
priority: P1
|
priority: P1
|
||||||
hardware_state: 'ON'
|
hardware_state: 'ON'
|
||||||
|
ip_address: 192.168.0.14
|
||||||
|
software_state: GOOD
|
||||||
|
file_system_state: GOOD
|
||||||
|
services:
|
||||||
|
- name: ftp
|
||||||
|
port: '21'
|
||||||
|
state: COMPROMISED
|
||||||
|
- itemType: NODE
|
||||||
|
node_id: '2'
|
||||||
|
name: server_1
|
||||||
|
node_class: SERVICE
|
||||||
|
node_type: SERVER
|
||||||
|
priority: P1
|
||||||
|
hardware_state: 'ON'
|
||||||
ip_address: 192.168.0.1
|
ip_address: 192.168.0.1
|
||||||
software_state: GOOD
|
software_state: GOOD
|
||||||
file_system_state: GOOD
|
file_system_state: GOOD
|
||||||
services:
|
services:
|
||||||
- name: ftp
|
- name: ftp
|
||||||
port: '21'
|
port: '21'
|
||||||
state: GOOD
|
state: COMPROMISED
|
||||||
- itemType: POSITION
|
- itemType: POSITION
|
||||||
positions:
|
positions:
|
||||||
- node: '1'
|
- node: '1'
|
||||||
x_pos: 309
|
x_pos: 309
|
||||||
y_pos: 78
|
y_pos: 78
|
||||||
- itemType: RED_POL
|
- node: '2'
|
||||||
id: '1'
|
x_pos: 200
|
||||||
startStep: 1
|
y_pos: 78
|
||||||
endStep: 3
|
- itemType: RED_IER
|
||||||
targetNodeId: '1'
|
id: '3'
|
||||||
initiator: DIRECT
|
startStep: 2
|
||||||
type: FILE
|
|
||||||
protocol: NA
|
|
||||||
state: CORRUPT
|
|
||||||
sourceNodeId: NA
|
|
||||||
sourceNodeService: NA
|
|
||||||
sourceNodeServiceState: NA
|
|
||||||
- itemType: RED_POL
|
|
||||||
id: '2'
|
|
||||||
startStep: 3
|
|
||||||
endStep: 15
|
endStep: 15
|
||||||
targetNodeId: '1'
|
load: 1000
|
||||||
initiator: DIRECT
|
protocol: ftp
|
||||||
type: FILE
|
port: CORRUPT
|
||||||
protocol: NA
|
source: '1'
|
||||||
state: GOOD
|
destination: '2'
|
||||||
sourceNodeId: NA
|
|
||||||
sourceNodeService: NA
|
|
||||||
sourceNodeServiceState: NA
|
|
||||||
|
|||||||
@@ -164,10 +164,13 @@ def _get_primaite_env_from_config(
|
|||||||
# Load in config data
|
# Load in config data
|
||||||
load_config_values()
|
load_config_values()
|
||||||
env = Primaite(config_values, [])
|
env = Primaite(config_values, [])
|
||||||
|
# Get the number of steps (which is stored in the child config file)
|
||||||
config_values.num_steps = env.episode_steps
|
config_values.num_steps = env.episode_steps
|
||||||
|
|
||||||
if env.config_values.agent_identifier == "GENERIC":
|
if env.config_values.agent_identifier == "GENERIC":
|
||||||
run_generic(env, config_values)
|
run_generic(env, config_values)
|
||||||
|
elif env.config_values.agent_identifier == "GENERIC_TEST":
|
||||||
|
run_generic_set_actions(env, config_values)
|
||||||
|
|
||||||
return env
|
return env
|
||||||
|
|
||||||
@@ -197,3 +200,40 @@ def run_generic(env, config_values):
|
|||||||
# env.reset()
|
# env.reset()
|
||||||
|
|
||||||
# env.close()
|
# env.close()
|
||||||
|
|
||||||
|
|
||||||
|
def run_generic_set_actions(env, config_values):
|
||||||
|
"""Run against a generic agent with specified blue agent actions."""
|
||||||
|
# Reset the environment at the start of the episode
|
||||||
|
# env.reset()
|
||||||
|
for episode in range(0, config_values.num_episodes):
|
||||||
|
for step in range(0, config_values.num_steps):
|
||||||
|
# Send the observation space to the agent to get an action
|
||||||
|
# TEMP - random action for now
|
||||||
|
# action = env.blue_agent_action(obs)
|
||||||
|
action = 0
|
||||||
|
if step == 5:
|
||||||
|
# [1, 1, 2, 1, 1, 1]
|
||||||
|
# Creates an ACL rule
|
||||||
|
# Deny traffic from server_1 to node_1 on port FTP
|
||||||
|
action = 7
|
||||||
|
elif step == 7:
|
||||||
|
# [1, 1, 2, 0] Node Action
|
||||||
|
# Sets Node 1 Hardware State to OFF
|
||||||
|
# Does not resolve any service
|
||||||
|
action = 16
|
||||||
|
print(action, "ran")
|
||||||
|
# Run the simulation step on the live environment
|
||||||
|
obs, reward, done, info = env.step(action)
|
||||||
|
|
||||||
|
# Break if done is True
|
||||||
|
if done:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Introduce a delay between steps
|
||||||
|
time.sleep(config_values.time_delay / 1000)
|
||||||
|
|
||||||
|
# Reset the environment at the end of the episode
|
||||||
|
# env.reset()
|
||||||
|
|
||||||
|
# env.close()
|
||||||
|
|||||||
@@ -1,26 +1,55 @@
|
|||||||
|
from primaite.common.enums import HardwareState
|
||||||
from tests import TEST_CONFIG_ROOT
|
from tests import TEST_CONFIG_ROOT
|
||||||
from tests.conftest import _get_primaite_env_from_config
|
from tests.conftest import _get_primaite_env_from_config
|
||||||
|
|
||||||
|
|
||||||
def test_single_action_space():
|
def test_single_action_space_is_valid():
|
||||||
"""Test to ensure the blue agent is using the ACL action space and is carrying out both kinds of operations."""
|
"""Test to ensure the blue agent is using the ACL action space and is carrying out both kinds of operations."""
|
||||||
env = _get_primaite_env_from_config(
|
env = _get_primaite_env_from_config(
|
||||||
main_config_path=TEST_CONFIG_ROOT / "single_action_space_main_config.yaml",
|
main_config_path=TEST_CONFIG_ROOT / "single_action_space_main_config.yaml",
|
||||||
lay_down_config_path=TEST_CONFIG_ROOT
|
lay_down_config_path=TEST_CONFIG_ROOT
|
||||||
/ "single_action_space_lay_down_config.yaml",
|
/ "single_action_space_lay_down_config.yaml",
|
||||||
)
|
)
|
||||||
"""
|
# Retrieve the action space dictionary values from environment
|
||||||
nv.action_space.n is the total number of actions in the Discrete action space
|
env_action_space_dict = env.action_dict.values()
|
||||||
This is the number of actions the agent has to choose from.
|
# Flags to check the conditions of the action space
|
||||||
|
contains_acl_actions = False
|
||||||
|
contains_node_actions = False
|
||||||
|
both_action_spaces = False
|
||||||
|
# Loop through each element of the list (which is every value from the dictionary)
|
||||||
|
for dict_item in env_action_space_dict:
|
||||||
|
# Node action detected
|
||||||
|
if len(dict_item) == 4:
|
||||||
|
contains_node_actions = True
|
||||||
|
# Link action detected
|
||||||
|
elif len(dict_item) == 6:
|
||||||
|
contains_acl_actions = True
|
||||||
|
# If both are there then the ANY action type is working
|
||||||
|
if contains_node_actions and contains_acl_actions:
|
||||||
|
both_action_spaces = True
|
||||||
|
# Check condition should be True
|
||||||
|
assert both_action_spaces
|
||||||
|
|
||||||
The total number of actions that an agent can type when a NODE action type is selected is: 6
|
|
||||||
The total number of actions that an agent can take when an ACL action type is selected is: 7
|
|
||||||
|
|
||||||
These action spaces are combined and the total number of actions is: 12
|
def test_agent_is_executing_actions_from_both_spaces():
|
||||||
This is due to both actions containing the action to "Do nothing", so it needs to be removed from one of the spaces,
|
"""Test to ensure the blue agent is carrying out both kinds of operations (NODE & ACL)."""
|
||||||
to avoid duplicate actions.
|
env = _get_primaite_env_from_config(
|
||||||
|
main_config_path=TEST_CONFIG_ROOT
|
||||||
As a result, 12 is the total number of action spaces.
|
/ "single_action_space_fixed_blue_actions_main_config.yaml",
|
||||||
"""
|
lay_down_config_path=TEST_CONFIG_ROOT
|
||||||
# e
|
/ "single_action_space_lay_down_config.yaml",
|
||||||
assert env.action_space.n == 12
|
)
|
||||||
|
# Retrieve hardware state of computer_1 node in laydown config
|
||||||
|
# Agent turned this off in Step 5
|
||||||
|
computer_node_hardware_state = env.nodes["1"].hardware_state
|
||||||
|
# Retrieve the Access Control List object stored by the environment at the end of the episode
|
||||||
|
access_control_list = env.acl
|
||||||
|
# Use the Access Control List object acl object attribute to get dictionary
|
||||||
|
# Use dictionary.values() to get total list of all items in the dictionary
|
||||||
|
acl_rules_list = access_control_list.acl.values()
|
||||||
|
# Length of this list tells you how many items are in the dictionary
|
||||||
|
# This number is the frequency of Access Control Rules in the environment
|
||||||
|
# In the scenario, we specified that the agent should create only 1 acl rule
|
||||||
|
num_of_rules = len(acl_rules_list)
|
||||||
|
# Therefore these statements below MUST be true
|
||||||
|
assert computer_node_hardware_state == HardwareState.OFF and num_of_rules == 1
|
||||||
|
|||||||
Reference in New Issue
Block a user