901 - merged dev into my branch
This commit is contained in:
@@ -29,6 +29,10 @@ jobs:
|
||||
pip install -e .[dev]
|
||||
displayName: 'Install Yawning-Titan for docs autosummary'
|
||||
|
||||
- script: |
|
||||
primaite setup
|
||||
displayName: 'Perform PrimAITE Setup'
|
||||
|
||||
- script: |
|
||||
cd docs
|
||||
make html
|
||||
|
||||
@@ -42,6 +42,10 @@ steps:
|
||||
python -m pip install $PRIMAITE_WHEEL[dev]
|
||||
displayName: 'Install PrimAITE'
|
||||
|
||||
- script: |
|
||||
primaite setup
|
||||
displayName: 'Perform PrimAITE Setup'
|
||||
|
||||
#- script: |
|
||||
# flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
# flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,10 +1,3 @@
|
||||
# PrimAITE Package
|
||||
src/primaite/outputs
|
||||
src/primaite/outputs/*
|
||||
src/primaite/logs
|
||||
src/primaite/logs/*
|
||||
TestResults
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
@@ -77,6 +70,7 @@ instance/
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
docs/source/_autosummary
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
include src/primaite/config/*.yaml
|
||||
include src/primaite/setup/_package_data/primaite_config.yaml
|
||||
include src/primaite/config/_package_data/*.yaml
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
@@ -8,13 +6,29 @@ SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
AUTOSUMMARY="source\_autosummary"
|
||||
|
||||
# Remove command is different depending on OS
|
||||
ifdef OS
|
||||
RM = IF exist $(AUTOSUMMARY) ( RMDIR $(AUTOSUMMARY) /s /q )
|
||||
else
|
||||
ifeq ($(shell uname), Linux)
|
||||
RM = rm -rf $(AUTOSUMMARY)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
clean:
|
||||
$(RM)
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
%: Makefile | clean
|
||||
pip-licenses --format=rst --with-urls --output-file=source/primaite-dependencies.rst
|
||||
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
37
docs/_templates/custom-class-template.rst
vendored
Normal file
37
docs/_templates/custom-class-template.rst
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
..
|
||||
Credit to https://github.com/JamesALeedham/Sphinx-Autosummary-Recursion for the custom templates.
|
||||
..
|
||||
{{ fullname | escape | underline}}
|
||||
|
||||
.. currentmodule:: {{ module }}
|
||||
|
||||
.. autoclass:: {{ objname }}
|
||||
:members:
|
||||
:show-inheritance:
|
||||
:inherited-members:
|
||||
:special-members: __call__, __add__, __mul__
|
||||
|
||||
{% block methods %}
|
||||
{% if methods %}
|
||||
.. rubric:: {{ _('Methods') }}
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
{% for item in methods %}
|
||||
{%- if not item.startswith('_') %}
|
||||
~{{ name }}.{{ item }}
|
||||
{%- endif -%}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block attributes %}
|
||||
{% if attributes %}
|
||||
.. rubric:: {{ _('Attributes') }}
|
||||
|
||||
.. autosummary::
|
||||
{% for item in attributes %}
|
||||
~{{ name }}.{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
69
docs/_templates/custom-module-template.rst
vendored
Normal file
69
docs/_templates/custom-module-template.rst
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
..
|
||||
Credit to https://github.com/JamesALeedham/Sphinx-Autosummary-Recursion for the custom templates.
|
||||
..
|
||||
{{ fullname | escape | underline}}
|
||||
|
||||
.. automodule:: {{ fullname }}
|
||||
|
||||
{% block attributes %}
|
||||
{% if attributes %}
|
||||
.. rubric:: Module attributes
|
||||
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
{% for item in attributes %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block functions %}
|
||||
{% if functions %}
|
||||
.. rubric:: {{ _('Functions') }}
|
||||
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
:nosignatures:
|
||||
{% for item in functions %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block classes %}
|
||||
{% if classes %}
|
||||
.. rubric:: {{ _('Classes') }}
|
||||
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
:template: custom-class-template.rst
|
||||
:nosignatures:
|
||||
{% for item in classes %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block exceptions %}
|
||||
{% if exceptions %}
|
||||
.. rubric:: {{ _('Exceptions') }}
|
||||
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
{% for item in exceptions %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block modules %}
|
||||
{% if modules %}
|
||||
.. autosummary::
|
||||
:toctree:
|
||||
:template: custom-module-template.rst
|
||||
:recursive:
|
||||
{% for item in modules %}
|
||||
{{ item }}
|
||||
{%- endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
16
docs/api.rst
Normal file
16
docs/api.rst
Normal file
@@ -0,0 +1,16 @@
|
||||
..
|
||||
DO NOT DELETE THIS FILE! It contains the all-important `.. autosummary::` directive with `:recursive:` option, without
|
||||
which API documentation wouldn't get extracted from docstrings by the `sphinx.ext.autosummary` engine. It is hidden
|
||||
(not declared in any toctree) to remove an unnecessary intermediate page; index.rst instead points directly to the
|
||||
package page. DO NOT REMOVE THIS FILE!
|
||||
|
||||
Credit to https://github.com/JamesALeedham/Sphinx-Autosummary-Recursion for the custom templates.
|
||||
..
|
||||
|
||||
.. autosummary::
|
||||
:toctree: source/_autosummary
|
||||
:template: custom-module-template.rst
|
||||
:recursive:
|
||||
|
||||
primaite
|
||||
tests
|
||||
18
docs/conf.py
18
docs/conf.py
@@ -17,7 +17,7 @@ sys.path.insert(0, os.path.abspath("../"))
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
year = datetime.datetime.now().year
|
||||
project = "primaite"
|
||||
project = "PrimAITE"
|
||||
copyright = f"Copyright (C) QinetiQ Training and Simulation Ltd 2021 - {year}"
|
||||
author = "QinetiQ Training and Simulation Ltd"
|
||||
|
||||
@@ -27,10 +27,24 @@ with open("../src/primaite/VERSION", "r") as file:
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = version
|
||||
|
||||
html_title = f"{project} v{release} docs"
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
extensions = []
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
"sphinx.ext.autodoc", # Core Sphinx library for auto html doc generation from docstrings
|
||||
"sphinx.ext.autosummary", # Create summary tables for modules/classes/methods etc
|
||||
"sphinx.ext.intersphinx", # Link to other project's documentation (see mapping below)
|
||||
"sphinx.ext.viewcode", # Add a link to the Python source code for classes, functions etc.
|
||||
"sphinx.ext.todo",
|
||||
"sphinx_copybutton", # Adds a copy button to code blocks
|
||||
"sphinx_code_tabs", # Enables tabbed code blocks
|
||||
]
|
||||
|
||||
|
||||
templates_path = ["_templates"]
|
||||
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||
|
||||
@@ -1,23 +1,18 @@
|
||||
.. PrimAITE documentation master file, created by
|
||||
sphinx-quickstart on Thu Dec 8 09:51:18 2022.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to PrimAITE's documentation
|
||||
====================================
|
||||
|
||||
What is PrimAITE?
|
||||
------------------------
|
||||
|
||||
PrimAITE (Primary-level AI Training Environment) is a simulation environment for training AI under the ARCD programme. It incorporates the functionality required of a Primary-level environment, as specified in the Dstl ARCD Training Environment Matrix document:
|
||||
PrimAITE (Primary-level AI Training Environment) is a simulation environment for training AI under the ARCD programme. It incorporates the functionality required of a Primary-level environment, as specified in the Dstl ARCD Training Environment Matrix document:
|
||||
|
||||
* The ability to model a relevant platform / system context;
|
||||
* The ability to model key characteristics of a platform / system by representing connections, IP addresses, ports, traffic loading, operating systems, file system, services and processes;
|
||||
* Operates at machine-speed to enable fast training cycles.
|
||||
|
||||
PrimAITE aims to evolve into an ARCD environment that could be used as the follow-on from Reception level approaches (e.g. YAWNING TITAN), and help bridge the Sim-to-Real gap into Secondary level environments (e.g. IMAGINARY YAK).
|
||||
PrimAITE aims to evolve into an ARCD environment that could be used as the follow-on from Reception level approaches (e.g. YAWNING TITAN), and help bridge the Sim-to-Real gap into Secondary level environments (e.g. IMAGINARY YAK).
|
||||
|
||||
This is similar to the approach taken by FVEY international partners (e.g. AUS CyBORG, US NSA FARLAND and CAN CyGil). These environments are referenced by the Dstl ARCD Agent Training Environments Knowledge Transfer document (TR141342).
|
||||
This is similar to the approach taken by FVEY international partners (e.g. AUS CyBORG, US NSA FARLAND and CAN CyGil). These environments are referenced by the Dstl ARCD Agent Training Environments Knowledge Transfer document (TR141342).
|
||||
|
||||
What is PrimAITE built with
|
||||
--------------------------------------
|
||||
@@ -34,9 +29,21 @@ The best place to start is :ref:`about`
|
||||
.. toctree::
|
||||
:maxdepth: 8
|
||||
:caption: Contents:
|
||||
:hidden:
|
||||
|
||||
source/about
|
||||
source/dependencies
|
||||
source/config
|
||||
source/session
|
||||
source/results
|
||||
source/primaite_session
|
||||
source/custom_agent
|
||||
PrimAITE API <source/_autosummary/primaite>
|
||||
PrimAITE Tests <source/_autosummary/tests>
|
||||
source/dependencies
|
||||
|
||||
.. toctree::
|
||||
:caption: Project Links:
|
||||
:hidden:
|
||||
|
||||
#Code <>
|
||||
#Issues <>
|
||||
#Pull Requests <>
|
||||
#Discussions <>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
@ECHO OFF
|
||||
|
||||
setlocal EnableDelayedExpansion
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
@@ -10,6 +12,8 @@ if "%SPHINXBUILD%" == "" (
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
|
||||
set AUTOSUMMARYDIR="%cd%\source\_autosummary\"
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
@@ -25,11 +29,30 @@ if errorlevel 9009 (
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
REM delete autosummary if it exists
|
||||
|
||||
IF EXIST %AUTOSUMMARYDIR% (
|
||||
echo deleting %AUTOSUMMARYDIR%
|
||||
RMDIR %AUTOSUMMARYDIR% /s /q
|
||||
)
|
||||
|
||||
REM print the YT licenses
|
||||
set LICENSEBUILD=pip-licenses --format=rst --with-urls
|
||||
set DEPS="%cd%\source\primaite-dependencies.rst"
|
||||
|
||||
%LICENSEBUILD% --output-file=%DEPS%
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:clean
|
||||
IF EXIST %AUTOSUMMARYDIR% (
|
||||
echo deleting %AUTOSUMMARYDIR%
|
||||
RMDIR %AUTOSUMMARYDIR% /s /q
|
||||
)
|
||||
|
||||
:end
|
||||
popd
|
||||
|
||||
@@ -8,51 +8,51 @@ Features
|
||||
|
||||
PrimAITE provides the following features:
|
||||
|
||||
* A flexible network / system laydown based on the Python networkx framework
|
||||
* Nodes and links (edges) host Python classes in order to present attributes and methods (and hence, a more representative model of a platform / system)
|
||||
* A ‘green agent’ Information Exchange Requirement (IER) function allows the representation of traffic (protocols and loading) on any / all links. Application of IERs is based on the status of node operating systems and services
|
||||
* A ‘green agent’ node Pattern-of-Life (PoL) function allows the representation of core behaviours on nodes (e.g. Hardware state, Software State, Service state, File System state)
|
||||
* An Access Control List (ACL) function, mimicking the behaviour of a network firewall, is applied across the model, following standard ACL rule format (e.g. DENY/ALLOW, source IP, destination IP, protocol and port). Application of IERs adheres to any ACL restrictions
|
||||
* Presents an OpenAI Gym interface to the environment, allowing integration with any OpenAI Gym compliant defensive agents
|
||||
* A flexible network / system laydown based on the Python networkx framework
|
||||
* Nodes and links (edges) host Python classes in order to present attributes and methods (and hence, a more representative model of a platform / system)
|
||||
* A ‘green agent’ Information Exchange Requirement (IER) function allows the representation of traffic (protocols and loading) on any / all links. Application of IERs is based on the status of node operating systems and services
|
||||
* A ‘green agent’ node Pattern-of-Life (PoL) function allows the representation of core behaviours on nodes (e.g. Hardware state, Software State, Service state, File System state)
|
||||
* An Access Control List (ACL) function, mimicking the behaviour of a network firewall, is applied across the model, following standard ACL rule format (e.g. DENY/ALLOW, source IP, destination IP, protocol and port). Application of IERs adheres to any ACL restrictions
|
||||
* Presents an OpenAI Gym interface to the environment, allowing integration with any OpenAI Gym compliant defensive agents
|
||||
* Red agent activity based on ‘red’ IERs and ‘red’ PoL
|
||||
* Defined reward function for use with RL agents (based on nodes status, and green / red IER success)
|
||||
* Fully configurable (network / system laydown, IERs, node PoL, ACL, episode step period, episode max steps) and repeatable to suit the training requirements of agents. Therefore, not bound to a representation of any particular platform, system or technology
|
||||
* Full capture of discrete metrics relating to agent training (full system state, agent actions taken, average reward)
|
||||
* Networkx provides laydown visualisation capability
|
||||
* Defined reward function for use with RL agents (based on nodes status, and green / red IER success)
|
||||
* Fully configurable (network / system laydown, IERs, node PoL, ACL, episode step period, episode max steps) and repeatable to suit the training requirements of agents. Therefore, not bound to a representation of any particular platform, system or technology
|
||||
* Full capture of discrete metrics relating to agent training (full system state, agent actions taken, average reward)
|
||||
* Networkx provides laydown visualisation capability
|
||||
|
||||
Architecture - Nodes and Links
|
||||
******************************
|
||||
|
||||
**Nodes**
|
||||
|
||||
An inheritance model has been adopted in order to model nodes. All nodes have the following base attributes (Class: Node):
|
||||
An inheritance model has been adopted in order to model nodes. All nodes have the following base attributes (Class: Node):
|
||||
|
||||
* ID
|
||||
* ID
|
||||
* Name
|
||||
* Type (e.g. computer, switch, RTU - enumeration)
|
||||
* Priority (P1, P2, P3, P4 or P5 - enumeration)
|
||||
* Hardware State (ON, OFF, RESETTING - enumeration)
|
||||
* Type (e.g. computer, switch, RTU - enumeration)
|
||||
* Priority (P1, P2, P3, P4 or P5 - enumeration)
|
||||
* Hardware State (ON, OFF, RESETTING, SHUTTING_DOWN, BOOTING - enumeration)
|
||||
|
||||
Active Nodes also have the following attributes (Class: Active Node):
|
||||
Active Nodes also have the following attributes (Class: Active Node):
|
||||
|
||||
* IP Address
|
||||
* Software State (GOOD, PATCHING, COMPROMISED - enumeration)
|
||||
* IP Address
|
||||
* Software State (GOOD, PATCHING, COMPROMISED - enumeration)
|
||||
* File System State (GOOD, CORRUPT, DESTROYED, REPAIRING, RESTORING - enumeration)
|
||||
|
||||
Service Nodes also have the following attributes (Class: Service Node):
|
||||
Service Nodes also have the following attributes (Class: Service Node):
|
||||
|
||||
* List of Services (where service is composed of service name and port). There is no theoretical limit on the number of services that can be modelled. Services and protocols are currently intrinsically linked (i.e. a service is an application on a node transmitting traffic of this protocol type)
|
||||
* List of Services (where service is composed of service name and port). There is no theoretical limit on the number of services that can be modelled. Services and protocols are currently intrinsically linked (i.e. a service is an application on a node transmitting traffic of this protocol type)
|
||||
* Service state (GOOD, PATCHING, COMPROMISED, OVERWHELMED - enumeration)
|
||||
|
||||
Passive Nodes are currently not used (but may be employed for non IP-based components such as machinery actuators in future releases).
|
||||
|
||||
**Links**
|
||||
|
||||
Links are modelled both as network edges (networkx) and as Python classes, in order to extend their functionality. Links include the following attributes:
|
||||
Links are modelled both as network edges (networkx) and as Python classes, in order to extend their functionality. Links include the following attributes:
|
||||
|
||||
* ID
|
||||
* ID
|
||||
* Name
|
||||
* Bandwidth (bits/s)
|
||||
* Bandwidth (bits/s)
|
||||
* Source node ID
|
||||
* Destination node ID
|
||||
* Protocol list (containing the loading of protocols currently running on the link)
|
||||
@@ -62,32 +62,32 @@ When the simulation runs, IERs are applied to the links in order to model traffi
|
||||
Information Exchange Requirements (IERs)
|
||||
****************************************
|
||||
|
||||
PrimAITE adopts the concept of Information Exchange Requirements (IERs) to model both green agent (background) and red agent (adversary) behaviour. IERs are used to initiate modelling of traffic loading on the network, and have the following attributes:
|
||||
PrimAITE adopts the concept of Information Exchange Requirements (IERs) to model both green agent (background) and red agent (adversary) behaviour. IERs are used to initiate modelling of traffic loading on the network, and have the following attributes:
|
||||
|
||||
* ID
|
||||
* Start step (i.e. which step in the training episode should the IER start)
|
||||
* End step (i.e. which step in the training episode should the IER end)
|
||||
* ID
|
||||
* Start step (i.e. which step in the training episode should the IER start)
|
||||
* End step (i.e. which step in the training episode should the IER end)
|
||||
* Source node ID
|
||||
* Destination node ID
|
||||
* Load (bits/s)
|
||||
* Protocol
|
||||
* Port
|
||||
* Destination node ID
|
||||
* Load (bits/s)
|
||||
* Protocol
|
||||
* Port
|
||||
* Running status (i.e. on / off)
|
||||
|
||||
The application of green agent IERs between a source and destination follows a number of rules. Specifically:
|
||||
The application of green agent IERs between a source and destination follows a number of rules. Specifically:
|
||||
|
||||
1. Does the current simulation time step fall between IER start and end step
|
||||
2. Is the source node operational (both physically and at an O/S level), and is the service (protocol / port) associated with the IER (a) present on this node, and (b) in an operational state (i.e. not PATCHING)
|
||||
3. Is the destination node operational (both physically and at an O/S level), and is the service (protocol / port) associated with the IER (a) present on this node, and (b) in an operational state (i.e. not PATCHING)
|
||||
4. Are there any Access Control List rules in place that prevent the application of this IER
|
||||
5. Are all switches in the (OSPF) path between source and destination operational (both physically and at an O/S level)
|
||||
1. Does the current simulation time step fall between IER start and end step
|
||||
2. Is the source node operational (both physically and at an O/S level), and is the service (protocol / port) associated with the IER (a) present on this node, and (b) in an operational state (i.e. not PATCHING)
|
||||
3. Is the destination node operational (both physically and at an O/S level), and is the service (protocol / port) associated with the IER (a) present on this node, and (b) in an operational state (i.e. not PATCHING)
|
||||
4. Are there any Access Control List rules in place that prevent the application of this IER
|
||||
5. Are all switches in the (OSPF) path between source and destination operational (both physically and at an O/S level)
|
||||
|
||||
For red agent IERs, the application of IERs between a source and destination follows a number of subtly different rules. Specifically:
|
||||
For red agent IERs, the application of IERs between a source and destination follows a number of subtly different rules. Specifically:
|
||||
|
||||
1. Does the current simulation time step fall between IER start and end step
|
||||
2. Is the source node operational, and is the service (protocol / port) associated with the IER (a) present on that node and (b) already in a compromised state
|
||||
3. Is the destination node operational, and is the service (protocol / port) associated with the IER present on that node
|
||||
4. Are there any Access Control List rules in place that prevent the application of this IER
|
||||
1. Does the current simulation time step fall between IER start and end step
|
||||
2. Is the source node operational, and is the service (protocol / port) associated with the IER (a) present on that node and (b) already in a compromised state
|
||||
3. Is the destination node operational, and is the service (protocol / port) associated with the IER present on that node
|
||||
4. Are there any Access Control List rules in place that prevent the application of this IER
|
||||
5. Are all switches in the (OSPF) path between source and destination operational (both physically and at an O/S level)
|
||||
|
||||
Assuming the rules pass, the IER is applied to all relevant links (based on use of OSPF) between source and destination.
|
||||
@@ -106,6 +106,8 @@ The status changes that can be made to a node are as follows:
|
||||
* ON
|
||||
* OFF
|
||||
* RESETTING - when a status of resetting is entered, the node will automatically exit this state after a number of steps (as defined by the nodeResetDuration configuration item) after which it returns to an ON state
|
||||
* BOOTING
|
||||
* SHUTTING_DOWN
|
||||
|
||||
* Active Nodes and Service Nodes:
|
||||
|
||||
@@ -149,7 +151,7 @@ Red agent pattern-of-life has an additional feature not found in the green patte
|
||||
Access Control List modelling
|
||||
*****************************
|
||||
|
||||
An Access Control List (ACL) is modelled to provide the means to manage traffic flows in the system. This will allow defensive agents the means to turn on / off rules, or potentially create new rules, to counter an attack.
|
||||
An Access Control List (ACL) is modelled to provide the means to manage traffic flows in the system. This will allow defensive agents the means to turn on / off rules, or potentially create new rules, to counter an attack.
|
||||
|
||||
The ACL follows a standard network firewall format. For example:
|
||||
|
||||
@@ -254,6 +256,8 @@ For the nodes, the following values are represented:
|
||||
* 1 = ON
|
||||
* 2 = OFF
|
||||
* 3 = RESETTING
|
||||
* 4 = SHUTTING_DOWN
|
||||
* 5 = BOOTING
|
||||
|
||||
* SoftwareState:
|
||||
|
||||
@@ -303,7 +307,7 @@ Each ``node_info`` contains the following:
|
||||
.. code-block::
|
||||
|
||||
[
|
||||
hardware_state (0=none, 1=ON, 2=OFF, 3=RESETTING)
|
||||
hardware_state (0=none, 1=ON, 2=OFF, 3=RESETTING, 4=SHUTTING_DOWN, 5=BOOTING)
|
||||
software_state (0=none, 1=GOOD, 2=PATCHING, 3=COMPROMISED)
|
||||
file_system_state (0=none, 1=GOOD, 2=CORRUPT, 3=DESTROYED, 4=REPAIRING, 5=RESTORING)
|
||||
service1_state (0=none, 1=GOOD, 2=PATCHING, 3=COMPROMISED)
|
||||
|
||||
@@ -5,17 +5,22 @@ The Config Files Explained
|
||||
|
||||
PrimAITE uses two configuration files for its operation:
|
||||
|
||||
* config_main.yaml - used to define the top-level settings of the PrimAITE environment, and the session that is to be run.
|
||||
* config_[name].yaml - used to define the low-level settings of a session, including the network laydown, green / red agent information exchange requirements (IERSs), Access Control Rules, Action Space type, and the number of steps in each episode.
|
||||
* **The Training Config**
|
||||
|
||||
config_main.yaml:
|
||||
*****************
|
||||
Used to define the top-level settings of the PrimAITE environment, the reward values, and the session that is to be run.
|
||||
|
||||
The config_main.yaml file consists of the following attributes:
|
||||
* **The Lay Down Config**
|
||||
|
||||
Used to define the low-level settings of a session, including the network laydown, green / red agent information exchange requirements (IERSs) and Access Control Rules.
|
||||
|
||||
Environment Config:
|
||||
*******************
|
||||
|
||||
The environment config file consists of the following attributes:
|
||||
|
||||
**Generic Config Values**
|
||||
|
||||
* **agentIdentifier** [enum]
|
||||
* **agent_identifier** [enum]
|
||||
|
||||
This identifies the agent to use for the session. Select from one of the following:
|
||||
|
||||
@@ -23,61 +28,70 @@ The config_main.yaml file consists of the following attributes:
|
||||
* STABLE_BASELINES3_PPO - Use a SB3 PPO agent
|
||||
* STABLE_BASELINES3_A2C - use a SB3 A2C agent
|
||||
|
||||
* **numEpisodes** [int]
|
||||
* **action_type** [enum]
|
||||
|
||||
This defines the number of episodes that the agent will train or be evaluated over. Each episode consists of a number of steps (with step number defined in the config_[name].yaml file)
|
||||
Determines whether a NODE, ACL, or ANY (combined NODE & ACL) action space format is adopted for the session
|
||||
|
||||
* **timeDelay** [int]
|
||||
|
||||
* **num_episodes** [int]
|
||||
|
||||
This defines the number of episodes that the agent will train or be evaluated over.
|
||||
|
||||
* **num_steps** [int]
|
||||
|
||||
Determines the number of steps to run in each episode of the session
|
||||
|
||||
|
||||
* **time_delay** [int]
|
||||
|
||||
The time delay (in milliseconds) to take between each step when running a GENERIC agent session
|
||||
|
||||
* **configFilename** [filename]
|
||||
|
||||
The name of the config_[name].yaml file to use for this session
|
||||
|
||||
* **sessionType** [text]
|
||||
* **session_type** [text]
|
||||
|
||||
Type of session to be run (TRAINING or EVALUATION)
|
||||
|
||||
* **loadAgent** [bool]
|
||||
* **load_agent** [bool]
|
||||
|
||||
Determine whether to load an agent from file
|
||||
|
||||
* **agentLoadFile** [text]
|
||||
* **agent_load_file** [text]
|
||||
|
||||
File path and file name of agent if you're loading one in
|
||||
|
||||
* **observationSpaceHighValue** [int]
|
||||
* **observation_space_high_value** [int]
|
||||
|
||||
The high value to use for values in the observation space. This is set to 1000000000 by default, and should not need changing in most cases
|
||||
|
||||
**Reward-Based Config Values**
|
||||
|
||||
* **Generic [allOk]** [int]
|
||||
Rewards are calculated based on the difference between the current state and reference state (the 'should be' state) of the environment.
|
||||
|
||||
* **Generic [all_ok]** [int]
|
||||
|
||||
The score to give when the current situation (for a given component) is no different from that expected in the baseline (i.e. as though no blue or red agent actions had been undertaken)
|
||||
|
||||
* **Node Hardware State [offShouldBeOn]** [int]
|
||||
* **Node Hardware State [off_should_be_on]** [int]
|
||||
|
||||
The score to give when the node should be on, but is off
|
||||
|
||||
* **Node Hardware State [offShouldBeResetting]** [int]
|
||||
* **Node Hardware State [off_should_be_resetting]** [int]
|
||||
|
||||
The score to give when the node should be resetting, but is off
|
||||
|
||||
* **Node Hardware State [onShouldBeOff]** [int]
|
||||
* **Node Hardware State [on_should_be_off]** [int]
|
||||
|
||||
The score to give when the node should be off, but is on
|
||||
|
||||
* **Node Hardware State [onShouldBeResetting]** [int]
|
||||
* **Node Hardware State [on_should_be_resetting]** [int]
|
||||
|
||||
The score to give when the node should be resetting, but is on
|
||||
|
||||
* **Node Hardware State [resettingShouldBeOn]** [int]
|
||||
* **Node Hardware State [resetting_should_be_on]** [int]
|
||||
|
||||
The score to give when the node should be on, but is resetting
|
||||
|
||||
* **Node Hardware State [resettingShouldBeOff]** [int]
|
||||
* **Node Hardware State [resetting_should_be_off]** [int]
|
||||
|
||||
The score to give when the node should be off, but is resetting
|
||||
|
||||
@@ -85,27 +99,27 @@ The config_main.yaml file consists of the following attributes:
|
||||
|
||||
The score to give when the node is resetting
|
||||
|
||||
* **Node Operating System or Service State [goodShouldBePatching]** [int]
|
||||
* **Node Operating System or Service State [good_should_be_patching]** [int]
|
||||
|
||||
The score to give when the state should be patching, but is good
|
||||
|
||||
* **Node Operating System or Service State [goodShouldBeCompromised]** [int]
|
||||
* **Node Operating System or Service State [good_should_be_compromised]** [int]
|
||||
|
||||
The score to give when the state should be compromised, but is good
|
||||
|
||||
* **Node Operating System or Service State [goodShouldBeOverwhelmed]** [int]
|
||||
* **Node Operating System or Service State [good_should_be_overwhelmed]** [int]
|
||||
|
||||
The score to give when the state should be overwhelmed, but is good
|
||||
|
||||
* **Node Operating System or Service State [patchingShouldBeGood]** [int]
|
||||
* **Node Operating System or Service State [patching_should_be_good]** [int]
|
||||
|
||||
The score to give when the state should be good, but is patching
|
||||
|
||||
* **Node Operating System or Service State [patchingShouldBeCompromised]** [int]
|
||||
* **Node Operating System or Service State [patching_should_be_compromised]** [int]
|
||||
|
||||
The score to give when the state should be compromised, but is patching
|
||||
|
||||
* **Node Operating System or Service State [patchingShouldBeOverwhelmed]** [int]
|
||||
* **Node Operating System or Service State [patching_should_be_overwhelmed]** [int]
|
||||
|
||||
The score to give when the state should be overwhelmed, but is patching
|
||||
|
||||
@@ -113,15 +127,15 @@ The config_main.yaml file consists of the following attributes:
|
||||
|
||||
The score to give when the state is patching
|
||||
|
||||
* **Node Operating System or Service State [compromisedShouldBeGood]** [int]
|
||||
* **Node Operating System or Service State [compromised_should_be_good]** [int]
|
||||
|
||||
The score to give when the state should be good, but is compromised
|
||||
|
||||
* **Node Operating System or Service State [compromisedShouldBePatching]** [int]
|
||||
* **Node Operating System or Service State [compromised_should_be_patching]** [int]
|
||||
|
||||
The score to give when the state should be patching, but is compromised
|
||||
|
||||
* **Node Operating System or Service State [compromisedShouldBeOverwhelmed]** [int]
|
||||
* **Node Operating System or Service State [compromised_should_be_overwhelmed]** [int]
|
||||
|
||||
The score to give when the state should be overwhelmed, but is compromised
|
||||
|
||||
@@ -129,15 +143,15 @@ The config_main.yaml file consists of the following attributes:
|
||||
|
||||
The score to give when the state is compromised
|
||||
|
||||
* **Node Operating System or Service State [overwhelmedShouldBeGood]** [int]
|
||||
* **Node Operating System or Service State [overwhelmed_should_be_good]** [int]
|
||||
|
||||
The score to give when the state should be good, but is overwhelmed
|
||||
|
||||
* **Node Operating System or Service State [overwhelmedShouldBePatching]** [int]
|
||||
* **Node Operating System or Service State [overwhelmed_should_be_patching]** [int]
|
||||
|
||||
The score to give when the state should be patching, but is overwhelmed
|
||||
|
||||
* **Node Operating System or Service State [overwhelmedShouldBeCompromised]** [int]
|
||||
* **Node Operating System or Service State [overwhelmed_should_be_compromised]** [int]
|
||||
|
||||
The score to give when the state should be compromised, but is overwhelmed
|
||||
|
||||
@@ -145,35 +159,35 @@ The config_main.yaml file consists of the following attributes:
|
||||
|
||||
The score to give when the state is overwhelmed
|
||||
|
||||
* **Node File System State [goodShouldBeRepairing]** [int]
|
||||
* **Node File System State [good_should_be_repairing]** [int]
|
||||
|
||||
The score to give when the state should be repairing, but is good
|
||||
|
||||
* **Node File System State [goodShouldBeRestoring]** [int]
|
||||
* **Node File System State [good_should_be_restoring]** [int]
|
||||
|
||||
The score to give when the state should be restoring, but is good
|
||||
|
||||
* **Node File System State [goodShouldBeCorrupt]** [int]
|
||||
* **Node File System State [good_should_be_corrupt]** [int]
|
||||
|
||||
The score to give when the state should be corrupt, but is good
|
||||
|
||||
* **Node File System State [goodShouldBeDestroyed]** [int]
|
||||
* **Node File System State [good_should_be_destroyed]** [int]
|
||||
|
||||
The score to give when the state should be destroyed, but is good
|
||||
|
||||
* **Node File System State [repairingShouldBeGood]** [int]
|
||||
* **Node File System State [repairing_should_be_good]** [int]
|
||||
|
||||
The score to give when the state should be good, but is repairing
|
||||
|
||||
* **Node File System State [repairingShouldBeRestoring]** [int]
|
||||
* **Node File System State [repairing_should_be_restoring]** [int]
|
||||
|
||||
The score to give when the state should be restoring, but is repairing
|
||||
|
||||
* **Node File System State [repairingShouldBeCorrupt]** [int]
|
||||
* **Node File System State [repairing_should_be_corrupt]** [int]
|
||||
|
||||
The score to give when the state should be corrupt, but is repairing
|
||||
|
||||
* **Node File System State [repairingShouldBeDestroyed]** [int]
|
||||
* **Node File System State [repairing_should_be_destroyed]** [int]
|
||||
|
||||
The score to give when the state should be destroyed, but is repairing
|
||||
|
||||
@@ -181,19 +195,19 @@ The config_main.yaml file consists of the following attributes:
|
||||
|
||||
The score to give when the state is repairing
|
||||
|
||||
* **Node File System State [restoringShouldBeGood]** [int]
|
||||
* **Node File System State [restoring_should_be_good]** [int]
|
||||
|
||||
The score to give when the state should be good, but is restoring
|
||||
|
||||
* **Node File System State [restoringShouldBeRepairing]** [int]
|
||||
* **Node File System State [restoring_should_be_repairing]** [int]
|
||||
|
||||
The score to give when the state should be repairing, but is restoring
|
||||
|
||||
* **Node File System State [restoringShouldBeCorrupt]** [int]
|
||||
* **Node File System State [restoring_should_be_corrupt]** [int]
|
||||
|
||||
The score to give when the state should be corrupt, but is restoring
|
||||
|
||||
* **Node File System State [restoringShouldBeDestroyed]** [int]
|
||||
* **Node File System State [restoring_should_be_destroyed]** [int]
|
||||
|
||||
The score to give when the state should be destroyed, but is restoring
|
||||
|
||||
@@ -201,19 +215,19 @@ The config_main.yaml file consists of the following attributes:
|
||||
|
||||
The score to give when the state is restoring
|
||||
|
||||
* **Node File System State [corruptShouldBeGood]** [int]
|
||||
* **Node File System State [corrupt_should_be_good]** [int]
|
||||
|
||||
The score to give when the state should be good, but is corrupt
|
||||
|
||||
* **Node File System State [corruptShouldBeRepairing]** [int]
|
||||
* **Node File System State [corrupt_should_be_repairing]** [int]
|
||||
|
||||
The score to give when the state should be repairing, but is corrupt
|
||||
|
||||
* **Node File System State [corruptShouldBeRestoring]** [int]
|
||||
* **Node File System State [corrupt_should_be_restoring]** [int]
|
||||
|
||||
The score to give when the state should be restoring, but is corrupt
|
||||
|
||||
* **Node File System State [corruptShouldBeDestroyed]** [int]
|
||||
* **Node File System State [corrupt_should_be_destroyed]** [int]
|
||||
|
||||
The score to give when the state should be destroyed, but is corrupt
|
||||
|
||||
@@ -221,19 +235,19 @@ The config_main.yaml file consists of the following attributes:
|
||||
|
||||
The score to give when the state is corrupt
|
||||
|
||||
* **Node File System State [destroyedShouldBeGood]** [int]
|
||||
* **Node File System State [destroyed_should_be_good]** [int]
|
||||
|
||||
The score to give when the state should be good, but is destroyed
|
||||
|
||||
* **Node File System State [destroyedShouldBeRepairing]** [int]
|
||||
* **Node File System State [destroyed_should_be_repairing]** [int]
|
||||
|
||||
The score to give when the state should be repairing, but is destroyed
|
||||
|
||||
* **Node File System State [destroyedShouldBeRestoring]** [int]
|
||||
* **Node File System State [destroyed_should_be_restoring]** [int]
|
||||
|
||||
The score to give when the state should be restoring, but is destroyed
|
||||
|
||||
* **Node File System State [destroyedShouldBeCorrupt]** [int]
|
||||
* **Node File System State [destroyed_should_be_corrupt]** [int]
|
||||
|
||||
The score to give when the state should be corrupt, but is destroyed
|
||||
|
||||
@@ -245,44 +259,44 @@ The config_main.yaml file consists of the following attributes:
|
||||
|
||||
The score to give when the state is scanning
|
||||
|
||||
* **IER Status [redIerRunning]** [int]
|
||||
* **IER Status [red_ier_running]** [int]
|
||||
|
||||
The score to give when a red agent IER is permitted to run
|
||||
|
||||
* **IER Status [greenIerBlocked]** [int]
|
||||
* **IER Status [green_ier_blocked]** [int]
|
||||
|
||||
The score to give when a green agent IER is prevented from running
|
||||
|
||||
**Patching / Reset Durations**
|
||||
|
||||
* **osPatchingDuration** [int]
|
||||
* **os_patching_duration** [int]
|
||||
|
||||
The number of steps to take when patching an Operating System
|
||||
|
||||
* **nodeResetDuration** [int]
|
||||
* **node_reset_duration** [int]
|
||||
|
||||
The number of steps to take when resetting a node's hardware state
|
||||
|
||||
* **servicePatchingDuration** [int]
|
||||
* **service_patching_duration** [int]
|
||||
|
||||
The number of steps to take when patching a service
|
||||
|
||||
* **fileSystemRepairingLimit** [int]:
|
||||
* **file_system_repairing_limit** [int]:
|
||||
|
||||
The number of steps to take when repairing the file system
|
||||
|
||||
* **fileSystemRestoringLimit** [int]
|
||||
* **file_system_restoring_limit** [int]
|
||||
|
||||
The number of steps to take when restoring the file system
|
||||
|
||||
* **fileSystemScanningLimit** [int]
|
||||
* **file_system_scanning_limit** [int]
|
||||
|
||||
The number of steps to take when scanning the file system
|
||||
|
||||
config_[name].yaml:
|
||||
The Lay Down Config
|
||||
*******************
|
||||
|
||||
The config_[name].yaml file consists of the following attributes:
|
||||
The lay down config file consists of the following attributes:
|
||||
|
||||
* **itemType: ACTIONS** [enum]
|
||||
|
||||
@@ -312,17 +326,15 @@ The config_[name].yaml file consists of the following attributes:
|
||||
|
||||
* **itemType: STEPS** [int]
|
||||
|
||||
Determines the number of steps to run in each episode of the session
|
||||
|
||||
* **itemType: PORTS** [int]
|
||||
* **item_type: PORTS** [int]
|
||||
|
||||
Provides a list of ports modelled in this session
|
||||
|
||||
* **itemType: SERVICES** [freetext]
|
||||
* **item_type: SERVICES** [freetext]
|
||||
|
||||
Provides a list of services modelled in this session
|
||||
|
||||
* **itemType: NODE**
|
||||
* **item_type: NODE**
|
||||
|
||||
Defines a node included in the system laydown being simulated. It should consist of the following attributes:
|
||||
|
||||
@@ -341,7 +353,7 @@ The config_[name].yaml file consists of the following attributes:
|
||||
* **port** [int]: Integer value of the port related to this service, but must match one of the ports defined for the system in the ports list
|
||||
* **state** [enum]: The initial state of the service. Can be one of GOOD, PATCHING, COMPROMISED or OVERWHELMED
|
||||
|
||||
* **itemType: LINK**
|
||||
* **item_type: LINK**
|
||||
|
||||
Defines a link included in the system laydown being simulated. It should consist of the following attributes:
|
||||
|
||||
@@ -351,53 +363,53 @@ The config_[name].yaml file consists of the following attributes:
|
||||
* **source** [int]: The ID of the source node
|
||||
* **destination** [int]: The ID of the destination node
|
||||
|
||||
* **itemType: GREEN_IER**
|
||||
* **item_type: GREEN_IER**
|
||||
|
||||
Defines a green agent Information Exchange Requirement (IER). It should consist of:
|
||||
|
||||
* **id** [int]: Unique ID for this YAML item
|
||||
* **startStep** [int]: The start step (in the episode) for this IER to begin
|
||||
* **endStep** [int]: The end step (in the episode) for this IER to finish
|
||||
* **start_step** [int]: The start step (in the episode) for this IER to begin
|
||||
* **end_step** [int]: The end step (in the episode) for this IER to finish
|
||||
* **load** [int]: The load (in bits/s) for this IER to apply to links
|
||||
* **protocol** [freetext]: The protocol to apply to the links. This must match a value in the services list
|
||||
* **port** [int]: The port that the protocol is running on. This must match a value in the ports list
|
||||
* **source** [int]: The ID of the source node
|
||||
* **destination** [int]: The ID of the destination node
|
||||
* **missionCriticality** [enum]: The mission criticality of this IER (with 5 being highest, 1 lowest)
|
||||
* **mission_criticality** [enum]: The mission criticality of this IER (with 5 being highest, 1 lowest)
|
||||
|
||||
* **itemType: RED_IER**
|
||||
* **item_type: RED_IER**
|
||||
|
||||
Defines a red agent Information Exchange Requirement (IER). It should consist of:
|
||||
|
||||
* **id** [int]: Unique ID for this YAML item
|
||||
* **startStep** [int]: The start step (in the episode) for this IER to begin
|
||||
* **endStep** [int]: The end step (in the episode) for this IER to finish
|
||||
* **start_step** [int]: The start step (in the episode) for this IER to begin
|
||||
* **end_step** [int]: The end step (in the episode) for this IER to finish
|
||||
* **load** [int]: The load (in bits/s) for this IER to apply to links
|
||||
* **protocol** [freetext]: The protocol to apply to the links. This must match a value in the services list
|
||||
* **port** [int]: The port that the protocol is running on. This must match a value in the ports list
|
||||
* **source** [int]: The ID of the source node
|
||||
* **destination** [int]: The ID of the destination node
|
||||
* **missionCriticality** [enum]: Not currently used. Default to 0
|
||||
* **mission_criticality** [enum]: Not currently used. Default to 0
|
||||
|
||||
* **itemType: GREEN_POL**
|
||||
* **item_type: GREEN_POL**
|
||||
|
||||
Defines a green agent pattern-of-life instruction. It should consist of:
|
||||
|
||||
* **id** [int]: Unique ID for this YAML item
|
||||
* **startStep** [int]: The start step (in the episode) for this PoL to begin
|
||||
* **endStep** [int]: Not currently used. Default to same as start step
|
||||
* **start_step** [int]: The start step (in the episode) for this PoL to begin
|
||||
* **end_step** [int]: Not currently used. Default to same as start step
|
||||
* **nodeId** [int]: The ID of the node to apply the PoL to
|
||||
* **type** [enum]: The type of PoL to apply. Can be one of OPERATING, OS or SERVICE
|
||||
* **protocol** [freetext]: The protocol to be affected if SERVICE type is chosen. Must match a value in the services list
|
||||
* **state** [enuum]: The state to apply to the node (which represents the PoL change). Can be one of ON, OFF or RESETTING (for node state) or GOOD, PATCHING or COMPROMISED (for Software State) or GOOD, PATCHING, COMPROMISED or OVERWHELMED (for service state)
|
||||
|
||||
* **itemType: RED_POL**
|
||||
* **item_type: RED_POL**
|
||||
|
||||
Defines a red agent pattern-of-life instruction. It should consist of:
|
||||
|
||||
* **id** [int]: Unique ID for this YAML item
|
||||
* **startStep** [int]: The start step (in the episode) for this PoL to begin
|
||||
* **endStep** [int]: Not currently used. Default to same as start step
|
||||
* **start_step** [int]: The start step (in the episode) for this PoL to begin
|
||||
* **end_step** [int]: Not currently used. Default to same as start step
|
||||
* **targetNodeId** [int]: The ID of the node to apply the PoL to
|
||||
* **initiator** [enum]: What initiates the PoL. Can be DIRECT, IER or SERVICE
|
||||
* **type** [enum]: The type of PoL to apply. Can be one of OPERATING, OS or SERVICE
|
||||
@@ -407,7 +419,7 @@ The config_[name].yaml file consists of the following attributes:
|
||||
* **sourceNodeService** [freetext]: The service on the source node to check (used for SERVICE initiator). Must match a value in the services list for this node
|
||||
* **sourceNodeServiceState** [enum]: The state of the source node service to check (used for SERVICE initiator). Can be one of GOOD, PATCHING, COMPROMISED or OVERWHELMED
|
||||
|
||||
* **itemType: ACL_RULE**
|
||||
* **item_type: ACL_RULE**
|
||||
|
||||
Defines an initial Access Control List (ACL) rule. It should consist of:
|
||||
|
||||
|
||||
65
docs/source/custom_agent.rst
Normal file
65
docs/source/custom_agent.rst
Normal file
@@ -0,0 +1,65 @@
|
||||
Custom Agents
|
||||
=============
|
||||
|
||||
|
||||
**Integrating a user defined blue agent**
|
||||
|
||||
Integrating a blue agent with PrimAITE requires some modification of the code within the main.py file. The main.py file
|
||||
consists of a number of functions, each of which will invoke training for a particular agent. These are:
|
||||
|
||||
* Generic (run_generic)
|
||||
* Stable Baselines 3 PPO (:func:`~primaite.main.run_stable_baselines3_ppo)
|
||||
* Stable Baselines 3 A2C (:func:`~primaite.main.run_stable_baselines3_a2c)
|
||||
|
||||
The selection of which agent type to use is made via the training config file. In order to train a user generated agent,
|
||||
the run_generic function should be selected, and should be modified (typically) to be:
|
||||
|
||||
.. code:: python
|
||||
|
||||
agent = MyAgent(environment, num_steps)
|
||||
for episode in range(0, num_episodes):
|
||||
agent.learn()
|
||||
env.close()
|
||||
save_agent(agent)
|
||||
|
||||
Where:
|
||||
|
||||
* *MyAgent* is the user created agent
|
||||
* *environment* is the :class:`~primaite.environment.primaite_env.Primaite` environment
|
||||
* *num_episodes* is the number of episodes in the session, as defined in the training config file
|
||||
* *num_steps* is the number of steps in an episode, as defined in the training config file
|
||||
* the *.learn()* function should be defined in the user created agent
|
||||
* the *env.close()* function is defined within PrimAITE
|
||||
* the *save_agent()* assumes that a *save()* function has been defined in the user created agent. If not, this line can
|
||||
be ommitted (although it is encouraged, since it will allow the agent to be saved and ported)
|
||||
|
||||
The code below provides a suggested format for the learn() function within the user created agent.
|
||||
It's important to include the *self.environment.reset()* call within the episode loop in order that the
|
||||
environment is reset between episodes. Note that the example below should not be considered exhaustive.
|
||||
|
||||
.. code:: python
|
||||
|
||||
def learn(self) :
|
||||
|
||||
# pre-reqs
|
||||
|
||||
# reset the environment
|
||||
self.environment.reset()
|
||||
done = False
|
||||
|
||||
for step in range(max_steps):
|
||||
# calculate the action
|
||||
action = ...
|
||||
|
||||
# execute the environment step
|
||||
new_state, reward, done, info = self.environment.step(action)
|
||||
|
||||
# algorithm updates
|
||||
...
|
||||
|
||||
# update to our new state
|
||||
state = new_state
|
||||
|
||||
# if done, finish episode
|
||||
if done == True:
|
||||
break
|
||||
@@ -1,24 +1,10 @@
|
||||
.. _dependencies:
|
||||
.. role:: raw-html(raw)
|
||||
:format: html
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
PrimAITE Dependencies
|
||||
=====================
|
||||
---------------------
|
||||
|
||||
PrimAITE is built with the following versions of dependencies:
|
||||
|
||||
* Python 3.10.9
|
||||
* PyYAML 6.0
|
||||
* numpy 1.23.5
|
||||
* networkx 2.8.8
|
||||
* gym 0.21.0
|
||||
* matplotlib 3.6.2
|
||||
* stable_baselines_3 1.6.2
|
||||
|
||||
The latest release of PrimAITE has been tested against the following versions of dependencies:
|
||||
|
||||
* Python 3.10.9
|
||||
* PyYAML 6.0
|
||||
* numpy 1.23.5
|
||||
* networkx 2.8.8
|
||||
* gym 0.21.0
|
||||
* matplotlib 3.6.2
|
||||
* stable_baselines_3 1.6.2
|
||||
.. include:: primaite-dependencies.rst
|
||||
|
||||
385
docs/source/primaite-dependencies.rst
Normal file
385
docs/source/primaite-dependencies.rst
Normal file
@@ -0,0 +1,385 @@
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| Name | Version | License | URL |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| Babel | 2.12.1 | BSD License | https://babel.pocoo.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| GPUtil | 1.4.0 | MIT | https://github.com/anderskm/gputil |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| Gymnasium | 0.26.3 | MIT | https://gymnasium.farama.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| Jinja2 | 3.1.2 | BSD License | https://palletsprojects.com/p/jinja/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| Markdown | 3.4.3 | BSD License | https://Python-Markdown.github.io/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| MarkupSafe | 2.1.2 | BSD License | https://palletsprojects.com/p/markupsafe/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| Pillow | 9.5.0 | Historical Permission Notice and Disclaimer (HPND) | https://python-pillow.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| PyWavelets | 1.4.1 | MIT License | https://github.com/PyWavelets/pywt |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| PyYAML | 6.0 | MIT License | https://pyyaml.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| Pygments | 2.15.1 | BSD License | https://pygments.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| Send2Trash | 1.8.2 | BSD License | https://github.com/arsenetar/send2trash |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| Sphinx | 6.1.3 | BSD License | https://www.sphinx-doc.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| Werkzeug | 2.3.4 | BSD License | UNKNOWN |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| absl-py | 1.4.0 | Apache Software License | https://github.com/abseil/abseil-py |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| aiofiles | 22.1.0 | Apache Software License | https://github.com/Tinche/aiofiles |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| aiosignal | 1.3.1 | Apache Software License | https://github.com/aio-libs/aiosignal |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| aiosqlite | 0.19.0 | MIT License | UNKNOWN |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| alabaster | 0.7.13 | BSD License | https://alabaster.readthedocs.io |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| anyio | 3.7.0 | MIT License | https://anyio.readthedocs.io/en/stable/versionhistory.html |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| argon2-cffi | 21.3.0 | MIT License | https://github.com/hynek/argon2-cffi/blob/main/CHANGELOG.md |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| argon2-cffi-bindings | 21.2.0 | MIT License | https://github.com/hynek/argon2-cffi-bindings |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| arrow | 1.2.3 | Apache Software License | https://arrow.readthedocs.io |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| asttokens | 2.2.1 | Apache 2.0 | https://github.com/gristlabs/asttokens |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| attrs | 23.1.0 | MIT License | https://www.attrs.org/en/stable/changelog.html |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| backcall | 0.2.0 | BSD License | https://github.com/takluyver/backcall |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| beautifulsoup4 | 4.12.2 | MIT License | https://www.crummy.com/software/BeautifulSoup/bs4/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| bleach | 6.0.0 | Apache Software License | https://github.com/mozilla/bleach |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| build | 0.10.0 | MIT License | UNKNOWN |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| cachetools | 5.3.0 | MIT License | https://github.com/tkem/cachetools/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| certifi | 2023.5.7 | Mozilla Public License 2.0 (MPL 2.0) | https://github.com/certifi/python-certifi |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| cffi | 1.15.1 | MIT License | http://cffi.readthedocs.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| cfgv | 3.3.1 | MIT License | https://github.com/asottile/cfgv |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| charset-normalizer | 3.1.0 | MIT License | https://github.com/Ousret/charset_normalizer |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| click | 8.1.3 | BSD License | https://palletsprojects.com/p/click/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| cloudpickle | 2.2.1 | BSD License | https://github.com/cloudpipe/cloudpickle |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| colorama | 0.4.6 | BSD License | https://github.com/tartley/colorama |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| comm | 0.1.3 | BSD License | https://github.com/ipython/comm |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| contourpy | 1.0.7 | BSD License | UNKNOWN |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| coverage | 7.2.6 | Apache Software License | https://github.com/nedbat/coveragepy |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| cycler | 0.11.0 | BSD License | https://github.com/matplotlib/cycler |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| debugpy | 1.6.7 | Eclipse Public License 2.0 (EPL-2.0); MIT License | https://aka.ms/debugpy |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| decorator | 5.1.1 | BSD License | https://github.com/micheles/decorator |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| defusedxml | 0.7.1 | Python Software Foundation License | https://github.com/tiran/defusedxml |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| distlib | 0.3.6 | Python Software Foundation License | https://github.com/pypa/distlib |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| dm-tree | 0.1.8 | Apache Software License | https://github.com/deepmind/tree |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| docutils | 0.19 | BSD License; GNU General Public License (GPL); Public Domain; Python Software Foundation License | https://docutils.sourceforge.io/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| exceptiongroup | 1.1.1 | MIT License | https://github.com/agronholm/exceptiongroup/blob/main/CHANGES.rst |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| executing | 1.2.0 | MIT License | https://github.com/alexmojaki/executing |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| fastjsonschema | 2.17.1 | BSD License | https://github.com/horejsek/python-fastjsonschema |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| filelock | 3.12.0 | The Unlicense (Unlicense) | https://github.com/tox-dev/py-filelock |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| flake8 | 6.0.0 | MIT License | https://github.com/pycqa/flake8 |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| fonttools | 4.39.4 | MIT License | http://github.com/fonttools/fonttools |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| fqdn | 1.5.1 | Mozilla Public License 2.0 (MPL 2.0) | https://github.com/ypcrts/fqdn |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| frozenlist | 1.3.3 | Apache Software License | https://github.com/aio-libs/frozenlist |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| furo | 2023.3.27 | MIT License | UNKNOWN |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| google-auth | 2.19.0 | Apache Software License | https://github.com/googleapis/google-auth-library-python |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| google-auth-oauthlib | 1.0.0 | Apache Software License | https://github.com/GoogleCloudPlatform/google-auth-library-python-oauthlib |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| grpcio | 1.51.3 | Apache Software License | https://grpc.io |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| gym | 0.21.0 | UNKNOWN | https://github.com/openai/gym |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| gymnasium-notices | 0.0.1 | MIT License | https://github.com/Farama-Foundation/gym-notices |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| identify | 2.5.24 | MIT License | https://github.com/pre-commit/identify |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| idna | 3.4 | BSD License | https://github.com/kjd/idna |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| imageio | 2.29.0 | BSD License | https://github.com/imageio/imageio |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| imagesize | 1.4.1 | MIT License | https://github.com/shibukawa/imagesize_py |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| importlib-metadata | 4.13.0 | Apache Software License | https://github.com/python/importlib_metadata |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| iniconfig | 2.0.0 | MIT License | https://github.com/pytest-dev/iniconfig |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| ipykernel | 6.23.1 | BSD License | https://ipython.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| ipython | 8.13.2 | BSD License | https://ipython.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| ipython-genutils | 0.2.0 | BSD License | http://ipython.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| isoduration | 20.11.0 | ISC License (ISCL) | https://github.com/bolsote/isoduration |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jedi | 0.18.2 | MIT License | https://github.com/davidhalter/jedi |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| json5 | 0.9.14 | Apache Software License | https://github.com/dpranke/pyjson5 |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jsonpointer | 2.3 | BSD License | https://github.com/stefankoegl/python-json-pointer |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jsonschema | 4.17.3 | MIT License | https://github.com/python-jsonschema/jsonschema |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jupyter-events | 0.6.3 | BSD License | http://jupyter.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jupyter-ydoc | 0.2.4 | BSD 3-Clause License | https://jupyter.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jupyter_client | 8.2.0 | BSD License | https://jupyter.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jupyter_core | 5.3.0 | BSD License | https://jupyter.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jupyter_server | 2.6.0 | BSD License | https://jupyter-server.readthedocs.io |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jupyter_server_fileid | 0.9.0 | BSD License | UNKNOWN |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jupyter_server_terminals | 0.4.4 | BSD License | https://jupyter.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jupyter_server_ydoc | 0.6.1 | BSD License | https://jupyter.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jupyterlab | 3.6.1 | BSD License | https://jupyter.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jupyterlab-pygments | 0.2.2 | BSD | https://github.com/jupyterlab/jupyterlab_pygments |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| jupyterlab_server | 2.22.1 | BSD License | https://jupyterlab-server.readthedocs.io |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| kiwisolver | 1.4.4 | BSD License | UNKNOWN |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| lazy_loader | 0.2 | BSD License | https://github.com/scientific-python/lazy_loader |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| lz4 | 4.3.2 | BSD License | https://github.com/python-lz4/python-lz4 |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| markdown-it-py | 2.2.0 | MIT License | https://github.com/executablebooks/markdown-it-py |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| matplotlib | 3.7.1 | Python Software Foundation License | https://matplotlib.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| matplotlib-inline | 0.1.6 | BSD 3-Clause | https://github.com/ipython/matplotlib-inline |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| mccabe | 0.7.0 | MIT License | https://github.com/pycqa/mccabe |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| mdurl | 0.1.2 | MIT License | https://github.com/executablebooks/mdurl |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| mistune | 2.0.5 | BSD License | https://github.com/lepture/mistune |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| mock | 5.0.2 | BSD License | http://mock.readthedocs.org/en/latest/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| mpmath | 1.3.0 | BSD License | http://mpmath.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| msgpack | 1.0.5 | Apache Software License | https://msgpack.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| nbclassic | 1.0.0 | BSD License | https://github.com/jupyter/nbclassic |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| nbclient | 0.8.0 | BSD License | https://jupyter.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| nbconvert | 7.4.0 | BSD License | https://jupyter.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| nbformat | 5.9.0 | BSD License | https://jupyter.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| nest-asyncio | 1.5.6 | BSD License | https://github.com/erdewit/nest_asyncio |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| networkx | 3.1 | BSD License | https://networkx.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| nodeenv | 1.8.0 | BSD License | https://github.com/ekalinin/nodeenv |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| notebook | 6.5.4 | BSD License | http://jupyter.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| notebook_shim | 0.2.3 | BSD License | UNKNOWN |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| numpy | 1.23.5 | BSD License | https://www.numpy.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| oauthlib | 3.2.2 | BSD License | https://github.com/oauthlib/oauthlib |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| overrides | 7.3.1 | Apache License, Version 2.0 | https://github.com/mkorpela/overrides |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| packaging | 23.1 | Apache Software License; BSD License | https://github.com/pypa/packaging |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pandas | 2.0.1 | BSD License | UNKNOWN |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pandocfilters | 1.5.0 | BSD License | http://github.com/jgm/pandocfilters |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| parso | 0.8.3 | MIT License | https://github.com/davidhalter/parso |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pickleshare | 0.7.5 | MIT License | https://github.com/pickleshare/pickleshare |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| platformdirs | 3.5.1 | MIT License | https://github.com/platformdirs/platformdirs |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pluggy | 1.0.0 | MIT License | https://github.com/pytest-dev/pluggy |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pre-commit | 2.20.0 | MIT License | https://github.com/pre-commit/pre-commit |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| primaite | 1.2.1 | GFX | UNKNOWN |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| prometheus-client | 0.17.0 | Apache Software License | https://github.com/prometheus/client_python |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| prompt-toolkit | 3.0.38 | BSD License | https://github.com/prompt-toolkit/python-prompt-toolkit |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| protobuf | 3.20.3 | BSD-3-Clause | https://developers.google.com/protocol-buffers/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| psutil | 5.9.5 | BSD License | https://github.com/giampaolo/psutil |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pure-eval | 0.2.2 | MIT License | http://github.com/alexmojaki/pure_eval |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pyasn1 | 0.5.0 | BSD License | https://github.com/pyasn1/pyasn1 |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pyasn1-modules | 0.3.0 | BSD License | https://github.com/pyasn1/pyasn1-modules |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pycodestyle | 2.10.0 | MIT License | https://pycodestyle.pycqa.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pycparser | 2.21 | BSD License | https://github.com/eliben/pycparser |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pyflakes | 3.0.1 | MIT License | https://github.com/PyCQA/pyflakes |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pyparsing | 3.0.9 | MIT License | https://github.com/pyparsing/pyparsing/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pyproject_hooks | 1.0.0 | MIT License | https://github.com/pypa/pyproject-hooks |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pyrsistent | 0.19.3 | MIT License | https://github.com/tobgu/pyrsistent/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pytest | 7.2.0 | MIT License | https://docs.pytest.org/en/latest/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pytest-cov | 4.0.0 | MIT License | https://github.com/pytest-dev/pytest-cov |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pytest-flake8 | 1.1.1 | BSD License | https://github.com/tholo/pytest-flake8 |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| python-dateutil | 2.8.2 | Apache Software License; BSD License | https://github.com/dateutil/dateutil |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| python-json-logger | 2.0.7 | BSD License | http://github.com/madzak/python-json-logger |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pytz | 2023.3 | MIT License | http://pythonhosted.org/pytz |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pywin32 | 306 | Python Software Foundation License | https://github.com/mhammond/pywin32 |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pywinpty | 2.0.10 | MIT | UNKNOWN |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| pyzmq | 25.1.0 | BSD License; GNU Library or Lesser General Public License (LGPL) | https://pyzmq.readthedocs.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| ray | 2.2.0 | Apache 2.0 | https://github.com/ray-project/ray |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| requests | 2.31.0 | Apache Software License | https://requests.readthedocs.io |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| requests-oauthlib | 1.3.1 | BSD License | https://github.com/requests/requests-oauthlib |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| rfc3339-validator | 0.1.4 | MIT License | https://github.com/naimetti/rfc3339-validator |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| rfc3986-validator | 0.1.1 | MIT License | https://github.com/naimetti/rfc3986-validator |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| rich | 13.3.5 | MIT License | https://github.com/Textualize/rich |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| rsa | 4.9 | Apache Software License | https://stuvel.eu/rsa |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| scikit-image | 0.20.0 | BSD License | https://scikit-image.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| scipy | 1.10.1 | BSD License | https://scipy.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| shellingham | 1.5.0.post1 | ISC License (ISCL) | https://github.com/sarugaku/shellingham |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| six | 1.16.0 | MIT License | https://github.com/benjaminp/six |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| sniffio | 1.3.0 | Apache Software License; MIT License | https://github.com/python-trio/sniffio |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| snowballstemmer | 2.2.0 | BSD License | https://github.com/snowballstem/snowball |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| soupsieve | 2.4.1 | MIT License | https://github.com/facelessuser/soupsieve |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| sphinx-basic-ng | 1.0.0b1 | MIT License | https://github.com/pradyunsg/sphinx-basic-ng |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| sphinx-code-tabs | 0.5.3 | The Unlicense (Unlicense) | https://github.com/coldfix/sphinx-code-tabs |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| sphinx-copybutton | 0.5.2 | MIT License | https://github.com/executablebooks/sphinx-copybutton |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| sphinxcontrib-applehelp | 1.0.4 | BSD License | https://www.sphinx-doc.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| sphinxcontrib-devhelp | 1.0.2 | BSD License | http://sphinx-doc.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| sphinxcontrib-htmlhelp | 2.0.1 | BSD License | https://www.sphinx-doc.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| sphinxcontrib-jsmath | 1.0.1 | BSD License | http://sphinx-doc.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| sphinxcontrib-qthelp | 1.0.3 | BSD License | http://sphinx-doc.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| sphinxcontrib-serializinghtml | 1.1.5 | BSD License | http://sphinx-doc.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| stable-baselines3 | 1.6.2 | MIT | https://github.com/DLR-RM/stable-baselines3 |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| stack-data | 0.6.2 | MIT License | http://github.com/alexmojaki/stack_data |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| sympy | 1.12 | BSD License | https://sympy.org |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| tabulate | 0.9.0 | MIT License | https://github.com/astanin/python-tabulate |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| tensorboard | 2.12.3 | Apache Software License | https://github.com/tensorflow/tensorboard |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| tensorboard-data-server | 0.7.0 | Apache Software License | https://github.com/tensorflow/tensorboard/tree/master/tensorboard/data/server |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| tensorboard-plugin-wit | 1.8.1 | Apache 2.0 | https://whatif-tool.dev |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| tensorboardX | 2.6 | MIT License | https://github.com/lanpa/tensorboardX |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| terminado | 0.17.1 | BSD License | https://github.com/jupyter/terminado |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| tifffile | 2023.4.12 | BSD License | https://www.cgohlke.com |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| tinycss2 | 1.2.1 | BSD License | https://www.courtbouillon.org/tinycss2 |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| toml | 0.10.2 | MIT License | https://github.com/uiri/toml |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| tomli | 2.0.1 | MIT License | https://github.com/hukkin/tomli |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| torch | 2.0.1 | BSD License | https://pytorch.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| tornado | 6.3.2 | Apache Software License | http://www.tornadoweb.org/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| traitlets | 5.9.0 | BSD License | https://github.com/ipython/traitlets |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| typer | 0.9.0 | MIT License | https://github.com/tiangolo/typer |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| typing_extensions | 4.6.2 | Python Software Foundation License | https://github.com/python/typing_extensions/issues |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| tzdata | 2023.3 | Apache Software License | https://github.com/python/tzdata |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| uri-template | 1.2.0 | MIT License | https://github.com/plinss/uri_template/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| urllib3 | 1.26.16 | MIT License | https://urllib3.readthedocs.io/ |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| virtualenv | 20.21.0 | MIT License | https://github.com/pypa/virtualenv |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| webcolors | 1.13 | BSD License | UNKNOWN |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| webencodings | 0.5.1 | BSD License | https://github.com/SimonSapin/python-webencodings |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| websocket-client | 1.5.2 | Apache Software License | https://github.com/websocket-client/websocket-client.git |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| y-py | 0.5.9 | MIT License | https://github.com/y-crdt/ypy |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| ypy-websocket | 0.8.2 | UNKNOWN | https://github.com/y-crdt/ypy-websocket |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
| zipp | 3.15.0 | MIT License | https://github.com/jaraco/zipp |
|
||||
+-------------------------------+-------------+--------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+
|
||||
92
docs/source/primaite_session.rst
Normal file
92
docs/source/primaite_session.rst
Normal file
@@ -0,0 +1,92 @@
|
||||
Run a PrimAITE Session
|
||||
======================
|
||||
|
||||
Run
|
||||
---
|
||||
|
||||
A PrimAITE session can be ran either with the ``primaite session`` command from the cli
|
||||
(See :func:`primaite.cli.session`), or by calling :func:`primaite.main.run` from a Python terminal or Jupyter Notebook.
|
||||
Both the ``primaite session`` and :func:`primaite.main.run` take a training config and a lay down config as parameters.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. code-tab:: bash
|
||||
:caption: Unix CLI
|
||||
|
||||
cd ~/primaite
|
||||
source ./.venv/bin/activate
|
||||
primaite session ./config/my_training_config.yaml ./config/my_lay_down_config.yaml
|
||||
|
||||
.. code-tab:: bash
|
||||
:caption: Powershell CLI
|
||||
|
||||
cd ~\primaite
|
||||
.\.venv\Scripts\activate
|
||||
primaite session .\config\my_training_config.yaml .\config\my_lay_down_config.yaml
|
||||
|
||||
|
||||
.. code-tab:: python
|
||||
:caption: Python
|
||||
|
||||
from primaite.main import run
|
||||
|
||||
training_config = <path to training config yaml file>
|
||||
lay_down_config = <path to lay down config yaml file>
|
||||
run(training_config, lay_down_config)
|
||||
|
||||
When a session is ran, a session output sub-directory is created in the users app sessions directory (``~/primaite/sessions``).
|
||||
The sub-directory is formatted as such: ``~/primaite/sessions/<yyyy-mm-dd>/<yyyy-mm-dd>_<hh-mm-dd>/``
|
||||
|
||||
For example, when running a session at 17:30:00 on 31st January 2023, the session will output to:
|
||||
``~/primaite/sessions/2023-01-31/2023-01-31_17-30-00/``.
|
||||
|
||||
|
||||
Outputs
|
||||
-------
|
||||
|
||||
PrimAITE produces four types of outputs:
|
||||
|
||||
* Session Metadata
|
||||
* Results
|
||||
* Diagrams
|
||||
* Saved agents
|
||||
|
||||
|
||||
**Session Metadata**
|
||||
|
||||
PrimAITE creates a ``session_metadata.json`` file that contains the following metadata:
|
||||
|
||||
* **uuid** - The UUID assigned to the session upon instantiation.
|
||||
* **start_datetime** - The date & time the session started in iso format.
|
||||
* **end_datetime** - The date & time the session ended in iso format.
|
||||
* **total_episodes** - The total number of training episodes completed.
|
||||
* **total_time_steps** - The total number of training time steps completed.
|
||||
* **env**
|
||||
* **training_config**
|
||||
* **All training config items**
|
||||
* **lay_down_config**
|
||||
* **All lay down config items**
|
||||
|
||||
|
||||
**Results**
|
||||
|
||||
PrimAITE automatically creates two sets of results from each session:
|
||||
|
||||
* Average reward per episode - a csv file listing the average reward for each episode of the session. This provides, for example, an indication of the change over a training session of the reward value
|
||||
* All transactions - a csv file listing the following values for every step of every episode:
|
||||
|
||||
* Timestamp
|
||||
* Episode number
|
||||
* Step number
|
||||
* Initial observation space (before red and blue agent actions have been taken). Individual elements of the observation space are presented in the format OSI_X_Y
|
||||
* Resulting observation space (after the red and blue agent actions have been taken) Individual elements of the observation space are presented in the format OSN_X_Y
|
||||
* Reward value
|
||||
* Action space (as presented by the blue agent on this step). Individual elements of the action space are presented in the format AS_X
|
||||
|
||||
**Diagrams**
|
||||
|
||||
For each session, PrimAITE automatically creates a visualisation of the system / network lay down configuration.
|
||||
|
||||
**Saved agents**
|
||||
|
||||
For each training session, assuming the agent being trained implements the *save()* function and this function is called by the code, PrimAITE automatically saves the agent state.
|
||||
@@ -1,42 +0,0 @@
|
||||
.. _results:
|
||||
|
||||
Results, Output and Logging from PrimAITE
|
||||
=========================================
|
||||
|
||||
PrimAITE produces four types of data:
|
||||
|
||||
* Outputs - Results
|
||||
* Outputs - Diagrams
|
||||
* Outputs - Saved agents
|
||||
* Logging
|
||||
|
||||
Outputs can be found in the *[Install Directory]\\Primaite\\Primaite\\outputs* directory
|
||||
|
||||
Logging can be found in the *[Install Directory]\\Primaite\\Primaite\\logs* directory
|
||||
|
||||
**Outputs - Results**
|
||||
|
||||
PrimAITE automatically creates two sets of results from each session, and stores them in the *Results* folder:
|
||||
|
||||
* Average reward per episode - a csv file listing the average reward for each episode of the session. This provides, for example, an indication of the change over a training session of the reward value
|
||||
* All transactions - a csv file listing the following values for every step of every episode:
|
||||
|
||||
* Timestamp
|
||||
* Episode number
|
||||
* Step number
|
||||
* Initial observation space (before red and blue agent actions have been taken). Individual elements of the observation space are presented in the format OSI_X_Y
|
||||
* Resulting observation space (after the red and blue agent actions have been taken) Individual elements of the observation space are presented in the format OSN_X_Y
|
||||
* Reward value
|
||||
* Action space (as presented by the blue agent on this step). Individual elements of the action space are presented in the format AS_X
|
||||
|
||||
**Outputs - Diagrams**
|
||||
|
||||
For each session, PrimAITE automatically creates a visualisation of the system / network laydown configuration, and stores it in the *Diagrams* folder.
|
||||
|
||||
**Outputs - Saved agents**
|
||||
|
||||
For each training session, assuming the agent being trained implements the *save()* function and this function is called by the code, PrimAITE automatically saves the agent state and stores it in the *agents* folder.
|
||||
|
||||
**Logging**
|
||||
|
||||
PrimAITE also provides output logs (for diagnosis) using the Python Logging package. These can be found in the *[Install Directory]\\Primaite\\Primaite\\logs* directory
|
||||
@@ -1,86 +0,0 @@
|
||||
.. _session:
|
||||
|
||||
Running a PrimAITE Training or Evaluation Session
|
||||
=================================================
|
||||
|
||||
The application will determine whether a Training or Evaluation session is being executed via the 'sessionType' value in the config_mail.yaml file. A PrimAITE session will usually be associated with a "Use Case Profile"; this document will present:
|
||||
|
||||
* The Use Case name, default number of steps in an episode and default number of episodes in a session. The number of steps and episodes can be modified in the configuration files
|
||||
* The system laydown being modelled
|
||||
* The objectives of the mission (steady-state), the red agent and the blue agent (in a defensive role)
|
||||
* The green agent pattern-of-life profile
|
||||
* The red agent attack profile
|
||||
* The observation space definition
|
||||
* The action space definition
|
||||
* Agent integration guidance
|
||||
* Initial Access Control List settings (if applicable)
|
||||
* The reward function definition
|
||||
|
||||
**Integrating a user defined blue agent**
|
||||
|
||||
Integrating a blue agent with PrimAITE requires some modification of the code within the main.py file. The main.py file consists of a number of functions, each of which will invoke training for a particular agent. These are:
|
||||
|
||||
* Generic (run_generic)
|
||||
* Stable Baselines 3 PPO (run_stable_baselines3_ppo)
|
||||
* Stable Baselines 3 A2C (run_stable_baselines3_a2c)
|
||||
|
||||
The selection of which agent type to use is made via the config_main.yaml file. In order to train a user generated agent,
|
||||
the run_generic function should be selected, and should be modified (typically) to be:
|
||||
|
||||
.. code:: python
|
||||
|
||||
agent = MyAgent(environment, max_steps)
|
||||
for episode in range(0, num_episodes):
|
||||
agent.learn()
|
||||
env.close()
|
||||
save_agent(agent)
|
||||
|
||||
Where:
|
||||
|
||||
* *MyAgent* is the user created agent
|
||||
* *environment* is the PrimAITE environment
|
||||
* *max_steps* is the number of steps in an episode, as defined in the config_[name].yaml file
|
||||
* *num_episodes* is the number of episodes in the session, as defined in the config_main.yaml file
|
||||
* the *.learn()* function should be defined in the user created agent
|
||||
* the *env.close()* function is defined within PrimAITE
|
||||
* the *save_agent()* assumes that a *save()* function has been defined in the user created agent. If not, this line can be ommitted (although it is encouraged, since it will allow the agent to be saved and ported)
|
||||
|
||||
The code below provides a suggested format for the learn() function within the user created agent.
|
||||
It's important to include the *self.environment.reset()* call within the episode loop in order that the
|
||||
environment is reset between episodes. Note that the example below should not be considered exhaustive.
|
||||
|
||||
.. code:: python
|
||||
|
||||
def learn(self) :
|
||||
|
||||
# pre-reqs
|
||||
|
||||
# reset the environment
|
||||
self.environment.reset()
|
||||
done = False
|
||||
|
||||
for step in range(max_steps):
|
||||
# calculate the action
|
||||
action = ...
|
||||
|
||||
# execute the environment step
|
||||
new_state, reward, done, info = self.environment.step(action)
|
||||
|
||||
# algorithm updates
|
||||
...
|
||||
|
||||
# update to our new state
|
||||
state = new_state
|
||||
|
||||
# if done, finish episode
|
||||
if done == True:
|
||||
break
|
||||
|
||||
**Running the session**
|
||||
|
||||
In order to execute a session, carry out the following steps:
|
||||
|
||||
1. Navigate to "[Install directory]\\Primaite\\Primaite\\”
|
||||
2. Start a console window (type “CMD” in path window, or start a console window first and navigate to “[Install Directory]\\Primaite\\Primaite\\”)
|
||||
3. Type “python main.py”
|
||||
4. The session will start with an output indicating the current episode, and average reward value for the episode
|
||||
@@ -26,11 +26,14 @@ classifiers = [
|
||||
|
||||
dependencies = [
|
||||
"gym==0.21.0",
|
||||
"jupyterlab==3.6.1",
|
||||
"matplotlib==3.7.1",
|
||||
"networkx==3.1",
|
||||
"numpy==1.23.5",
|
||||
"platformdirs==3.5.1",
|
||||
"PyYAML==6.0",
|
||||
"stable-baselines3==1.6.2"
|
||||
"stable-baselines3==1.6.2",
|
||||
"typer[all]==0.9.0"
|
||||
]
|
||||
|
||||
[tool.setuptools.dynamic]
|
||||
@@ -45,17 +48,23 @@ license-files = ["LICENSE"]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"setuptools==66",
|
||||
"pytest==7.2.0",
|
||||
"build==0.10.0",
|
||||
"flake8==6.0.0",
|
||||
"Sphinx==6.1.3",
|
||||
"furo==2023.3.27",
|
||||
"sphinx-code-tabs==0.5.3",
|
||||
"sphinx-copybutton==0.5.2",
|
||||
"pytest-cov==4.0.0",
|
||||
"pytest-flake8==1.1.1",
|
||||
"pip-licenses==4.3.0",
|
||||
"pre-commit==2.20.0",
|
||||
"wheel==0.38.4",
|
||||
"build==0.10.0"
|
||||
"pytest==7.2.0",
|
||||
"pytest-cov==4.0.0",
|
||||
"pytest-flake8==1.1.1",
|
||||
"setuptools==66",
|
||||
"Sphinx==6.1.3",
|
||||
"sphinx-code-tabs==0.5.3",
|
||||
"sphinx-copybutton==0.5.2",
|
||||
"wheel==0.38.4"
|
||||
]
|
||||
tensorflow = [
|
||||
"tensorflow==2.12.0",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
primaite = "primaite.cli:app"
|
||||
|
||||
7
setup.py
7
setup.py
@@ -1,14 +1,13 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
from setuptools import setup
|
||||
from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
|
||||
from wheel.bdist_wheel import bdist_wheel as _bdist_wheel # noqa
|
||||
|
||||
|
||||
class bdist_wheel(_bdist_wheel): # noqa
|
||||
def finalize_options(self): # noqa
|
||||
super().finalize_options()
|
||||
# forces whee to be platform and Python version specific
|
||||
# Source: https://stackoverflow.com/a/45150383
|
||||
self.root_is_pure = False
|
||||
# Set to False if you need to build OS and Python specific wheels
|
||||
self.root_is_pure = True # noqa
|
||||
|
||||
|
||||
setup(
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.2.1
|
||||
2.0.0dev0
|
||||
|
||||
125
src/primaite/__init__.py
Normal file
125
src/primaite/__init__.py
Normal file
@@ -0,0 +1,125 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
import logging
|
||||
import logging.config
|
||||
import sys
|
||||
from logging import Logger, StreamHandler
|
||||
from logging.handlers import RotatingFileHandler
|
||||
from pathlib import Path
|
||||
from typing import Final
|
||||
|
||||
import pkg_resources
|
||||
import yaml
|
||||
from platformdirs import PlatformDirs
|
||||
|
||||
_PLATFORM_DIRS: Final[PlatformDirs] = PlatformDirs(appname="primaite")
|
||||
"""An instance of `PlatformDirs` set with appname='primaite'."""
|
||||
|
||||
|
||||
def _get_primaite_config():
|
||||
config_path = _PLATFORM_DIRS.user_config_path / "primaite_config.yaml"
|
||||
if not config_path.exists():
|
||||
config_path = Path(
|
||||
pkg_resources.resource_filename(
|
||||
"primaite", "setup/_package_data/primaite_config.yaml"
|
||||
)
|
||||
)
|
||||
with open(config_path, "r") as file:
|
||||
primaite_config = yaml.safe_load(file)
|
||||
log_level_map = {
|
||||
"NOTSET": logging.NOTSET,
|
||||
"DEBUG": logging.DEBUG,
|
||||
"INFO": logging.INFO,
|
||||
"WARN": logging.WARN,
|
||||
"ERROR": logging.ERROR,
|
||||
"CRITICAL": logging.CRITICAL
|
||||
}
|
||||
primaite_config["log_level"] = log_level_map[primaite_config["log_level"]]
|
||||
return primaite_config
|
||||
|
||||
|
||||
_PRIMAITE_CONFIG = _get_primaite_config()
|
||||
|
||||
_USER_DIRS: Final[Path] = Path.home() / "primaite"
|
||||
"""The users home space for PrimAITE which is located at: ~/primaite."""
|
||||
|
||||
NOTEBOOKS_DIR: Final[Path] = _USER_DIRS / "notebooks"
|
||||
"""
|
||||
The path to the users notebooks directory as an instance of `Path` or
|
||||
`PosixPath`, depending on the OS.
|
||||
|
||||
Users notebooks are stored at: ``~/primaite/notebooks``.
|
||||
"""
|
||||
|
||||
USERS_CONFIG_DIR: Final[Path] = _USER_DIRS / "config"
|
||||
"""
|
||||
The path to the users config directory as an instance of `Path` or
|
||||
`PosixPath`, depending on the OS.
|
||||
|
||||
Users config files are stored at: ``~/primaite/config``.
|
||||
"""
|
||||
|
||||
SESSIONS_DIR: Final[Path] = _USER_DIRS / "sessions"
|
||||
"""
|
||||
The path to the users PrimAITE Sessions directory as an instance of `Path` or
|
||||
`PosixPath`, depending on the OS.
|
||||
|
||||
Users PrimAITE Sessions are stored at: ``~/primaite/sessions``.
|
||||
"""
|
||||
|
||||
|
||||
# region Setup Logging
|
||||
def _log_dir() -> Path:
|
||||
if sys.platform == "win32":
|
||||
dir_path = _PLATFORM_DIRS.user_data_path / "logs"
|
||||
else:
|
||||
dir_path = _PLATFORM_DIRS.user_log_path
|
||||
return dir_path
|
||||
|
||||
|
||||
LOG_DIR: Final[Path] = _log_dir()
|
||||
"""The path to the app log directory as an instance of `Path` or `PosixPath`, depending on the OS."""
|
||||
|
||||
LOG_DIR.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
LOG_PATH: Final[Path] = LOG_DIR / "primaite.log"
|
||||
"""The primaite.log file path as an instance of `Path` or `PosixPath`, depending on the OS."""
|
||||
|
||||
_STREAM_HANDLER: Final[StreamHandler] = StreamHandler()
|
||||
_FILE_HANDLER: Final[RotatingFileHandler] = RotatingFileHandler(
|
||||
filename=LOG_PATH,
|
||||
maxBytes=10485760, # 10MB
|
||||
backupCount=9, # Max 100MB of logs
|
||||
encoding="utf8",
|
||||
)
|
||||
_STREAM_HANDLER.setLevel(_PRIMAITE_CONFIG["log_level"])
|
||||
_FILE_HANDLER.setLevel(_PRIMAITE_CONFIG["log_level"])
|
||||
|
||||
_LOG_FORMAT_STR: Final[str] = _PRIMAITE_CONFIG["logger_format"]
|
||||
_STREAM_HANDLER.setFormatter(logging.Formatter(_LOG_FORMAT_STR))
|
||||
_FILE_HANDLER.setFormatter(logging.Formatter(_LOG_FORMAT_STR))
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
_LOGGER.addHandler(_STREAM_HANDLER)
|
||||
_LOGGER.addHandler(_FILE_HANDLER)
|
||||
|
||||
|
||||
def getLogger(name: str) -> Logger:
|
||||
"""
|
||||
Get a PrimAITE logger.
|
||||
|
||||
:param name: The logger name. Use ``__name__``.
|
||||
:return: An instance of :py:class:`logging.Logger` with the PrimAITE
|
||||
logging config.
|
||||
"""
|
||||
logger = logging.getLogger(name)
|
||||
logger.setLevel(_PRIMAITE_CONFIG["log_level"])
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
with open(Path(__file__).parent.resolve() / "VERSION", "r") as file:
|
||||
__version__ = file.readline()
|
||||
@@ -11,12 +11,21 @@ _LOGGER: Final[logging.Logger] = logging.getLogger(__name__)
|
||||
class AccessControlList:
|
||||
"""Access Control List class."""
|
||||
|
||||
def __init__(self, implicit_permission):
|
||||
def __init__(self, implicit_permission, max_acl_rules):
|
||||
"""Init."""
|
||||
# A list of ACL Rules
|
||||
self.acl: List[ACLRule] = []
|
||||
# Implicit ALLOW or DENY firewall spec
|
||||
# Last rule in the ACL list
|
||||
self.acl_implicit_rule = implicit_permission
|
||||
self.max_acl_rules: int
|
||||
# Create implicit rule based on input
|
||||
if self.acl_implicit_rule == "DENY":
|
||||
implicit_rule = ACLRule("DENY", "ANY", "ANY", "ANY", "ANY")
|
||||
else:
|
||||
implicit_rule = ACLRule("ALLOW", "ANY", "ANY", "ANY", "ANY")
|
||||
|
||||
# Maximum number of ACL Rules in ACL
|
||||
self.max_acl_rules: int = max_acl_rules
|
||||
# A list of ACL Rules
|
||||
self.acl: List[ACLRule] = [implicit_rule]
|
||||
|
||||
def check_address_match(self, _rule, _source_ip_address, _dest_ip_address):
|
||||
"""
|
||||
@@ -62,21 +71,15 @@ class AccessControlList:
|
||||
Returns:
|
||||
Indicates block if all conditions are satisfied.
|
||||
"""
|
||||
for rule_key, rule_value in self.acl.items():
|
||||
if self.check_address_match(
|
||||
rule_value, _source_ip_address, _dest_ip_address
|
||||
):
|
||||
for rule in self.acl:
|
||||
if self.check_address_match(rule, _source_ip_address, _dest_ip_address):
|
||||
if (
|
||||
rule_value.get_protocol() == _protocol
|
||||
or rule_value.get_protocol() == "ANY"
|
||||
) and (
|
||||
str(rule_value.get_port()) == str(_port)
|
||||
or rule_value.get_port() == "ANY"
|
||||
):
|
||||
rule.get_protocol() == _protocol or rule.get_protocol() == "ANY"
|
||||
) and (str(rule.get_port()) == str(_port) or rule.get_port() == "ANY"):
|
||||
# There's a matching rule. Get the permission
|
||||
if rule_value.get_permission() == "DENY":
|
||||
if rule.get_permission() == "DENY":
|
||||
return True
|
||||
elif rule_value.get_permission() == "ALLOW":
|
||||
elif rule.get_permission() == "ALLOW":
|
||||
return False
|
||||
|
||||
# If there has been no rule to allow the IER through, it will return a blocked signal by default
|
||||
@@ -92,18 +95,26 @@ class AccessControlList:
|
||||
_dest_ip: the destination IP address
|
||||
_protocol: the protocol
|
||||
_port: the port
|
||||
_position: position to insert ACL rule into ACL list
|
||||
_position: position to insert ACL rule into ACL list (starting from index 1 and NOT 0)
|
||||
"""
|
||||
position_index = int(_position) - 1
|
||||
new_rule = ACLRule(_permission, _source_ip, _dest_ip, _protocol, str(_port))
|
||||
|
||||
if _position < self.max_acl_rules - 1 and _position < 0:
|
||||
if _position < len(self.acl):
|
||||
self.acl.insert(_position, new_rule)
|
||||
if len(self.acl) < self.max_acl_rules:
|
||||
if len(self.acl) > position_index > -1:
|
||||
try:
|
||||
self.acl.insert(position_index, new_rule)
|
||||
except Exception:
|
||||
_LOGGER.info(
|
||||
f"New Rule could NOT be added to list at position {position_index}."
|
||||
)
|
||||
else:
|
||||
print("check logic on this")
|
||||
_LOGGER.info(
|
||||
f"Position {position_index} is an invalid index for list and/or overwrites implicit firewall rule"
|
||||
)
|
||||
else:
|
||||
_LOGGER.info(
|
||||
f"Position {_position} is an invalid index for list/overwriting implicit firewall rule"
|
||||
f"The ACL list is FULL."
|
||||
f"The list of ACLs has length {len(self.acl)} and it has a max capacity of {self.max_acl_rules}."
|
||||
)
|
||||
|
||||
def remove_rule(self, _permission, _source_ip, _dest_ip, _protocol, _port):
|
||||
|
||||
171
src/primaite/cli.py
Normal file
171
src/primaite/cli.py
Normal file
@@ -0,0 +1,171 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
"""Provides a CLI using Typer as an entry point."""
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from enum import Enum
|
||||
from typing import Optional
|
||||
|
||||
import pkg_resources
|
||||
import typer
|
||||
import yaml
|
||||
from platformdirs import PlatformDirs
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = typer.Typer()
|
||||
|
||||
|
||||
@app.command()
|
||||
def build_dirs():
|
||||
"""Build the PrimAITE app directories."""
|
||||
from primaite.setup import setup_app_dirs
|
||||
|
||||
setup_app_dirs.run()
|
||||
|
||||
|
||||
@app.command()
|
||||
def reset_notebooks(overwrite: bool = True):
|
||||
"""
|
||||
Force a reset of the demo notebooks in the users notebooks directory.
|
||||
|
||||
:param overwrite: If True, will overwrite existing demo notebooks.
|
||||
"""
|
||||
from primaite.setup import reset_demo_notebooks
|
||||
|
||||
reset_demo_notebooks.run(overwrite)
|
||||
|
||||
|
||||
@app.command()
|
||||
def logs(last_n: Annotated[int, typer.Option("-n")]):
|
||||
"""
|
||||
Print the PrimAITE log file.
|
||||
|
||||
:param last_n: The number of lines to print. Default value is 10.
|
||||
"""
|
||||
import re
|
||||
from primaite import LOG_PATH
|
||||
|
||||
if os.path.isfile(LOG_PATH):
|
||||
with open(LOG_PATH) as file:
|
||||
lines = file.readlines()
|
||||
for line in lines[-last_n:]:
|
||||
print(re.sub(r"\n*", "", line))
|
||||
|
||||
|
||||
_LogLevel = Enum("LogLevel", {k: k for k in logging._levelToName.values()}) # noqa
|
||||
|
||||
|
||||
@app.command()
|
||||
def log_level(level: Annotated[Optional[_LogLevel], typer.Argument()] = None):
|
||||
"""
|
||||
View or set the PrimAITE Log Level.
|
||||
|
||||
To View, simply call: primaite log-level
|
||||
|
||||
To set, call: primaite log-level <desired log level>
|
||||
|
||||
For example, to set the to debug, call: primaite log-level DEBUG
|
||||
"""
|
||||
app_dirs = PlatformDirs(appname="primaite")
|
||||
app_dirs.user_config_path.mkdir(exist_ok=True, parents=True)
|
||||
user_config_path = app_dirs.user_config_path / "primaite_config.yaml"
|
||||
if user_config_path.exists():
|
||||
with open(user_config_path, "r") as file:
|
||||
primaite_config = yaml.safe_load(file)
|
||||
|
||||
if level:
|
||||
primaite_config["log_level"] = level.value
|
||||
with open(user_config_path, "w") as file:
|
||||
yaml.dump(primaite_config, file)
|
||||
else:
|
||||
level = primaite_config["log_level"]
|
||||
print(f"PrimAITE Log Level: {level}")
|
||||
|
||||
|
||||
@app.command()
|
||||
def notebooks():
|
||||
"""Start Jupyter Lab in the users PrimAITE notebooks directory."""
|
||||
from primaite.notebooks import start_jupyter_session
|
||||
|
||||
start_jupyter_session()
|
||||
|
||||
|
||||
@app.command()
|
||||
def version():
|
||||
"""Get the installed PrimAITE version number."""
|
||||
import primaite
|
||||
|
||||
print(primaite.__version__)
|
||||
|
||||
|
||||
@app.command()
|
||||
def clean_up():
|
||||
"""Cleans up left over files from previous version installations."""
|
||||
from primaite.setup import old_installation_clean_up
|
||||
|
||||
old_installation_clean_up.run()
|
||||
|
||||
|
||||
@app.command()
|
||||
def setup(overwrite_existing: bool = True):
|
||||
"""
|
||||
Perform the PrimAITE first-time setup.
|
||||
|
||||
WARNING: All user-data will be lost.
|
||||
"""
|
||||
# Does this way to avoid using PrimAITE package before config is loaded
|
||||
app_dirs = PlatformDirs(appname="primaite")
|
||||
app_dirs.user_config_path.mkdir(exist_ok=True, parents=True)
|
||||
user_config_path = app_dirs.user_config_path / "primaite_config.yaml"
|
||||
build_config = overwrite_existing or (not user_config_path.exists())
|
||||
if build_config:
|
||||
pkg_config_path = Path(
|
||||
pkg_resources.resource_filename(
|
||||
"primaite", "setup/_package_data/primaite_config.yaml"
|
||||
)
|
||||
)
|
||||
|
||||
shutil.copy2(pkg_config_path, user_config_path)
|
||||
|
||||
from primaite import getLogger
|
||||
from primaite.setup import (
|
||||
old_installation_clean_up,
|
||||
reset_demo_notebooks,
|
||||
reset_example_configs,
|
||||
setup_app_dirs,
|
||||
)
|
||||
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
_LOGGER.info("Performing the PrimAITE first-time setup...")
|
||||
|
||||
if build_config:
|
||||
_LOGGER.info("Building primaite_config.yaml...")
|
||||
|
||||
_LOGGER.info("Building the PrimAITE app directories...")
|
||||
setup_app_dirs.run()
|
||||
|
||||
_LOGGER.info("Rebuilding the demo notebooks...")
|
||||
reset_demo_notebooks.run(overwrite_existing=True)
|
||||
|
||||
_LOGGER.info("Rebuilding the example notebooks...")
|
||||
reset_example_configs.run(overwrite_existing=True)
|
||||
|
||||
_LOGGER.info("Performing a clean-up of previous PrimAITE installations...")
|
||||
old_installation_clean_up.run()
|
||||
|
||||
_LOGGER.info("PrimAITE setup complete!")
|
||||
|
||||
|
||||
@app.command()
|
||||
def session(tc: str, ldc: str):
|
||||
"""
|
||||
Run a PrimAITE session.
|
||||
|
||||
:param tc: The training config filepath.
|
||||
:param ldc: The lay down config file path.
|
||||
"""
|
||||
from primaite.main import run
|
||||
|
||||
run(training_config_path=tc, lay_down_config_path=ldc)
|
||||
@@ -1,91 +0,0 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
"""The config class."""
|
||||
|
||||
|
||||
class ConfigValuesMain(object):
|
||||
"""Class to hold main config values."""
|
||||
|
||||
def __init__(self):
|
||||
"""Init."""
|
||||
# Generic
|
||||
self.agent_identifier = "" # the agent in use
|
||||
self.observation_config = None # observation space config
|
||||
self.num_episodes = 0 # number of episodes to train over
|
||||
self.num_steps = 0 # number of steps in an episode
|
||||
self.time_delay = 0 # delay between steps (ms) - applies to generic agents only
|
||||
self.config_filename_use_case = "" # the filename for the Use Case config file
|
||||
self.session_type = "" # the session type to run (TRAINING or EVALUATION)
|
||||
|
||||
# Environment
|
||||
self.observation_space_high_value = (
|
||||
0 # The high value for the observation space
|
||||
)
|
||||
|
||||
# Reward values
|
||||
# Generic
|
||||
self.all_ok = 0
|
||||
# Node Hardware State
|
||||
self.off_should_be_on = 0
|
||||
self.off_should_be_resetting = 0
|
||||
self.on_should_be_off = 0
|
||||
self.on_should_be_resetting = 0
|
||||
self.resetting_should_be_on = 0
|
||||
self.resetting_should_be_off = 0
|
||||
self.resetting = 0
|
||||
# Node Software or Service State
|
||||
self.good_should_be_patching = 0
|
||||
self.good_should_be_compromised = 0
|
||||
self.good_should_be_overwhelmed = 0
|
||||
self.patching_should_be_good = 0
|
||||
self.patching_should_be_compromised = 0
|
||||
self.patching_should_be_overwhelmed = 0
|
||||
self.patching = 0
|
||||
self.compromised_should_be_good = 0
|
||||
self.compromised_should_be_patching = 0
|
||||
self.compromised_should_be_overwhelmed = 0
|
||||
self.compromised = 0
|
||||
self.overwhelmed_should_be_good = 0
|
||||
self.overwhelmed_should_be_patching = 0
|
||||
self.overwhelmed_should_be_compromised = 0
|
||||
self.overwhelmed = 0
|
||||
# Node File System State
|
||||
self.good_should_be_repairing = 0
|
||||
self.good_should_be_restoring = 0
|
||||
self.good_should_be_corrupt = 0
|
||||
self.good_should_be_destroyed = 0
|
||||
self.repairing_should_be_good = 0
|
||||
self.repairing_should_be_restoring = 0
|
||||
self.repairing_should_be_corrupt = 0
|
||||
self.repairing_should_be_destroyed = (
|
||||
0 # Repairing does not fix destroyed state - you need to restore
|
||||
)
|
||||
self.repairing = 0
|
||||
self.restoring_should_be_good = 0
|
||||
self.restoring_should_be_repairing = 0
|
||||
self.restoring_should_be_corrupt = (
|
||||
0 # Not the optimal method (as repair will fix corruption)
|
||||
)
|
||||
self.restoring_should_be_destroyed = 0
|
||||
self.restoring = 0
|
||||
self.corrupt_should_be_good = 0
|
||||
self.corrupt_should_be_repairing = 0
|
||||
self.corrupt_should_be_restoring = 0
|
||||
self.corrupt_should_be_destroyed = 0
|
||||
self.corrupt = 0
|
||||
self.destroyed_should_be_good = 0
|
||||
self.destroyed_should_be_repairing = 0
|
||||
self.destroyed_should_be_restoring = 0
|
||||
self.destroyed_should_be_corrupt = 0
|
||||
self.destroyed = 0
|
||||
self.scanning = 0
|
||||
# IER status
|
||||
self.red_ier_running = 0
|
||||
self.green_ier_blocked = 0
|
||||
|
||||
# Patching / Reset
|
||||
self.os_patching_duration = 0 # The time taken to patch the OS
|
||||
self.node_reset_duration = 0 # The time taken to reset a node (hardware)
|
||||
self.service_patching_duration = 0 # The time taken to patch a service
|
||||
self.file_system_repairing_limit = 0 # The time take to repair a file
|
||||
self.file_system_restoring_limit = 0 # The time take to restore a file
|
||||
self.file_system_scanning_limit = 0 # The time taken to scan the file system
|
||||
@@ -35,6 +35,8 @@ class HardwareState(Enum):
|
||||
ON = 1
|
||||
OFF = 2
|
||||
RESETTING = 3
|
||||
SHUTTING_DOWN = 4
|
||||
BOOTING = 5
|
||||
|
||||
|
||||
class SoftwareState(Enum):
|
||||
|
||||
95
src/primaite/common/training_config.py
Normal file
95
src/primaite/common/training_config.py
Normal file
@@ -0,0 +1,95 @@
|
||||
# # Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
# """The config class."""
|
||||
# from dataclasses import dataclass
|
||||
#
|
||||
# from primaite.common.enums import ActionType
|
||||
#
|
||||
#
|
||||
# @dataclass()
|
||||
# class TrainingConfig:
|
||||
# """Class to hold main config values."""
|
||||
#
|
||||
# # Generic
|
||||
# agent_identifier: str # The Red Agent algo/class to be used
|
||||
# action_type: ActionType # type of action to use (NODE/ACL/ANY)
|
||||
# num_episodes: int # number of episodes to train over
|
||||
# num_steps: int # number of steps in an episode
|
||||
# time_delay: int # delay between steps (ms) - applies to generic agents only
|
||||
# # file
|
||||
# session_type: str # the session type to run (TRAINING or EVALUATION)
|
||||
# load_agent: str # Determine whether to load an agent from file
|
||||
# agent_load_file: str # File path and file name of agent if you're loading one in
|
||||
#
|
||||
# # Environment
|
||||
# observation_space_high_value: int # The high value for the observation space
|
||||
#
|
||||
# # Reward values
|
||||
# # Generic
|
||||
# all_ok: int
|
||||
# # Node Hardware State
|
||||
# off_should_be_on: int
|
||||
# off_should_be_resetting: int
|
||||
# on_should_be_off: int
|
||||
# on_should_be_resetting: int
|
||||
# resetting_should_be_on: int
|
||||
# resetting_should_be_off: int
|
||||
# resetting: int
|
||||
# # Node Software or Service State
|
||||
# good_should_be_patching: int
|
||||
# good_should_be_compromised: int
|
||||
# good_should_be_overwhelmed: int
|
||||
# patching_should_be_good: int
|
||||
# patching_should_be_compromised: int
|
||||
# patching_should_be_overwhelmed: int
|
||||
# patching: int
|
||||
# compromised_should_be_good: int
|
||||
# compromised_should_be_patching: int
|
||||
# compromised_should_be_overwhelmed: int
|
||||
# compromised: int
|
||||
# overwhelmed_should_be_good: int
|
||||
# overwhelmed_should_be_patching: int
|
||||
# overwhelmed_should_be_compromised: int
|
||||
# overwhelmed: int
|
||||
# # Node File System State
|
||||
# good_should_be_repairing: int
|
||||
# good_should_be_restoring: int
|
||||
# good_should_be_corrupt: int
|
||||
# good_should_be_destroyed: int
|
||||
# repairing_should_be_good: int
|
||||
# repairing_should_be_restoring: int
|
||||
# repairing_should_be_corrupt: int
|
||||
# repairing_should_be_destroyed: int # Repairing does not fix destroyed state - you need to restore
|
||||
#
|
||||
# repairing: int
|
||||
# restoring_should_be_good: int
|
||||
# restoring_should_be_repairing: int
|
||||
# restoring_should_be_corrupt: int # Not the optimal method (as repair will fix corruption)
|
||||
#
|
||||
# restoring_should_be_destroyed: int
|
||||
# restoring: int
|
||||
# corrupt_should_be_good: int
|
||||
# corrupt_should_be_repairing: int
|
||||
# corrupt_should_be_restoring: int
|
||||
# corrupt_should_be_destroyed: int
|
||||
# corrupt: int
|
||||
# destroyed_should_be_good: int
|
||||
# destroyed_should_be_repairing: int
|
||||
# destroyed_should_be_restoring: int
|
||||
# destroyed_should_be_corrupt: int
|
||||
# destroyed: int
|
||||
# scanning: int
|
||||
# # IER status
|
||||
# red_ier_running: int
|
||||
# green_ier_blocked: int
|
||||
#
|
||||
# # Patching / Reset
|
||||
# os_patching_duration: int # The time taken to patch the OS
|
||||
# node_reset_duration: int # The time taken to reset a node (hardware)
|
||||
# node_booting_duration = 0 # The Time taken to turn on the node
|
||||
# node_shutdown_duration = 0 # The time taken to turn off the node
|
||||
# service_patching_duration: int # The time taken to patch a service
|
||||
# file_system_repairing_limit: int # The time take to repair a file
|
||||
# file_system_restoring_limit: int # The time take to restore a file
|
||||
# file_system_scanning_limit: int # The time taken to scan the file system
|
||||
# # Patching / Reset
|
||||
#
|
||||
@@ -1,14 +1,14 @@
|
||||
- itemType: ACTIONS
|
||||
- item_type: ACTIONS
|
||||
type: NODE
|
||||
- itemType: STEPS
|
||||
- item_type: STEPS
|
||||
steps: 128
|
||||
- itemType: PORTS
|
||||
portsList:
|
||||
- item_type: PORTS
|
||||
ports_list:
|
||||
- port: '80'
|
||||
- itemType: SERVICES
|
||||
serviceList:
|
||||
- item_type: SERVICES
|
||||
service_list:
|
||||
- name: TCP
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '1'
|
||||
name: PC1
|
||||
node_class: SERVICE
|
||||
@@ -22,7 +22,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '2'
|
||||
name: SERVER
|
||||
node_class: SERVICE
|
||||
@@ -36,7 +36,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '3'
|
||||
name: PC2
|
||||
node_class: SERVICE
|
||||
@@ -50,7 +50,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '4'
|
||||
name: SWITCH1
|
||||
node_class: ACTIVE
|
||||
@@ -60,7 +60,7 @@
|
||||
ip_address: 192.168.1.5
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '5'
|
||||
name: SWITCH2
|
||||
node_class: ACTIVE
|
||||
@@ -70,7 +70,7 @@
|
||||
ip_address: 192.168.1.6
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '6'
|
||||
name: SWITCH3
|
||||
node_class: ACTIVE
|
||||
@@ -80,56 +80,56 @@
|
||||
ip_address: 192.168.1.7
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '7'
|
||||
name: link1
|
||||
bandwidth: 1000000000
|
||||
source: '1'
|
||||
destination: '4'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '8'
|
||||
name: link2
|
||||
bandwidth: 1000000000
|
||||
source: '4'
|
||||
destination: '2'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '9'
|
||||
name: link3
|
||||
bandwidth: 1000000000
|
||||
source: '2'
|
||||
destination: '5'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '10'
|
||||
name: link4
|
||||
bandwidth: 1000000000
|
||||
source: '2'
|
||||
destination: '6'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '11'
|
||||
name: link5
|
||||
bandwidth: 1000000000
|
||||
source: '5'
|
||||
destination: '3'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '12'
|
||||
name: link6
|
||||
bandwidth: 1000000000
|
||||
source: '6'
|
||||
destination: '3'
|
||||
- itemType: GREEN_IER
|
||||
- item_type: GREEN_IER
|
||||
id: '13'
|
||||
startStep: 1
|
||||
endStep: 128
|
||||
start_step: 1
|
||||
end_step: 128
|
||||
load: 100000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '3'
|
||||
destination: '2'
|
||||
missionCriticality: 5
|
||||
- itemType: RED_POL
|
||||
mission_criticality: 5
|
||||
- item_type: RED_POL
|
||||
id: '14'
|
||||
startStep: 50
|
||||
endStep: 50
|
||||
start_step: 50
|
||||
end_step: 50
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: SERVICE
|
||||
@@ -138,20 +138,20 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_IER
|
||||
- item_type: RED_IER
|
||||
id: '15'
|
||||
startStep: 60
|
||||
endStep: 100
|
||||
start_step: 60
|
||||
end_step: 100
|
||||
load: 1000000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '1'
|
||||
destination: '2'
|
||||
missionCriticality: 0
|
||||
- itemType: RED_POL
|
||||
mission_criticality: 0
|
||||
- item_type: RED_POL
|
||||
id: '16'
|
||||
startStep: 80
|
||||
endStep: 80
|
||||
start_step: 80
|
||||
end_step: 80
|
||||
targetNodeId: '2'
|
||||
initiator: IER
|
||||
type: SERVICE
|
||||
@@ -160,7 +160,7 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '17'
|
||||
permission: ALLOW
|
||||
source: ANY
|
||||
@@ -1,14 +1,14 @@
|
||||
- itemType: ACTIONS
|
||||
- item_type: ACTIONS
|
||||
type: NODE
|
||||
- itemType: STEPS
|
||||
- item_type: STEPS
|
||||
steps: 128
|
||||
- itemType: PORTS
|
||||
portsList:
|
||||
- item_type: PORTS
|
||||
ports_list:
|
||||
- port: '80'
|
||||
- itemType: SERVICES
|
||||
serviceList:
|
||||
- item_type: SERVICES
|
||||
service_list:
|
||||
- name: TCP
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '1'
|
||||
name: PC1
|
||||
node_class: SERVICE
|
||||
@@ -22,7 +22,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '2'
|
||||
name: PC2
|
||||
node_class: SERVICE
|
||||
@@ -36,7 +36,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '3'
|
||||
name: PC3
|
||||
node_class: SERVICE
|
||||
@@ -50,7 +50,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '4'
|
||||
name: PC4
|
||||
node_class: SERVICE
|
||||
@@ -64,7 +64,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '5'
|
||||
name: SWITCH1
|
||||
node_class: ACTIVE
|
||||
@@ -74,7 +74,7 @@
|
||||
ip_address: 192.168.1.2
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '6'
|
||||
name: IDS
|
||||
node_class: SERVICE
|
||||
@@ -88,7 +88,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '7'
|
||||
name: SWITCH2
|
||||
node_class: ACTIVE
|
||||
@@ -98,7 +98,7 @@
|
||||
ip_address: 192.168.1.3
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '8'
|
||||
name: LOP1
|
||||
node_class: SERVICE
|
||||
@@ -112,7 +112,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '9'
|
||||
name: SERVER1
|
||||
node_class: SERVICE
|
||||
@@ -126,7 +126,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '10'
|
||||
name: SERVER2
|
||||
node_class: SERVICE
|
||||
@@ -140,173 +140,173 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '11'
|
||||
name: link1
|
||||
bandwidth: 1000000000
|
||||
source: '1'
|
||||
destination: '5'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '12'
|
||||
name: link2
|
||||
bandwidth: 1000000000
|
||||
source: '2'
|
||||
destination: '5'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '13'
|
||||
name: link3
|
||||
bandwidth: 1000000000
|
||||
source: '3'
|
||||
destination: '5'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '14'
|
||||
name: link4
|
||||
bandwidth: 1000000000
|
||||
source: '4'
|
||||
destination: '5'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '15'
|
||||
name: link5
|
||||
bandwidth: 1000000000
|
||||
source: '5'
|
||||
destination: '6'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '16'
|
||||
name: link6
|
||||
bandwidth: 1000000000
|
||||
source: '5'
|
||||
destination: '8'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '17'
|
||||
name: link7
|
||||
bandwidth: 1000000000
|
||||
source: '6'
|
||||
destination: '7'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '18'
|
||||
name: link8
|
||||
bandwidth: 1000000000
|
||||
source: '8'
|
||||
destination: '7'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '19'
|
||||
name: link9
|
||||
bandwidth: 1000000000
|
||||
source: '7'
|
||||
destination: '9'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '20'
|
||||
name: link10
|
||||
bandwidth: 1000000000
|
||||
source: '7'
|
||||
destination: '10'
|
||||
- itemType: GREEN_IER
|
||||
- item_type: GREEN_IER
|
||||
id: '21'
|
||||
startStep: 1
|
||||
endStep: 128
|
||||
start_step: 1
|
||||
end_step: 128
|
||||
load: 100000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '1'
|
||||
destination: '9'
|
||||
missionCriticality: 2
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 2
|
||||
- item_type: GREEN_IER
|
||||
id: '22'
|
||||
startStep: 1
|
||||
endStep: 128
|
||||
start_step: 1
|
||||
end_step: 128
|
||||
load: 100000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '2'
|
||||
destination: '9'
|
||||
missionCriticality: 2
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 2
|
||||
- item_type: GREEN_IER
|
||||
id: '23'
|
||||
startStep: 1
|
||||
endStep: 128
|
||||
start_step: 1
|
||||
end_step: 128
|
||||
load: 100000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '9'
|
||||
destination: '3'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 5
|
||||
- item_type: GREEN_IER
|
||||
id: '24'
|
||||
startStep: 1
|
||||
endStep: 128
|
||||
start_step: 1
|
||||
end_step: 128
|
||||
load: 100000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '4'
|
||||
destination: '10'
|
||||
missionCriticality: 2
|
||||
- itemType: ACL_RULE
|
||||
mission_criticality: 2
|
||||
- item_type: ACL_RULE
|
||||
id: '25'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.11
|
||||
destination: 192.168.10.14
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '26'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.12
|
||||
destination: 192.168.10.14
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '27'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.13
|
||||
destination: 192.168.10.14
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '28'
|
||||
permission: ALLOW
|
||||
source: 192.168.20.14
|
||||
destination: 192.168.20.15
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '29'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.14
|
||||
destination: 192.168.10.13
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '30'
|
||||
permission: DENY
|
||||
source: 192.168.10.11
|
||||
destination: 192.168.20.15
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '31'
|
||||
permission: DENY
|
||||
source: 192.168.10.12
|
||||
destination: 192.168.20.15
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '32'
|
||||
permission: DENY
|
||||
source: 192.168.10.13
|
||||
destination: 192.168.20.15
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '33'
|
||||
permission: DENY
|
||||
source: 192.168.20.14
|
||||
destination: 192.168.10.14
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '34'
|
||||
startStep: 20
|
||||
endStep: 20
|
||||
start_step: 20
|
||||
end_step: 20
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: SERVICE
|
||||
@@ -315,10 +315,10 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '35'
|
||||
startStep: 20
|
||||
endStep: 20
|
||||
start_step: 20
|
||||
end_step: 20
|
||||
targetNodeId: '2'
|
||||
initiator: DIRECT
|
||||
type: SERVICE
|
||||
@@ -327,30 +327,30 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_IER
|
||||
- item_type: RED_IER
|
||||
id: '36'
|
||||
startStep: 30
|
||||
endStep: 128
|
||||
start_step: 30
|
||||
end_step: 128
|
||||
load: 440000000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '1'
|
||||
destination: '9'
|
||||
missionCriticality: 0
|
||||
- itemType: RED_IER
|
||||
mission_criticality: 0
|
||||
- item_type: RED_IER
|
||||
id: '37'
|
||||
startStep: 30
|
||||
endStep: 128
|
||||
start_step: 30
|
||||
end_step: 128
|
||||
load: 440000000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '2'
|
||||
destination: '9'
|
||||
missionCriticality: 0
|
||||
- itemType: RED_POL
|
||||
mission_criticality: 0
|
||||
- item_type: RED_POL
|
||||
id: '38'
|
||||
startStep: 30
|
||||
endStep: 30
|
||||
start_step: 30
|
||||
end_step: 30
|
||||
targetNodeId: '9'
|
||||
initiator: IER
|
||||
type: SERVICE
|
||||
@@ -1,14 +1,14 @@
|
||||
- itemType: ACTIONS
|
||||
- item_type: ACTIONS
|
||||
type: NODE
|
||||
- itemType: STEPS
|
||||
- item_type: STEPS
|
||||
steps: 256
|
||||
- itemType: PORTS
|
||||
portsList:
|
||||
- item_type: PORTS
|
||||
ports_list:
|
||||
- port: '80'
|
||||
- itemType: SERVICES
|
||||
serviceList:
|
||||
- item_type: SERVICES
|
||||
service_list:
|
||||
- name: TCP
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '1'
|
||||
name: PC1
|
||||
node_class: SERVICE
|
||||
@@ -22,7 +22,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '2'
|
||||
name: PC2
|
||||
node_class: SERVICE
|
||||
@@ -36,7 +36,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '3'
|
||||
name: SWITCH1
|
||||
node_class: ACTIVE
|
||||
@@ -46,7 +46,7 @@
|
||||
ip_address: 192.168.1.1
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '4'
|
||||
name: SERVER1
|
||||
node_class: SERVICE
|
||||
@@ -60,79 +60,79 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '5'
|
||||
name: link1
|
||||
bandwidth: 1000000000
|
||||
source: '1'
|
||||
destination: '3'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '6'
|
||||
name: link2
|
||||
bandwidth: 1000000000
|
||||
source: '2'
|
||||
destination: '3'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '7'
|
||||
name: link3
|
||||
bandwidth: 1000000000
|
||||
source: '3'
|
||||
destination: '4'
|
||||
- itemType: GREEN_IER
|
||||
- item_type: GREEN_IER
|
||||
id: '8'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 10000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '1'
|
||||
destination: '4'
|
||||
missionCriticality: 1
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 1
|
||||
- item_type: GREEN_IER
|
||||
id: '9'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 10000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '2'
|
||||
destination: '4'
|
||||
missionCriticality: 1
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 1
|
||||
- item_type: GREEN_IER
|
||||
id: '10'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 10000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '4'
|
||||
destination: '2'
|
||||
missionCriticality: 5
|
||||
- itemType: ACL_RULE
|
||||
mission_criticality: 5
|
||||
- item_type: ACL_RULE
|
||||
id: '11'
|
||||
permission: ALLOW
|
||||
source: 192.168.1.2
|
||||
destination: 192.168.1.4
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '12'
|
||||
permission: ALLOW
|
||||
source: 192.168.1.3
|
||||
destination: 192.168.1.4
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '13'
|
||||
permission: ALLOW
|
||||
source: 192.168.1.4
|
||||
destination: 192.168.1.3
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '14'
|
||||
startStep: 20
|
||||
endStep: 20
|
||||
start_step: 20
|
||||
end_step: 20
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: SERVICE
|
||||
@@ -141,20 +141,20 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_IER
|
||||
- item_type: RED_IER
|
||||
id: '15'
|
||||
startStep: 30
|
||||
endStep: 256
|
||||
start_step: 30
|
||||
end_step: 256
|
||||
load: 10000000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '1'
|
||||
destination: '4'
|
||||
missionCriticality: 0
|
||||
- itemType: RED_POL
|
||||
mission_criticality: 0
|
||||
- item_type: RED_POL
|
||||
id: '16'
|
||||
startStep: 40
|
||||
endStep: 40
|
||||
start_step: 40
|
||||
end_step: 40
|
||||
targetNodeId: '4'
|
||||
initiator: IER
|
||||
type: SERVICE
|
||||
@@ -1,18 +1,14 @@
|
||||
- itemType: ACTIONS
|
||||
type: NODE
|
||||
- itemType: STEPS
|
||||
steps: 256
|
||||
- itemType: PORTS
|
||||
portsList:
|
||||
- item_type: PORTS
|
||||
ports_list:
|
||||
- port: '80'
|
||||
- port: '1433'
|
||||
- port: '53'
|
||||
- itemType: SERVICES
|
||||
serviceList:
|
||||
- item_type: SERVICES
|
||||
service_list:
|
||||
- name: TCP
|
||||
- name: TCP_SQL
|
||||
- name: UDP
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '1'
|
||||
name: CLIENT_1
|
||||
node_class: SERVICE
|
||||
@@ -29,7 +25,7 @@
|
||||
- name: UDP
|
||||
port: '53'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '2'
|
||||
name: CLIENT_2
|
||||
node_class: SERVICE
|
||||
@@ -43,7 +39,7 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '3'
|
||||
name: SWITCH_1
|
||||
node_class: ACTIVE
|
||||
@@ -53,7 +49,7 @@
|
||||
ip_address: 192.168.10.1
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '4'
|
||||
name: SECURITY_SUITE
|
||||
node_class: SERVICE
|
||||
@@ -70,7 +66,7 @@
|
||||
- name: UDP
|
||||
port: '53'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '5'
|
||||
name: MANAGEMENT_CONSOLE
|
||||
node_class: SERVICE
|
||||
@@ -87,7 +83,7 @@
|
||||
- name: UDP
|
||||
port: '53'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '6'
|
||||
name: SWITCH_2
|
||||
node_class: ACTIVE
|
||||
@@ -97,7 +93,7 @@
|
||||
ip_address: 192.168.2.1
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '7'
|
||||
name: WEB_SERVER
|
||||
node_class: SERVICE
|
||||
@@ -114,7 +110,7 @@
|
||||
- name: TCP_SQL
|
||||
port: '1433'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '8'
|
||||
name: DATABASE_SERVER
|
||||
node_class: SERVICE
|
||||
@@ -134,7 +130,7 @@
|
||||
- name: UDP
|
||||
port: '53'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '9'
|
||||
name: BACKUP_SERVER
|
||||
node_class: SERVICE
|
||||
@@ -148,323 +144,323 @@
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '10'
|
||||
name: LINK_1
|
||||
bandwidth: 1000000000
|
||||
source: '1'
|
||||
destination: '3'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '11'
|
||||
name: LINK_2
|
||||
bandwidth: 1000000000
|
||||
source: '2'
|
||||
destination: '3'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '12'
|
||||
name: LINK_3
|
||||
bandwidth: 1000000000
|
||||
source: '3'
|
||||
destination: '4'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '13'
|
||||
name: LINK_4
|
||||
bandwidth: 1000000000
|
||||
source: '3'
|
||||
destination: '5'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '14'
|
||||
name: LINK_5
|
||||
bandwidth: 1000000000
|
||||
source: '4'
|
||||
destination: '6'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '15'
|
||||
name: LINK_6
|
||||
bandwidth: 1000000000
|
||||
source: '5'
|
||||
destination: '6'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '16'
|
||||
name: LINK_7
|
||||
bandwidth: 1000000000
|
||||
source: '6'
|
||||
destination: '7'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '17'
|
||||
name: LINK_8
|
||||
bandwidth: 1000000000
|
||||
source: '6'
|
||||
destination: '8'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '18'
|
||||
name: LINK_9
|
||||
bandwidth: 1000000000
|
||||
source: '6'
|
||||
destination: '9'
|
||||
- itemType: GREEN_IER
|
||||
- item_type: GREEN_IER
|
||||
id: '19'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 10000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '1'
|
||||
destination: '7'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 5
|
||||
- item_type: GREEN_IER
|
||||
id: '20'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 10000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '7'
|
||||
destination: '1'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 5
|
||||
- item_type: GREEN_IER
|
||||
id: '21'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 10000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '2'
|
||||
destination: '7'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 5
|
||||
- item_type: GREEN_IER
|
||||
id: '22'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 10000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '7'
|
||||
destination: '2'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 5
|
||||
- item_type: GREEN_IER
|
||||
id: '23'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 5000
|
||||
protocol: TCP_SQL
|
||||
port: '1433'
|
||||
source: '7'
|
||||
destination: '8'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 5
|
||||
- item_type: GREEN_IER
|
||||
id: '24'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 100000
|
||||
protocol: TCP_SQL
|
||||
port: '1433'
|
||||
source: '8'
|
||||
destination: '7'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 5
|
||||
- item_type: GREEN_IER
|
||||
id: '25'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 50000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '1'
|
||||
destination: '9'
|
||||
missionCriticality: 2
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 2
|
||||
- item_type: GREEN_IER
|
||||
id: '26'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 50000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '2'
|
||||
destination: '9'
|
||||
missionCriticality: 2
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 2
|
||||
- item_type: GREEN_IER
|
||||
id: '27'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 5000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '5'
|
||||
destination: '7'
|
||||
missionCriticality: 1
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 1
|
||||
- item_type: GREEN_IER
|
||||
id: '28'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 5000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '7'
|
||||
destination: '5'
|
||||
missionCriticality: 1
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 1
|
||||
- item_type: GREEN_IER
|
||||
id: '29'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 5000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '5'
|
||||
destination: '8'
|
||||
missionCriticality: 1
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 1
|
||||
- item_type: GREEN_IER
|
||||
id: '30'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 5000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '8'
|
||||
destination: '5'
|
||||
missionCriticality: 1
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 1
|
||||
- item_type: GREEN_IER
|
||||
id: '31'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 5000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '5'
|
||||
destination: '9'
|
||||
missionCriticality: 1
|
||||
- itemType: GREEN_IER
|
||||
mission_criticality: 1
|
||||
- item_type: GREEN_IER
|
||||
id: '32'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
start_step: 1
|
||||
end_step: 256
|
||||
load: 5000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '9'
|
||||
destination: '5'
|
||||
missionCriticality: 1
|
||||
- itemType: ACL_RULE
|
||||
mission_criticality: 1
|
||||
- item_type: ACL_RULE
|
||||
id: '33'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.11
|
||||
destination: 192.168.2.10
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '34'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.11
|
||||
destination: 192.168.2.14
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '35'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.12
|
||||
destination: 192.168.2.14
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '36'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.12
|
||||
destination: 192.168.2.10
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '37'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.10
|
||||
destination: 192.168.10.11
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '38'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.10
|
||||
destination: 192.168.10.12
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '39'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.10
|
||||
destination: 192.168.2.14
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '40'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.14
|
||||
destination: 192.168.2.10
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '41'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.11
|
||||
destination: 192.168.2.16
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '42'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.12
|
||||
destination: 192.168.2.16
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '43'
|
||||
permission: ALLOW
|
||||
source: 192.168.1.12
|
||||
destination: 192.168.2.10
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '44'
|
||||
permission: ALLOW
|
||||
source: 192.168.1.12
|
||||
destination: 192.168.2.14
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '45'
|
||||
permission: ALLOW
|
||||
source: 192.168.1.12
|
||||
destination: 192.168.2.16
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '46'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.10
|
||||
destination: 192.168.1.12
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '47'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.14
|
||||
destination: 192.168.1.12
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '48'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.16
|
||||
destination: 192.168.1.12
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '49'
|
||||
permission: DENY
|
||||
source: ANY
|
||||
destination: ANY
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '50'
|
||||
startStep: 50
|
||||
endStep: 50
|
||||
start_step: 50
|
||||
end_step: 50
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: SERVICE
|
||||
@@ -473,20 +469,20 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_IER
|
||||
- item_type: RED_IER
|
||||
id: '51'
|
||||
startStep: 75
|
||||
endStep: 105
|
||||
start_step: 75
|
||||
end_step: 105
|
||||
load: 10000
|
||||
protocol: UDP
|
||||
port: '53'
|
||||
source: '1'
|
||||
destination: '8'
|
||||
missionCriticality: 0
|
||||
- itemType: RED_POL
|
||||
mission_criticality: 0
|
||||
- item_type: RED_POL
|
||||
id: '52'
|
||||
startStep: 100
|
||||
endStep: 100
|
||||
start_step: 100
|
||||
end_step: 100
|
||||
targetNodeId: '8'
|
||||
initiator: IER
|
||||
type: SERVICE
|
||||
@@ -495,10 +491,10 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '53'
|
||||
startStep: 105
|
||||
endStep: 105
|
||||
start_step: 105
|
||||
end_step: 105
|
||||
targetNodeId: '8'
|
||||
initiator: SERVICE
|
||||
type: FILE
|
||||
@@ -507,10 +503,10 @@
|
||||
sourceNodeId: '8'
|
||||
sourceNodeService: UDP
|
||||
sourceNodeServiceState: COMPROMISED
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '54'
|
||||
startStep: 105
|
||||
endStep: 105
|
||||
start_step: 105
|
||||
end_step: 105
|
||||
targetNodeId: '8'
|
||||
initiator: SERVICE
|
||||
type: SERVICE
|
||||
@@ -519,10 +515,10 @@
|
||||
sourceNodeId: '8'
|
||||
sourceNodeService: UDP
|
||||
sourceNodeServiceState: COMPROMISED
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '55'
|
||||
startStep: 125
|
||||
endStep: 125
|
||||
start_step: 125
|
||||
end_step: 125
|
||||
targetNodeId: '7'
|
||||
initiator: SERVICE
|
||||
type: SERVICE
|
||||
@@ -0,0 +1,94 @@
|
||||
# Main Config File
|
||||
|
||||
# Generic config values
|
||||
# Choose one of these (dependent on Agent being trained)
|
||||
# "STABLE_BASELINES3_PPO"
|
||||
# "STABLE_BASELINES3_A2C"
|
||||
# "GENERIC"
|
||||
agent_identifier: STABLE_BASELINES3_A2C
|
||||
# Sets How the Action Space is defined:
|
||||
# "NODE"
|
||||
# "ACL"
|
||||
# "ANY" node and acl actions
|
||||
action_type: NODE
|
||||
# Number of episodes to run per session
|
||||
num_episodes: 10
|
||||
# Number of time_steps per episode
|
||||
num_steps: 256
|
||||
# Time delay between steps (for generic agents)
|
||||
time_delay: 10
|
||||
# Type of session to be run (TRAINING or EVALUATION)
|
||||
session_type: TRAINING
|
||||
# Determine whether to load an agent from file
|
||||
load_agent: False
|
||||
# File path and file name of agent if you're loading one in
|
||||
agent_load_file: C:\[Path]\[agent_saved_filename.zip]
|
||||
|
||||
# Environment config values
|
||||
# The high value for the observation space
|
||||
observation_space_high_value: 1000000000
|
||||
|
||||
# Reward values
|
||||
# Generic
|
||||
all_ok: 0
|
||||
# Node Hardware State
|
||||
off_should_be_on: -10
|
||||
off_should_be_resetting: -5
|
||||
on_should_be_off: -2
|
||||
on_should_be_resetting: -5
|
||||
resetting_should_be_on: -5
|
||||
resetting_should_be_off: -2
|
||||
resetting: -3
|
||||
# Node Software or Service State
|
||||
good_should_be_patching: 2
|
||||
good_should_be_compromised: 5
|
||||
good_should_be_overwhelmed: 5
|
||||
patching_should_be_good: -5
|
||||
patching_should_be_compromised: 2
|
||||
patching_should_be_overwhelmed: 2
|
||||
patching: -3
|
||||
compromised_should_be_good: -20
|
||||
compromised_should_be_patching: -20
|
||||
compromised_should_be_overwhelmed: -20
|
||||
compromised: -20
|
||||
overwhelmed_should_be_good: -20
|
||||
overwhelmed_should_be_patching: -20
|
||||
overwhelmed_should_be_compromised: -20
|
||||
overwhelmed: -20
|
||||
# Node File System State
|
||||
good_should_be_repairing: 2
|
||||
good_should_be_restoring: 2
|
||||
good_should_be_corrupt: 5
|
||||
good_should_be_destroyed: 10
|
||||
repairing_should_be_good: -5
|
||||
repairing_should_be_restoring: 2
|
||||
repairing_should_be_corrupt: 2
|
||||
repairing_should_be_destroyed: 0
|
||||
repairing: -3
|
||||
restoring_should_be_good: -10
|
||||
restoring_should_be_repairing: -2
|
||||
restoring_should_be_corrupt: 1
|
||||
restoring_should_be_destroyed: 2
|
||||
restoring: -6
|
||||
corrupt_should_be_good: -10
|
||||
corrupt_should_be_repairing: -10
|
||||
corrupt_should_be_restoring: -10
|
||||
corrupt_should_be_destroyed: 2
|
||||
corrupt: -10
|
||||
destroyed_should_be_good: -20
|
||||
destroyed_should_be_repairing: -20
|
||||
destroyed_should_be_restoring: -20
|
||||
destroyed_should_be_corrupt: -20
|
||||
destroyed: -20
|
||||
scanning: -2
|
||||
# IER status
|
||||
red_ier_running: -5
|
||||
green_ier_blocked: -10
|
||||
|
||||
# Patching / Reset durations
|
||||
os_patching_duration: 5 # The time taken to patch the OS
|
||||
node_reset_duration: 5 # The time taken to reset a node (hardware)
|
||||
service_patching_duration: 5 # The time taken to patch a service
|
||||
file_system_repairing_limit: 5 # The time take to repair the file system
|
||||
file_system_restoring_limit: 5 # The time take to restore the file system
|
||||
file_system_scanning_limit: 5 # The time taken to scan the file system
|
||||
@@ -1,533 +0,0 @@
|
||||
- itemType: ACTIONS
|
||||
type: NODE
|
||||
- itemType: STEPS
|
||||
steps: 256
|
||||
- itemType: PORTS
|
||||
portsList:
|
||||
- port: '80'
|
||||
- port: '1433'
|
||||
- port: '53'
|
||||
- itemType: SERVICES
|
||||
serviceList:
|
||||
- name: TCP
|
||||
- name: TCP_SQL
|
||||
- name: UDP
|
||||
- itemType: NODE
|
||||
node_id: '1'
|
||||
name: CLIENT_1
|
||||
node_class: SERVICE
|
||||
node_type: COMPUTER
|
||||
priority: P5
|
||||
hardware_state: 'ON'
|
||||
ip_address: 192.168.10.11
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
services:
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- name: UDP
|
||||
port: '53'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
node_id: '2'
|
||||
name: CLIENT_2
|
||||
node_class: SERVICE
|
||||
node_type: COMPUTER
|
||||
priority: P5
|
||||
hardware_state: 'ON'
|
||||
ip_address: 192.168.10.12
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
services:
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
node_id: '3'
|
||||
name: SWITCH_1
|
||||
node_class: ACTIVE
|
||||
node_type: SWITCH
|
||||
priority: P2
|
||||
hardware_state: 'ON'
|
||||
ip_address: 192.168.10.1
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
- itemType: NODE
|
||||
node_id: '4'
|
||||
name: SECURITY_SUITE
|
||||
node_class: SERVICE
|
||||
node_type: SERVER
|
||||
priority: P5
|
||||
hardware_state: 'ON'
|
||||
ip_address: 192.168.1.10
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
services:
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- name: UDP
|
||||
port: '53'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
node_id: '5'
|
||||
name: MANAGEMENT_CONSOLE
|
||||
node_class: SERVICE
|
||||
node_type: SERVER
|
||||
priority: P5
|
||||
hardware_state: 'ON'
|
||||
ip_address: 192.168.1.12
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
services:
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- name: UDP
|
||||
port: '53'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
node_id: '6'
|
||||
name: SWITCH_2
|
||||
node_class: ACTIVE
|
||||
node_type: SWITCH
|
||||
priority: P2
|
||||
hardware_state: 'ON'
|
||||
ip_address: 192.168.2.1
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
- itemType: NODE
|
||||
node_id: '7'
|
||||
name: WEB_SERVER
|
||||
node_class: SERVICE
|
||||
node_type: SERVER
|
||||
priority: P5
|
||||
hardware_state: 'ON'
|
||||
ip_address: 192.168.2.10
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
services:
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- name: TCP_SQL
|
||||
port: '1433'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
node_id: '8'
|
||||
name: DATABASE_SERVER
|
||||
node_class: SERVICE
|
||||
node_type: SERVER
|
||||
priority: P5
|
||||
hardware_state: 'ON'
|
||||
ip_address: 192.168.2.14
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
services:
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- name: TCP_SQL
|
||||
port: '1433'
|
||||
state: GOOD
|
||||
- name: UDP
|
||||
port: '53'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
node_id: '9'
|
||||
name: BACKUP_SERVER
|
||||
node_class: SERVICE
|
||||
node_type: SERVER
|
||||
priority: P5
|
||||
hardware_state: 'ON'
|
||||
ip_address: 192.168.2.16
|
||||
software_state: GOOD
|
||||
file_system_state: GOOD
|
||||
services:
|
||||
- name: TCP
|
||||
port: '80'
|
||||
state: GOOD
|
||||
- itemType: LINK
|
||||
id: '10'
|
||||
name: LINK_1
|
||||
bandwidth: 1000000000
|
||||
source: '1'
|
||||
destination: '3'
|
||||
- itemType: LINK
|
||||
id: '11'
|
||||
name: LINK_2
|
||||
bandwidth: 1000000000
|
||||
source: '2'
|
||||
destination: '3'
|
||||
- itemType: LINK
|
||||
id: '12'
|
||||
name: LINK_3
|
||||
bandwidth: 1000000000
|
||||
source: '3'
|
||||
destination: '4'
|
||||
- itemType: LINK
|
||||
id: '13'
|
||||
name: LINK_4
|
||||
bandwidth: 1000000000
|
||||
source: '3'
|
||||
destination: '5'
|
||||
- itemType: LINK
|
||||
id: '14'
|
||||
name: LINK_5
|
||||
bandwidth: 1000000000
|
||||
source: '4'
|
||||
destination: '6'
|
||||
- itemType: LINK
|
||||
id: '15'
|
||||
name: LINK_6
|
||||
bandwidth: 1000000000
|
||||
source: '5'
|
||||
destination: '6'
|
||||
- itemType: LINK
|
||||
id: '16'
|
||||
name: LINK_7
|
||||
bandwidth: 1000000000
|
||||
source: '6'
|
||||
destination: '7'
|
||||
- itemType: LINK
|
||||
id: '17'
|
||||
name: LINK_8
|
||||
bandwidth: 1000000000
|
||||
source: '6'
|
||||
destination: '8'
|
||||
- itemType: LINK
|
||||
id: '18'
|
||||
name: LINK_9
|
||||
bandwidth: 1000000000
|
||||
source: '6'
|
||||
destination: '9'
|
||||
- itemType: GREEN_IER
|
||||
id: '19'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 10000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '1'
|
||||
destination: '7'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
id: '20'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 10000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '7'
|
||||
destination: '1'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
id: '21'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 10000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '2'
|
||||
destination: '7'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
id: '22'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 10000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '7'
|
||||
destination: '2'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
id: '23'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 5000
|
||||
protocol: TCP_SQL
|
||||
port: '1433'
|
||||
source: '7'
|
||||
destination: '8'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
id: '24'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 100000
|
||||
protocol: TCP_SQL
|
||||
port: '1433'
|
||||
source: '8'
|
||||
destination: '7'
|
||||
missionCriticality: 5
|
||||
- itemType: GREEN_IER
|
||||
id: '25'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 50000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '1'
|
||||
destination: '9'
|
||||
missionCriticality: 2
|
||||
- itemType: GREEN_IER
|
||||
id: '26'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 50000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '2'
|
||||
destination: '9'
|
||||
missionCriticality: 2
|
||||
- itemType: GREEN_IER
|
||||
id: '27'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 5000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '5'
|
||||
destination: '7'
|
||||
missionCriticality: 1
|
||||
- itemType: GREEN_IER
|
||||
id: '28'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 5000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '7'
|
||||
destination: '5'
|
||||
missionCriticality: 1
|
||||
- itemType: GREEN_IER
|
||||
id: '29'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 5000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '5'
|
||||
destination: '8'
|
||||
missionCriticality: 1
|
||||
- itemType: GREEN_IER
|
||||
id: '30'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 5000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '8'
|
||||
destination: '5'
|
||||
missionCriticality: 1
|
||||
- itemType: GREEN_IER
|
||||
id: '31'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 5000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '5'
|
||||
destination: '9'
|
||||
missionCriticality: 1
|
||||
- itemType: GREEN_IER
|
||||
id: '32'
|
||||
startStep: 1
|
||||
endStep: 256
|
||||
load: 5000
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '9'
|
||||
destination: '5'
|
||||
missionCriticality: 1
|
||||
- itemType: ACL_RULE
|
||||
id: '33'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.11
|
||||
destination: 192.168.2.10
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '34'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.11
|
||||
destination: 192.168.2.14
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '35'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.12
|
||||
destination: 192.168.2.14
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '36'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.12
|
||||
destination: 192.168.2.10
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '37'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.10
|
||||
destination: 192.168.10.11
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '38'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.10
|
||||
destination: 192.168.10.12
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '39'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.10
|
||||
destination: 192.168.2.14
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '40'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.14
|
||||
destination: 192.168.2.10
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '41'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.11
|
||||
destination: 192.168.2.16
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '42'
|
||||
permission: ALLOW
|
||||
source: 192.168.10.12
|
||||
destination: 192.168.2.16
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '43'
|
||||
permission: ALLOW
|
||||
source: 192.168.1.12
|
||||
destination: 192.168.2.10
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '44'
|
||||
permission: ALLOW
|
||||
source: 192.168.1.12
|
||||
destination: 192.168.2.14
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '45'
|
||||
permission: ALLOW
|
||||
source: 192.168.1.12
|
||||
destination: 192.168.2.16
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '46'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.10
|
||||
destination: 192.168.1.12
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '47'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.14
|
||||
destination: 192.168.1.12
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '48'
|
||||
permission: ALLOW
|
||||
source: 192.168.2.16
|
||||
destination: 192.168.1.12
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: ACL_RULE
|
||||
id: '49'
|
||||
permission: DENY
|
||||
source: ANY
|
||||
destination: ANY
|
||||
protocol: ANY
|
||||
port: ANY
|
||||
- itemType: RED_POL
|
||||
id: '50'
|
||||
startStep: 50
|
||||
endStep: 50
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: SERVICE
|
||||
protocol: UDP
|
||||
state: COMPROMISED
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_IER
|
||||
id: '51'
|
||||
startStep: 75
|
||||
endStep: 105
|
||||
load: 10000
|
||||
protocol: UDP
|
||||
port: '53'
|
||||
source: '1'
|
||||
destination: '8'
|
||||
missionCriticality: 0
|
||||
- itemType: RED_POL
|
||||
id: '52'
|
||||
startStep: 100
|
||||
endStep: 100
|
||||
targetNodeId: '8'
|
||||
initiator: IER
|
||||
type: SERVICE
|
||||
protocol: UDP
|
||||
state: COMPROMISED
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_POL
|
||||
id: '53'
|
||||
startStep: 105
|
||||
endStep: 105
|
||||
targetNodeId: '8'
|
||||
initiator: SERVICE
|
||||
type: FILE
|
||||
protocol: NA
|
||||
state: CORRUPT
|
||||
sourceNodeId: '8'
|
||||
sourceNodeService: UDP
|
||||
sourceNodeServiceState: COMPROMISED
|
||||
- itemType: RED_POL
|
||||
id: '54'
|
||||
startStep: 105
|
||||
endStep: 105
|
||||
targetNodeId: '8'
|
||||
initiator: SERVICE
|
||||
type: SERVICE
|
||||
protocol: TCP_SQL
|
||||
state: COMPROMISED
|
||||
sourceNodeId: '8'
|
||||
sourceNodeService: UDP
|
||||
sourceNodeServiceState: COMPROMISED
|
||||
- itemType: RED_POL
|
||||
id: '55'
|
||||
startStep: 125
|
||||
endStep: 125
|
||||
targetNodeId: '7'
|
||||
initiator: SERVICE
|
||||
type: SERVICE
|
||||
protocol: TCP
|
||||
state: OVERWHELMED
|
||||
sourceNodeId: '8'
|
||||
sourceNodeService: TCP_SQL
|
||||
sourceNodeServiceState: COMPROMISED
|
||||
69
src/primaite/config/lay_down_config.py
Normal file
69
src/primaite/config/lay_down_config.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
from pathlib import Path
|
||||
from typing import Final
|
||||
|
||||
from primaite import USERS_CONFIG_DIR, getLogger
|
||||
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
_EXAMPLE_LAY_DOWN: Final[Path] = USERS_CONFIG_DIR / "example_config" / "lay_down"
|
||||
|
||||
|
||||
def ddos_basic_one_config_path() -> Path:
|
||||
"""
|
||||
The path to the example lay_down_config_1_DDOS_basic.yaml file.
|
||||
|
||||
:return: The file path.
|
||||
"""
|
||||
path = _EXAMPLE_LAY_DOWN / "lay_down_config_1_DDOS_basic.yaml"
|
||||
if not path.exists():
|
||||
msg = "Example config not found. Please run 'primaite setup'"
|
||||
_LOGGER.critical(msg)
|
||||
raise FileNotFoundError(msg)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def ddos_basic_two_config_path() -> Path:
|
||||
"""
|
||||
The path to the example lay_down_config_2_DDOS_basic.yaml file.
|
||||
|
||||
:return: The file path.
|
||||
"""
|
||||
path = _EXAMPLE_LAY_DOWN / "lay_down_config_2_DDOS_basic.yaml"
|
||||
if not path.exists():
|
||||
msg = "Example config not found. Please run 'primaite setup'"
|
||||
_LOGGER.critical(msg)
|
||||
raise FileNotFoundError(msg)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def dos_very_basic_config_path() -> Path:
|
||||
"""
|
||||
The path to the example lay_down_config_3_DOS_very_basic.yaml file.
|
||||
|
||||
:return: The file path.
|
||||
"""
|
||||
path = _EXAMPLE_LAY_DOWN / "lay_down_config_3_DOS_very_basic.yaml"
|
||||
if not path.exists():
|
||||
msg = "Example config not found. Please run 'primaite setup'"
|
||||
_LOGGER.critical(msg)
|
||||
raise FileNotFoundError(msg)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def data_manipulation_config_path() -> Path:
|
||||
"""
|
||||
The path to the example lay_down_config_5_data_manipulation.yaml file.
|
||||
|
||||
:return: The file path.
|
||||
"""
|
||||
path = _EXAMPLE_LAY_DOWN / "lay_down_config_5_data_manipulation.yaml"
|
||||
if not path.exists():
|
||||
msg = "Example config not found. Please run 'primaite setup'"
|
||||
_LOGGER.critical(msg)
|
||||
raise FileNotFoundError(msg)
|
||||
|
||||
return path
|
||||
316
src/primaite/config/training_config.py
Normal file
316
src/primaite/config/training_config.py
Normal file
@@ -0,0 +1,316 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Final, Union, Optional
|
||||
|
||||
import yaml
|
||||
|
||||
from primaite import USERS_CONFIG_DIR, getLogger
|
||||
from primaite.common.enums import ActionType
|
||||
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
_EXAMPLE_TRAINING: Final[Path] = USERS_CONFIG_DIR / "example_config" / "training"
|
||||
|
||||
|
||||
@dataclass()
|
||||
class TrainingConfig:
|
||||
"""The Training Config class."""
|
||||
|
||||
# Generic
|
||||
agent_identifier: str = "STABLE_BASELINES3_A2C"
|
||||
"The Red Agent algo/class to be used."
|
||||
|
||||
action_type: ActionType = ActionType.ANY
|
||||
"The ActionType to use."
|
||||
|
||||
num_episodes: int = 10
|
||||
"The number of episodes to train over."
|
||||
|
||||
num_steps: int = 256
|
||||
"The number of steps in an episode."
|
||||
observation_space: dict = field(
|
||||
default_factory=lambda: {"components": [{"name": "NODE_LINK_TABLE"}]}
|
||||
)
|
||||
"The observation space config dict."
|
||||
|
||||
time_delay: int = 10
|
||||
"The delay between steps (ms). Applies to generic agents only."
|
||||
|
||||
# file
|
||||
session_type: str = "TRAINING"
|
||||
"the session type to run (TRAINING or EVALUATION)"
|
||||
|
||||
load_agent: str = False
|
||||
"Determine whether to load an agent from file."
|
||||
|
||||
agent_load_file: Optional[str] = None
|
||||
"File path and file name of agent if you're loading one in."
|
||||
|
||||
# Environment
|
||||
observation_space_high_value: int = 1000000000
|
||||
"The high value for the observation space."
|
||||
|
||||
# Reward values
|
||||
# Generic
|
||||
all_ok: int = 0
|
||||
|
||||
# Node Hardware State
|
||||
off_should_be_on: int = -10
|
||||
off_should_be_resetting: int = -5
|
||||
on_should_be_off: int = -2
|
||||
on_should_be_resetting: int = -5
|
||||
resetting_should_be_on: int = -5
|
||||
resetting_should_be_off: int = -2
|
||||
resetting: int = -3
|
||||
|
||||
# Node Software or Service State
|
||||
good_should_be_patching: int = 2
|
||||
good_should_be_compromised: int = 5
|
||||
good_should_be_overwhelmed: int = 5
|
||||
patching_should_be_good: int = -5
|
||||
patching_should_be_compromised: int = 2
|
||||
patching_should_be_overwhelmed: int = 2
|
||||
patching: int = -3
|
||||
compromised_should_be_good: int = -20
|
||||
compromised_should_be_patching: int = -20
|
||||
compromised_should_be_overwhelmed: int = -20
|
||||
compromised: int = -20
|
||||
overwhelmed_should_be_good: int = -20
|
||||
overwhelmed_should_be_patching: int = -20
|
||||
overwhelmed_should_be_compromised: int = -20
|
||||
overwhelmed: int = -20
|
||||
|
||||
# Node File System State
|
||||
good_should_be_repairing: int = 2
|
||||
good_should_be_restoring: int = 2
|
||||
good_should_be_corrupt: int = 5
|
||||
good_should_be_destroyed: int = 10
|
||||
repairing_should_be_good: int = -5
|
||||
repairing_should_be_restoring: int = 2
|
||||
repairing_should_be_corrupt: int = 2
|
||||
repairing_should_be_destroyed: int = 0
|
||||
repairing: int = -3
|
||||
restoring_should_be_good: int = -10
|
||||
restoring_should_be_repairing: int = -2
|
||||
restoring_should_be_corrupt: int = 1
|
||||
restoring_should_be_destroyed: int = 2
|
||||
restoring: int = -6
|
||||
corrupt_should_be_good: int = -10
|
||||
corrupt_should_be_repairing: int = -10
|
||||
corrupt_should_be_restoring: int = -10
|
||||
corrupt_should_be_destroyed: int = 2
|
||||
corrupt: int = -10
|
||||
destroyed_should_be_good: int = -20
|
||||
destroyed_should_be_repairing: int = -20
|
||||
destroyed_should_be_restoring: int = -20
|
||||
destroyed_should_be_corrupt: int = -20
|
||||
destroyed: int = -20
|
||||
scanning: int = -2
|
||||
|
||||
# IER status
|
||||
red_ier_running: int = -5
|
||||
green_ier_blocked: int = -10
|
||||
|
||||
# Patching / Reset durations
|
||||
os_patching_duration: int = 5
|
||||
"The time taken to patch the OS."
|
||||
|
||||
node_reset_duration: int = 5
|
||||
"The time taken to reset a node (hardware)."
|
||||
|
||||
node_booting_duration: int = 3
|
||||
"The Time taken to turn on the node."
|
||||
|
||||
node_shutdown_duration: int = 2
|
||||
"The time taken to turn off the node."
|
||||
|
||||
service_patching_duration: int = 5
|
||||
"The time taken to patch a service."
|
||||
|
||||
file_system_repairing_limit: int = 5
|
||||
"The time take to repair the file system."
|
||||
|
||||
file_system_restoring_limit: int = 5
|
||||
"The time take to restore the file system."
|
||||
|
||||
file_system_scanning_limit: int = 5
|
||||
"The time taken to scan the file system."
|
||||
|
||||
def to_dict(self, json_serializable: bool = True):
|
||||
"""
|
||||
Serialise the ``TrainingConfig`` as dict.
|
||||
|
||||
:param json_serializable: If True, Enums are converted to their
|
||||
string name.
|
||||
:return: The ``TrainingConfig`` as a dict.
|
||||
"""
|
||||
data = self.__dict__
|
||||
if json_serializable:
|
||||
data["action_type"] = self.action_type.value
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def main_training_config_path() -> Path:
|
||||
"""
|
||||
The path to the example training_config_main.yaml file.
|
||||
|
||||
:return: The file path.
|
||||
"""
|
||||
path = _EXAMPLE_TRAINING / "training_config_main.yaml"
|
||||
if not path.exists():
|
||||
msg = "Example config not found. Please run 'primaite setup'"
|
||||
_LOGGER.critical(msg)
|
||||
raise FileNotFoundError(msg)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def load(file_path: Union[str, Path],
|
||||
legacy_file: bool = False) -> TrainingConfig:
|
||||
"""
|
||||
Read in a training config yaml file.
|
||||
|
||||
:param file_path: The config file path.
|
||||
:param legacy_file: True if the config file is legacy format, otherwise
|
||||
False.
|
||||
:return: An instance of
|
||||
:class:`~primaite.config.training_config.TrainingConfig`.
|
||||
:raises ValueError: If the file_path does not exist.
|
||||
:raises TypeError: When the TrainingConfig object cannot be created
|
||||
using the values from the config file read from ``file_path``.
|
||||
"""
|
||||
if not isinstance(file_path, Path):
|
||||
file_path = Path(file_path)
|
||||
if file_path.exists():
|
||||
with open(file_path, "r") as file:
|
||||
config = yaml.safe_load(file)
|
||||
_LOGGER.debug(f"Loading training config file: {file_path}")
|
||||
if legacy_file:
|
||||
try:
|
||||
config = convert_legacy_training_config_dict(config)
|
||||
except KeyError:
|
||||
msg = (
|
||||
f"Failed to convert training config file {file_path} "
|
||||
f"from legacy format. Attempting to use file as is."
|
||||
)
|
||||
_LOGGER.error(msg)
|
||||
# Convert values to Enums
|
||||
config["action_type"] = ActionType[config["action_type"]]
|
||||
try:
|
||||
return TrainingConfig(**config)
|
||||
except TypeError as e:
|
||||
msg = (
|
||||
f"Error when creating an instance of {TrainingConfig} "
|
||||
f"from the training config file {file_path}"
|
||||
)
|
||||
_LOGGER.critical(msg, exc_info=True)
|
||||
raise e
|
||||
msg = f"Cannot load the training config as it does not exist: {file_path}"
|
||||
_LOGGER.error(msg)
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
def convert_legacy_training_config_dict(
|
||||
legacy_config_dict: Dict[str, Any],
|
||||
num_steps: int = 256,
|
||||
action_type: str = "ANY"
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Convert a legacy training config dict to the new format.
|
||||
|
||||
:param legacy_config_dict: A legacy training config dict.
|
||||
:param num_steps: The number of steps to set as legacy training configs
|
||||
don't have num_steps values.
|
||||
:param action_type: The action space type to set as legacy training configs
|
||||
don't have action_type values.
|
||||
:return: The converted training config dict.
|
||||
"""
|
||||
config_dict = {
|
||||
"num_steps": num_steps,
|
||||
"action_type": action_type
|
||||
}
|
||||
for legacy_key, value in legacy_config_dict.items():
|
||||
new_key = _get_new_key_from_legacy(legacy_key)
|
||||
if new_key:
|
||||
config_dict[new_key] = value
|
||||
return config_dict
|
||||
|
||||
|
||||
def _get_new_key_from_legacy(legacy_key: str) -> str:
|
||||
"""
|
||||
Maps legacy training config keys to the new format keys.
|
||||
|
||||
:param legacy_key: A legacy training config key.
|
||||
:return: The mapped key.
|
||||
"""
|
||||
key_mapping = {
|
||||
"agentIdentifier": "agent_identifier",
|
||||
"numEpisodes": "num_episodes",
|
||||
"timeDelay": "time_delay",
|
||||
"configFilename": None,
|
||||
"sessionType": "session_type",
|
||||
"loadAgent": "load_agent",
|
||||
"agentLoadFile": "agent_load_file",
|
||||
"observationSpaceHighValue": "observation_space_high_value",
|
||||
"allOk": "all_ok",
|
||||
"offShouldBeOn": "off_should_be_on",
|
||||
"offShouldBeResetting": "off_should_be_resetting",
|
||||
"onShouldBeOff": "on_should_be_off",
|
||||
"onShouldBeResetting": "on_should_be_resetting",
|
||||
"resettingShouldBeOn": "resetting_should_be_on",
|
||||
"resettingShouldBeOff": "resetting_should_be_off",
|
||||
"resetting": "resetting",
|
||||
"goodShouldBePatching": "good_should_be_patching",
|
||||
"goodShouldBeCompromised": "good_should_be_compromised",
|
||||
"goodShouldBeOverwhelmed": "good_should_be_overwhelmed",
|
||||
"patchingShouldBeGood": "patching_should_be_good",
|
||||
"patchingShouldBeCompromised": "patching_should_be_compromised",
|
||||
"patchingShouldBeOverwhelmed": "patching_should_be_overwhelmed",
|
||||
"patching": "patching",
|
||||
"compromisedShouldBeGood": "compromised_should_be_good",
|
||||
"compromisedShouldBePatching": "compromised_should_be_patching",
|
||||
"compromisedShouldBeOverwhelmed": "compromised_should_be_overwhelmed",
|
||||
"compromised": "compromised",
|
||||
"overwhelmedShouldBeGood": "overwhelmed_should_be_good",
|
||||
"overwhelmedShouldBePatching": "overwhelmed_should_be_patching",
|
||||
"overwhelmedShouldBeCompromised": "overwhelmed_should_be_compromised",
|
||||
"overwhelmed": "overwhelmed",
|
||||
"goodShouldBeRepairing": "good_should_be_repairing",
|
||||
"goodShouldBeRestoring": "good_should_be_restoring",
|
||||
"goodShouldBeCorrupt": "good_should_be_corrupt",
|
||||
"goodShouldBeDestroyed": "good_should_be_destroyed",
|
||||
"repairingShouldBeGood": "repairing_should_be_good",
|
||||
"repairingShouldBeRestoring": "repairing_should_be_restoring",
|
||||
"repairingShouldBeCorrupt": "repairing_should_be_corrupt",
|
||||
"repairingShouldBeDestroyed": "repairing_should_be_destroyed",
|
||||
"repairing": "repairing",
|
||||
"restoringShouldBeGood": "restoring_should_be_good",
|
||||
"restoringShouldBeRepairing": "restoring_should_be_repairing",
|
||||
"restoringShouldBeCorrupt": "restoring_should_be_corrupt",
|
||||
"restoringShouldBeDestroyed": "restoring_should_be_destroyed",
|
||||
"restoring": "restoring",
|
||||
"corruptShouldBeGood": "corrupt_should_be_good",
|
||||
"corruptShouldBeRepairing": "corrupt_should_be_repairing",
|
||||
"corruptShouldBeRestoring": "corrupt_should_be_restoring",
|
||||
"corruptShouldBeDestroyed": "corrupt_should_be_destroyed",
|
||||
"corrupt": "corrupt",
|
||||
"destroyedShouldBeGood": "destroyed_should_be_good",
|
||||
"destroyedShouldBeRepairing": "destroyed_should_be_repairing",
|
||||
"destroyedShouldBeRestoring": "destroyed_should_be_restoring",
|
||||
"destroyedShouldBeCorrupt": "destroyed_should_be_corrupt",
|
||||
"destroyed": "destroyed",
|
||||
"scanning": "scanning",
|
||||
"redIerRunning": "red_ier_running",
|
||||
"greenIerBlocked": "green_ier_blocked",
|
||||
"osPatchingDuration": "os_patching_duration",
|
||||
"nodeResetDuration": "node_reset_duration",
|
||||
"nodeBootingDuration": "node_booting_duration",
|
||||
"nodeShutdownDuration": "node_shutdown_duration",
|
||||
"servicePatchingDuration": "service_patching_duration",
|
||||
"fileSystemRepairingLimit": "file_system_repairing_limit",
|
||||
"fileSystemRestoringLimit": "file_system_restoring_limit",
|
||||
"fileSystemScanningLimit": "file_system_scanning_limit",
|
||||
}
|
||||
return key_mapping[legacy_key]
|
||||
@@ -355,21 +355,50 @@ class AccessControlList(AbstractObservationComponent):
|
||||
# 3. Initialise observation with zeroes
|
||||
self.current_observation = np.zeros(len(shape), dtype=self._DATA_TYPE)
|
||||
|
||||
# Dictionary to map services to numbers for obs space
|
||||
self.services_dict = {}
|
||||
|
||||
def update(self):
|
||||
"""Update the observation based on current environment state.
|
||||
|
||||
The structure of the observation space is described in :class:`.AccessControlList`
|
||||
"""
|
||||
obs = []
|
||||
for acl_rule in self.env.acl:
|
||||
for acl_rule in self.env.acl.acl:
|
||||
permission = acl_rule.permission
|
||||
source_ip = acl_rule.source_ip
|
||||
dest_ip = acl_rule.dest_ip
|
||||
protocol = acl_rule.protocol
|
||||
port = acl_rule.port
|
||||
position = self.env.acl.index(acl_rule)
|
||||
position = self.env.acl.acl.index(acl_rule)
|
||||
if permission == "DENY":
|
||||
permission_int = 0
|
||||
else:
|
||||
permission_int = 1
|
||||
|
||||
obs.extend([permission, source_ip, dest_ip, protocol, port, position])
|
||||
if source_ip == "ANY":
|
||||
source_ip = 0
|
||||
if dest_ip == "ANY":
|
||||
dest_ip = 0
|
||||
if port == "ANY":
|
||||
port = 0
|
||||
if protocol == "ANY":
|
||||
protocol_int = 0
|
||||
else:
|
||||
while True:
|
||||
if protocol in self.service_dict:
|
||||
protocol_int = self.services_dict[protocol]
|
||||
break
|
||||
else:
|
||||
self.services_dict[protocol] = len(self.services_dict) + 1
|
||||
continue
|
||||
# [0 - DENY, 1 - ALLOW] Permission
|
||||
# [0 - ANY, x - IP Address/Protocol/Port]
|
||||
|
||||
print(permission_int, source_ip, dest_ip, protocol_int, port)
|
||||
obs.extend(
|
||||
[permission_int, source_ip, dest_ip, protocol_int, port, position]
|
||||
)
|
||||
|
||||
self.current_observation[:] = obs
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
"""Main environment module containing the PRIMmary AI Training Evironment (Primaite) class."""
|
||||
|
||||
import copy
|
||||
import csv
|
||||
import logging
|
||||
import os.path
|
||||
from datetime import datetime
|
||||
from typing import Dict, Tuple
|
||||
from pathlib import Path
|
||||
from typing import Dict, Tuple, Union
|
||||
|
||||
import networkx as nx
|
||||
import numpy as np
|
||||
@@ -24,11 +23,13 @@ from primaite.common.enums import (
|
||||
NodePOLInitiator,
|
||||
NodePOLType,
|
||||
NodeType,
|
||||
ObservationType,
|
||||
Priority,
|
||||
RulePermissionType,
|
||||
SoftwareState,
|
||||
)
|
||||
from primaite.common.service import Service
|
||||
from primaite.config import training_config
|
||||
from primaite.config.training_config import TrainingConfig
|
||||
from primaite.environment.observations import ObservationsHandler
|
||||
from primaite.environment.reward import calculate_reward_function
|
||||
from primaite.links.link import Link
|
||||
@@ -56,29 +57,41 @@ class Primaite(Env):
|
||||
ACTION_SPACE_ACL_ACTION_VALUES: int = 3
|
||||
ACTION_SPACE_ACL_PERMISSION_VALUES: int = 2
|
||||
|
||||
def __init__(self, _config_values, _transaction_list):
|
||||
def __init__(
|
||||
self,
|
||||
training_config_path: Union[str, Path],
|
||||
lay_down_config_path: Union[str, Path],
|
||||
transaction_list,
|
||||
session_path: Path,
|
||||
timestamp_str: str,
|
||||
):
|
||||
"""
|
||||
Init.
|
||||
The Primaite constructor.
|
||||
|
||||
Args:
|
||||
_episode_steps: The number of steps for the episode
|
||||
_config_filename: The name of config file
|
||||
_transaction_list: The list of transactions to populate
|
||||
_agent_identifier: Identifier for the agent
|
||||
:param training_config_path: The training config filepath.
|
||||
:param lay_down_config_path: The lay down config filepath.
|
||||
:param transaction_list: The list of transactions to populate.
|
||||
:param session_path: The directory path the session is writing to.
|
||||
:param timestamp_str: The session timestamp in the format:
|
||||
<yyyy-mm-dd>_<hh-mm-ss>.
|
||||
"""
|
||||
super(Primaite, self).__init__()
|
||||
self._training_config_path = training_config_path
|
||||
self._lay_down_config_path = lay_down_config_path
|
||||
|
||||
# Take a copy of the config values
|
||||
self.config_values = _config_values
|
||||
self.training_config: TrainingConfig = training_config.load(
|
||||
training_config_path
|
||||
)
|
||||
|
||||
# Number of steps in an episode
|
||||
self.episode_steps = 0
|
||||
self.episode_steps = self.training_config.num_steps
|
||||
|
||||
super(Primaite, self).__init__()
|
||||
|
||||
# Transaction list
|
||||
self.transaction_list = _transaction_list
|
||||
self.transaction_list = transaction_list
|
||||
|
||||
# The agent in use
|
||||
self.agent_identifier = self.config_values.agent_identifier
|
||||
self.agent_identifier = self.training_config.agent_identifier
|
||||
|
||||
# Create a dictionary to hold all the nodes
|
||||
self.nodes: Dict[str, NodeUnion] = {}
|
||||
@@ -122,6 +135,9 @@ class Primaite(Env):
|
||||
# Create step count
|
||||
self.step_count = 0
|
||||
|
||||
self.total_step_count: int = 0
|
||||
"""The total number of time steps completed."""
|
||||
|
||||
# Create step info dictionary
|
||||
self.step_info = {}
|
||||
|
||||
@@ -149,29 +165,21 @@ class Primaite(Env):
|
||||
# The action type
|
||||
self.action_type = 0
|
||||
|
||||
# TODO fix up with TrainingConfig
|
||||
# stores the observation config from the yaml, default is NODE_LINK_TABLE
|
||||
self.obs_config: dict = {"components": [{"name": "NODE_LINK_TABLE"}]}
|
||||
if self.config_values.observation_config is not None:
|
||||
self.obs_config = self.config_values.observation_config
|
||||
if self.training_config.observation_space is not None:
|
||||
self.obs_config = self.training_config.observation_space
|
||||
|
||||
# Observation Handler manages the user-configurable observation space.
|
||||
# It will be initialised later.
|
||||
self.obs_handler: ObservationsHandler
|
||||
|
||||
# Set by main_config
|
||||
# Adds a DENY ALL or ALLOW ALL to the end of the Access Control List
|
||||
self.acl_implicit_rule = RulePermissionType.DENY
|
||||
|
||||
# Sets a limit to how many ACL
|
||||
self.max_acl_rules = 0
|
||||
# Open the config file and build the environment laydown
|
||||
try:
|
||||
self.config_file = open(self.config_values.config_filename_use_case, "r")
|
||||
self.config_data = yaml.safe_load(self.config_file)
|
||||
self.load_config()
|
||||
except Exception:
|
||||
_LOGGER.error("Could not load the environment configuration")
|
||||
_LOGGER.error("Exception occured", exc_info=True)
|
||||
with open(self._lay_down_config_path, "r") as file:
|
||||
# Open the config file and build the environment laydown
|
||||
self.lay_down_config = yaml.safe_load(file)
|
||||
self.load_lay_down_config()
|
||||
|
||||
# Store the node objects as node attributes
|
||||
# (This is so we can access them as objects)
|
||||
@@ -188,15 +196,10 @@ class Primaite(Env):
|
||||
try:
|
||||
plt.tight_layout()
|
||||
nx.draw_networkx(self.network, with_labels=True)
|
||||
now = datetime.now() # current date and time
|
||||
time = now.strftime("%Y%m%d_%H%M%S")
|
||||
datetime.now() # current date and time
|
||||
|
||||
path = "outputs/diagrams"
|
||||
is_dir = os.path.isdir(path)
|
||||
if not is_dir:
|
||||
os.makedirs(path)
|
||||
filename = "outputs/diagrams/network_" + time + ".png"
|
||||
plt.savefig(filename, format="PNG")
|
||||
file_path = session_path / f"network_{timestamp_str}.png"
|
||||
plt.savefig(file_path, format="PNG")
|
||||
plt.clf()
|
||||
except Exception:
|
||||
_LOGGER.error("Could not save network diagram")
|
||||
@@ -207,7 +210,7 @@ class Primaite(Env):
|
||||
self.observation_space, self.env_obs = self.init_observations()
|
||||
|
||||
# Define Action Space - depends on action space type (Node or ACL)
|
||||
if self.action_type == ActionType.NODE:
|
||||
if self.training_config.action_type == ActionType.NODE:
|
||||
_LOGGER.info("Action space type NODE selected")
|
||||
# Terms (for node action space):
|
||||
# [0, num nodes] - node ID (0 = nothing, node ID)
|
||||
@@ -216,7 +219,7 @@ class Primaite(Env):
|
||||
# [0, num services] - resolves to service ID (0 = nothing, resolves to service) # noqa
|
||||
self.action_dict = self.create_node_action_dict()
|
||||
self.action_space = spaces.Discrete(len(self.action_dict))
|
||||
elif self.action_type == ActionType.ACL:
|
||||
elif self.training_config.action_type == ActionType.ACL:
|
||||
_LOGGER.info("Action space type ACL selected")
|
||||
# Terms (for ACL action space):
|
||||
# [0, 2] - Action (0 = do nothing, 1 = create rule, 2 = delete rule)
|
||||
@@ -227,25 +230,21 @@ class Primaite(Env):
|
||||
# [0, num ports] - Port (0 = any, then 1 -> x resolving to port)
|
||||
self.action_dict = self.create_acl_action_dict()
|
||||
self.action_space = spaces.Discrete(len(self.action_dict))
|
||||
elif self.action_type == ActionType.ANY:
|
||||
elif self.training_config.action_type == ActionType.ANY:
|
||||
_LOGGER.info("Action space type ANY selected - Node + ACL")
|
||||
self.action_dict = self.create_node_and_acl_action_dict()
|
||||
self.action_space = spaces.Discrete(len(self.action_dict))
|
||||
else:
|
||||
_LOGGER.info("Invalid action type selected")
|
||||
_LOGGER.info(
|
||||
f"Invalid action type selected: {self.training_config.action_type}"
|
||||
)
|
||||
# Set up a csv to store the results of the training
|
||||
try:
|
||||
now = datetime.now() # current date and time
|
||||
time = now.strftime("%Y%m%d_%H%M%S")
|
||||
header = ["Episode", "Average Reward"]
|
||||
|
||||
# Check whether the output/rerults folder exists (doesn't exist by default install)
|
||||
path = "outputs/results/"
|
||||
is_dir = os.path.isdir(path)
|
||||
if not is_dir:
|
||||
os.makedirs(path)
|
||||
filename = "outputs/results/average_reward_per_episode_" + time + ".csv"
|
||||
self.csv_file = open(filename, "w", encoding="UTF8", newline="")
|
||||
file_name = f"average_reward_per_episode_{timestamp_str}.csv"
|
||||
file_path = session_path / file_name
|
||||
self.csv_file = open(file_path, "w", encoding="UTF8", newline="")
|
||||
self.csv_writer = csv.writer(self.csv_file)
|
||||
self.csv_writer.writerow(header)
|
||||
except Exception:
|
||||
@@ -304,7 +303,8 @@ class Primaite(Env):
|
||||
done = False
|
||||
|
||||
self.step_count += 1
|
||||
# print("Episode step: " + str(self.stepCount))
|
||||
self.total_step_count += 1
|
||||
# print("Episode step: " + str(self.step_count))
|
||||
|
||||
# Need to clear traffic on all links first
|
||||
for link_key, link_value in self.links.items():
|
||||
@@ -376,13 +376,13 @@ class Primaite(Env):
|
||||
self.green_iers,
|
||||
self.red_iers,
|
||||
self.step_count,
|
||||
self.config_values,
|
||||
self.training_config,
|
||||
)
|
||||
print(f" Step {self.step_count} Reward: {str(reward)}")
|
||||
# print(f" Step {self.step_count} Reward: {str(reward)}")
|
||||
self.total_reward += reward
|
||||
if self.step_count == self.episode_steps:
|
||||
self.average_reward = self.total_reward / self.step_count
|
||||
if self.config_values.session_type == "EVALUATION":
|
||||
if self.training_config.session_type == "EVALUATION":
|
||||
# For evaluation, need to trigger the done value = True when
|
||||
# step count is reached in order to prevent neverending episode
|
||||
done = True
|
||||
@@ -407,7 +407,6 @@ class Primaite(Env):
|
||||
def __close__(self):
|
||||
"""Override close function."""
|
||||
self.csv_file.close()
|
||||
self.config_file.close()
|
||||
|
||||
def init_acl(self):
|
||||
"""Initialise the Access Control List."""
|
||||
@@ -433,9 +432,10 @@ class Primaite(Env):
|
||||
_action: The action space from the agent
|
||||
"""
|
||||
# At the moment, actions are only affecting nodes
|
||||
if self.action_type == ActionType.NODE:
|
||||
|
||||
if self.training_config.action_type == ActionType.NODE:
|
||||
self.apply_actions_to_nodes(_action)
|
||||
elif self.action_type == ActionType.ACL:
|
||||
elif self.training_config.action_type == ActionType.ACL:
|
||||
self.apply_actions_to_acl(_action)
|
||||
elif (
|
||||
len(self.action_dict[_action]) == 6
|
||||
@@ -673,44 +673,39 @@ class Primaite(Env):
|
||||
self.obs_handler.update_obs()
|
||||
self.env_obs = self.obs_handler.current_observation
|
||||
|
||||
def load_config(self):
|
||||
def load_lay_down_config(self):
|
||||
"""Loads config data in order to build the environment configuration."""
|
||||
for item in self.config_data:
|
||||
if item["itemType"] == "NODE":
|
||||
for item in self.lay_down_config:
|
||||
if item["item_type"] == "NODE":
|
||||
# Create a node
|
||||
self.create_node(item)
|
||||
elif item["itemType"] == "LINK":
|
||||
elif item["item_type"] == "LINK":
|
||||
# Create a link
|
||||
self.create_link(item)
|
||||
elif item["itemType"] == "GREEN_IER":
|
||||
elif item["item_type"] == "GREEN_IER":
|
||||
# Create a Green IER
|
||||
self.create_green_ier(item)
|
||||
elif item["itemType"] == "GREEN_POL":
|
||||
elif item["item_type"] == "GREEN_POL":
|
||||
# Create a Green PoL
|
||||
self.create_green_pol(item)
|
||||
elif item["itemType"] == "RED_IER":
|
||||
elif item["item_type"] == "RED_IER":
|
||||
# Create a Red IER
|
||||
self.create_red_ier(item)
|
||||
elif item["itemType"] == "RED_POL":
|
||||
elif item["item_type"] == "RED_POL":
|
||||
# Create a Red PoL
|
||||
self.create_red_pol(item)
|
||||
elif item["itemType"] == "ACL_RULE":
|
||||
elif item["item_type"] == "ACL_RULE":
|
||||
# Create an ACL rule
|
||||
self.create_acl_rule(item)
|
||||
elif item["itemType"] == "SERVICES":
|
||||
elif item["item_type"] == "SERVICES":
|
||||
# Create the list of services
|
||||
self.create_services_list(item)
|
||||
elif item["itemType"] == "PORTS":
|
||||
elif item["item_type"] == "PORTS":
|
||||
# Create the list of ports
|
||||
self.create_ports_list(item)
|
||||
elif item["itemType"] == "ACTIONS":
|
||||
# Get the action information
|
||||
self.get_action_info(item)
|
||||
elif item["itemType"] == "STEPS":
|
||||
# Get the steps information
|
||||
self.get_steps_info(item)
|
||||
else:
|
||||
# Do nothing (bad formatting)
|
||||
item_type = item["item_type"]
|
||||
_LOGGER.error(f"Invalid item_type: {item_type}")
|
||||
pass
|
||||
|
||||
_LOGGER.info("Environment configuration loaded")
|
||||
@@ -738,7 +733,7 @@ class Primaite(Env):
|
||||
node_type,
|
||||
node_priority,
|
||||
node_hardware_state,
|
||||
self.config_values,
|
||||
self.training_config,
|
||||
)
|
||||
elif node_class == "ACTIVE":
|
||||
# Active nodes have IP address, Software State and file system state
|
||||
@@ -754,7 +749,7 @@ class Primaite(Env):
|
||||
node_ip_address,
|
||||
node_software_state,
|
||||
node_file_system_state,
|
||||
self.config_values,
|
||||
self.training_config,
|
||||
)
|
||||
elif node_class == "SERVICE":
|
||||
# Service nodes have IP address, Software State, file system state and list of services
|
||||
@@ -770,7 +765,7 @@ class Primaite(Env):
|
||||
node_ip_address,
|
||||
node_software_state,
|
||||
node_file_system_state,
|
||||
self.config_values,
|
||||
self.training_config,
|
||||
)
|
||||
node_services = item["services"]
|
||||
for service in node_services:
|
||||
@@ -849,14 +844,14 @@ class Primaite(Env):
|
||||
item: A config data item
|
||||
"""
|
||||
ier_id = item["id"]
|
||||
ier_start_step = item["startStep"]
|
||||
ier_end_step = item["endStep"]
|
||||
ier_start_step = item["start_step"]
|
||||
ier_end_step = item["end_step"]
|
||||
ier_load = item["load"]
|
||||
ier_protocol = item["protocol"]
|
||||
ier_port = item["port"]
|
||||
ier_source = item["source"]
|
||||
ier_destination = item["destination"]
|
||||
ier_mission_criticality = item["missionCriticality"]
|
||||
ier_mission_criticality = item["mission_criticality"]
|
||||
|
||||
# Create IER and add to green IER dictionary
|
||||
self.green_iers[ier_id] = IER(
|
||||
@@ -879,14 +874,14 @@ class Primaite(Env):
|
||||
item: A config data item
|
||||
"""
|
||||
ier_id = item["id"]
|
||||
ier_start_step = item["startStep"]
|
||||
ier_end_step = item["endStep"]
|
||||
ier_start_step = item["start_step"]
|
||||
ier_end_step = item["end_step"]
|
||||
ier_load = item["load"]
|
||||
ier_protocol = item["protocol"]
|
||||
ier_port = item["port"]
|
||||
ier_source = item["source"]
|
||||
ier_destination = item["destination"]
|
||||
ier_mission_criticality = item["missionCriticality"]
|
||||
ier_mission_criticality = item["mission_criticality"]
|
||||
|
||||
# Create IER and add to red IER dictionary
|
||||
self.red_iers[ier_id] = IER(
|
||||
@@ -909,8 +904,8 @@ class Primaite(Env):
|
||||
item: A config data item
|
||||
"""
|
||||
pol_id = item["id"]
|
||||
pol_start_step = item["startStep"]
|
||||
pol_end_step = item["endStep"]
|
||||
pol_start_step = item["start_step"]
|
||||
pol_end_step = item["end_step"]
|
||||
pol_node = item["nodeId"]
|
||||
pol_type = NodePOLType[item["type"]]
|
||||
|
||||
@@ -943,8 +938,8 @@ class Primaite(Env):
|
||||
item: A config data item
|
||||
"""
|
||||
pol_id = item["id"]
|
||||
pol_start_step = item["startStep"]
|
||||
pol_end_step = item["endStep"]
|
||||
pol_start_step = item["start_step"]
|
||||
pol_end_step = item["end_step"]
|
||||
pol_target_node_id = item["targetNodeId"]
|
||||
pol_initiator = NodePOLInitiator[item["initiator"]]
|
||||
pol_type = NodePOLType[item["type"]]
|
||||
@@ -1004,7 +999,7 @@ class Primaite(Env):
|
||||
Args:
|
||||
item: A config data item representing the services
|
||||
"""
|
||||
service_list = services["serviceList"]
|
||||
service_list = services["service_list"]
|
||||
|
||||
for service in service_list:
|
||||
service_name = service["name"]
|
||||
@@ -1020,7 +1015,7 @@ class Primaite(Env):
|
||||
Args:
|
||||
item: A config data item representing the ports
|
||||
"""
|
||||
ports_list = ports["portsList"]
|
||||
ports_list = ports["ports_list"]
|
||||
|
||||
for port in ports_list:
|
||||
port_value = port["port"]
|
||||
@@ -1029,6 +1024,14 @@ class Primaite(Env):
|
||||
# Set the number of ports
|
||||
self.num_ports = len(self.ports_list)
|
||||
|
||||
def get_observation_info(self, observation_info):
|
||||
"""Extracts observation_info.
|
||||
|
||||
:param observation_info: Config item that defines which type of observation space to use
|
||||
:type observation_info: str
|
||||
"""
|
||||
self.observation_type = ObservationType[observation_info["type"]]
|
||||
|
||||
def get_action_info(self, action_info):
|
||||
"""
|
||||
Extracts action_info.
|
||||
@@ -1050,16 +1053,6 @@ class Primaite(Env):
|
||||
"""
|
||||
self.obs_config = obs_config
|
||||
|
||||
def get_steps_info(self, steps_info):
|
||||
"""
|
||||
Extracts steps_info.
|
||||
|
||||
Args:
|
||||
item: A config data item representing steps info
|
||||
"""
|
||||
self.episode_steps = int(steps_info["steps"])
|
||||
_LOGGER.info("Training episodes have " + str(self.episode_steps) + " steps")
|
||||
|
||||
def reset_environment(self):
|
||||
"""
|
||||
# Resets environment.
|
||||
@@ -1067,11 +1060,11 @@ class Primaite(Env):
|
||||
Uses config data config data in order to build the environment
|
||||
configuration.
|
||||
"""
|
||||
for item in self.config_data:
|
||||
if item["itemType"] == "NODE":
|
||||
for item in self.lay_down_config:
|
||||
if item["item_type"] == "NODE":
|
||||
# Reset a node's state (normal and reference)
|
||||
self.reset_node(item)
|
||||
elif item["itemType"] == "ACL_RULE":
|
||||
elif item["item_type"] == "ACL_RULE":
|
||||
# Create an ACL rule (these are cleared on reset, so just need to recreate them)
|
||||
self.create_acl_rule(item)
|
||||
else:
|
||||
@@ -1173,7 +1166,7 @@ class Primaite(Env):
|
||||
def create_acl_action_dict(self):
|
||||
"""Creates a dictionary mapping each possible discrete action to more readable multidiscrete action."""
|
||||
# reserve 0 action to be a nothing action
|
||||
actions = {0: [0, 0, 0, 0, 0, 0, 0]}
|
||||
actions = {0: [0, 0, 0, 0, 0, 0]}
|
||||
|
||||
action_key = 1
|
||||
# 3 possible action decisions, 0=NOTHING, 1=CREATE, 2=DELETE
|
||||
@@ -1185,16 +1178,14 @@ class Primaite(Env):
|
||||
for dest_ip in range(self.num_nodes + 1):
|
||||
for protocol in range(self.num_services + 1):
|
||||
for port in range(self.num_ports + 1):
|
||||
for position in range(self.max_acl_rules - 1):
|
||||
action = [
|
||||
action_decision,
|
||||
action_permission,
|
||||
source_ip,
|
||||
dest_ip,
|
||||
protocol,
|
||||
port,
|
||||
position,
|
||||
]
|
||||
action = [
|
||||
action_decision,
|
||||
action_permission,
|
||||
source_ip,
|
||||
dest_ip,
|
||||
protocol,
|
||||
port,
|
||||
]
|
||||
# Check to see if its an action we want to include as possible i.e. not a nothing action
|
||||
if is_valid_acl_action_extra(action):
|
||||
actions[action_key] = action
|
||||
|
||||
@@ -1,29 +1,42 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
"""
|
||||
Primaite - main (harness) module.
|
||||
The main PrimAITE session runner module.
|
||||
|
||||
Coding Standards: PEP 8
|
||||
TODO: This will eventually be refactored out into a proper Session class.
|
||||
TODO: The passing about of session_dir and timestamp_str is temporary and
|
||||
will be cleaned up once we move to a proper Session class.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os.path
|
||||
import argparse
|
||||
import json
|
||||
import time
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Final, Union
|
||||
from uuid import uuid4
|
||||
|
||||
import yaml
|
||||
from stable_baselines3 import A2C, PPO
|
||||
from stable_baselines3.common.evaluation import evaluate_policy
|
||||
from stable_baselines3.common.on_policy_algorithm import OnPolicyAlgorithm
|
||||
from stable_baselines3.ppo import MlpPolicy as PPOMlp
|
||||
|
||||
from primaite.common.config_values_main import ConfigValuesMain
|
||||
from primaite import SESSIONS_DIR, getLogger
|
||||
from primaite.config.training_config import TrainingConfig
|
||||
from primaite.environment.primaite_env import Primaite
|
||||
from primaite.transactions.transactions_to_file import write_transaction_to_file
|
||||
from primaite.transactions.transactions_to_file import \
|
||||
write_transaction_to_file
|
||||
|
||||
# FUNCTIONS #
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
|
||||
def run_generic():
|
||||
"""Run against a generic agent."""
|
||||
def run_generic(env: Primaite, config_values: TrainingConfig):
|
||||
"""
|
||||
Run against a generic agent.
|
||||
|
||||
:param env: An instance of
|
||||
:class:`~primaite.environment.primaite_env.Primaite`.
|
||||
:param config_values: An instance of
|
||||
:class:`~primaite.config.training_config.TrainingConfig`.
|
||||
"""
|
||||
for episode in range(0, config_values.num_episodes):
|
||||
env.reset()
|
||||
for step in range(0, config_values.num_steps):
|
||||
@@ -47,9 +60,21 @@ def run_generic():
|
||||
env.close()
|
||||
|
||||
|
||||
def run_stable_baselines3_ppo():
|
||||
"""Run against a stable_baselines3 PPO agent."""
|
||||
if config_values.load_agent == True:
|
||||
def run_stable_baselines3_ppo(
|
||||
env: Primaite, config_values: TrainingConfig, session_path: Path, timestamp_str: str
|
||||
):
|
||||
"""
|
||||
Run against a stable_baselines3 PPO agent.
|
||||
|
||||
:param env: An instance of
|
||||
:class:`~primaite.environment.primaite_env.Primaite`.
|
||||
:param config_values: An instance of
|
||||
:class:`~primaite.config.training_config.TrainingConfig`.
|
||||
:param session_path: The directory path the session is writing to.
|
||||
:param timestamp_str: The session timestamp in the format:
|
||||
<yyyy-mm-dd>_<hh-mm-ss>.
|
||||
"""
|
||||
if config_values.load_agent:
|
||||
try:
|
||||
agent = PPO.load(
|
||||
config_values.agent_load_file,
|
||||
@@ -62,30 +87,42 @@ def run_stable_baselines3_ppo():
|
||||
"ERROR: Could not load agent at location: "
|
||||
+ config_values.agent_load_file
|
||||
)
|
||||
logging.error("Could not load agent")
|
||||
logging.error("Exception occured", exc_info=True)
|
||||
_LOGGER.error("Could not load agent")
|
||||
_LOGGER.error("Exception occured", exc_info=True)
|
||||
else:
|
||||
agent = PPO(PPOMlp, env, verbose=0, n_steps=config_values.num_steps)
|
||||
|
||||
if config_values.session_type == "TRAINING":
|
||||
# We're in a training session
|
||||
print("Starting training session...")
|
||||
logging.info("Starting training session...")
|
||||
for episode in range(0, config_values.num_episodes):
|
||||
agent.learn(total_timesteps=1)
|
||||
save_agent(agent)
|
||||
_LOGGER.debug("Starting training session...")
|
||||
for episode in range(config_values.num_episodes):
|
||||
agent.learn(total_timesteps=config_values.num_steps)
|
||||
_save_agent(agent, session_path, timestamp_str)
|
||||
else:
|
||||
# Default to being in an evaluation session
|
||||
print("Starting evaluation session...")
|
||||
logging.info("Starting evaluation session...")
|
||||
_LOGGER.debug("Starting evaluation session...")
|
||||
evaluate_policy(agent, env, n_eval_episodes=config_values.num_episodes)
|
||||
|
||||
env.close()
|
||||
|
||||
|
||||
def run_stable_baselines3_a2c():
|
||||
"""Run against a stable_baselines3 A2C agent."""
|
||||
if config_values.load_agent == True:
|
||||
def run_stable_baselines3_a2c(
|
||||
env: Primaite, config_values: TrainingConfig, session_path: Path, timestamp_str: str
|
||||
):
|
||||
"""
|
||||
Run against a stable_baselines3 A2C agent.
|
||||
|
||||
:param env: An instance of
|
||||
:class:`~primaite.environment.primaite_env.Primaite`.
|
||||
:param config_values: An instance of
|
||||
:class:`~primaite.config.training_config.TrainingConfig`.
|
||||
param session_path: The directory path the session is writing to.
|
||||
:param timestamp_str: The session timestamp in the format:
|
||||
<yyyy-mm-dd>_<hh-mm-ss>.
|
||||
"""
|
||||
if config_values.load_agent:
|
||||
try:
|
||||
agent = A2C.load(
|
||||
config_values.agent_load_file,
|
||||
@@ -98,288 +135,219 @@ def run_stable_baselines3_a2c():
|
||||
"ERROR: Could not load agent at location: "
|
||||
+ config_values.agent_load_file
|
||||
)
|
||||
logging.error("Could not load agent")
|
||||
logging.error("Exception occured", exc_info=True)
|
||||
_LOGGER.error("Could not load agent")
|
||||
_LOGGER.error("Exception occured", exc_info=True)
|
||||
else:
|
||||
agent = A2C("MlpPolicy", env, verbose=0, n_steps=config_values.num_steps)
|
||||
|
||||
if config_values.session_type == "TRAINING":
|
||||
# We're in a training session
|
||||
print("Starting training session...")
|
||||
logging.info("Starting training session...")
|
||||
for episode in range(0, config_values.num_episodes):
|
||||
agent.learn(total_timesteps=1)
|
||||
save_agent(agent)
|
||||
_LOGGER.debug("Starting training session...")
|
||||
for episode in range(config_values.num_episodes):
|
||||
agent.learn(total_timesteps=config_values.num_steps)
|
||||
_save_agent(agent, session_path, timestamp_str)
|
||||
else:
|
||||
# Default to being in an evaluation session
|
||||
print("Starting evaluation session...")
|
||||
logging.info("Starting evaluation session...")
|
||||
_LOGGER.debug("Starting evaluation session...")
|
||||
evaluate_policy(agent, env, n_eval_episodes=config_values.num_episodes)
|
||||
|
||||
env.close()
|
||||
|
||||
|
||||
def save_agent(_agent):
|
||||
"""Persist an agent (only works for stable baselines3 agents at present)."""
|
||||
now = datetime.now() # current date and time
|
||||
time = now.strftime("%Y%m%d_%H%M%S")
|
||||
def _write_session_metadata_file(
|
||||
session_dir: Path, uuid: str, session_timestamp: datetime, env: Primaite
|
||||
):
|
||||
"""
|
||||
Write the ``session_metadata.json`` file.
|
||||
|
||||
try:
|
||||
path = "outputs/agents/"
|
||||
is_dir = os.path.isdir(path)
|
||||
if not is_dir:
|
||||
os.makedirs(path)
|
||||
filename = "outputs/agents/agent_saved_" + time
|
||||
_agent.save(filename)
|
||||
logging.info("Trained agent saved as " + filename)
|
||||
except Exception:
|
||||
logging.error("Could not save agent")
|
||||
logging.error("Exception occured", exc_info=True)
|
||||
Creates a ``session_metadata.json`` in the ``session_dir`` directory
|
||||
and adds the following key/value pairs:
|
||||
|
||||
- uuid: The UUID assigned to the session upon instantiation.
|
||||
- start_datetime: The date & time the session started in iso format.
|
||||
- end_datetime: NULL.
|
||||
- total_episodes: NULL.
|
||||
- total_time_steps: NULL.
|
||||
- env:
|
||||
- training_config:
|
||||
- All training config items
|
||||
- lay_down_config:
|
||||
- All lay down config items
|
||||
|
||||
"""
|
||||
metadata_dict = {
|
||||
"uuid": uuid,
|
||||
"start_datetime": session_timestamp.isoformat(),
|
||||
"end_datetime": None,
|
||||
"total_episodes": None,
|
||||
"total_time_steps": None,
|
||||
"env": {
|
||||
"training_config": env.training_config.to_dict(json_serializable=True),
|
||||
"lay_down_config": env.lay_down_config,
|
||||
},
|
||||
}
|
||||
filepath = session_dir / "session_metadata.json"
|
||||
_LOGGER.debug(f"Writing Session Metadata file: {filepath}")
|
||||
with open(filepath, "w") as file:
|
||||
json.dump(metadata_dict, file)
|
||||
|
||||
|
||||
def configure_logging():
|
||||
"""Configures logging."""
|
||||
try:
|
||||
now = datetime.now() # current date and time
|
||||
time = now.strftime("%Y%m%d_%H%M%S")
|
||||
filename = "logs/app_" + time + ".log"
|
||||
path = "logs/"
|
||||
is_dir = os.path.isdir(path)
|
||||
if not is_dir:
|
||||
os.makedirs(path)
|
||||
logging.basicConfig(
|
||||
filename=filename,
|
||||
filemode="w",
|
||||
format="%(asctime)s - %(levelname)s - %(message)s",
|
||||
datefmt="%d-%b-%y %H:%M:%S",
|
||||
level=logging.INFO,
|
||||
)
|
||||
except Exception:
|
||||
print("ERROR: Could not start logging")
|
||||
def _update_session_metadata_file(session_dir: Path, env: Primaite):
|
||||
"""
|
||||
Update the ``session_metadata.json`` file.
|
||||
|
||||
Updates the `session_metadata.json`` in the ``session_dir`` directory
|
||||
with the following key/value pairs:
|
||||
|
||||
- end_datetime: NULL.
|
||||
- total_episodes: NULL.
|
||||
- total_time_steps: NULL.
|
||||
"""
|
||||
with open(session_dir / "session_metadata.json", "r") as file:
|
||||
metadata_dict = json.load(file)
|
||||
|
||||
metadata_dict["end_datetime"] = datetime.now().isoformat()
|
||||
metadata_dict["total_episodes"] = env.episode_count
|
||||
metadata_dict["total_time_steps"] = env.total_step_count
|
||||
|
||||
filepath = session_dir / "session_metadata.json"
|
||||
_LOGGER.debug(f"Updating Session Metadata file: {filepath}")
|
||||
with open(filepath, "w") as file:
|
||||
json.dump(metadata_dict, file)
|
||||
|
||||
|
||||
def load_config_values():
|
||||
"""Loads the config values from the main config file into a config object."""
|
||||
try:
|
||||
# Generic
|
||||
config_values.agent_identifier = config_data["agentIdentifier"]
|
||||
if "observationSpace" in config_data:
|
||||
config_values.observation_config = config_data["observationSpace"]
|
||||
else:
|
||||
config_values.observation_config = None
|
||||
config_values.num_episodes = int(config_data["numEpisodes"])
|
||||
config_values.time_delay = int(config_data["timeDelay"])
|
||||
config_values.config_filename_use_case = (
|
||||
"config/" + config_data["configFilename"]
|
||||
)
|
||||
config_values.session_type = config_data["sessionType"]
|
||||
config_values.load_agent = bool(config_data["loadAgent"])
|
||||
config_values.agent_load_file = config_data["agentLoadFile"]
|
||||
# Environment
|
||||
config_values.observation_space_high_value = int(
|
||||
config_data["observationSpaceHighValue"]
|
||||
)
|
||||
# Reward values
|
||||
# Generic
|
||||
config_values.all_ok = int(config_data["allOk"])
|
||||
# Node Hardware State
|
||||
config_values.off_should_be_on = int(config_data["offShouldBeOn"])
|
||||
config_values.off_should_be_resetting = int(config_data["offShouldBeResetting"])
|
||||
config_values.on_should_be_off = int(config_data["onShouldBeOff"])
|
||||
config_values.on_should_be_resetting = int(config_data["onShouldBeResetting"])
|
||||
config_values.resetting_should_be_on = int(config_data["resettingShouldBeOn"])
|
||||
config_values.resetting_should_be_off = int(config_data["resettingShouldBeOff"])
|
||||
config_values.resetting = int(config_data["resetting"])
|
||||
# Node Software or Service State
|
||||
config_values.good_should_be_patching = int(config_data["goodShouldBePatching"])
|
||||
config_values.good_should_be_compromised = int(
|
||||
config_data["goodShouldBeCompromised"]
|
||||
)
|
||||
config_values.good_should_be_overwhelmed = int(
|
||||
config_data["goodShouldBeOverwhelmed"]
|
||||
)
|
||||
config_values.patching_should_be_good = int(config_data["patchingShouldBeGood"])
|
||||
config_values.patching_should_be_compromised = int(
|
||||
config_data["patchingShouldBeCompromised"]
|
||||
)
|
||||
config_values.patching_should_be_overwhelmed = int(
|
||||
config_data["patchingShouldBeOverwhelmed"]
|
||||
)
|
||||
config_values.patching = int(config_data["patching"])
|
||||
config_values.compromised_should_be_good = int(
|
||||
config_data["compromisedShouldBeGood"]
|
||||
)
|
||||
config_values.compromised_should_be_patching = int(
|
||||
config_data["compromisedShouldBePatching"]
|
||||
)
|
||||
config_values.compromised_should_be_overwhelmed = int(
|
||||
config_data["compromisedShouldBeOverwhelmed"]
|
||||
)
|
||||
config_values.compromised = int(config_data["compromised"])
|
||||
config_values.overwhelmed_should_be_good = int(
|
||||
config_data["overwhelmedShouldBeGood"]
|
||||
)
|
||||
config_values.overwhelmed_should_be_patching = int(
|
||||
config_data["overwhelmedShouldBePatching"]
|
||||
)
|
||||
config_values.overwhelmed_should_be_compromised = int(
|
||||
config_data["overwhelmedShouldBeCompromised"]
|
||||
)
|
||||
config_values.overwhelmed = int(config_data["overwhelmed"])
|
||||
# Node File System State
|
||||
config_values.good_should_be_repairing = int(
|
||||
config_data["goodShouldBeRepairing"]
|
||||
)
|
||||
config_values.good_should_be_restoring = int(
|
||||
config_data["goodShouldBeRestoring"]
|
||||
)
|
||||
config_values.good_should_be_corrupt = int(config_data["goodShouldBeCorrupt"])
|
||||
config_values.good_should_be_destroyed = int(
|
||||
config_data["goodShouldBeDestroyed"]
|
||||
)
|
||||
config_values.repairing_should_be_good = int(
|
||||
config_data["repairingShouldBeGood"]
|
||||
)
|
||||
config_values.repairing_should_be_restoring = int(
|
||||
config_data["repairingShouldBeRestoring"]
|
||||
)
|
||||
config_values.repairing_should_be_corrupt = int(
|
||||
config_data["repairingShouldBeCorrupt"]
|
||||
)
|
||||
config_values.repairing_should_be_destroyed = int(
|
||||
config_data["repairingShouldBeDestroyed"]
|
||||
)
|
||||
config_values.repairing = int(config_data["repairing"])
|
||||
config_values.restoring_should_be_good = int(
|
||||
config_data["restoringShouldBeGood"]
|
||||
)
|
||||
config_values.restoring_should_be_repairing = int(
|
||||
config_data["restoringShouldBeRepairing"]
|
||||
)
|
||||
config_values.restoring_should_be_corrupt = int(
|
||||
config_data["restoringShouldBeCorrupt"]
|
||||
)
|
||||
config_values.restoring_should_be_destroyed = int(
|
||||
config_data["restoringShouldBeDestroyed"]
|
||||
)
|
||||
config_values.restoring = int(config_data["restoring"])
|
||||
config_values.corrupt_should_be_good = int(config_data["corruptShouldBeGood"])
|
||||
config_values.corrupt_should_be_repairing = int(
|
||||
config_data["corruptShouldBeRepairing"]
|
||||
)
|
||||
config_values.corrupt_should_be_restoring = int(
|
||||
config_data["corruptShouldBeRestoring"]
|
||||
)
|
||||
config_values.corrupt_should_be_destroyed = int(
|
||||
config_data["corruptShouldBeDestroyed"]
|
||||
)
|
||||
config_values.corrupt = int(config_data["corrupt"])
|
||||
config_values.destroyed_should_be_good = int(
|
||||
config_data["destroyedShouldBeGood"]
|
||||
)
|
||||
config_values.destroyed_should_be_repairing = int(
|
||||
config_data["destroyedShouldBeRepairing"]
|
||||
)
|
||||
config_values.destroyed_should_be_restoring = int(
|
||||
config_data["destroyedShouldBeRestoring"]
|
||||
)
|
||||
config_values.destroyed_should_be_corrupt = int(
|
||||
config_data["destroyedShouldBeCorrupt"]
|
||||
)
|
||||
config_values.destroyed = int(config_data["destroyed"])
|
||||
config_values.scanning = int(config_data["scanning"])
|
||||
# IER status
|
||||
config_values.red_ier_running = int(config_data["redIerRunning"])
|
||||
config_values.green_ier_blocked = int(config_data["greenIerBlocked"])
|
||||
# Patching / Reset durations
|
||||
config_values.os_patching_duration = int(config_data["osPatchingDuration"])
|
||||
config_values.node_reset_duration = int(config_data["nodeResetDuration"])
|
||||
config_values.service_patching_duration = int(
|
||||
config_data["servicePatchingDuration"]
|
||||
)
|
||||
config_values.file_system_repairing_limit = int(
|
||||
config_data["fileSystemRepairingLimit"]
|
||||
)
|
||||
config_values.file_system_restoring_limit = int(
|
||||
config_data["fileSystemRestoringLimit"]
|
||||
)
|
||||
config_values.file_system_scanning_limit = int(
|
||||
config_data["fileSystemScanningLimit"]
|
||||
)
|
||||
def _save_agent(agent: OnPolicyAlgorithm, session_path: Path, timestamp_str: str):
|
||||
"""
|
||||
Persist an agent.
|
||||
|
||||
logging.info("Training agent: " + config_values.agent_identifier)
|
||||
logging.info(
|
||||
"Training environment config: " + config_values.config_filename_use_case
|
||||
)
|
||||
logging.info(
|
||||
"Training cycle has " + str(config_values.num_episodes) + " episodes"
|
||||
)
|
||||
Only works for stable baselines3 agents at present.
|
||||
|
||||
except Exception:
|
||||
logging.error("Could not save load config data")
|
||||
logging.error("Exception occured", exc_info=True)
|
||||
:param session_path: The directory path the session is writing to.
|
||||
:param timestamp_str: The session timestamp in the format:
|
||||
<yyyy-mm-dd>_<hh-mm-ss>.
|
||||
"""
|
||||
if not isinstance(agent, OnPolicyAlgorithm):
|
||||
msg = f"Can only save {OnPolicyAlgorithm} agents, got {type(agent)}."
|
||||
_LOGGER.error(msg)
|
||||
else:
|
||||
filepath = session_path / f"agent_saved_{timestamp_str}"
|
||||
agent.save(filepath)
|
||||
_LOGGER.debug(f"Trained agent saved as: {filepath}")
|
||||
|
||||
|
||||
# MAIN PROCESS #
|
||||
def _get_session_path(session_timestamp: datetime) -> Path:
|
||||
"""
|
||||
Get the directory path the session will output to.
|
||||
|
||||
# Starting point
|
||||
This is set in the format of:
|
||||
~/primaite/sessions/<yyyy-mm-dd>/<yyyy-mm-dd>_<hh-mm-ss>.
|
||||
|
||||
# Welcome message
|
||||
print("Welcome to the Primary-level AI Training Environment (PrimAITE)")
|
||||
:param session_timestamp: This is the datetime that the session started.
|
||||
:return: The session directory path.
|
||||
"""
|
||||
date_dir = session_timestamp.strftime("%Y-%m-%d")
|
||||
session_dir = session_timestamp.strftime("%Y-%m-%d_%H-%M-%S")
|
||||
session_path = SESSIONS_DIR / date_dir / session_dir
|
||||
session_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
# Configure logging
|
||||
configure_logging()
|
||||
return session_path
|
||||
|
||||
# Open the main config file
|
||||
try:
|
||||
config_file_main = open("config/config_main.yaml", "r")
|
||||
config_data = yaml.safe_load(config_file_main)
|
||||
# Create a config class
|
||||
config_values = ConfigValuesMain()
|
||||
# Load in config data
|
||||
load_config_values()
|
||||
except Exception:
|
||||
logging.error("Could not load main config")
|
||||
logging.error("Exception occured", exc_info=True)
|
||||
|
||||
# Create a list of transactions
|
||||
# A transaction is an object holding the:
|
||||
# - episode #
|
||||
# - step #
|
||||
# - initial observation space
|
||||
# - action
|
||||
# - reward
|
||||
# - new observation space
|
||||
transaction_list = []
|
||||
def run(training_config_path: Union[str, Path], lay_down_config_path: Union[str, Path]):
|
||||
"""Run the PrimAITE Session.
|
||||
|
||||
# Create the Primaite environment
|
||||
# try:
|
||||
env = Primaite(config_values, transaction_list)
|
||||
# logging.info("PrimAITE environment created")
|
||||
# except Exception:
|
||||
# logging.error("Could not create PrimAITE environment")
|
||||
# logging.error("Exception occured", exc_info=True)
|
||||
:param training_config_path: The training config filepath.
|
||||
:param lay_down_config_path: The lay down config filepath.
|
||||
"""
|
||||
# Welcome message
|
||||
print("Welcome to the Primary-level AI Training Environment (PrimAITE)")
|
||||
uuid = str(uuid4())
|
||||
session_timestamp: Final[datetime] = datetime.now()
|
||||
session_dir = _get_session_path(session_timestamp)
|
||||
timestamp_str = session_timestamp.strftime("%Y-%m-%d_%H-%M-%S")
|
||||
|
||||
# Get the number of steps (which is stored in the child config file)
|
||||
config_values.num_steps = env.episode_steps
|
||||
print(f"The output directory for this session is: {session_dir}")
|
||||
|
||||
# Run environment against an agent
|
||||
if config_values.agent_identifier == "GENERIC":
|
||||
run_generic()
|
||||
elif config_values.agent_identifier == "STABLE_BASELINES3_PPO":
|
||||
run_stable_baselines3_ppo()
|
||||
elif config_values.agent_identifier == "STABLE_BASELINES3_A2C":
|
||||
run_stable_baselines3_a2c()
|
||||
# Create a list of transactions
|
||||
# A transaction is an object holding the:
|
||||
# - episode #
|
||||
# - step #
|
||||
# - initial observation space
|
||||
# - action
|
||||
# - reward
|
||||
# - new observation space
|
||||
transaction_list = []
|
||||
|
||||
print("Session finished")
|
||||
logging.info("Session finished")
|
||||
# Create the Primaite environment
|
||||
env = Primaite(
|
||||
training_config_path=training_config_path,
|
||||
lay_down_config_path=lay_down_config_path,
|
||||
transaction_list=transaction_list,
|
||||
session_path=session_dir,
|
||||
timestamp_str=timestamp_str,
|
||||
)
|
||||
|
||||
print("Saving transaction logs...")
|
||||
logging.info("Saving transaction logs...")
|
||||
print("Writing Session Metadata file...")
|
||||
|
||||
write_transaction_to_file(transaction_list)
|
||||
_write_session_metadata_file(
|
||||
session_dir=session_dir, uuid=uuid, session_timestamp=session_timestamp, env=env
|
||||
)
|
||||
|
||||
config_values = env.training_config
|
||||
|
||||
# Get the number of steps (which is stored in the child config file)
|
||||
config_values.num_steps = env.episode_steps
|
||||
|
||||
# Run environment against an agent
|
||||
if config_values.agent_identifier == "GENERIC":
|
||||
run_generic(env=env, config_values=config_values)
|
||||
elif config_values.agent_identifier == "STABLE_BASELINES3_PPO":
|
||||
run_stable_baselines3_ppo(
|
||||
env=env,
|
||||
config_values=config_values,
|
||||
session_path=session_dir,
|
||||
timestamp_str=timestamp_str,
|
||||
)
|
||||
elif config_values.agent_identifier == "STABLE_BASELINES3_A2C":
|
||||
run_stable_baselines3_a2c(
|
||||
env=env,
|
||||
config_values=config_values,
|
||||
session_path=session_dir,
|
||||
timestamp_str=timestamp_str,
|
||||
)
|
||||
|
||||
print("Session finished")
|
||||
_LOGGER.debug("Session finished")
|
||||
|
||||
print("Saving transaction logs...")
|
||||
write_transaction_to_file(
|
||||
transaction_list=transaction_list,
|
||||
session_path=session_dir,
|
||||
timestamp_str=timestamp_str,
|
||||
)
|
||||
|
||||
print("Updating Session Metadata file...")
|
||||
_update_session_metadata_file(session_dir=session_dir, env=env)
|
||||
|
||||
print("Finished")
|
||||
_LOGGER.debug("Finished")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--tc")
|
||||
parser.add_argument("--ldc")
|
||||
args = parser.parse_args()
|
||||
if not args.tc:
|
||||
_LOGGER.error(
|
||||
"Please provide a training config file using the --tc " "argument"
|
||||
)
|
||||
if not args.ldc:
|
||||
_LOGGER.error(
|
||||
"Please provide a lay down config file using the --ldc " "argument"
|
||||
)
|
||||
run(training_config_path=args.tc, lay_down_config_path=args.ldc)
|
||||
|
||||
config_file_main.close()
|
||||
|
||||
print("Finished")
|
||||
logging.info("Finished")
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import logging
|
||||
from typing import Final
|
||||
|
||||
from primaite.common.config_values_main import ConfigValuesMain
|
||||
from primaite.common.enums import (
|
||||
FileSystemState,
|
||||
HardwareState,
|
||||
@@ -11,6 +10,7 @@ from primaite.common.enums import (
|
||||
Priority,
|
||||
SoftwareState,
|
||||
)
|
||||
from primaite.config.training_config import TrainingConfig
|
||||
from primaite.nodes.node import Node
|
||||
|
||||
_LOGGER: Final[logging.Logger] = logging.getLogger(__name__)
|
||||
@@ -29,7 +29,7 @@ class ActiveNode(Node):
|
||||
ip_address: str,
|
||||
software_state: SoftwareState,
|
||||
file_system_state: FileSystemState,
|
||||
config_values: ConfigValuesMain,
|
||||
config_values: TrainingConfig,
|
||||
):
|
||||
"""
|
||||
Init.
|
||||
@@ -210,3 +210,17 @@ class ActiveNode(Node):
|
||||
self.file_system_state_observed = self.file_system_state_actual
|
||||
self.file_system_scanning = False
|
||||
self.file_system_scanning_count = 0
|
||||
|
||||
def update_resetting_status(self):
|
||||
"""Updates the reset count & makes software and file state to GOOD."""
|
||||
super().update_resetting_status()
|
||||
if self.resetting_count <= 0:
|
||||
self.file_system_state_actual = FileSystemState.GOOD
|
||||
self.software_state = SoftwareState.GOOD
|
||||
|
||||
def update_booting_status(self):
|
||||
"""Updates the booting software and file state to GOOD."""
|
||||
super().update_booting_status()
|
||||
if self.booting_count <= 0:
|
||||
self.file_system_state_actual = FileSystemState.GOOD
|
||||
self.software_state = SoftwareState.GOOD
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"""The base Node class."""
|
||||
from typing import Final
|
||||
|
||||
from primaite.common.config_values_main import ConfigValuesMain
|
||||
from primaite.common.enums import HardwareState, NodeType, Priority
|
||||
from primaite.config.training_config import TrainingConfig
|
||||
|
||||
|
||||
class Node:
|
||||
@@ -16,7 +16,7 @@ class Node:
|
||||
node_type: NodeType,
|
||||
priority: Priority,
|
||||
hardware_state: HardwareState,
|
||||
config_values: ConfigValuesMain,
|
||||
config_values: TrainingConfig,
|
||||
):
|
||||
"""
|
||||
Init.
|
||||
@@ -34,7 +34,9 @@ class Node:
|
||||
self.priority = priority
|
||||
self.hardware_state: HardwareState = hardware_state
|
||||
self.resetting_count: int = 0
|
||||
self.config_values: ConfigValuesMain = config_values
|
||||
self.config_values: TrainingConfig = config_values
|
||||
self.booting_count: int = 0
|
||||
self.shutting_down_count: int = 0
|
||||
|
||||
def __repr__(self):
|
||||
"""Returns the name of the node."""
|
||||
@@ -42,11 +44,12 @@ class Node:
|
||||
|
||||
def turn_on(self):
|
||||
"""Sets the node state to ON."""
|
||||
self.hardware_state = HardwareState.ON
|
||||
|
||||
self.hardware_state = HardwareState.BOOTING
|
||||
self.booting_count = self.config_values.node_booting_duration
|
||||
def turn_off(self):
|
||||
"""Sets the node state to OFF."""
|
||||
self.hardware_state = HardwareState.OFF
|
||||
self.shutting_down_count = self.config_values.node_shutdown_duration
|
||||
|
||||
def reset(self):
|
||||
"""Sets the node state to Resetting and starts the reset count."""
|
||||
@@ -59,3 +62,17 @@ class Node:
|
||||
if self.resetting_count <= 0:
|
||||
self.resetting_count = 0
|
||||
self.hardware_state = HardwareState.ON
|
||||
|
||||
def update_booting_status(self):
|
||||
"""Updates the booting count"""
|
||||
self.booting_count -= 1
|
||||
if self.booting_count <= 0:
|
||||
self.booting_count = 0
|
||||
self.hardware_state = HardwareState.ON
|
||||
|
||||
def update_shutdown_status(self):
|
||||
"""Updates the shutdown count"""
|
||||
self.shutting_down_count -= 1
|
||||
if self.shutting_down_count <= 0:
|
||||
self.shutting_down_count = 0
|
||||
self.hardware_state = HardwareState.OFF
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
"""The Passive Node class (i.e. an actuator)."""
|
||||
from primaite.common.config_values_main import ConfigValuesMain
|
||||
from primaite.common.enums import HardwareState, NodeType, Priority
|
||||
from primaite.config.training_config import TrainingConfig
|
||||
from primaite.nodes.node import Node
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class PassiveNode(Node):
|
||||
node_type: NodeType,
|
||||
priority: Priority,
|
||||
hardware_state: HardwareState,
|
||||
config_values: ConfigValuesMain,
|
||||
config_values: TrainingConfig,
|
||||
):
|
||||
"""
|
||||
Init.
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import logging
|
||||
from typing import Dict, Final
|
||||
|
||||
from primaite.common.config_values_main import ConfigValuesMain
|
||||
from primaite.common.enums import (
|
||||
FileSystemState,
|
||||
HardwareState,
|
||||
@@ -12,6 +11,7 @@ from primaite.common.enums import (
|
||||
SoftwareState,
|
||||
)
|
||||
from primaite.common.service import Service
|
||||
from primaite.config.training_config import TrainingConfig
|
||||
from primaite.nodes.active_node import ActiveNode
|
||||
|
||||
_LOGGER: Final[logging.Logger] = logging.getLogger(__name__)
|
||||
@@ -30,7 +30,7 @@ class ServiceNode(ActiveNode):
|
||||
ip_address: str,
|
||||
software_state: SoftwareState,
|
||||
file_system_state: FileSystemState,
|
||||
config_values: ConfigValuesMain,
|
||||
config_values: TrainingConfig,
|
||||
):
|
||||
"""
|
||||
Init.
|
||||
@@ -188,3 +188,15 @@ class ServiceNode(ActiveNode):
|
||||
for service_key, service_value in self.services.items():
|
||||
if service_value.software_state == SoftwareState.PATCHING:
|
||||
service_value.reduce_patching_count()
|
||||
|
||||
def update_resetting_status(self):
|
||||
super().update_resetting_status()
|
||||
if self.resetting_count <= 0:
|
||||
for service in self.services.values():
|
||||
service.software_state = SoftwareState.GOOD
|
||||
|
||||
def update_booting_status(self):
|
||||
super().update_booting_status()
|
||||
if self.booting_count <= 0:
|
||||
for service in self.services.values():
|
||||
service.software_state =SoftwareState.GOOD
|
||||
|
||||
32
src/primaite/notebooks/__init__.py
Normal file
32
src/primaite/notebooks/__init__.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
import importlib.util
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from primaite import NOTEBOOKS_DIR, getLogger
|
||||
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
|
||||
def start_jupyter_session():
|
||||
"""
|
||||
Starts a new Jupyter notebook session in the app notebooks directory.
|
||||
|
||||
Currently only works on Windows OS.
|
||||
|
||||
.. todo:: Figure out how to get this working for Linux and MacOS too.
|
||||
"""
|
||||
|
||||
if importlib.util.find_spec("jupyter") is not None:
|
||||
jupyter_cmd = "python3 -m jupyter lab"
|
||||
if sys.platform == "win32":
|
||||
jupyter_cmd = "jupyter lab"
|
||||
|
||||
working_dir = os.getcwd()
|
||||
os.chdir(NOTEBOOKS_DIR)
|
||||
subprocess.Popen(jupyter_cmd)
|
||||
os.chdir(working_dir)
|
||||
else:
|
||||
# Jupyter is not installed
|
||||
_LOGGER.error("Cannot start jupyter lab as it is not installed")
|
||||
1
src/primaite/setup/__init__.py
Normal file
1
src/primaite/setup/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
5
src/primaite/setup/_package_data/primaite_config.yaml
Normal file
5
src/primaite/setup/_package_data/primaite_config.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
# The main PrimAITE application config file
|
||||
|
||||
# Logging
|
||||
log_level: INFO
|
||||
logger_format: '%(asctime)s::%(levelname)s::%(name)s::%(lineno)s::%(message)s'
|
||||
13
src/primaite/setup/old_installation_clean_up.py
Normal file
13
src/primaite/setup/old_installation_clean_up.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
from primaite import getLogger
|
||||
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
|
||||
def run():
|
||||
"""Perform the full clean-up."""
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
39
src/primaite/setup/reset_demo_notebooks.py
Normal file
39
src/primaite/setup/reset_demo_notebooks.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
import filecmp
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
import pkg_resources
|
||||
|
||||
from primaite import NOTEBOOKS_DIR, getLogger
|
||||
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
|
||||
def run(overwrite_existing: bool = True):
|
||||
"""
|
||||
Resets the demo jupyter notebooks in the users app notebooks directory.
|
||||
|
||||
:param overwrite_existing: A bool to toggle replacing existing edited
|
||||
notebooks on or off.
|
||||
"""
|
||||
notebooks_package_data_root = pkg_resources.resource_filename(
|
||||
"primaite", "notebooks/_package_data"
|
||||
)
|
||||
for subdir, dirs, files in os.walk(notebooks_package_data_root):
|
||||
for file in files:
|
||||
fp = os.path.join(subdir, file)
|
||||
path_split = os.path.relpath(fp, notebooks_package_data_root).split(os.sep)
|
||||
target_fp = NOTEBOOKS_DIR / Path(*path_split)
|
||||
target_fp.parent.mkdir(exist_ok=True, parents=True)
|
||||
copy_file = not target_fp.is_file()
|
||||
|
||||
if overwrite_existing and not copy_file:
|
||||
copy_file = (not filecmp.cmp(fp, target_fp)) and (
|
||||
".ipynb_checkpoints" not in str(target_fp)
|
||||
)
|
||||
|
||||
if copy_file:
|
||||
shutil.copy2(fp, target_fp)
|
||||
_LOGGER.info(f"Reset example notebook: {target_fp}")
|
||||
37
src/primaite/setup/reset_example_configs.py
Normal file
37
src/primaite/setup/reset_example_configs.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import filecmp
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
import pkg_resources
|
||||
|
||||
from primaite import USERS_CONFIG_DIR, getLogger
|
||||
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
|
||||
def run(overwrite_existing=True):
|
||||
"""
|
||||
Resets the example config files in the users app config directory.
|
||||
|
||||
:param overwrite_existing: A bool to toggle replacing existing edited
|
||||
config on or off.
|
||||
"""
|
||||
configs_package_data_root = pkg_resources.resource_filename(
|
||||
"primaite", "config/_package_data"
|
||||
)
|
||||
|
||||
for subdir, dirs, files in os.walk(configs_package_data_root):
|
||||
for file in files:
|
||||
fp = os.path.join(subdir, file)
|
||||
path_split = os.path.relpath(fp, configs_package_data_root).split(os.sep)
|
||||
target_fp = USERS_CONFIG_DIR / "example_config" / Path(*path_split)
|
||||
target_fp.parent.mkdir(exist_ok=True, parents=True)
|
||||
copy_file = not target_fp.is_file()
|
||||
|
||||
if overwrite_existing and not copy_file:
|
||||
copy_file = not filecmp.cmp(fp, target_fp)
|
||||
|
||||
if copy_file:
|
||||
shutil.copy2(fp, target_fp)
|
||||
_LOGGER.info(f"Reset example config: {target_fp}")
|
||||
27
src/primaite/setup/setup_app_dirs.py
Normal file
27
src/primaite/setup/setup_app_dirs.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
from primaite import _USER_DIRS, LOG_DIR, NOTEBOOKS_DIR, getLogger
|
||||
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
|
||||
def run():
|
||||
"""
|
||||
Handles creation of application directories and user directories.
|
||||
|
||||
Uses `platformdirs.PlatformDirs` and `pathlib.Path` to create the required
|
||||
app directories in the correct locations based on the users OS.
|
||||
"""
|
||||
app_dirs = [
|
||||
_USER_DIRS,
|
||||
NOTEBOOKS_DIR,
|
||||
LOG_DIR,
|
||||
]
|
||||
|
||||
for app_dir in app_dirs:
|
||||
if not app_dir.is_dir():
|
||||
app_dir.mkdir(parents=True, exist_ok=True)
|
||||
_LOGGER.info(f"Created directory: {app_dir}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
@@ -2,9 +2,11 @@
|
||||
"""Writes the Transaction log list out to file for evaluation to utilse."""
|
||||
|
||||
import csv
|
||||
import logging
|
||||
import os.path
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from primaite import getLogger
|
||||
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
|
||||
def turn_action_space_to_array(_action_space):
|
||||
@@ -14,11 +16,10 @@ def turn_action_space_to_array(_action_space):
|
||||
Args:
|
||||
_action_space: The action space.
|
||||
"""
|
||||
return_array = []
|
||||
for x in range(len(_action_space)):
|
||||
return_array.append(str(_action_space[x]))
|
||||
|
||||
return return_array
|
||||
if isinstance(_action_space, list):
|
||||
return [str(i) for i in _action_space]
|
||||
else:
|
||||
return [str(_action_space)]
|
||||
|
||||
|
||||
def turn_obs_space_to_array(_obs_space, _obs_assets, _obs_features):
|
||||
@@ -38,18 +39,22 @@ def turn_obs_space_to_array(_obs_space, _obs_assets, _obs_features):
|
||||
return return_array
|
||||
|
||||
|
||||
def write_transaction_to_file(_transaction_list):
|
||||
def write_transaction_to_file(transaction_list, session_path: Path, timestamp_str: str):
|
||||
"""
|
||||
Writes transaction logs to file to support training evaluation.
|
||||
|
||||
Args:
|
||||
_transaction_list: The list of transactions from all steps and all episodes
|
||||
_num_episodes: The number of episodes that were conducted.
|
||||
:param transaction_list: The list of transactions from all steps and all
|
||||
episodes.
|
||||
:param session_path: The directory path the session is writing to.
|
||||
:param timestamp_str: The session timestamp in the format:
|
||||
<yyyy-mm-dd>_<hh-mm-ss>.
|
||||
"""
|
||||
# Get the first transaction and use it to determine the makeup of the observation space and action space
|
||||
# Label the obs space fields in csv as "OSI_1_1", "OSN_1_1" and action space as "AS_1"
|
||||
# Get the first transaction and use it to determine the makeup of the
|
||||
# observation space and action space
|
||||
# Label the obs space fields in csv as "OSI_1_1", "OSN_1_1" and action
|
||||
# space as "AS_1"
|
||||
# This will be tied into the PrimAITE Use Case so that they make sense
|
||||
template_transation = _transaction_list[0]
|
||||
template_transation = transaction_list[0]
|
||||
action_length = template_transation.action_space.size
|
||||
obs_shape = template_transation.obs_space_post.shape
|
||||
obs_assets = template_transation.obs_space_post.shape[0]
|
||||
@@ -75,21 +80,15 @@ def write_transaction_to_file(_transaction_list):
|
||||
# Open up a csv file
|
||||
header = ["Timestamp", "Episode", "Step", "Reward"]
|
||||
header = header + action_header + obs_header_initial + obs_header_new
|
||||
now = datetime.now() # current date and time
|
||||
time = now.strftime("%Y%m%d_%H%M%S")
|
||||
|
||||
try:
|
||||
path = "outputs/results/"
|
||||
is_dir = os.path.isdir(path)
|
||||
if not is_dir:
|
||||
os.makedirs(path)
|
||||
|
||||
filename = "outputs/results/all_transactions_" + time + ".csv"
|
||||
filename = session_path / f"all_transactions_{timestamp_str}.csv"
|
||||
_LOGGER.debug(f"Saving transaction logs: {filename}")
|
||||
csv_file = open(filename, "w", encoding="UTF8", newline="")
|
||||
csv_writer = csv.writer(csv_file)
|
||||
csv_writer.writerow(header)
|
||||
|
||||
for transaction in _transaction_list:
|
||||
for transaction in transaction_list:
|
||||
csv_data = [
|
||||
str(transaction.timestamp),
|
||||
str(transaction.episode_number),
|
||||
@@ -110,5 +109,4 @@ def write_transaction_to_file(_transaction_list):
|
||||
|
||||
csv_file.close()
|
||||
except Exception:
|
||||
logging.error("Could not save the transaction file")
|
||||
logging.error("Exception occured", exc_info=True)
|
||||
_LOGGER.error("Could not save the transaction file", exc_info=True)
|
||||
|
||||
32
src/primaite/utils/package_data.py
Normal file
32
src/primaite/utils/package_data.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import pkg_resources
|
||||
|
||||
from primaite import getLogger
|
||||
|
||||
_LOGGER = getLogger(__name__)
|
||||
|
||||
|
||||
def get_file_path(path: str) -> Path:
|
||||
"""
|
||||
Get PrimAITE package data.
|
||||
|
||||
:Example:
|
||||
|
||||
>>> from primaite.utils.package_data import get_file_path
|
||||
>>> main_env_config = get_file_path("config/_package_data/training_config_main.yaml")
|
||||
|
||||
|
||||
:param path: The path from the primaite root.
|
||||
:return: The file path of the package data file.
|
||||
:raise FileNotFoundError: When the filepath does not exist.
|
||||
"""
|
||||
fp = pkg_resources.resource_filename("primaite", path)
|
||||
if os.path.isfile(fp):
|
||||
return Path(fp)
|
||||
else:
|
||||
msg = f"Cannot PrimAITE package data: {fp}"
|
||||
_LOGGER.error(msg)
|
||||
raise FileNotFoundError(msg)
|
||||
@@ -83,6 +83,8 @@ greenIerBlocked: -10
|
||||
# Patching / Reset durations
|
||||
osPatchingDuration: 5 # The time taken to patch the OS
|
||||
nodeResetDuration: 5 # The time taken to reset a node (hardware)
|
||||
nodeBootingDuration: 3 # The Time taken to turn on the node
|
||||
nodeShutdownDuration: 2 # The time taken to turn off the node
|
||||
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
|
||||
94
tests/config/legacy/new_training_config.yaml
Normal file
94
tests/config/legacy/new_training_config.yaml
Normal file
@@ -0,0 +1,94 @@
|
||||
# Main Config File
|
||||
|
||||
# Generic config values
|
||||
# Choose one of these (dependent on Agent being trained)
|
||||
# "STABLE_BASELINES3_PPO"
|
||||
# "STABLE_BASELINES3_A2C"
|
||||
# "GENERIC"
|
||||
agent_identifier: STABLE_BASELINES3_A2C
|
||||
# Sets How the Action Space is defined:
|
||||
# "NODE"
|
||||
# "ACL"
|
||||
# "ANY" node and acl actions
|
||||
action_type: ANY
|
||||
# Number of episodes to run per session
|
||||
num_episodes: 10
|
||||
# Number of time_steps per episode
|
||||
num_steps: 256
|
||||
# Time delay between steps (for generic agents)
|
||||
time_delay: 10
|
||||
# Type of session to be run (TRAINING or EVALUATION)
|
||||
session_type: TRAINING
|
||||
# Determine whether to load an agent from file
|
||||
load_agent: False
|
||||
# File path and file name of agent if you're loading one in
|
||||
agent_load_file: C:\[Path]\[agent_saved_filename.zip]
|
||||
|
||||
# Environment config values
|
||||
# The high value for the observation space
|
||||
observation_space_high_value: 1000000000
|
||||
|
||||
# Reward values
|
||||
# Generic
|
||||
all_ok: 0
|
||||
# Node Hardware State
|
||||
off_should_be_on: -10
|
||||
off_should_be_resetting: -5
|
||||
on_should_be_off: -2
|
||||
on_should_be_resetting: -5
|
||||
resetting_should_be_on: -5
|
||||
resetting_should_be_off: -2
|
||||
resetting: -3
|
||||
# Node Software or Service State
|
||||
good_should_be_patching: 2
|
||||
good_should_be_compromised: 5
|
||||
good_should_be_overwhelmed: 5
|
||||
patching_should_be_good: -5
|
||||
patching_should_be_compromised: 2
|
||||
patching_should_be_overwhelmed: 2
|
||||
patching: -3
|
||||
compromised_should_be_good: -20
|
||||
compromised_should_be_patching: -20
|
||||
compromised_should_be_overwhelmed: -20
|
||||
compromised: -20
|
||||
overwhelmed_should_be_good: -20
|
||||
overwhelmed_should_be_patching: -20
|
||||
overwhelmed_should_be_compromised: -20
|
||||
overwhelmed: -20
|
||||
# Node File System State
|
||||
good_should_be_repairing: 2
|
||||
good_should_be_restoring: 2
|
||||
good_should_be_corrupt: 5
|
||||
good_should_be_destroyed: 10
|
||||
repairing_should_be_good: -5
|
||||
repairing_should_be_restoring: 2
|
||||
repairing_should_be_corrupt: 2
|
||||
repairing_should_be_destroyed: 0
|
||||
repairing: -3
|
||||
restoring_should_be_good: -10
|
||||
restoring_should_be_repairing: -2
|
||||
restoring_should_be_corrupt: 1
|
||||
restoring_should_be_destroyed: 2
|
||||
restoring: -6
|
||||
corrupt_should_be_good: -10
|
||||
corrupt_should_be_repairing: -10
|
||||
corrupt_should_be_restoring: -10
|
||||
corrupt_should_be_destroyed: 2
|
||||
corrupt: -10
|
||||
destroyed_should_be_good: -20
|
||||
destroyed_should_be_repairing: -20
|
||||
destroyed_should_be_restoring: -20
|
||||
destroyed_should_be_corrupt: -20
|
||||
destroyed: -20
|
||||
scanning: -2
|
||||
# IER status
|
||||
red_ier_running: -5
|
||||
green_ier_blocked: -10
|
||||
|
||||
# Patching / Reset durations
|
||||
os_patching_duration: 5 # The time taken to patch the OS
|
||||
node_reset_duration: 5 # The time taken to reset a node (hardware)
|
||||
service_patching_duration: 5 # The time taken to patch a service
|
||||
file_system_repairing_limit: 5 # The time take to repair the file system
|
||||
file_system_restoring_limit: 5 # The time take to restore the file system
|
||||
file_system_scanning_limit: 5 # The time taken to scan the file system
|
||||
@@ -1,19 +1,15 @@
|
||||
- itemType: ACTIONS
|
||||
type: NODE
|
||||
- itemType: STEPS
|
||||
steps: 5
|
||||
- itemType: PORTS
|
||||
portsList:
|
||||
- item_type: PORTS
|
||||
ports_list:
|
||||
- port: '80'
|
||||
- port: '53'
|
||||
- itemType: SERVICES
|
||||
serviceList:
|
||||
- item_type: SERVICES
|
||||
service_list:
|
||||
- name: TCP
|
||||
- name: UDP
|
||||
|
||||
########################################
|
||||
# Nodes
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '1'
|
||||
name: PC1
|
||||
node_class: SERVICE
|
||||
@@ -30,7 +26,7 @@
|
||||
- name: UDP
|
||||
port: '53'
|
||||
state: GOOD
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '2'
|
||||
name: SERVER
|
||||
node_class: SERVICE
|
||||
@@ -47,7 +43,7 @@
|
||||
- name: UDP
|
||||
port: '53'
|
||||
state: OVERWHELMED
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '3'
|
||||
name: SWITCH1
|
||||
node_class: ACTIVE
|
||||
@@ -60,13 +56,13 @@
|
||||
|
||||
########################################
|
||||
# Links
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '4'
|
||||
name: link1
|
||||
bandwidth: 1000
|
||||
source: '1'
|
||||
destination: '3'
|
||||
- itemType: LINK
|
||||
- item_type: LINK
|
||||
id: '5'
|
||||
name: link2
|
||||
bandwidth: 1000
|
||||
@@ -75,27 +71,27 @@
|
||||
|
||||
#########################################
|
||||
# IERS
|
||||
- itemType: GREEN_IER
|
||||
- item_type: GREEN_IER
|
||||
id: '5'
|
||||
startStep: 0
|
||||
endStep: 5
|
||||
start_step: 0
|
||||
end_step: 5
|
||||
load: 999
|
||||
protocol: TCP
|
||||
port: '80'
|
||||
source: '1'
|
||||
destination: '2'
|
||||
missionCriticality: 5
|
||||
mission_criticality: 5
|
||||
|
||||
#########################################
|
||||
# ACL Rules
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '6'
|
||||
permission: ALLOW
|
||||
source: 192.168.1.1
|
||||
destination: 192.168.1.2
|
||||
protocol: TCP
|
||||
port: 80
|
||||
- itemType: ACL_RULE
|
||||
- item_type: ACL_RULE
|
||||
id: '7'
|
||||
permission: ALLOW
|
||||
source: 192.168.1.2
|
||||
|
||||
98
tests/config/obs_tests/main_config_ACCESS_CONTROL_LIST.yaml
Normal file
98
tests/config/obs_tests/main_config_ACCESS_CONTROL_LIST.yaml
Normal file
@@ -0,0 +1,98 @@
|
||||
# Main Config File
|
||||
|
||||
# Generic config values
|
||||
# Choose one of these (dependent on Agent being trained)
|
||||
# "STABLE_BASELINES3_PPO"
|
||||
# "STABLE_BASELINES3_A2C"
|
||||
# "GENERIC"
|
||||
agentIdentifier: NONE
|
||||
# Number of episodes to run per session
|
||||
observationSpace:
|
||||
components:
|
||||
- name: ACCESS_CONTROL_LIST
|
||||
options:
|
||||
implicit_acl_rule: DENY
|
||||
max_number_of_acl_rules: 10
|
||||
|
||||
implicit_acl_rule: DENY
|
||||
max_number_acl_rules: 10
|
||||
numEpisodes: 1
|
||||
# Time delay between steps (for generic agents)
|
||||
timeDelay: 1
|
||||
# Filename of the scenario / laydown
|
||||
configFilename: one_node_states_on_off_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: 1_000_000_000
|
||||
|
||||
# Reward values
|
||||
# Generic
|
||||
allOk: 0
|
||||
# Node Hardware State
|
||||
offShouldBeOn: -10
|
||||
offShouldBeResetting: -5
|
||||
onShouldBeOff: -2
|
||||
onShouldBeResetting: -5
|
||||
resettingShouldBeOn: -5
|
||||
resettingShouldBeOff: -2
|
||||
resetting: -3
|
||||
# Node Software 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
|
||||
@@ -5,92 +5,100 @@
|
||||
# "STABLE_BASELINES3_PPO"
|
||||
# "STABLE_BASELINES3_A2C"
|
||||
# "GENERIC"
|
||||
agentIdentifier: NONE
|
||||
agent_identifier: STABLE_BASELINES3_A2C
|
||||
# Sets How the Action Space is defined:
|
||||
# "NODE"
|
||||
# "ACL"
|
||||
# "ANY" node and acl actions
|
||||
action_type: ANY
|
||||
# Number of episodes to run per session
|
||||
observationSpace:
|
||||
num_episodes: 1
|
||||
# Number of time_steps per episode
|
||||
num_steps: 5
|
||||
|
||||
|
||||
observation_space:
|
||||
components:
|
||||
- name: LINK_TRAFFIC_LEVELS
|
||||
options:
|
||||
combine_service_traffic: false
|
||||
quantisation_levels: 8
|
||||
|
||||
numEpisodes: 1
|
||||
# Time delay between steps (for generic agents)
|
||||
timeDelay: 1
|
||||
# Filename of the scenario / laydown
|
||||
configFilename: one_node_states_on_off_lay_down_config.yaml
|
||||
time_delay: 1
|
||||
|
||||
# Type of session to be run (TRAINING or EVALUATION)
|
||||
sessionType: TRAINING
|
||||
session_type: TRAINING
|
||||
# Determine whether to load an agent from file
|
||||
loadAgent: False
|
||||
load_agent: False
|
||||
# File path and file name of agent if you're loading one in
|
||||
agentLoadFile: C:\[Path]\[agent_saved_filename.zip]
|
||||
agent_load_file: C:\[Path]\[agent_saved_filename.zip]
|
||||
|
||||
# Environment config values
|
||||
# The high value for the observation space
|
||||
observationSpaceHighValue: 1_000_000_000
|
||||
observation_space_high_value: 1_000_000_000
|
||||
|
||||
# Reward values
|
||||
# Generic
|
||||
allOk: 0
|
||||
all_ok: 0
|
||||
# Node Hardware State
|
||||
offShouldBeOn: -10
|
||||
offShouldBeResetting: -5
|
||||
onShouldBeOff: -2
|
||||
onShouldBeResetting: -5
|
||||
resettingShouldBeOn: -5
|
||||
resettingShouldBeOff: -2
|
||||
off_should_be_on: -10
|
||||
off_should_be_resetting: -5
|
||||
on_should_be_off: -2
|
||||
on_should_be_resetting: -5
|
||||
resetting_should_be_on: -5
|
||||
resetting_should_be_off: -2
|
||||
resetting: -3
|
||||
# Node Software or Service State
|
||||
goodShouldBePatching: 2
|
||||
goodShouldBeCompromised: 5
|
||||
goodShouldBeOverwhelmed: 5
|
||||
patchingShouldBeGood: -5
|
||||
patchingShouldBeCompromised: 2
|
||||
patchingShouldBeOverwhelmed: 2
|
||||
good_should_be_patching: 2
|
||||
good_should_be_compromised: 5
|
||||
good_should_be_overwhelmed: 5
|
||||
patching_should_be_good: -5
|
||||
patching_should_be_compromised: 2
|
||||
patching_should_be_overwhelmed: 2
|
||||
patching: -3
|
||||
compromisedShouldBeGood: -20
|
||||
compromisedShouldBePatching: -20
|
||||
compromisedShouldBeOverwhelmed: -20
|
||||
compromised_should_be_good: -20
|
||||
compromised_should_be_patching: -20
|
||||
compromised_should_be_overwhelmed: -20
|
||||
compromised: -20
|
||||
overwhelmedShouldBeGood: -20
|
||||
overwhelmedShouldBePatching: -20
|
||||
overwhelmedShouldBeCompromised: -20
|
||||
overwhelmed_should_be_good: -20
|
||||
overwhelmed_should_be_patching: -20
|
||||
overwhelmed_should_be_compromised: -20
|
||||
overwhelmed: -20
|
||||
# Node File System State
|
||||
goodShouldBeRepairing: 2
|
||||
goodShouldBeRestoring: 2
|
||||
goodShouldBeCorrupt: 5
|
||||
goodShouldBeDestroyed: 10
|
||||
repairingShouldBeGood: -5
|
||||
repairingShouldBeRestoring: 2
|
||||
repairingShouldBeCorrupt: 2
|
||||
repairingShouldBeDestroyed: 0
|
||||
good_should_be_repairing: 2
|
||||
good_should_be_restoring: 2
|
||||
good_should_be_corrupt: 5
|
||||
good_should_be_destroyed: 10
|
||||
repairing_should_be_good: -5
|
||||
repairing_should_be_restoring: 2
|
||||
repairing_should_be_corrupt: 2
|
||||
repairing_should_be_destroyed: 0
|
||||
repairing: -3
|
||||
restoringShouldBeGood: -10
|
||||
restoringShouldBeRepairing: -2
|
||||
restoringShouldBeCorrupt: 1
|
||||
restoringShouldBeDestroyed: 2
|
||||
restoring_should_be_good: -10
|
||||
restoring_should_be_repairing: -2
|
||||
restoring_should_be_corrupt: 1
|
||||
restoring_should_be_destroyed: 2
|
||||
restoring: -6
|
||||
corruptShouldBeGood: -10
|
||||
corruptShouldBeRepairing: -10
|
||||
corruptShouldBeRestoring: -10
|
||||
corruptShouldBeDestroyed: 2
|
||||
corrupt_should_be_good: -10
|
||||
corrupt_should_be_repairing: -10
|
||||
corrupt_should_be_restoring: -10
|
||||
corrupt_should_be_destroyed: 2
|
||||
corrupt: -10
|
||||
destroyedShouldBeGood: -20
|
||||
destroyedShouldBeRepairing: -20
|
||||
destroyedShouldBeRestoring: -20
|
||||
destroyedShouldBeCorrupt: -20
|
||||
destroyed_should_be_good: -20
|
||||
destroyed_should_be_repairing: -20
|
||||
destroyed_should_be_restoring: -20
|
||||
destroyed_should_be_corrupt: -20
|
||||
destroyed: -20
|
||||
scanning: -2
|
||||
# IER status
|
||||
redIerRunning: -5
|
||||
greenIerBlocked: -10
|
||||
red_ier_running: -5
|
||||
green_ier_blocked: -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
|
||||
os_patching_duration: 5 # The time taken to patch the OS
|
||||
node_reset_duration: 5 # The time taken to reset a node (hardware)
|
||||
service_patching_duration: 5 # The time taken to patch a service
|
||||
file_system_repairing_limit: 5 # The time take to repair the file system
|
||||
file_system_restoring_limit: 5 # The time take to restore the file system
|
||||
file_system_scanning_limit: 5 # The time taken to scan the file system
|
||||
|
||||
@@ -5,89 +5,96 @@
|
||||
# "STABLE_BASELINES3_PPO"
|
||||
# "STABLE_BASELINES3_A2C"
|
||||
# "GENERIC"
|
||||
agentIdentifier: NONE
|
||||
agent_identifier: NONE
|
||||
# Sets How the Action Space is defined:
|
||||
# "NODE"
|
||||
# "ACL"
|
||||
# "ANY" node and acl actions
|
||||
action_type: ANY
|
||||
# Number of episodes to run per session
|
||||
observationSpace:
|
||||
num_episodes: 1
|
||||
# Number of time_steps per episode
|
||||
num_steps: 5
|
||||
|
||||
observation_space:
|
||||
components:
|
||||
- name: NODE_LINK_TABLE
|
||||
|
||||
numEpisodes: 1
|
||||
# Time delay between steps (for generic agents)
|
||||
timeDelay: 1
|
||||
time_delay: 1
|
||||
# Filename of the scenario / laydown
|
||||
configFilename: one_node_states_on_off_lay_down_config.yaml
|
||||
# Type of session to be run (TRAINING or EVALUATION)
|
||||
sessionType: TRAINING
|
||||
|
||||
session_type: TRAINING
|
||||
# Determine whether to load an agent from file
|
||||
loadAgent: False
|
||||
load_agent: False
|
||||
# File path and file name of agent if you're loading one in
|
||||
agentLoadFile: C:\[Path]\[agent_saved_filename.zip]
|
||||
agent_load_file: C:\[Path]\[agent_saved_filename.zip]
|
||||
|
||||
# Environment config values
|
||||
# The high value for the observation space
|
||||
observationSpaceHighValue: 1_000_000_000
|
||||
observation_space_high_value: 1_000_000_000
|
||||
|
||||
# Reward values
|
||||
# Generic
|
||||
allOk: 0
|
||||
all_ok: 0
|
||||
# Node Hardware State
|
||||
offShouldBeOn: -10
|
||||
offShouldBeResetting: -5
|
||||
onShouldBeOff: -2
|
||||
onShouldBeResetting: -5
|
||||
resettingShouldBeOn: -5
|
||||
resettingShouldBeOff: -2
|
||||
off_should_be_on: -10
|
||||
off_should_be_resetting: -5
|
||||
on_should_be_off: -2
|
||||
on_should_be_resetting: -5
|
||||
resetting_should_be_on: -5
|
||||
resetting_should_be_off: -2
|
||||
resetting: -3
|
||||
# Node Software or Service State
|
||||
goodShouldBePatching: 2
|
||||
goodShouldBeCompromised: 5
|
||||
goodShouldBeOverwhelmed: 5
|
||||
patchingShouldBeGood: -5
|
||||
patchingShouldBeCompromised: 2
|
||||
patchingShouldBeOverwhelmed: 2
|
||||
good_should_be_patching: 2
|
||||
good_should_be_compromised: 5
|
||||
good_should_be_overwhelmed: 5
|
||||
patching_should_be_good: -5
|
||||
patching_should_be_compromised: 2
|
||||
patching_should_be_overwhelmed: 2
|
||||
patching: -3
|
||||
compromisedShouldBeGood: -20
|
||||
compromisedShouldBePatching: -20
|
||||
compromisedShouldBeOverwhelmed: -20
|
||||
compromised_should_be_good: -20
|
||||
compromised_should_be_patching: -20
|
||||
compromised_should_be_overwhelmed: -20
|
||||
compromised: -20
|
||||
overwhelmedShouldBeGood: -20
|
||||
overwhelmedShouldBePatching: -20
|
||||
overwhelmedShouldBeCompromised: -20
|
||||
overwhelmed_should_be_good: -20
|
||||
overwhelmed_should_be_patching: -20
|
||||
overwhelmed_should_be_compromised: -20
|
||||
overwhelmed: -20
|
||||
# Node File System State
|
||||
goodShouldBeRepairing: 2
|
||||
goodShouldBeRestoring: 2
|
||||
goodShouldBeCorrupt: 5
|
||||
goodShouldBeDestroyed: 10
|
||||
repairingShouldBeGood: -5
|
||||
repairingShouldBeRestoring: 2
|
||||
repairingShouldBeCorrupt: 2
|
||||
repairingShouldBeDestroyed: 0
|
||||
good_should_be_repairing: 2
|
||||
good_should_be_restoring: 2
|
||||
good_should_be_corrupt: 5
|
||||
good_should_be_destroyed: 10
|
||||
repairing_should_be_good: -5
|
||||
repairing_should_be_restoring: 2
|
||||
repairing_should_be_corrupt: 2
|
||||
repairing_should_be_destroyed: 0
|
||||
repairing: -3
|
||||
restoringShouldBeGood: -10
|
||||
restoringShouldBeRepairing: -2
|
||||
restoringShouldBeCorrupt: 1
|
||||
restoringShouldBeDestroyed: 2
|
||||
restoring_should_be_good: -10
|
||||
restoring_should_be_repairing: -2
|
||||
restoring_should_be_corrupt: 1
|
||||
restoring_should_be_destroyed: 2
|
||||
restoring: -6
|
||||
corruptShouldBeGood: -10
|
||||
corruptShouldBeRepairing: -10
|
||||
corruptShouldBeRestoring: -10
|
||||
corruptShouldBeDestroyed: 2
|
||||
corrupt_should_be_good: -10
|
||||
corrupt_should_be_repairing: -10
|
||||
corrupt_should_be_restoring: -10
|
||||
corrupt_should_be_destroyed: 2
|
||||
corrupt: -10
|
||||
destroyedShouldBeGood: -20
|
||||
destroyedShouldBeRepairing: -20
|
||||
destroyedShouldBeRestoring: -20
|
||||
destroyedShouldBeCorrupt: -20
|
||||
destroyed_should_be_good: -20
|
||||
destroyed_should_be_repairing: -20
|
||||
destroyed_should_be_restoring: -20
|
||||
destroyed_should_be_corrupt: -20
|
||||
destroyed: -20
|
||||
scanning: -2
|
||||
# IER status
|
||||
redIerRunning: -5
|
||||
greenIerBlocked: -10
|
||||
red_ier_running: -5
|
||||
green_ier_blocked: -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
|
||||
os_patching_duration: 5 # The time taken to patch the OS
|
||||
node_reset_duration: 5 # The time taken to reset a node (hardware)
|
||||
service_patching_duration: 5 # The time taken to patch a service
|
||||
file_system_repairing_limit: 5 # The time take to repair the file system
|
||||
file_system_restoring_limit: 5 # The time take to restore the file system
|
||||
file_system_scanning_limit: 5 # The time taken to scan the file system
|
||||
|
||||
@@ -5,89 +5,97 @@
|
||||
# "STABLE_BASELINES3_PPO"
|
||||
# "STABLE_BASELINES3_A2C"
|
||||
# "GENERIC"
|
||||
agentIdentifier: NONE
|
||||
agent_identifier: NONE
|
||||
# Sets How the Action Space is defined:
|
||||
# "NODE"
|
||||
# "ACL"
|
||||
# "ANY" node and acl actions
|
||||
action_type: ANY
|
||||
# Number of episodes to run per session
|
||||
observationSpace:
|
||||
num_episodes: 1
|
||||
# Number of time_steps per episode
|
||||
num_steps: 5
|
||||
|
||||
observation_space:
|
||||
components:
|
||||
- name: NODE_STATUSES
|
||||
|
||||
numEpisodes: 1
|
||||
|
||||
# Time delay between steps (for generic agents)
|
||||
timeDelay: 1
|
||||
# Filename of the scenario / laydown
|
||||
configFilename: one_node_states_on_off_lay_down_config.yaml
|
||||
time_delay: 1
|
||||
|
||||
# Type of session to be run (TRAINING or EVALUATION)
|
||||
sessionType: TRAINING
|
||||
session_type: TRAINING
|
||||
# Determine whether to load an agent from file
|
||||
loadAgent: False
|
||||
load_agent: False
|
||||
# File path and file name of agent if you're loading one in
|
||||
agentLoadFile: C:\[Path]\[agent_saved_filename.zip]
|
||||
agent_load_file: C:\[Path]\[agent_saved_filename.zip]
|
||||
|
||||
# Environment config values
|
||||
# The high value for the observation space
|
||||
observationSpaceHighValue: 1_000_000_000
|
||||
observation_space_high_value: 1_000_000_000
|
||||
|
||||
# Reward values
|
||||
# Generic
|
||||
allOk: 0
|
||||
all_ok: 0
|
||||
# Node Hardware State
|
||||
offShouldBeOn: -10
|
||||
offShouldBeResetting: -5
|
||||
onShouldBeOff: -2
|
||||
onShouldBeResetting: -5
|
||||
resettingShouldBeOn: -5
|
||||
resettingShouldBeOff: -2
|
||||
off_should_be_on: -10
|
||||
off_should_be_resetting: -5
|
||||
on_should_be_off: -2
|
||||
on_should_be_resetting: -5
|
||||
resetting_should_be_on: -5
|
||||
resetting_should_be_off: -2
|
||||
resetting: -3
|
||||
# Node Software or Service State
|
||||
goodShouldBePatching: 2
|
||||
goodShouldBeCompromised: 5
|
||||
goodShouldBeOverwhelmed: 5
|
||||
patchingShouldBeGood: -5
|
||||
patchingShouldBeCompromised: 2
|
||||
patchingShouldBeOverwhelmed: 2
|
||||
good_should_be_patching: 2
|
||||
good_should_be_compromised: 5
|
||||
good_should_be_overwhelmed: 5
|
||||
patching_should_be_good: -5
|
||||
patching_should_be_compromised: 2
|
||||
patching_should_be_overwhelmed: 2
|
||||
patching: -3
|
||||
compromisedShouldBeGood: -20
|
||||
compromisedShouldBePatching: -20
|
||||
compromisedShouldBeOverwhelmed: -20
|
||||
compromised_should_be_good: -20
|
||||
compromised_should_be_patching: -20
|
||||
compromised_should_be_overwhelmed: -20
|
||||
compromised: -20
|
||||
overwhelmedShouldBeGood: -20
|
||||
overwhelmedShouldBePatching: -20
|
||||
overwhelmedShouldBeCompromised: -20
|
||||
overwhelmed_should_be_good: -20
|
||||
overwhelmed_should_be_patching: -20
|
||||
overwhelmed_should_be_compromised: -20
|
||||
overwhelmed: -20
|
||||
# Node File System State
|
||||
goodShouldBeRepairing: 2
|
||||
goodShouldBeRestoring: 2
|
||||
goodShouldBeCorrupt: 5
|
||||
goodShouldBeDestroyed: 10
|
||||
repairingShouldBeGood: -5
|
||||
repairingShouldBeRestoring: 2
|
||||
repairingShouldBeCorrupt: 2
|
||||
repairingShouldBeDestroyed: 0
|
||||
good_should_be_repairing: 2
|
||||
good_should_be_restoring: 2
|
||||
good_should_be_corrupt: 5
|
||||
good_should_be_destroyed: 10
|
||||
repairing_should_be_good: -5
|
||||
repairing_should_be_restoring: 2
|
||||
repairing_should_be_corrupt: 2
|
||||
repairing_should_be_destroyed: 0
|
||||
repairing: -3
|
||||
restoringShouldBeGood: -10
|
||||
restoringShouldBeRepairing: -2
|
||||
restoringShouldBeCorrupt: 1
|
||||
restoringShouldBeDestroyed: 2
|
||||
restoring_should_be_good: -10
|
||||
restoring_should_be_repairing: -2
|
||||
restoring_should_be_corrupt: 1
|
||||
restoring_should_be_destroyed: 2
|
||||
restoring: -6
|
||||
corruptShouldBeGood: -10
|
||||
corruptShouldBeRepairing: -10
|
||||
corruptShouldBeRestoring: -10
|
||||
corruptShouldBeDestroyed: 2
|
||||
corrupt_should_be_good: -10
|
||||
corrupt_should_be_repairing: -10
|
||||
corrupt_should_be_restoring: -10
|
||||
corrupt_should_be_destroyed: 2
|
||||
corrupt: -10
|
||||
destroyedShouldBeGood: -20
|
||||
destroyedShouldBeRepairing: -20
|
||||
destroyedShouldBeRestoring: -20
|
||||
destroyedShouldBeCorrupt: -20
|
||||
destroyed_should_be_good: -20
|
||||
destroyed_should_be_repairing: -20
|
||||
destroyed_should_be_restoring: -20
|
||||
destroyed_should_be_corrupt: -20
|
||||
destroyed: -20
|
||||
scanning: -2
|
||||
# IER status
|
||||
redIerRunning: -5
|
||||
greenIerBlocked: -10
|
||||
red_ier_running: -5
|
||||
green_ier_blocked: -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
|
||||
os_patching_duration: 5 # The time taken to patch the OS
|
||||
node_reset_duration: 5 # The time taken to reset a node (hardware)
|
||||
service_patching_duration: 5 # The time taken to patch a service
|
||||
file_system_repairing_limit: 5 # The time take to repair the file system
|
||||
file_system_restoring_limit: 5 # The time take to restore the file system
|
||||
file_system_scanning_limit: 5 # The time taken to scan the file system
|
||||
|
||||
@@ -5,85 +5,92 @@
|
||||
# "STABLE_BASELINES3_PPO"
|
||||
# "STABLE_BASELINES3_A2C"
|
||||
# "GENERIC"
|
||||
agentIdentifier: NONE
|
||||
agent_identifier: NONE
|
||||
# Sets How the Action Space is defined:
|
||||
# "NODE"
|
||||
# "ACL"
|
||||
# "ANY" node and acl actions
|
||||
action_type: ANY
|
||||
# Number of episodes to run per session
|
||||
numEpisodes: 1
|
||||
num_episodes: 1
|
||||
# Number of time_steps per episode
|
||||
num_steps: 5
|
||||
# Time delay between steps (for generic agents)
|
||||
timeDelay: 1
|
||||
# Filename of the scenario / laydown
|
||||
configFilename: one_node_states_on_off_lay_down_config.yaml
|
||||
time_delay: 1
|
||||
# Type of session to be run (TRAINING or EVALUATION)
|
||||
sessionType: TRAINING
|
||||
session_type: TRAINING
|
||||
# Determine whether to load an agent from file
|
||||
loadAgent: False
|
||||
load_agent: False
|
||||
# File path and file name of agent if you're loading one in
|
||||
agentLoadFile: C:\[Path]\[agent_saved_filename.zip]
|
||||
agent_load_file: C:\[Path]\[agent_saved_filename.zip]
|
||||
|
||||
# Environment config values
|
||||
# The high value for the observation space
|
||||
observationSpaceHighValue: 1_000_000_000
|
||||
observation_space_high_value: 1_000_000_000
|
||||
|
||||
implicit_acl_rule: DENY
|
||||
max_number_acl_rules: 10
|
||||
# Reward values
|
||||
# Generic
|
||||
allOk: 0
|
||||
all_ok: 0
|
||||
# Node Hardware State
|
||||
offShouldBeOn: -10
|
||||
offShouldBeResetting: -5
|
||||
onShouldBeOff: -2
|
||||
onShouldBeResetting: -5
|
||||
resettingShouldBeOn: -5
|
||||
resettingShouldBeOff: -2
|
||||
off_should_be_on: -10
|
||||
off_should_be_resetting: -5
|
||||
on_should_be_off: -2
|
||||
on_should_be_resetting: -5
|
||||
resetting_should_be_on: -5
|
||||
resetting_should_be_off: -2
|
||||
resetting: -3
|
||||
# Node Software or Service State
|
||||
goodShouldBePatching: 2
|
||||
goodShouldBeCompromised: 5
|
||||
goodShouldBeOverwhelmed: 5
|
||||
patchingShouldBeGood: -5
|
||||
patchingShouldBeCompromised: 2
|
||||
patchingShouldBeOverwhelmed: 2
|
||||
good_should_be_patching: 2
|
||||
good_should_be_compromised: 5
|
||||
good_should_be_overwhelmed: 5
|
||||
patching_should_be_good: -5
|
||||
patching_should_be_compromised: 2
|
||||
patching_should_be_overwhelmed: 2
|
||||
patching: -3
|
||||
compromisedShouldBeGood: -20
|
||||
compromisedShouldBePatching: -20
|
||||
compromisedShouldBeOverwhelmed: -20
|
||||
compromised_should_be_good: -20
|
||||
compromised_should_be_patching: -20
|
||||
compromised_should_be_overwhelmed: -20
|
||||
compromised: -20
|
||||
overwhelmedShouldBeGood: -20
|
||||
overwhelmedShouldBePatching: -20
|
||||
overwhelmedShouldBeCompromised: -20
|
||||
overwhelmed_should_be_good: -20
|
||||
overwhelmed_should_be_patching: -20
|
||||
overwhelmed_should_be_compromised: -20
|
||||
overwhelmed: -20
|
||||
# Node File System State
|
||||
goodShouldBeRepairing: 2
|
||||
goodShouldBeRestoring: 2
|
||||
goodShouldBeCorrupt: 5
|
||||
goodShouldBeDestroyed: 10
|
||||
repairingShouldBeGood: -5
|
||||
repairingShouldBeRestoring: 2
|
||||
repairingShouldBeCorrupt: 2
|
||||
repairingShouldBeDestroyed: 0
|
||||
good_should_be_repairing: 2
|
||||
good_should_be_restoring: 2
|
||||
good_should_be_corrupt: 5
|
||||
good_should_be_destroyed: 10
|
||||
repairing_should_be_good: -5
|
||||
repairing_should_be_restoring: 2
|
||||
repairing_should_be_corrupt: 2
|
||||
repairing_should_be_destroyed: 0
|
||||
repairing: -3
|
||||
restoringShouldBeGood: -10
|
||||
restoringShouldBeRepairing: -2
|
||||
restoringShouldBeCorrupt: 1
|
||||
restoringShouldBeDestroyed: 2
|
||||
restoring_should_be_good: -10
|
||||
restoring_should_be_repairing: -2
|
||||
restoring_should_be_corrupt: 1
|
||||
restoring_should_be_destroyed: 2
|
||||
restoring: -6
|
||||
corruptShouldBeGood: -10
|
||||
corruptShouldBeRepairing: -10
|
||||
corruptShouldBeRestoring: -10
|
||||
corruptShouldBeDestroyed: 2
|
||||
corrupt_should_be_good: -10
|
||||
corrupt_should_be_repairing: -10
|
||||
corrupt_should_be_restoring: -10
|
||||
corrupt_should_be_destroyed: 2
|
||||
corrupt: -10
|
||||
destroyedShouldBeGood: -20
|
||||
destroyedShouldBeRepairing: -20
|
||||
destroyedShouldBeRestoring: -20
|
||||
destroyedShouldBeCorrupt: -20
|
||||
destroyed_should_be_good: -20
|
||||
destroyed_should_be_repairing: -20
|
||||
destroyed_should_be_restoring: -20
|
||||
destroyed_should_be_corrupt: -20
|
||||
destroyed: -20
|
||||
scanning: -2
|
||||
# IER status
|
||||
redIerRunning: -5
|
||||
greenIerBlocked: -10
|
||||
red_ier_running: -5
|
||||
green_ier_blocked: -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
|
||||
os_patching_duration: 5 # The time taken to patch the OS
|
||||
node_reset_duration: 5 # The time taken to reset a node (hardware)
|
||||
service_patching_duration: 5 # The time taken to patch a service
|
||||
file_system_repairing_limit: 5 # The time take to repair the file system
|
||||
file_system_restoring_limit: 5 # The time take to restore the file system
|
||||
file_system_scanning_limit: 5 # The time taken to scan the file system
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
- itemType: ACTIONS
|
||||
type: NODE
|
||||
- itemType: STEPS
|
||||
steps: 15
|
||||
- itemType: PORTS
|
||||
portsList:
|
||||
- item_type: PORTS
|
||||
ports_list:
|
||||
- port: '21'
|
||||
- itemType: SERVICES
|
||||
serviceList:
|
||||
- item_type: SERVICES
|
||||
service_list:
|
||||
- name: ftp
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '1'
|
||||
name: node
|
||||
node_class: SERVICE
|
||||
@@ -22,15 +18,15 @@
|
||||
- name: ftp
|
||||
port: '21'
|
||||
state: GOOD
|
||||
- itemType: POSITION
|
||||
- item_type: POSITION
|
||||
positions:
|
||||
- node: '1'
|
||||
x_pos: 309
|
||||
y_pos: 78
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '1'
|
||||
startStep: 1
|
||||
endStep: 3
|
||||
start_step: 1
|
||||
end_step: 3
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: FILE
|
||||
@@ -39,10 +35,10 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '2'
|
||||
startStep: 3
|
||||
endStep: 15
|
||||
start_step: 3
|
||||
end_step: 15
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: FILE
|
||||
@@ -51,10 +47,10 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '3'
|
||||
startStep: 4
|
||||
endStep: 6
|
||||
start_step: 4
|
||||
end_step: 6
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: OPERATING
|
||||
@@ -63,10 +59,10 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '4'
|
||||
startStep: 6
|
||||
endStep: 15
|
||||
start_step: 6
|
||||
end_step: 15
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: OPERATING
|
||||
@@ -75,10 +71,10 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '5'
|
||||
startStep: 7
|
||||
endStep: 9
|
||||
start_step: 7
|
||||
end_step: 9
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: SERVICE
|
||||
@@ -87,10 +83,10 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '6'
|
||||
startStep: 9
|
||||
endStep: 15
|
||||
start_step: 9
|
||||
end_step: 15
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: SERVICE
|
||||
@@ -99,10 +95,10 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '7'
|
||||
startStep: 10
|
||||
endStep: 12
|
||||
start_step: 10
|
||||
end_step: 12
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: OS
|
||||
@@ -111,10 +107,10 @@
|
||||
sourceNodeId: NA
|
||||
sourceNodeService: NA
|
||||
sourceNodeServiceState: NA
|
||||
- itemType: RED_POL
|
||||
- item_type: RED_POL
|
||||
id: '8'
|
||||
startStep: 12
|
||||
endStep: 15
|
||||
start_step: 12
|
||||
end_step: 15
|
||||
targetNodeId: '1'
|
||||
initiator: DIRECT
|
||||
type: OS
|
||||
|
||||
@@ -4,86 +4,93 @@
|
||||
# Choose one of these (dependent on Agent being trained)
|
||||
# "STABLE_BASELINES3_PPO"
|
||||
# "STABLE_BASELINES3_A2C"
|
||||
# "GENERIC"
|
||||
agentIdentifier: GENERIC
|
||||
agent_identifier: GENERIC
|
||||
# Sets How the Action Space is defined:
|
||||
# "NODE"
|
||||
# "ACL"
|
||||
# "ANY" node and acl actions
|
||||
action_type: NODE
|
||||
# Number of episodes to run per session
|
||||
numEpisodes: 1
|
||||
num_episodes: 1
|
||||
# Number of time_steps per episode
|
||||
num_steps: 15
|
||||
# Time delay between steps (for generic agents)
|
||||
timeDelay: 1
|
||||
# Filename of the scenario / laydown
|
||||
configFilename: one_node_states_on_off_lay_down_config.yaml
|
||||
time_delay: 1
|
||||
|
||||
# Type of session to be run (TRAINING or EVALUATION)
|
||||
sessionType: TRAINING
|
||||
session_type: TRAINING
|
||||
# Determine whether to load an agent from file
|
||||
loadAgent: False
|
||||
load_agent: False
|
||||
# File path and file name of agent if you're loading one in
|
||||
agentLoadFile: C:\[Path]\[agent_saved_filename.zip]
|
||||
agent_load_file: C:\[Path]\[agent_saved_filename.zip]
|
||||
|
||||
# Environment config values
|
||||
# The high value for the observation space
|
||||
observationSpaceHighValue: 1000000000
|
||||
observation_space_high_value: 1000000000
|
||||
|
||||
implicit_acl_rule: DENY
|
||||
max_number_acl_rules: 10
|
||||
# Reward values
|
||||
# Generic
|
||||
allOk: 0
|
||||
all_ok: 0
|
||||
# Node Hardware State
|
||||
offShouldBeOn: -10
|
||||
offShouldBeResetting: -5
|
||||
onShouldBeOff: -2
|
||||
onShouldBeResetting: -5
|
||||
resettingShouldBeOn: -5
|
||||
resettingShouldBeOff: -2
|
||||
off_should_be_on: -10
|
||||
off_should_be_resetting: -5
|
||||
on_should_be_off: -2
|
||||
on_should_be_resetting: -5
|
||||
resetting_should_be_on: -5
|
||||
resetting_should_be_off: -2
|
||||
resetting: -3
|
||||
# Node Software or Service State
|
||||
goodShouldBePatching: 2
|
||||
goodShouldBeCompromised: 5
|
||||
goodShouldBeOverwhelmed: 5
|
||||
patchingShouldBeGood: -5
|
||||
patchingShouldBeCompromised: 2
|
||||
patchingShouldBeOverwhelmed: 2
|
||||
good_should_be_patching: 2
|
||||
good_should_be_compromised: 5
|
||||
good_should_be_overwhelmed: 5
|
||||
patching_should_be_good: -5
|
||||
patching_should_be_compromised: 2
|
||||
patching_should_be_overwhelmed: 2
|
||||
patching: -3
|
||||
compromisedShouldBeGood: -20
|
||||
compromisedShouldBePatching: -20
|
||||
compromisedShouldBeOverwhelmed: -20
|
||||
compromised_should_be_good: -20
|
||||
compromised_should_be_patching: -20
|
||||
compromised_should_be_overwhelmed: -20
|
||||
compromised: -20
|
||||
overwhelmedShouldBeGood: -20
|
||||
overwhelmedShouldBePatching: -20
|
||||
overwhelmedShouldBeCompromised: -20
|
||||
overwhelmed_should_be_good: -20
|
||||
overwhelmed_should_be_patching: -20
|
||||
overwhelmed_should_be_compromised: -20
|
||||
overwhelmed: -20
|
||||
# Node File System State
|
||||
goodShouldBeRepairing: 2
|
||||
goodShouldBeRestoring: 2
|
||||
goodShouldBeCorrupt: 5
|
||||
goodShouldBeDestroyed: 10
|
||||
repairingShouldBeGood: -5
|
||||
repairingShouldBeRestoring: 2
|
||||
repairingShouldBeCorrupt: 2
|
||||
repairingShouldBeDestroyed: 0
|
||||
good_should_be_repairing: 2
|
||||
good_should_be_restoring: 2
|
||||
good_should_be_corrupt: 5
|
||||
good_should_be_destroyed: 10
|
||||
repairing_should_be_good: -5
|
||||
repairing_should_be_restoring: 2
|
||||
repairing_should_be_corrupt: 2
|
||||
repairing_should_be_destroyed: 0
|
||||
repairing: -3
|
||||
restoringShouldBeGood: -10
|
||||
restoringShouldBeRepairing: -2
|
||||
restoringShouldBeCorrupt: 1
|
||||
restoringShouldBeDestroyed: 2
|
||||
restoring_should_be_good: -10
|
||||
restoring_should_be_repairing: -2
|
||||
restoring_should_be_corrupt: 1
|
||||
restoring_should_be_destroyed: 2
|
||||
restoring: -6
|
||||
corruptShouldBeGood: -10
|
||||
corruptShouldBeRepairing: -10
|
||||
corruptShouldBeRestoring: -10
|
||||
corruptShouldBeDestroyed: 2
|
||||
corrupt_should_be_good: -10
|
||||
corrupt_should_be_repairing: -10
|
||||
corrupt_should_be_restoring: -10
|
||||
corrupt_should_be_destroyed: 2
|
||||
corrupt: -10
|
||||
destroyedShouldBeGood: -20
|
||||
destroyedShouldBeRepairing: -20
|
||||
destroyedShouldBeRestoring: -20
|
||||
destroyedShouldBeCorrupt: -20
|
||||
destroyed_should_be_good: -20
|
||||
destroyed_should_be_repairing: -20
|
||||
destroyed_should_be_restoring: -20
|
||||
destroyed_should_be_corrupt: -20
|
||||
destroyed: -20
|
||||
scanning: -2
|
||||
# IER status
|
||||
redIerRunning: -5
|
||||
greenIerBlocked: -10
|
||||
red_ier_running: -5
|
||||
green_ier_blocked: -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
|
||||
os_patching_duration: 5 # The time taken to patch the OS
|
||||
node_reset_duration: 5 # The time taken to reset a node (hardware)
|
||||
service_patching_duration: 5 # The time taken to patch a service
|
||||
file_system_repairing_limit: 5 # The time take to repair the file system
|
||||
file_system_restoring_limit: 5 # The time take to restore the file system
|
||||
file_system_scanning_limit: 5 # The time taken to scan the file system
|
||||
|
||||
@@ -5,85 +5,90 @@
|
||||
# "STABLE_BASELINES3_PPO"
|
||||
# "STABLE_BASELINES3_A2C"
|
||||
# "GENERIC"
|
||||
agentIdentifier: GENERIC
|
||||
agent_identifier: GENERIC
|
||||
# Sets How the Action Space is defined:
|
||||
# "NODE"
|
||||
# "ACL"
|
||||
# "ANY" node and acl actions
|
||||
action_type: ANY
|
||||
# Number of episodes to run per session
|
||||
numEpisodes: 1
|
||||
num_episodes: 1
|
||||
# Number of time_steps per episode
|
||||
num_steps: 15
|
||||
# Time delay between steps (for generic agents)
|
||||
timeDelay: 1
|
||||
# Filename of the scenario / laydown
|
||||
configFilename: single_action_space_lay_down_config.yaml
|
||||
time_delay: 1
|
||||
# Type of session to be run (TRAINING or EVALUATION)
|
||||
sessionType: TRAINING
|
||||
session_type: TRAINING
|
||||
# Determine whether to load an agent from file
|
||||
loadAgent: False
|
||||
load_agent: False
|
||||
# File path and file name of agent if you're loading one in
|
||||
agentLoadFile: C:\[Path]\[agent_saved_filename.zip]
|
||||
agent_load_file: C:\[Path]\[agent_saved_filename.zip]
|
||||
|
||||
# Environment config values
|
||||
# The high value for the observation space
|
||||
observationSpaceHighValue: 1000000000
|
||||
observation_space_high_value: 1000000000
|
||||
|
||||
# Reward values
|
||||
# Generic
|
||||
allOk: 0
|
||||
all_ok: 0
|
||||
# Node Operating State
|
||||
offShouldBeOn: -10
|
||||
offShouldBeResetting: -5
|
||||
onShouldBeOff: -2
|
||||
onShouldBeResetting: -5
|
||||
resettingShouldBeOn: -5
|
||||
resettingShouldBeOff: -2
|
||||
off_should_be_on: -10
|
||||
off_should_be_resetting: -5
|
||||
on_should_be_off: -2
|
||||
on_should_be_resetting: -5
|
||||
resetting_should_be_on: -5
|
||||
resetting_should_be_off: -2
|
||||
resetting: -3
|
||||
# Node O/S or Service State
|
||||
goodShouldBePatching: 2
|
||||
goodShouldBeCompromised: 5
|
||||
goodShouldBeOverwhelmed: 5
|
||||
patchingShouldBeGood: -5
|
||||
patchingShouldBeCompromised: 2
|
||||
patchingShouldBeOverwhelmed: 2
|
||||
good_should_be_patching: 2
|
||||
good_should_be_compromised: 5
|
||||
good_should_be_overwhelmed: 5
|
||||
patching_should_be_good: -5
|
||||
patching_should_be_compromised: 2
|
||||
patching_should_be_overwhelmed: 2
|
||||
patching: -3
|
||||
compromisedShouldBeGood: -20
|
||||
compromisedShouldBePatching: -20
|
||||
compromisedShouldBeOverwhelmed: -20
|
||||
compromised_should_be_good: -20
|
||||
compromised_should_be_patching: -20
|
||||
compromised_should_be_overwhelmed: -20
|
||||
compromised: -20
|
||||
overwhelmedShouldBeGood: -20
|
||||
overwhelmedShouldBePatching: -20
|
||||
overwhelmedShouldBeCompromised: -20
|
||||
overwhelmed_should_be_good: -20
|
||||
overwhelmed_should_be_patching: -20
|
||||
overwhelmed_should_be_compromised: -20
|
||||
overwhelmed: -20
|
||||
# Node File System State
|
||||
goodShouldBeRepairing: 2
|
||||
goodShouldBeRestoring: 2
|
||||
goodShouldBeCorrupt: 5
|
||||
goodShouldBeDestroyed: 10
|
||||
repairingShouldBeGood: -5
|
||||
repairingShouldBeRestoring: 2
|
||||
repairingShouldBeCorrupt: 2
|
||||
repairingShouldBeDestroyed: 0
|
||||
good_should_be_repairing: 2
|
||||
good_should_be_restoring: 2
|
||||
good_should_be_corrupt: 5
|
||||
good_should_be_destroyed: 10
|
||||
repairing_should_be_good: -5
|
||||
repairing_should_be_restoring: 2
|
||||
repairing_should_be_corrupt: 2
|
||||
repairing_should_be_destroyed: 0
|
||||
repairing: -3
|
||||
restoringShouldBeGood: -10
|
||||
restoringShouldBeRepairing: -2
|
||||
restoringShouldBeCorrupt: 1
|
||||
restoringShouldBeDestroyed: 2
|
||||
restoring_should_be_good: -10
|
||||
restoring_should_be_repairing: -2
|
||||
restoring_should_be_corrupt: 1
|
||||
restoring_should_be_destroyed: 2
|
||||
restoring: -6
|
||||
corruptShouldBeGood: -10
|
||||
corruptShouldBeRepairing: -10
|
||||
corruptShouldBeRestoring: -10
|
||||
corruptShouldBeDestroyed: 2
|
||||
corrupt_should_be_good: -10
|
||||
corrupt_should_be_repairing: -10
|
||||
corrupt_should_be_restoring: -10
|
||||
corrupt_should_be_destroyed: 2
|
||||
corrupt: -10
|
||||
destroyedShouldBeGood: -20
|
||||
destroyedShouldBeRepairing: -20
|
||||
destroyedShouldBeRestoring: -20
|
||||
destroyedShouldBeCorrupt: -20
|
||||
destroyed_should_be_good: -20
|
||||
destroyed_should_be_repairing: -20
|
||||
destroyed_should_be_restoring: -20
|
||||
destroyed_should_be_corrupt: -20
|
||||
destroyed: -20
|
||||
scanning: -2
|
||||
# IER status
|
||||
redIerRunning: -5
|
||||
greenIerBlocked: -10
|
||||
red_ier_running: -5
|
||||
green_ier_blocked: -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
|
||||
os_patching_duration: 5 # The time taken to patch the OS
|
||||
node_reset_duration: 5 # The time taken to reset a node (hardware)
|
||||
service_patching_duration: 5 # The time taken to patch a service
|
||||
file_system_repairing_limit: 5 # The time take to repair the file system
|
||||
file_system_restoring_limit: 5 # The time take to restore the file system
|
||||
file_system_scanning_limit: 5 # The time taken to scan the file system
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
- itemType: ACTIONS
|
||||
type: ANY
|
||||
- itemType: STEPS
|
||||
steps: 15
|
||||
- itemType: PORTS
|
||||
portsList:
|
||||
- item_type: PORTS
|
||||
ports_list:
|
||||
- port: '21'
|
||||
- itemType: SERVICES
|
||||
serviceList:
|
||||
- item_type: SERVICES
|
||||
service_list:
|
||||
- name: ftp
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '1'
|
||||
name: node
|
||||
node_class: SERVICE
|
||||
@@ -22,7 +18,7 @@
|
||||
- name: ftp
|
||||
port: '21'
|
||||
state: COMPROMISED
|
||||
- itemType: NODE
|
||||
- item_type: NODE
|
||||
node_id: '2'
|
||||
name: server_1
|
||||
node_class: SERVICE
|
||||
@@ -36,7 +32,7 @@
|
||||
- name: ftp
|
||||
port: '21'
|
||||
state: COMPROMISED
|
||||
- itemType: POSITION
|
||||
- item_type: POSITION
|
||||
positions:
|
||||
- node: '1'
|
||||
x_pos: 309
|
||||
@@ -44,12 +40,13 @@
|
||||
- node: '2'
|
||||
x_pos: 200
|
||||
y_pos: 78
|
||||
- itemType: RED_IER
|
||||
- item_type: RED_IER
|
||||
id: '3'
|
||||
startStep: 2
|
||||
endStep: 15
|
||||
start_step: 2
|
||||
end_step: 15
|
||||
load: 1000
|
||||
protocol: ftp
|
||||
port: CORRUPT
|
||||
source: '1'
|
||||
destination: '2'
|
||||
mission_criticality: 0
|
||||
|
||||
@@ -5,85 +5,92 @@
|
||||
# "STABLE_BASELINES3_PPO"
|
||||
# "STABLE_BASELINES3_A2C"
|
||||
# "GENERIC"
|
||||
agentIdentifier: GENERIC
|
||||
agent_identifier: GENERIC
|
||||
# Sets How the Action Space is defined:
|
||||
# "NODE"
|
||||
# "ACL"
|
||||
# "ANY" node and acl actions
|
||||
action_type: ANY
|
||||
# Number of episodes to run per session
|
||||
numEpisodes: 1
|
||||
num_episodes: 1
|
||||
# Number of time_steps per episode
|
||||
num_steps: 5
|
||||
# Time delay between steps (for generic agents)
|
||||
timeDelay: 1
|
||||
# Filename of the scenario / laydown
|
||||
configFilename: single_action_space_lay_down_config.yaml
|
||||
time_delay: 1
|
||||
# Type of session to be run (TRAINING or EVALUATION)
|
||||
sessionType: TRAINING
|
||||
session_type: TRAINING
|
||||
# Determine whether to load an agent from file
|
||||
loadAgent: False
|
||||
load_agent: False
|
||||
# File path and file name of agent if you're loading one in
|
||||
agentLoadFile: C:\[Path]\[agent_saved_filename.zip]
|
||||
agent_load_file: C:\[Path]\[agent_saved_filename.zip]
|
||||
|
||||
# Environment config values
|
||||
# The high value for the observation space
|
||||
observationSpaceHighValue: 1000000000
|
||||
observation_space_high_value: 1000000000
|
||||
|
||||
implicit_acl_rule: DENY
|
||||
max_number_acl_rules: 10
|
||||
# Reward values
|
||||
# Generic
|
||||
allOk: 0
|
||||
all_ok: 0
|
||||
# Node Operating State
|
||||
offShouldBeOn: -10
|
||||
offShouldBeResetting: -5
|
||||
onShouldBeOff: -2
|
||||
onShouldBeResetting: -5
|
||||
resettingShouldBeOn: -5
|
||||
resettingShouldBeOff: -2
|
||||
off_should_be_on: -10
|
||||
off_should_be_resetting: -5
|
||||
on_should_be_off: -2
|
||||
on_should_be_resetting: -5
|
||||
resetting_should_be_on: -5
|
||||
resetting_should_be_off: -2
|
||||
resetting: -3
|
||||
# Node O/S or Service State
|
||||
goodShouldBePatching: 2
|
||||
goodShouldBeCompromised: 5
|
||||
goodShouldBeOverwhelmed: 5
|
||||
patchingShouldBeGood: -5
|
||||
patchingShouldBeCompromised: 2
|
||||
patchingShouldBeOverwhelmed: 2
|
||||
good_should_be_patching: 2
|
||||
good_should_be_compromised: 5
|
||||
good_should_be_overwhelmed: 5
|
||||
patching_should_be_good: -5
|
||||
patching_should_be_compromised: 2
|
||||
patching_should_be_overwhelmed: 2
|
||||
patching: -3
|
||||
compromisedShouldBeGood: -20
|
||||
compromisedShouldBePatching: -20
|
||||
compromisedShouldBeOverwhelmed: -20
|
||||
compromised_should_be_good: -20
|
||||
compromised_should_be_patching: -20
|
||||
compromised_should_be_overwhelmed: -20
|
||||
compromised: -20
|
||||
overwhelmedShouldBeGood: -20
|
||||
overwhelmedShouldBePatching: -20
|
||||
overwhelmedShouldBeCompromised: -20
|
||||
overwhelmed_should_be_good: -20
|
||||
overwhelmed_should_be_patching: -20
|
||||
overwhelmed_should_be_compromised: -20
|
||||
overwhelmed: -20
|
||||
# Node File System State
|
||||
goodShouldBeRepairing: 2
|
||||
goodShouldBeRestoring: 2
|
||||
goodShouldBeCorrupt: 5
|
||||
goodShouldBeDestroyed: 10
|
||||
repairingShouldBeGood: -5
|
||||
repairingShouldBeRestoring: 2
|
||||
repairingShouldBeCorrupt: 2
|
||||
repairingShouldBeDestroyed: 0
|
||||
good_should_be_repairing: 2
|
||||
good_should_be_restoring: 2
|
||||
good_should_be_corrupt: 5
|
||||
good_should_be_destroyed: 10
|
||||
repairing_should_be_good: -5
|
||||
repairing_should_be_restoring: 2
|
||||
repairing_should_be_corrupt: 2
|
||||
repairing_should_be_destroyed: 0
|
||||
repairing: -3
|
||||
restoringShouldBeGood: -10
|
||||
restoringShouldBeRepairing: -2
|
||||
restoringShouldBeCorrupt: 1
|
||||
restoringShouldBeDestroyed: 2
|
||||
restoring_should_be_good: -10
|
||||
restoring_should_be_repairing: -2
|
||||
restoring_should_be_corrupt: 1
|
||||
restoring_should_be_destroyed: 2
|
||||
restoring: -6
|
||||
corruptShouldBeGood: -10
|
||||
corruptShouldBeRepairing: -10
|
||||
corruptShouldBeRestoring: -10
|
||||
corruptShouldBeDestroyed: 2
|
||||
corrupt_should_be_good: -10
|
||||
corrupt_should_be_repairing: -10
|
||||
corrupt_should_be_restoring: -10
|
||||
corrupt_should_be_destroyed: 2
|
||||
corrupt: -10
|
||||
destroyedShouldBeGood: -20
|
||||
destroyedShouldBeRepairing: -20
|
||||
destroyedShouldBeRestoring: -20
|
||||
destroyedShouldBeCorrupt: -20
|
||||
destroyed_should_be_good: -20
|
||||
destroyed_should_be_repairing: -20
|
||||
destroyed_should_be_restoring: -20
|
||||
destroyed_should_be_corrupt: -20
|
||||
destroyed: -20
|
||||
scanning: -2
|
||||
# IER status
|
||||
redIerRunning: -5
|
||||
greenIerBlocked: -10
|
||||
red_ier_running: -5
|
||||
green_ier_blocked: -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
|
||||
os_patching_duration: 5 # The time taken to patch the OS
|
||||
node_reset_duration: 5 # The time taken to reset a node (hardware)
|
||||
service_patching_duration: 5 # The time taken to patch a service
|
||||
file_system_repairing_limit: 5 # The time take to repair the file system
|
||||
file_system_restoring_limit: 5 # The time take to restore the file system
|
||||
file_system_scanning_limit: 5 # The time taken to scan the file system
|
||||
|
||||
@@ -1,180 +1,55 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
import tempfile
|
||||
import time
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Union
|
||||
|
||||
import yaml
|
||||
|
||||
from primaite.common.config_values_main import ConfigValuesMain
|
||||
from primaite.environment.primaite_env import Primaite
|
||||
|
||||
ACTION_SPACE_NODE_VALUES = 1
|
||||
ACTION_SPACE_NODE_ACTION_VALUES = 1
|
||||
|
||||
|
||||
def _get_temp_session_path(session_timestamp: datetime) -> Path:
|
||||
"""
|
||||
Get a temp directory session path the test session will output to.
|
||||
|
||||
:param session_timestamp: This is the datetime that the session started.
|
||||
:return: The session directory path.
|
||||
"""
|
||||
date_dir = session_timestamp.strftime("%Y-%m-%d")
|
||||
session_dir = session_timestamp.strftime("%Y-%m-%d_%H-%M-%S")
|
||||
session_path = Path(tempfile.gettempdir()) / "primaite" / date_dir / session_dir
|
||||
session_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
return session_path
|
||||
|
||||
|
||||
def _get_primaite_env_from_config(
|
||||
main_config_path: Union[str, Path], lay_down_config_path: Union[str, Path]
|
||||
training_config_path: Union[str, Path], lay_down_config_path: Union[str, Path]
|
||||
):
|
||||
"""Takes a config path and returns the created instance of Primaite."""
|
||||
session_timestamp: datetime = datetime.now()
|
||||
session_path = _get_temp_session_path(session_timestamp)
|
||||
|
||||
def load_config_values():
|
||||
config_values.agent_identifier = config_data["agentIdentifier"]
|
||||
if "observationSpace" in config_data:
|
||||
config_values.observation_config = config_data["observationSpace"]
|
||||
else:
|
||||
config_values.observation_config = None
|
||||
config_values.num_episodes = int(config_data["numEpisodes"])
|
||||
config_values.time_delay = int(config_data["timeDelay"])
|
||||
config_values.config_filename_use_case = lay_down_config_path
|
||||
config_values.session_type = config_data["sessionType"]
|
||||
config_values.load_agent = bool(config_data["loadAgent"])
|
||||
config_values.agent_load_file = config_data["agentLoadFile"]
|
||||
# Environment
|
||||
config_values.observation_space_high_value = int(
|
||||
config_data["observationSpaceHighValue"]
|
||||
)
|
||||
# Reward values
|
||||
# Generic
|
||||
config_values.all_ok = int(config_data["allOk"])
|
||||
# Node Hardware State
|
||||
config_values.off_should_be_on = int(config_data["offShouldBeOn"])
|
||||
config_values.off_should_be_resetting = int(config_data["offShouldBeResetting"])
|
||||
config_values.on_should_be_off = int(config_data["onShouldBeOff"])
|
||||
config_values.on_should_be_resetting = int(config_data["onShouldBeResetting"])
|
||||
config_values.resetting_should_be_on = int(config_data["resettingShouldBeOn"])
|
||||
config_values.resetting_should_be_off = int(config_data["resettingShouldBeOff"])
|
||||
config_values.resetting = int(config_data["resetting"])
|
||||
# Node Software or Service State
|
||||
config_values.good_should_be_patching = int(config_data["goodShouldBePatching"])
|
||||
config_values.good_should_be_compromised = int(
|
||||
config_data["goodShouldBeCompromised"]
|
||||
)
|
||||
config_values.good_should_be_overwhelmed = int(
|
||||
config_data["goodShouldBeOverwhelmed"]
|
||||
)
|
||||
config_values.patching_should_be_good = int(config_data["patchingShouldBeGood"])
|
||||
config_values.patching_should_be_compromised = int(
|
||||
config_data["patchingShouldBeCompromised"]
|
||||
)
|
||||
config_values.patching_should_be_overwhelmed = int(
|
||||
config_data["patchingShouldBeOverwhelmed"]
|
||||
)
|
||||
config_values.patching = int(config_data["patching"])
|
||||
config_values.compromised_should_be_good = int(
|
||||
config_data["compromisedShouldBeGood"]
|
||||
)
|
||||
config_values.compromised_should_be_patching = int(
|
||||
config_data["compromisedShouldBePatching"]
|
||||
)
|
||||
config_values.compromised_should_be_overwhelmed = int(
|
||||
config_data["compromisedShouldBeOverwhelmed"]
|
||||
)
|
||||
config_values.compromised = int(config_data["compromised"])
|
||||
config_values.overwhelmed_should_be_good = int(
|
||||
config_data["overwhelmedShouldBeGood"]
|
||||
)
|
||||
config_values.overwhelmed_should_be_patching = int(
|
||||
config_data["overwhelmedShouldBePatching"]
|
||||
)
|
||||
config_values.overwhelmed_should_be_compromised = int(
|
||||
config_data["overwhelmedShouldBeCompromised"]
|
||||
)
|
||||
config_values.overwhelmed = int(config_data["overwhelmed"])
|
||||
# Node File System State
|
||||
config_values.good_should_be_repairing = int(
|
||||
config_data["goodShouldBeRepairing"]
|
||||
)
|
||||
config_values.good_should_be_restoring = int(
|
||||
config_data["goodShouldBeRestoring"]
|
||||
)
|
||||
config_values.good_should_be_corrupt = int(config_data["goodShouldBeCorrupt"])
|
||||
config_values.good_should_be_destroyed = int(
|
||||
config_data["goodShouldBeDestroyed"]
|
||||
)
|
||||
config_values.repairing_should_be_good = int(
|
||||
config_data["repairingShouldBeGood"]
|
||||
)
|
||||
config_values.repairing_should_be_restoring = int(
|
||||
config_data["repairingShouldBeRestoring"]
|
||||
)
|
||||
config_values.repairing_should_be_corrupt = int(
|
||||
config_data["repairingShouldBeCorrupt"]
|
||||
)
|
||||
config_values.repairing_should_be_destroyed = int(
|
||||
config_data["repairingShouldBeDestroyed"]
|
||||
)
|
||||
config_values.repairing = int(config_data["repairing"])
|
||||
config_values.restoring_should_be_good = int(
|
||||
config_data["restoringShouldBeGood"]
|
||||
)
|
||||
config_values.restoring_should_be_repairing = int(
|
||||
config_data["restoringShouldBeRepairing"]
|
||||
)
|
||||
config_values.restoring_should_be_corrupt = int(
|
||||
config_data["restoringShouldBeCorrupt"]
|
||||
)
|
||||
config_values.restoring_should_be_destroyed = int(
|
||||
config_data["restoringShouldBeDestroyed"]
|
||||
)
|
||||
config_values.restoring = int(config_data["restoring"])
|
||||
config_values.corrupt_should_be_good = int(config_data["corruptShouldBeGood"])
|
||||
config_values.corrupt_should_be_repairing = int(
|
||||
config_data["corruptShouldBeRepairing"]
|
||||
)
|
||||
config_values.corrupt_should_be_restoring = int(
|
||||
config_data["corruptShouldBeRestoring"]
|
||||
)
|
||||
config_values.corrupt_should_be_destroyed = int(
|
||||
config_data["corruptShouldBeDestroyed"]
|
||||
)
|
||||
config_values.corrupt = int(config_data["corrupt"])
|
||||
config_values.destroyed_should_be_good = int(
|
||||
config_data["destroyedShouldBeGood"]
|
||||
)
|
||||
config_values.destroyed_should_be_repairing = int(
|
||||
config_data["destroyedShouldBeRepairing"]
|
||||
)
|
||||
config_values.destroyed_should_be_restoring = int(
|
||||
config_data["destroyedShouldBeRestoring"]
|
||||
)
|
||||
config_values.destroyed_should_be_corrupt = int(
|
||||
config_data["destroyedShouldBeCorrupt"]
|
||||
)
|
||||
config_values.destroyed = int(config_data["destroyed"])
|
||||
config_values.scanning = int(config_data["scanning"])
|
||||
# IER status
|
||||
config_values.red_ier_running = int(config_data["redIerRunning"])
|
||||
config_values.green_ier_blocked = int(config_data["greenIerBlocked"])
|
||||
# Patching / Reset durations
|
||||
config_values.os_patching_duration = int(config_data["osPatchingDuration"])
|
||||
config_values.node_reset_duration = int(config_data["nodeResetDuration"])
|
||||
config_values.service_patching_duration = int(
|
||||
config_data["servicePatchingDuration"]
|
||||
)
|
||||
config_values.file_system_repairing_limit = int(
|
||||
config_data["fileSystemRepairingLimit"]
|
||||
)
|
||||
config_values.file_system_restoring_limit = int(
|
||||
config_data["fileSystemRestoringLimit"]
|
||||
)
|
||||
config_values.file_system_scanning_limit = int(
|
||||
config_data["fileSystemScanningLimit"]
|
||||
)
|
||||
|
||||
config_file_main = open(main_config_path, "r")
|
||||
config_data = yaml.safe_load(config_file_main)
|
||||
# Create a config class
|
||||
config_values = ConfigValuesMain()
|
||||
# Load in config data
|
||||
load_config_values()
|
||||
env = Primaite(config_values, [])
|
||||
# Get the number of steps (which is stored in the child config file)
|
||||
timestamp_str = session_timestamp.strftime("%Y-%m-%d_%H-%M-%S")
|
||||
env = Primaite(
|
||||
training_config_path=training_config_path,
|
||||
lay_down_config_path=lay_down_config_path,
|
||||
transaction_list=[],
|
||||
session_path=session_path,
|
||||
timestamp_str=timestamp_str,
|
||||
)
|
||||
config_values = env.training_config
|
||||
config_values.num_steps = env.episode_steps
|
||||
|
||||
if env.config_values.agent_identifier == "GENERIC":
|
||||
# TOOD: This needs t be refactored to happen outside. Should be part of
|
||||
# a main Session class.
|
||||
if env.training_config.agent_identifier == "GENERIC":
|
||||
run_generic(env, config_values)
|
||||
|
||||
return env, config_values
|
||||
return env
|
||||
|
||||
|
||||
def run_generic(env, config_values):
|
||||
|
||||
0
tests/e2e_integration_tests/__init__.py
Normal file
0
tests/e2e_integration_tests/__init__.py
Normal file
8
tests/e2e_integration_tests/test_primaite_main.py
Normal file
8
tests/e2e_integration_tests/test_primaite_main.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from primaite.config.lay_down_config import data_manipulation_config_path
|
||||
from primaite.config.training_config import main_training_config_path
|
||||
from primaite.main import run
|
||||
|
||||
|
||||
def test_primaite_main_e2e():
|
||||
"""Tests the primaite.main.run function end-to-end."""
|
||||
run(main_training_config_path(), data_manipulation_config_path())
|
||||
@@ -7,7 +7,7 @@ from primaite.acl.acl_rule import ACLRule
|
||||
|
||||
def test_acl_address_match_1():
|
||||
"""Test that matching IP addresses produce True."""
|
||||
acl = AccessControlList()
|
||||
acl = AccessControlList("DENY", 10)
|
||||
|
||||
rule = ACLRule("ALLOW", "192.168.1.1", "192.168.1.2", "TCP", "80")
|
||||
|
||||
@@ -16,7 +16,7 @@ def test_acl_address_match_1():
|
||||
|
||||
def test_acl_address_match_2():
|
||||
"""Test that mismatching IP addresses produce False."""
|
||||
acl = AccessControlList()
|
||||
acl = AccessControlList("DENY", 10)
|
||||
|
||||
rule = ACLRule("ALLOW", "192.168.1.1", "192.168.1.2", "TCP", "80")
|
||||
|
||||
@@ -25,7 +25,7 @@ def test_acl_address_match_2():
|
||||
|
||||
def test_acl_address_match_3():
|
||||
"""Test the ANY condition for source IP addresses produce True."""
|
||||
acl = AccessControlList()
|
||||
acl = AccessControlList("DENY", 10)
|
||||
|
||||
rule = ACLRule("ALLOW", "ANY", "192.168.1.2", "TCP", "80")
|
||||
|
||||
@@ -34,7 +34,7 @@ def test_acl_address_match_3():
|
||||
|
||||
def test_acl_address_match_4():
|
||||
"""Test the ANY condition for dest IP addresses produce True."""
|
||||
acl = AccessControlList()
|
||||
acl = AccessControlList("DENY", 10)
|
||||
|
||||
rule = ACLRule("ALLOW", "192.168.1.1", "ANY", "TCP", "80")
|
||||
|
||||
@@ -44,7 +44,7 @@ def test_acl_address_match_4():
|
||||
def test_check_acl_block_affirmative():
|
||||
"""Test the block function (affirmative)."""
|
||||
# Create the Access Control List
|
||||
acl = AccessControlList()
|
||||
acl = AccessControlList("DENY", 10)
|
||||
|
||||
# Create a rule
|
||||
acl_rule_permission = "ALLOW"
|
||||
@@ -52,6 +52,7 @@ def test_check_acl_block_affirmative():
|
||||
acl_rule_destination = "192.168.1.2"
|
||||
acl_rule_protocol = "TCP"
|
||||
acl_rule_port = "80"
|
||||
acl_position_in_list = "1"
|
||||
|
||||
acl.add_rule(
|
||||
acl_rule_permission,
|
||||
@@ -59,15 +60,15 @@ def test_check_acl_block_affirmative():
|
||||
acl_rule_destination,
|
||||
acl_rule_protocol,
|
||||
acl_rule_port,
|
||||
acl_position_in_list,
|
||||
)
|
||||
|
||||
assert acl.is_blocked("192.168.1.1", "192.168.1.2", "TCP", "80") == False
|
||||
|
||||
|
||||
def test_check_acl_block_negative():
|
||||
"""Test the block function (negative)."""
|
||||
# Create the Access Control List
|
||||
acl = AccessControlList()
|
||||
acl = AccessControlList("DENY", 10)
|
||||
|
||||
# Create a rule
|
||||
acl_rule_permission = "DENY"
|
||||
@@ -75,6 +76,7 @@ def test_check_acl_block_negative():
|
||||
acl_rule_destination = "192.168.1.2"
|
||||
acl_rule_protocol = "TCP"
|
||||
acl_rule_port = "80"
|
||||
acl_position_in_list = "1"
|
||||
|
||||
acl.add_rule(
|
||||
acl_rule_permission,
|
||||
@@ -82,6 +84,7 @@ def test_check_acl_block_negative():
|
||||
acl_rule_destination,
|
||||
acl_rule_protocol,
|
||||
acl_rule_port,
|
||||
acl_position_in_list,
|
||||
)
|
||||
|
||||
assert acl.is_blocked("192.168.1.1", "192.168.1.2", "TCP", "80") == True
|
||||
@@ -90,7 +93,7 @@ def test_check_acl_block_negative():
|
||||
def test_rule_hash():
|
||||
"""Test the rule hash."""
|
||||
# Create the Access Control List
|
||||
acl = AccessControlList()
|
||||
acl = AccessControlList("DENY", 10)
|
||||
|
||||
rule = ACLRule("DENY", "192.168.1.1", "192.168.1.2", "TCP", "80")
|
||||
hash_value_local = hash(rule)
|
||||
|
||||
@@ -16,10 +16,10 @@ from tests.conftest import _get_primaite_env_from_config
|
||||
def env(request):
|
||||
"""Build Primaite environment for integration tests of observation space."""
|
||||
marker = request.node.get_closest_marker("env_config_paths")
|
||||
main_config_path = marker.args[0]["main_config_path"]
|
||||
training_config_path = marker.args[0]["training_config_path"]
|
||||
lay_down_config_path = marker.args[0]["lay_down_config_path"]
|
||||
env, _ = _get_primaite_env_from_config(
|
||||
main_config_path=main_config_path,
|
||||
env = _get_primaite_env_from_config(
|
||||
training_config_path=training_config_path,
|
||||
lay_down_config_path=lay_down_config_path,
|
||||
)
|
||||
yield env
|
||||
@@ -27,7 +27,7 @@ def env(request):
|
||||
|
||||
@pytest.mark.env_config_paths(
|
||||
dict(
|
||||
main_config_path=TEST_CONFIG_ROOT / "obs_tests/main_config_without_obs.yaml",
|
||||
training_config_path=TEST_CONFIG_ROOT / "obs_tests/main_config_without_obs.yaml",
|
||||
lay_down_config_path=TEST_CONFIG_ROOT / "obs_tests/laydown.yaml",
|
||||
)
|
||||
)
|
||||
@@ -43,7 +43,7 @@ def test_default_obs_space(env: Primaite):
|
||||
|
||||
@pytest.mark.env_config_paths(
|
||||
dict(
|
||||
main_config_path=TEST_CONFIG_ROOT / "obs_tests/main_config_without_obs.yaml",
|
||||
training_config_path=TEST_CONFIG_ROOT / "obs_tests/main_config_without_obs.yaml",
|
||||
lay_down_config_path=TEST_CONFIG_ROOT / "obs_tests/laydown.yaml",
|
||||
)
|
||||
)
|
||||
@@ -59,7 +59,7 @@ def test_registering_components(env: Primaite):
|
||||
|
||||
@pytest.mark.env_config_paths(
|
||||
dict(
|
||||
main_config_path=TEST_CONFIG_ROOT
|
||||
training_config_path=TEST_CONFIG_ROOT
|
||||
/ "obs_tests/main_config_NODE_LINK_TABLE.yaml",
|
||||
lay_down_config_path=TEST_CONFIG_ROOT / "obs_tests/laydown.yaml",
|
||||
)
|
||||
@@ -140,7 +140,7 @@ class TestNodeLinkTable:
|
||||
|
||||
@pytest.mark.env_config_paths(
|
||||
dict(
|
||||
main_config_path=TEST_CONFIG_ROOT / "obs_tests/main_config_NODE_STATUSES.yaml",
|
||||
training_config_path=TEST_CONFIG_ROOT / "obs_tests/main_config_NODE_STATUSES.yaml",
|
||||
lay_down_config_path=TEST_CONFIG_ROOT / "obs_tests/laydown.yaml",
|
||||
)
|
||||
)
|
||||
@@ -184,7 +184,7 @@ class TestNodeStatuses:
|
||||
|
||||
@pytest.mark.env_config_paths(
|
||||
dict(
|
||||
main_config_path=TEST_CONFIG_ROOT
|
||||
training_config_path=TEST_CONFIG_ROOT
|
||||
/ "obs_tests/main_config_LINK_TRAFFIC_LEVELS.yaml",
|
||||
lay_down_config_path=TEST_CONFIG_ROOT / "obs_tests/laydown.yaml",
|
||||
)
|
||||
|
||||
103
tests/test_resetting_node.py
Normal file
103
tests/test_resetting_node.py
Normal file
@@ -0,0 +1,103 @@
|
||||
"""Used to test Active Node functions."""
|
||||
import pytest
|
||||
|
||||
from primaite.common.enums import FileSystemState, HardwareState, SoftwareState, NodeType, Priority
|
||||
from primaite.common.service import Service
|
||||
from primaite.config.training_config import TrainingConfig
|
||||
from primaite.nodes.active_node import ActiveNode
|
||||
from primaite.nodes.service_node import ServiceNode
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"starting_operating_state, expected_operating_state",
|
||||
[
|
||||
(HardwareState.RESETTING, HardwareState.ON)
|
||||
],
|
||||
)
|
||||
def test_node_resets_correctly(starting_operating_state, expected_operating_state):
|
||||
"""
|
||||
Tests that a node resets correctly.
|
||||
"""
|
||||
active_node = ActiveNode(
|
||||
node_id = "0",
|
||||
name = "node",
|
||||
node_type = NodeType.COMPUTER,
|
||||
priority = Priority.P1,
|
||||
hardware_state = starting_operating_state,
|
||||
ip_address = "192.168.0.1",
|
||||
software_state = SoftwareState.COMPROMISED,
|
||||
file_system_state = FileSystemState.CORRUPT,
|
||||
config_values=TrainingConfig()
|
||||
)
|
||||
|
||||
for x in range(5):
|
||||
active_node.update_resetting_status()
|
||||
|
||||
assert active_node.software_state == SoftwareState.GOOD
|
||||
assert active_node.file_system_state_actual == FileSystemState.GOOD
|
||||
assert active_node.hardware_state == expected_operating_state
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"operating_state, expected_operating_state",
|
||||
[
|
||||
(HardwareState.BOOTING, HardwareState.ON)
|
||||
],
|
||||
)
|
||||
def test_node_boots_correctly(operating_state, expected_operating_state):
|
||||
"""
|
||||
Tests that a node boots correctly.
|
||||
"""
|
||||
service_node = ServiceNode(
|
||||
node_id = 0,
|
||||
name = "node",
|
||||
node_type = "COMPUTER",
|
||||
priority = "1",
|
||||
hardware_state = operating_state,
|
||||
ip_address = "192.168.0.1",
|
||||
software_state = SoftwareState.GOOD,
|
||||
file_system_state = "GOOD",
|
||||
config_values = 1,
|
||||
)
|
||||
service_attributes = Service(
|
||||
name = "node",
|
||||
port = "80",
|
||||
software_state = SoftwareState.COMPROMISED
|
||||
)
|
||||
service_node.add_service(
|
||||
service_attributes
|
||||
)
|
||||
|
||||
for x in range(5):
|
||||
service_node.update_booting_status()
|
||||
|
||||
assert service_attributes.software_state == SoftwareState.GOOD
|
||||
assert service_node.hardware_state == expected_operating_state
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"operating_state, expected_operating_state",
|
||||
[
|
||||
(HardwareState.SHUTTING_DOWN, HardwareState.OFF)
|
||||
],
|
||||
)
|
||||
def test_node_shutdown_correctly(operating_state, expected_operating_state):
|
||||
"""
|
||||
Tests that a node shutdown correctly.
|
||||
"""
|
||||
active_node = ActiveNode(
|
||||
node_id = 0,
|
||||
name = "node",
|
||||
node_type = "COMPUTER",
|
||||
priority = "1",
|
||||
hardware_state = operating_state,
|
||||
ip_address = "192.168.0.1",
|
||||
software_state = SoftwareState.GOOD,
|
||||
file_system_state = "GOOD",
|
||||
config_values = 1,
|
||||
)
|
||||
|
||||
for x in range(5):
|
||||
active_node.update_shutdown_status()
|
||||
|
||||
assert active_node.hardware_state == expected_operating_state
|
||||
|
||||
|
||||
@@ -8,8 +8,9 @@ def test_rewards_are_being_penalised_at_each_step_function():
|
||||
|
||||
When the initial state is OFF compared to reference state which is ON.
|
||||
"""
|
||||
env, config_values = _get_primaite_env_from_config(
|
||||
main_config_path=TEST_CONFIG_ROOT / "one_node_states_on_off_main_config.yaml",
|
||||
env = _get_primaite_env_from_config(
|
||||
training_config_path=TEST_CONFIG_ROOT
|
||||
/ "one_node_states_on_off_main_config.yaml",
|
||||
lay_down_config_path=TEST_CONFIG_ROOT
|
||||
/ "one_node_states_on_off_lay_down_config.yaml",
|
||||
)
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import time
|
||||
|
||||
from primaite.common.enums import HardwareState
|
||||
from primaite.environment.primaite_env import Primaite
|
||||
from tests import TEST_CONFIG_ROOT
|
||||
from tests.conftest import _get_primaite_env_from_config
|
||||
|
||||
|
||||
def run_generic_set_actions(env, config_values):
|
||||
def run_generic_set_actions(env: Primaite):
|
||||
"""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):
|
||||
training_config = env.training_config
|
||||
for episode in range(0, training_config.num_episodes):
|
||||
for step in range(0, training_config.num_steps):
|
||||
# Send the observation space to the agent to get an action
|
||||
# TEMP - random action for now
|
||||
# action = env.blue_agent_action(obs)
|
||||
@@ -34,7 +36,7 @@ def run_generic_set_actions(env, config_values):
|
||||
break
|
||||
|
||||
# Introduce a delay between steps
|
||||
time.sleep(config_values.time_delay / 1000)
|
||||
time.sleep(training_config.time_delay / 1000)
|
||||
|
||||
# Reset the environment at the end of the episode
|
||||
# env.reset()
|
||||
@@ -44,13 +46,12 @@ def run_generic_set_actions(env, config_values):
|
||||
|
||||
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."""
|
||||
env, config_values = _get_primaite_env_from_config(
|
||||
main_config_path=TEST_CONFIG_ROOT / "single_action_space_main_config.yaml",
|
||||
lay_down_config_path=TEST_CONFIG_ROOT
|
||||
/ "single_action_space_lay_down_config.yaml",
|
||||
env = _get_primaite_env_from_config(
|
||||
training_config_path=TEST_CONFIG_ROOT / "single_action_space_main_config.yaml",
|
||||
lay_down_config_path=TEST_CONFIG_ROOT / "single_action_space_lay_down_config.yaml",
|
||||
)
|
||||
|
||||
run_generic_set_actions(env, config_values)
|
||||
run_generic_set_actions(env)
|
||||
|
||||
# Retrieve the action space dictionary values from environment
|
||||
env_action_space_dict = env.action_dict.values()
|
||||
@@ -75,14 +76,12 @@ def test_single_action_space_is_valid():
|
||||
|
||||
def test_agent_is_executing_actions_from_both_spaces():
|
||||
"""Test to ensure the blue agent is carrying out both kinds of operations (NODE & ACL)."""
|
||||
env, config_values = _get_primaite_env_from_config(
|
||||
main_config_path=TEST_CONFIG_ROOT
|
||||
/ "single_action_space_fixed_blue_actions_main_config.yaml",
|
||||
lay_down_config_path=TEST_CONFIG_ROOT
|
||||
/ "single_action_space_lay_down_config.yaml",
|
||||
env = _get_primaite_env_from_config(
|
||||
training_config_path=TEST_CONFIG_ROOT / "single_action_space_fixed_blue_actions_main_config.yaml",
|
||||
lay_down_config_path=TEST_CONFIG_ROOT / "single_action_space_lay_down_config.yaml",
|
||||
)
|
||||
# Run environment with specified fixed blue agent actions only
|
||||
run_generic_set_actions(env, config_values)
|
||||
run_generic_set_actions(env)
|
||||
# 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
|
||||
|
||||
36
tests/test_training_config.py
Normal file
36
tests/test_training_config.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# Crown Copyright (C) Dstl 2022. DEFCON 703. Shared in confidence.
|
||||
import yaml
|
||||
|
||||
from primaite.config import training_config
|
||||
from tests import TEST_CONFIG_ROOT
|
||||
|
||||
|
||||
def test_legacy_lay_down_config_yaml_conversion():
|
||||
"""Tests the conversion of legacy lay down config files."""
|
||||
legacy_path = TEST_CONFIG_ROOT / "legacy" / "legacy_training_config.yaml"
|
||||
new_path = TEST_CONFIG_ROOT / "legacy" / "new_training_config.yaml"
|
||||
|
||||
with open(legacy_path, "r") as file:
|
||||
legacy_dict = yaml.safe_load(file)
|
||||
|
||||
with open(new_path, "r") as file:
|
||||
new_dict = yaml.safe_load(file)
|
||||
|
||||
converted_dict = training_config.convert_legacy_training_config_dict(legacy_dict)
|
||||
|
||||
for key, value in new_dict.items():
|
||||
assert converted_dict[key] == value
|
||||
|
||||
|
||||
def test_create_config_values_main_from_file():
|
||||
"""Tests creating an instance of TrainingConfig from file."""
|
||||
new_path = TEST_CONFIG_ROOT / "legacy" / "new_training_config.yaml"
|
||||
|
||||
training_config.load(new_path)
|
||||
|
||||
|
||||
def test_create_config_values_main_from_legacy_file():
|
||||
"""Tests creating an instance of TrainingConfig from legacy file."""
|
||||
new_path = TEST_CONFIG_ROOT / "legacy" / "legacy_training_config.yaml"
|
||||
|
||||
training_config.load(new_path, legacy_file=True)
|
||||
Reference in New Issue
Block a user