diff --git a/.github/workflows/build-sphinx.yml b/.github/workflows/build-sphinx.yml index da20fbd3..4bfa4f4e 100644 --- a/.github/workflows/build-sphinx.yml +++ b/.github/workflows/build-sphinx.yml @@ -1,8 +1,8 @@ name: build-sphinx-to-github-pages env: - GITHUB_ACTOR: Autonomous-Resilient-Cyber-Defence - GITHUB_REPOSITORY: Autonomous-Resilient-Cyber-Defence/PrimAITE + GITHUB_ACTOR: {todo:fill in URL} + GITHUB_REPOSITORY: {todo:fill in URL}/PrimAITE GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN}} on: diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 1b85f4be..1e803d92 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -5,13 +5,11 @@ on: branches: - main - dev - - dev-gui - 'release/**' pull_request: branches: - main - dev - - dev-gui - 'release/**' jobs: build: @@ -19,7 +17,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10"] + python-version: ["3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v3 @@ -54,13 +52,6 @@ jobs: run: | primaite setup - - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. - flake8 . --count --exit-zero --max-complexity=10 --max-line-length=120 --statistics - - name: Run tests run: | pytest tests/ diff --git a/.gitignore b/.gitignore index 2ba8d4a7..e48dc5dc 100644 --- a/.gitignore +++ b/.gitignore @@ -148,7 +148,7 @@ cython_debug/ # IDE .idea/ -docs/source/primaite-dependencies.rst + .vscode/ # outputs diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0565efb0..3088dc1d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,10 +10,8 @@ repos: hooks: - id: check-yaml exclude: | - (?x)^( - .*/scenario_with_placeholders/.*| - .*/mini_scenario_with_simulation_variation/.* - )$ + | scenario_with_placeholders/ + | mini_scenario_with_simulation_variation/ - id: end-of-file-fixer - id: trailing-whitespace - id: check-added-large-files diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d70ebb3..bf5e75e4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,20 +4,20 @@ ### **Did you find a bug?** -* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/issues). -* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/issues/new?assignees=&labels=bug&projects=&template=bug_report.md&title=%5BBUG%5D+-+%3Cbug+title+goes+here%3E). Be sure to follow our bug report template with the headers **Describe the bug**, **To Reproduce**, **Expected behaviour**, **Screenshots/Outputs**, **Environment**, and **Additional context** +* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/{todo:fill in URL}/PrimAITE/issues). +* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/{todo:fill in URL}/PrimAITE/issues/new?assignees=&labels=bug&projects=&template=bug_report.md&title=%5BBUG%5D+-+%3Cbug+title+goes+here%3E). Be sure to follow our bug report template with the headers **Describe the bug**, **To Reproduce**, **Expected behaviour**, **Screenshots/Outputs**, **Environment**, and **Additional context** ### **Do you have a solution to fix the bug?** -* [Fork the repository](https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/fork). +* [Fork the repository](https://github.com/{todo:fill in URL}/PrimAITE/fork). * Install the pre-commit hook with `pre-commit install`. * Implement the bug fix. * Update documentation where applicable. * Update the **UNRELEASED** section of the [CHANGELOG.md](CHANGELOG.md) file * Write a suitable test/tests. -* Commit the bug fix to the dev branch on your fork. If the bug has an open issue under [Issues](https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/issues), reference the issue in the commit message (e.g. #1 references issue 1). -* Submit a pull request from your dev branch to the Autonomous-Resilient-Cyber-Defence/PrimAITE dev branch. Again, if the bug has an open issue under [Issues](https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/issues), reference the issue in the pull request description. +* Commit the bug fix to the dev branch on your fork. If the bug has an open issue under [Issues](https://github.com/{todo:fill in URL}/PrimAITE/issues), reference the issue in the commit message (e.g. #1 references issue 1). +* Submit a pull request from your dev branch to the {todo:fill in URL}/PrimAITE dev branch. Again, if the bug has an open issue under [Issues](https://github.com/{todo:fill in URL}/PrimAITE/issues), reference the issue in the pull request description. ### **Did you fix whitespace, format code, or make a purely cosmetic patch?** @@ -25,7 +25,7 @@ Changes that are cosmetic in nature and do not add anything substantial to the s ### **Do you intend to add a new feature or change an existing one?** -* Submit a [feature request issue](https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/issues/new?assignees=&labels=feature_request&projects=&template=feature_request.md&title=%5BREQUEST%5D+-+%3Crequest+title+goes+here%3E). +* Submit a [feature request issue](https://github.com/{todo:fill in URL}/PrimAITE/issues/new?assignees=&labels=feature_request&projects=&template=feature_request.md&title=%5BREQUEST%5D+-+%3Crequest+title+goes+here%3E). * Know how to implement the new feature or change? Follow the same steps in the bug fix section above to fork, build, document, test, commit, and submit a pull request. ### **Do you have questions about the source code?** diff --git a/LICENSE b/LICENSE index 93d6f98b..9575f430 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,27 @@ -MIT License +MIT License License -Copyright (c) 2023 - 2025 Defence Science and Technology Laboratory UK (https://dstl.gov.uk) +MIT License Conditions -Permission is hereby granted, free of charge, to any person obtaining a copy +These MIT License conditions confirm the provision of the following artefacts as MIT License by Defence Science and Technology of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights +request to the QQ or FNC mailbox): + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +- Use Case Release Packs furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +Suppliers are required to read and confirm acceptance of the {todo:fill in URL} Foundry SyOPs (https://github.com/{todo:fill in URL}/foundry-syops) before being admitted access to material hosted on the {todo:fill in URL} Foundry GitHub site. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + +The material is supplied in confidence to QQ / FNC and their subcontractors under SERAPIS, and is issued to inform only those OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +of DSTL. The material must be stored and protected appropriately. All material must be destroyed at the end of the task. + diff --git a/README.md b/README.md index 68a8488b..137852f5 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Currently, the PrimAITE wheel can only be installed from GitHub. This may change #### Windows (PowerShell) **Prerequisites:** -* Manual install of Python >= 3.8 < 3.12 +* Manual install of Python >= 3.9 < 3.12 **Install:** @@ -43,7 +43,7 @@ cd ~\primaite python3 -m venv .venv attrib +h .venv /s /d # Hides the .venv directory .\.venv\Scripts\activate -pip install primaite-3.0.0-py3-none-any.whl[rl] +pip install primaite-{VERSION}-py3-none-any.whl[rl] primaite setup ``` @@ -66,7 +66,7 @@ mkdir ~/primaite cd ~/primaite python3 -m venv .venv source .venv/bin/activate -pip install primaite-3.0.0-py3-none-any.whl[rl] +pip install primaite-{VERSION}-py3-none-any.whl[rl] primaite setup ``` @@ -77,7 +77,7 @@ To make your own changes to PrimAITE, perform the install from source (developer #### 1. Clone the PrimAITE repository ``` unix -git clone git@github.com:Autonomous-Resilient-Cyber-Defence/PrimAITE.git +git clone git@github.com:{todo:fill in URL}/PrimAITE.git ``` #### 2. CD into the repo directory diff --git a/docs/Makefile b/docs/Makefile index fcf64a6a..99e19d16 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK # Minimal makefile for Sphinx documentation # You can set these variables from the command line, and also # from the environment for the first two. diff --git a/docs/build-sphinx-docs-to-github-pages.sh b/docs/build-sphinx-docs-to-github-pages.sh index f1d40647..9e43a2b4 100644 --- a/docs/build-sphinx-docs-to-github-pages.sh +++ b/docs/build-sphinx-docs-to-github-pages.sh @@ -1,3 +1,4 @@ +# © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK #!/bin/bash set -x @@ -42,7 +43,7 @@ touch .nojekyll # Add README cat > README.md < Any: This allows developers to create new notebooks without having to worry about updating documentation when a new notebook is included within PrimAITE. """ - notebook_asset_types = [".ipynb", ".png"] + notebook_asset_types = [".ipynb", ".png", ".svg"] notebook_directories = [] # find paths where notebooks are contained diff --git a/docs/make.bat b/docs/make.bat index a341af57..807fe3da 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -1,4 +1,5 @@ @ECHO OFF +REM © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK setlocal EnableDelayedExpansion diff --git a/docs/source/example_notebooks.rst b/docs/source/example_notebooks.rst index 731ea566..466beca3 100644 --- a/docs/source/example_notebooks.rst +++ b/docs/source/example_notebooks.rst @@ -77,6 +77,6 @@ The following extensions should now be installed :width: 300 :align: center -VSCode will then ask for a Python environment version to use. PrimAITE is compatible with Python versions 3.8 - 3.11 +VSCode will then ask for a Python environment version to use. PrimAITE is compatible with Python versions 3.9 - 3.11 You should now be able to interact with the notebook. diff --git a/docs/source/game_layer.rst b/docs/source/game_layer.rst index a4b14e94..2fa6639f 100644 --- a/docs/source/game_layer.rst +++ b/docs/source/game_layer.rst @@ -85,7 +85,6 @@ blue_agent: weight: 1.0 options: agent_name: client_2_green_user - ``` When defining agent reward sharing, users must be careful to avoid circular references, as that would lead to an infinite calculation loop. PrimAITE will prevent circular dependencies and provide a helpful error message if they are detected in the yaml. diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 28630cb4..ded92c60 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -113,7 +113,7 @@ For example: .. code-block:: bash - git clone https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE + git clone https://github.com/{todo:fill in URL}/PrimAITE cd primaite 2. Create and activate your Python virtual environment (venv) diff --git a/pyproject.toml b/pyproject.toml index 290720bc..31ce5312 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,17 +7,15 @@ name = "primaite" description = "PrimAITE (Primary-level AI Training Environment) is a simulation environment for training AI under the ARCD programme." authors = [{name="Defence Science and Technology Laboratory UK", email="oss@dstl.gov.uk"}] license = {file = "LICENSE"} -requires-python = ">=3.8, <3.12" +requires-python = ">=3.9, <3.12" dynamic = ["version", "readme"] classifiers = [ - "License :: OSI Approved :: MIT License", "Development Status :: 5 - Production/Stable", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS", "Operating System :: POSIX :: Linux", "Operating System :: Unix", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -91,7 +89,7 @@ order_by_type = "False" line-length = 120 [project.urls] -Homepage = "https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE" -Documentation = "https://Autonomous-Resilient-Cyber-Defence.github.io/PrimAITE/" -Repository = "https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE" -Changelog = "https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE/blob/dev/CHANGELOG.md" +Homepage = "https://github.com/{todo:fill in URL}/PrimAITE" +Documentation = "https://{todo:fill in URL}.github.io/PrimAITE" +Repository = "https://github.com/{todo:fill in URL}/PrimAITE" +Changelog = "https://github.com/{todo:fill in URL}/PrimAITE/blob/main/CHANGELOG.md" diff --git a/setup.cfg b/setup.cfg index e46aafd6..9c0cb0e6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,4 +1,4 @@ [metadata] -url = https://github.com/Autonomous-Resilient-Cyber-Defence/PrimAITE +url = https://github.com/{todo:fill in URL}/PrimAITE author = Defence Science and Technology Laboratory UK author_email = oss@dstl.gov.uk diff --git a/src/primaite/__init__.py b/src/primaite/__init__.py index 1048faff..8dd84428 100644 --- a/src/primaite/__init__.py +++ b/src/primaite/__init__.py @@ -203,3 +203,6 @@ def getLogger(name: str) -> Logger: # noqa logger.setLevel(PRIMAITE_CONFIG["logging"]["log_level"]) return logger + + +DEFAULT_BANDWIDTH: Final[int] = 100 diff --git a/src/primaite/config/_package_data/data_manipulation.yaml b/src/primaite/config/_package_data/data_manipulation.yaml index 6cded5f2..1ff24abe 100644 --- a/src/primaite/config/_package_data/data_manipulation.yaml +++ b/src/primaite/config/_package_data/data_manipulation.yaml @@ -476,7 +476,7 @@ agents: 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -489,7 +489,7 @@ agents: 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -502,7 +502,7 @@ agents: 48: # old action num: 24 # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -515,7 +515,7 @@ agents: 49: # old action num: 25 # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -528,7 +528,7 @@ agents: 50: # old action num: 26 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -541,7 +541,7 @@ agents: 51: # old action num: 27 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -554,52 +554,52 @@ agents: 52: # old action num: 28 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 53: # old action num: 29 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 54: # old action num: 30 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 55: # old action num: 31 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 56: # old action num: 32 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 57: # old action num: 33 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 58: # old action num: 34 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 59: # old action num: 35 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 60: # old action num: 36 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 61: # old action num: 37 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 62: # old action num: 38 action: "HOST_NIC_DISABLE" diff --git a/src/primaite/config/_package_data/data_manipulation_marl.yaml b/src/primaite/config/_package_data/data_manipulation_marl.yaml index 45779036..2e8221a0 100644 --- a/src/primaite/config/_package_data/data_manipulation_marl.yaml +++ b/src/primaite/config/_package_data/data_manipulation_marl.yaml @@ -470,7 +470,7 @@ agents: 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -483,7 +483,7 @@ agents: 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -496,7 +496,7 @@ agents: 48: # old action num: 24 # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -509,7 +509,7 @@ agents: 49: # old action num: 25 # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -522,7 +522,7 @@ agents: 50: # old action num: 26 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -535,7 +535,7 @@ agents: 51: # old action num: 27 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -548,52 +548,52 @@ agents: 52: # old action num: 28 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 53: # old action num: 29 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 54: # old action num: 30 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 55: # old action num: 31 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 56: # old action num: 32 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 57: # old action num: 33 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 58: # old action num: 34 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 59: # old action num: 35 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 60: # old action num: 36 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 61: # old action num: 37 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 62: # old action num: 38 action: "HOST_NIC_DISABLE" @@ -834,10 +834,10 @@ agents: - type: NODE_RESET - type: ROUTER_ACL_ADDRULE options: - target_router_nodename: router_1 + target_router: router_1 - type: ROUTER_ACL_REMOVERULE options: - target_router_nodename: router_1 + target_router: router_1 - type: HOST_NIC_ENABLE - type: HOST_NIC_DISABLE @@ -1053,7 +1053,7 @@ agents: 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -1066,7 +1066,7 @@ agents: 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -1079,7 +1079,7 @@ agents: 48: # old action num: 24 # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -1092,7 +1092,7 @@ agents: 49: # old action num: 25 # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -1105,7 +1105,7 @@ agents: 50: # old action num: 26 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -1118,7 +1118,7 @@ agents: 51: # old action num: 27 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -1131,52 +1131,52 @@ agents: 52: # old action num: 28 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 53: # old action num: 29 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 54: # old action num: 30 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 55: # old action num: 31 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 56: # old action num: 32 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 57: # old action num: 33 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 58: # old action num: 34 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 59: # old action num: 35 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 60: # old action num: 36 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 61: # old action num: 37 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 62: # old action num: 38 action: "HOST_NIC_DISABLE" diff --git a/src/primaite/game/agent/actions.py b/src/primaite/game/agent/actions.py index f63926c2..e165c9ad 100644 --- a/src/primaite/game/agent/actions.py +++ b/src/primaite/game/agent/actions.py @@ -11,9 +11,10 @@ AbstractAction. The ActionManager is responsible for: """ import itertools from abc import ABC, abstractmethod -from typing import Dict, List, Optional, Tuple, TYPE_CHECKING, Union +from typing import Dict, List, Literal, Optional, Tuple, TYPE_CHECKING, Union from gymnasium import spaces +from pydantic import BaseModel, Field, field_validator, ValidationInfo from primaite import getLogger @@ -321,12 +322,12 @@ class NodeFileCreateAction(AbstractAction): super().__init__(manager, num_nodes=num_nodes, num_folders=num_folders, **kwargs) self.verb: str = "create" - def form_request(self, node_id: int, folder_name: str, file_name: str) -> List[str]: + def form_request(self, node_id: int, folder_name: str, file_name: str, force: Optional[bool] = False) -> List[str]: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" node_name = self.manager.get_node_name_by_idx(node_id) if node_name is None or folder_name is None or file_name is None: return ["do_nothing"] - return ["network", "node", node_name, "file_system", "create", "file", folder_name, file_name] + return ["network", "node", node_name, "file_system", "create", "file", folder_name, file_name, force] class NodeFolderCreateAction(AbstractAction): @@ -493,6 +494,47 @@ class NodeResetAction(NodeAbstractAction): class RouterACLAddRuleAction(AbstractAction): """Action which adds a rule to a router's ACL.""" + class ACLRuleOptions(BaseModel): + """Validator for ACL_ADD_RULE options.""" + + target_router: str + """On which router to add the rule, must be specified.""" + position: int + """At what position to add the rule, must be specified.""" + permission: Literal[1, 2] + """Whether to allow or deny traffic, must be specified. 1 = PERMIT, 2 = DENY.""" + source_ip_id: int = Field(default=1, ge=1) + """Rule source IP address. By default, all ip addresses.""" + source_wildcard_id: int = Field(default=0, ge=0) + """Rule source IP wildcard. By default, use the wildcard at index 0 from action manager.""" + source_port_id: int = Field(default=1, ge=1) + """Rule source port. By default, all source ports.""" + dest_ip_id: int = Field(default=1, ge=1) + """Rule destination IP address. By default, all ip addresses.""" + dest_wildcard_id: int = Field(default=0, ge=0) + """Rule destination IP wildcard. By default, use the wildcard at index 0 from action manager.""" + dest_port_id: int = Field(default=1, ge=1) + """Rule destination port. By default, all destination ports.""" + protocol_id: int = Field(default=1, ge=1) + """Rule protocol. By default, all protocols.""" + + @field_validator( + "source_ip_id", + "source_port_id", + "source_wildcard_id", + "dest_ip_id", + "dest_port_id", + "dest_wildcard_id", + "protocol_id", + mode="before", + ) + @classmethod + def not_none(cls, v: str, info: ValidationInfo) -> int: + """If None is passed, use the default value instead.""" + if v is None: + return cls.model_fields[info.field_name].default + return v + def __init__( self, manager: "ActionManager", @@ -529,7 +571,7 @@ class RouterACLAddRuleAction(AbstractAction): def form_request( self, - target_router_nodename: str, + target_router: str, position: int, permission: int, source_ip_id: int, @@ -541,62 +583,63 @@ class RouterACLAddRuleAction(AbstractAction): protocol_id: int, ) -> List[str]: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" - if permission == 0: - permission_str = "UNUSED" - return ["do_nothing"] # NOT SUPPORTED, JUST DO NOTHING IF WE COME ACROSS THIS - elif permission == 1: + # Validate incoming data. + parsed_options = RouterACLAddRuleAction.ACLRuleOptions( + target_router=target_router, + position=position, + permission=permission, + source_ip_id=source_ip_id, + source_wildcard_id=source_wildcard_id, + dest_ip_id=dest_ip_id, + dest_wildcard_id=dest_wildcard_id, + source_port_id=source_port_id, + dest_port_id=dest_port_id, + protocol_id=protocol_id, + ) + if parsed_options.permission == 1: permission_str = "PERMIT" - elif permission == 2: + elif parsed_options.permission == 2: permission_str = "DENY" else: _LOGGER.warning(f"{self.__class__} received permission {permission}, expected 0 or 1.") - if protocol_id == 0: - return ["do_nothing"] # NOT SUPPORTED, JUST DO NOTHING IF WE COME ACROSS THIS - - if protocol_id == 1: + if parsed_options.protocol_id == 1: protocol = "ALL" else: - protocol = self.manager.get_internet_protocol_by_idx(protocol_id - 2) + protocol = self.manager.get_internet_protocol_by_idx(parsed_options.protocol_id - 2) # subtract 2 to account for UNUSED=0 and ALL=1. - if source_ip_id == 0: - return ["do_nothing"] # invalid formulation - elif source_ip_id == 1: + if parsed_options.source_ip_id == 1: src_ip = "ALL" else: - src_ip = self.manager.get_ip_address_by_idx(source_ip_id - 2) + src_ip = self.manager.get_ip_address_by_idx(parsed_options.source_ip_id - 2) # subtract 2 to account for UNUSED=0, and ALL=1 - src_wildcard = self.manager.get_wildcard_by_idx(source_wildcard_id) - if source_port_id == 0: - return ["do_nothing"] # invalid formulation - elif source_port_id == 1: + + src_wildcard = self.manager.get_wildcard_by_idx(parsed_options.source_wildcard_id) + + if parsed_options.source_port_id == 1: src_port = "ALL" else: - src_port = self.manager.get_port_by_idx(source_port_id - 2) + src_port = self.manager.get_port_by_idx(parsed_options.source_port_id - 2) # subtract 2 to account for UNUSED=0, and ALL=1 - if dest_ip_id == 0: - return ["do_nothing"] # invalid formulation - elif dest_ip_id == 1: + if parsed_options.dest_ip_id == 1: dst_ip = "ALL" else: - dst_ip = self.manager.get_ip_address_by_idx(dest_ip_id - 2) + dst_ip = self.manager.get_ip_address_by_idx(parsed_options.dest_ip_id - 2) # subtract 2 to account for UNUSED=0, and ALL=1 - dst_wildcard = self.manager.get_wildcard_by_idx(dest_wildcard_id) + dst_wildcard = self.manager.get_wildcard_by_idx(parsed_options.dest_wildcard_id) - if dest_port_id == 0: - return ["do_nothing"] # invalid formulation - elif dest_port_id == 1: + if parsed_options.dest_port_id == 1: dst_port = "ALL" else: - dst_port = self.manager.get_port_by_idx(dest_port_id - 2) + dst_port = self.manager.get_port_by_idx(parsed_options.dest_port_id - 2) # subtract 2 to account for UNUSED=0, and ALL=1 return [ "network", "node", - target_router_nodename, + target_router, "acl", "add_rule", permission_str, @@ -625,9 +668,9 @@ class RouterACLRemoveRuleAction(AbstractAction): super().__init__(manager=manager) self.shape: Dict[str, int] = {"position": max_acl_rules} - def form_request(self, target_router_nodename: str, position: int) -> List[str]: + def form_request(self, target_router: str, position: int) -> List[str]: """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" - return ["network", "node", target_router_nodename, "acl", "remove_rule", position] + return ["network", "node", target_router, "acl", "remove_rule", position] class FirewallACLAddRuleAction(AbstractAction): @@ -877,7 +920,10 @@ class NodeNMAPPingScanAction(AbstractAction): def __init__(self, manager: "ActionManager", **kwargs) -> None: super().__init__(manager=manager) - def form_request(self, source_node: str, target_ip_address: Union[str, List[str]]) -> List[str]: # noqa + def form_request( + self, source_node: str, target_ip_address: Union[str, List[str]], show: Optional[bool] = False + ) -> List[str]: # noqa + """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" return [ "network", "node", @@ -885,7 +931,7 @@ class NodeNMAPPingScanAction(AbstractAction): "application", "NMAP", "ping_scan", - {"target_ip_address": target_ip_address}, + {"target_ip_address": target_ip_address, "show": show}, ] @@ -901,6 +947,7 @@ class NodeNMAPPortScanAction(AbstractAction): target_ip_address: Union[str, List[str]], target_protocol: Optional[Union[str, List[str]]] = None, target_port: Optional[Union[str, List[str]]] = None, + show: Optional[bool] = False, ) -> List[str]: # noqa """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" return [ @@ -910,7 +957,12 @@ class NodeNMAPPortScanAction(AbstractAction): "application", "NMAP", "port_scan", - {"target_ip_address": target_ip_address, "target_port": target_port, "target_protocol": target_protocol}, + { + "target_ip_address": target_ip_address, + "target_port": target_port, + "target_protocol": target_protocol, + "show": show, + }, ] @@ -926,6 +978,7 @@ class NodeNetworkServiceReconAction(AbstractAction): target_ip_address: Union[str, List[str]], target_protocol: Optional[Union[str, List[str]]] = None, target_port: Optional[Union[str, List[str]]] = None, + show: Optional[bool] = False, ) -> List[str]: # noqa """Return the action formatted as a request which can be ingested by the PrimAITE simulation.""" return [ @@ -935,7 +988,12 @@ class NodeNetworkServiceReconAction(AbstractAction): "application", "NMAP", "network_service_recon", - {"target_ip_address": target_ip_address, "target_port": target_port, "target_protocol": target_protocol}, + { + "target_ip_address": target_ip_address, + "target_port": target_port, + "target_protocol": target_protocol, + "show": show, + }, ] diff --git a/src/primaite/game/agent/interface.py b/src/primaite/game/agent/interface.py index 43ca2dc9..95468331 100644 --- a/src/primaite/game/agent/interface.py +++ b/src/primaite/game/agent/interface.py @@ -107,6 +107,8 @@ class AbstractAgent(ABC): :type observation_space: Optional[ObservationSpace] :param reward_function: Reward function for the agent. :type reward_function: Optional[RewardFunction] + :param agent_settings: Configurable Options for Abstracted Agents + :type agent_settings: Optional[AgentSettings] """ self.agent_name: str = agent_name or "unnamed_agent" self.action_manager: Optional[ActionManager] = action_space diff --git a/src/primaite/game/game.py b/src/primaite/game/game.py index 2a889993..8a79d068 100644 --- a/src/primaite/game/game.py +++ b/src/primaite/game/game.py @@ -5,7 +5,7 @@ from typing import Dict, List, Optional from pydantic import BaseModel, ConfigDict -from primaite import getLogger +from primaite import DEFAULT_BANDWIDTH, getLogger from primaite.game.agent.actions import ActionManager from primaite.game.agent.interface import AbstractAgent, AgentSettings, ProxyAgent from primaite.game.agent.observations.observation_manager import ObservationManager @@ -406,7 +406,7 @@ class PrimaiteGame: for link_cfg in links_cfg: node_a = net.get_node_by_hostname(link_cfg["endpoint_a_hostname"]) node_b = net.get_node_by_hostname(link_cfg["endpoint_b_hostname"]) - bandwidth = link_cfg.get("bandwidth", 100) # default value if not configured + bandwidth = link_cfg.get("bandwidth", DEFAULT_BANDWIDTH) # default value if not configured if isinstance(node_a, Switch): endpoint_a = node_a.network_interface[link_cfg["endpoint_a_port"]] diff --git a/src/primaite/interface/request.py b/src/primaite/interface/request.py index 41875779..1a9f0e5f 100644 --- a/src/primaite/interface/request.py +++ b/src/primaite/interface/request.py @@ -1,7 +1,7 @@ # © Crown-owned copyright 2024, Defence Science and Technology Laboratory UK from typing import Dict, ForwardRef, List, Literal, Union -from pydantic import BaseModel, ConfigDict, StrictBool, validate_call +from pydantic import BaseModel, ConfigDict, StrictBool # , validate_call RequestFormat = List[Union[str, int, float, Dict]] @@ -31,7 +31,7 @@ class RequestResponse(BaseModel): # much. However, in the future we might consider making them mandatory. @classmethod - @validate_call + # @validate_call # this slows down execution quite a bit. def from_bool(cls, status_bool: StrictBool) -> RequestResponse: """ Construct a basic request response from a boolean. diff --git a/src/primaite/notebooks/Data-Manipulation-Customising-Red-Agent.ipynb b/src/primaite/notebooks/Data-Manipulation-Customising-Red-Agent.ipynb index 33d56fb0..dd5def9e 100644 --- a/src/primaite/notebooks/Data-Manipulation-Customising-Red-Agent.ipynb +++ b/src/primaite/notebooks/Data-Manipulation-Customising-Red-Agent.ipynb @@ -458,7 +458,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.10.11" } }, "nbformat": 4, diff --git a/src/primaite/notebooks/Requests-and-Responses.ipynb b/src/primaite/notebooks/Requests-and-Responses.ipynb index ca9f02f5..da614c93 100644 --- a/src/primaite/notebooks/Requests-and-Responses.ipynb +++ b/src/primaite/notebooks/Requests-and-Responses.ipynb @@ -6,9 +6,9 @@ "source": [ "# Requests and Responses\n", "\n", - "Agents interact with the PrimAITE simulation via the Request system.\n", + "© Crown-owned copyright 2024, Defence Science and Technology Laboratory UK\n", "\n", - "© Crown-owned copyright 2024, Defence Science and Technology Laboratory UK\n" + "Agents interact with the PrimAITE simulation via the Request system.\n" ] }, { diff --git a/src/primaite/notebooks/Using-Episode-Schedules.ipynb b/src/primaite/notebooks/Using-Episode-Schedules.ipynb index e04fd6da..14012264 100644 --- a/src/primaite/notebooks/Using-Episode-Schedules.ipynb +++ b/src/primaite/notebooks/Using-Episode-Schedules.ipynb @@ -423,7 +423,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.10.11" } }, "nbformat": 4, diff --git a/src/primaite/session/environment.py b/src/primaite/session/environment.py index 2a0f40ca..6cc1282f 100644 --- a/src/primaite/session/environment.py +++ b/src/primaite/session/environment.py @@ -60,7 +60,7 @@ class PrimaiteGymEnv(gymnasium.Env): next_obs = self._get_obs() # this doesn't update observation, just gets the current observation reward = self.agent.reward_function.current_reward - _LOGGER.info(f"step: {self.game.step_counter}, Blue reward: {reward}") + _LOGGER.debug(f"step: {self.game.step_counter}, Blue reward: {reward}") terminated = False truncated = self.game.calculate_truncated() info = { diff --git a/src/primaite/setup/reset_demo_notebooks.py b/src/primaite/setup/reset_demo_notebooks.py index 8b54341d..f17fb211 100644 --- a/src/primaite/setup/reset_demo_notebooks.py +++ b/src/primaite/setup/reset_demo_notebooks.py @@ -45,11 +45,7 @@ def run(overwrite_existing: bool = True) -> None: shutil.copy2(src_fp, dst_fp) _LOGGER.info(f"Reset example notebook: {dst_fp}") - for src_fp in primaite_root.glob("notebooks/_package_data/*"): - dst_fp = example_notebooks_user_dir / "_package_data" / src_fp.name - if should_copy_file(src_fp, dst_fp, overwrite_existing): - if not Path.exists(example_notebooks_user_dir / "_package_data/"): - Path.mkdir(example_notebooks_user_dir / "_package_data/") - print(dst_fp) - shutil.copy2(src_fp, dst_fp) - _LOGGER.info(f"Copied notebook resource to: {dst_fp}") + src = primaite_root / "notebooks/_package_data/" + dst = example_notebooks_user_dir / "_package_data/" + + shutil.copytree(src, dst, dirs_exist_ok=True) diff --git a/src/primaite/simulator/core.py b/src/primaite/simulator/core.py index 551a30b7..8c7d64c9 100644 --- a/src/primaite/simulator/core.py +++ b/src/primaite/simulator/core.py @@ -221,7 +221,7 @@ class SimComponent(BaseModel): } return state - @validate_call + # @validate_call # this slows down execution quite a bit. def apply_request(self, request: RequestFormat, context: Optional[Dict] = None) -> RequestResponse: """ Apply a request to a simulation component. Request data is passed in as a 'namespaced' list of strings. diff --git a/src/primaite/simulator/file_system/file.py b/src/primaite/simulator/file_system/file.py index d4760426..ba39c791 100644 --- a/src/primaite/simulator/file_system/file.py +++ b/src/primaite/simulator/file_system/file.py @@ -6,6 +6,8 @@ import json import warnings from typing import Dict, Optional +from prettytable import MARKDOWN, PrettyTable + from primaite import getLogger from primaite.simulator.file_system.file_system_item_abc import FileSystemItemABC, FileSystemItemHealthStatus from primaite.simulator.file_system.file_type import FileType, get_file_type_from_extension @@ -203,3 +205,18 @@ class File(FileSystemItemABC): self.deleted = True self.sys_log.info(f"File deleted {self.folder_name}/{self.name}") return True + + def show(self, markdown: bool = False): + """ + Prints a table of the file, displaying the file type, name and the file's access count. + + :param markdown: Flag indicating if output should be in markdown format. + """ + headers = ["File Name", "File Type", "Number of Accesses"] + table = PrettyTable(headers) + if markdown: + table.set_style(MARKDOWN) + table.align = "l" + table.title = f"{self.name}" + table.add_row([self.name, self.file_type.name, self.num_access]) + print(table) diff --git a/src/primaite/simulator/file_system/file_system.py b/src/primaite/simulator/file_system/file_system.py index 95460e1c..456b800c 100644 --- a/src/primaite/simulator/file_system/file_system.py +++ b/src/primaite/simulator/file_system/file_system.py @@ -67,7 +67,7 @@ class FileSystem(SimComponent): self._create_manager = RequestManager() def _create_file_action(request: List[Any], context: Any) -> RequestResponse: - file = self.create_file(folder_name=request[0], file_name=request[1]) + file = self.create_file(folder_name=request[0], file_name=request[1], force=request[2]) if not file: return RequestResponse.from_bool(False) return RequestResponse( @@ -75,7 +75,7 @@ class FileSystem(SimComponent): data={ "file_name": file.name, "folder_name": file.folder_name, - "file_type": file.file_type, + "file_type": file.file_type.name, "file_size": file.size, }, ) @@ -111,9 +111,9 @@ class FileSystem(SimComponent): data={ "file_name": file.name, "folder_name": file.folder_name, - "file_type": file.file_type, + "file_type": file.file_type.name, "file_size": file.size, - "file_status": file.health_status, + "file_status": file.health_status.name, }, ) return RequestResponse.from_bool(False) @@ -160,6 +160,21 @@ class FileSystem(SimComponent): """ return sum(folder.size for folder in self.folders.values()) + def show_num_files(self, markdown: bool = False): + """ + Prints a table showing a host's number of file creations & deletions. + + :param markdown: Flag indicating if output should be in markdown format. + """ + headers = ["File creations", "File deletions"] + table = PrettyTable(headers) + if markdown: + table.set_style(MARKDOWN) + table.align = "l" + table.title = f"{self.sys_log.hostname} Number of Creations & Deletions" + table.add_row([self.num_file_creations, self.num_file_deletions]) + print(table) + def show(self, markdown: bool = False, full: bool = False): """ Prints a table of the FileSystem, displaying either just folders or full files. @@ -167,7 +182,7 @@ class FileSystem(SimComponent): :param markdown: Flag indicating if output should be in markdown format. :param full: Flag indicating if to show full files. """ - headers = ["Folder", "Size", "Deleted"] + headers = ["Folder", "Size", "Health status", "Visible health status", "Deleted"] if full: headers[0] = "File Path" table = PrettyTable(headers) @@ -178,14 +193,38 @@ class FileSystem(SimComponent): folders = {**self.folders, **self.deleted_folders} for folder in folders.values(): if not full: - table.add_row([folder.name, folder.size_str, folder.deleted]) + table.add_row( + [ + folder.name, + folder.size_str, + folder.health_status.name, + folder.visible_health_status.name, + folder.deleted, + ] + ) else: files = {**folder.files, **folder.deleted_files} if not files: - table.add_row([folder.name, folder.size_str, folder.deleted]) + table.add_row( + [ + folder.name, + folder.size_str, + folder.health_status.name, + folder.visible_health_status.name, + folder.deleted, + ] + ) else: for file in files.values(): - table.add_row([file.path, file.size_str, file.deleted]) + table.add_row( + [ + file.path, + file.size_str, + file.health_status.name, + file.visible_health_status.name, + file.deleted, + ] + ) if full: print(table.get_string(sortby="File Path")) else: @@ -201,15 +240,15 @@ class FileSystem(SimComponent): :param folder_name: The name of the folder. """ # check if folder with name already exists - if self.get_folder(folder_name): - raise Exception(f"Cannot create folder as it already exists: {folder_name}") - - folder = Folder(name=folder_name, sys_log=self.sys_log) - + folder = self.get_folder(folder_name) + if folder: + self.sys_log.info(f"Cannot create folder as it already exists: {folder_name}") + else: + folder = Folder(name=folder_name, sys_log=self.sys_log) + self._folder_request_manager.add_request( + name=folder.name, request_type=RequestType(func=folder._request_manager) + ) self.folders[folder.uuid] = folder - self._folder_request_manager.add_request( - name=folder.name, request_type=RequestType(func=folder._request_manager) - ) return folder def delete_folder(self, folder_name: str) -> bool: @@ -289,6 +328,7 @@ class FileSystem(SimComponent): size: Optional[int] = None, file_type: Optional[FileType] = None, folder_name: Optional[str] = None, + force: Optional[bool] = False, ) -> File: """ Creates a File and adds it to the list of files. @@ -297,6 +337,7 @@ class FileSystem(SimComponent): :param size: The size the file takes on disk in bytes. :param file_type: The type of the file. :param folder_name: The folder to add the file to. + :param force: Replaces the file if it already exists. """ if folder_name: # check if file with name already exists @@ -308,17 +349,23 @@ class FileSystem(SimComponent): # Use root folder if folder_name not supplied folder = self.get_folder("root") - # Create the file and add it to the folder - file = File( - name=file_name, - sim_size=size, - file_type=file_type, - folder_id=folder.uuid, - folder_name=folder.name, - sim_root=self.sim_root, - sys_log=self.sys_log, - ) - folder.add_file(file) + file = self.get_file(folder, file_name) + if file: + self.sys_log.info(f"Cannot create file {file_name} as it already exists.") + if force: + self.sys_log.info(f"Replacing {file_name}") + else: + # Create the file and add it to the folder + file = File( + name=file_name, + sim_size=size, + file_type=file_type, + folder_id=folder.uuid, + folder_name=folder.name, + sim_root=self.sim_root, + sys_log=self.sys_log, + ) + folder.add_file(file, force=force) self._file_request_manager.add_request(name=file.name, request_type=RequestType(func=file._request_manager)) # increment file creation self.num_file_creations += 1 diff --git a/src/primaite/simulator/file_system/file_type.py b/src/primaite/simulator/file_system/file_type.py index 084acc6a..8f0cb778 100644 --- a/src/primaite/simulator/file_system/file_type.py +++ b/src/primaite/simulator/file_system/file_type.py @@ -96,6 +96,20 @@ class FileType(Enum): DB = 32 "Generic DB file. Used by sqlite3." + # Script file types + PS1 = 33 + "A Powershell script. Used in Windows operating systems." + BAT = 34 + "Windows batch file. Used in Windows operating systems." + SH = 35 + "Linux shell script. Used in Unix based operating systems." + + # Executable file types + PE = 36 + "Portable Executable. Used in Windows operating systems." + ELF = 37 + "Executable and Linkable Format. Used in Unix based operating systems." + @classmethod def _missing_(cls, value: Any) -> FileType: return cls.UNKNOWN @@ -116,8 +130,11 @@ class FileType(Enum): Returns 0 if a default size does not exist. """ - size = file_type_sizes_bytes[self] - return size if size else 0 + try: + size = file_type_sizes_bytes[self] + return size + except KeyError: + return 0 def get_file_type_from_extension(file_type_extension: str) -> FileType: diff --git a/src/primaite/simulator/network/hardware/base.py b/src/primaite/simulator/network/hardware/base.py index 21ba2060..01745215 100644 --- a/src/primaite/simulator/network/hardware/base.py +++ b/src/primaite/simulator/network/hardware/base.py @@ -11,6 +11,7 @@ from typing import Any, Dict, Optional, Type, TypeVar, Union from prettytable import MARKDOWN, PrettyTable from pydantic import BaseModel, Field +import primaite.simulator.network.nmne from primaite import getLogger from primaite.exceptions import NetworkError from primaite.interface.request import RequestResponse @@ -1049,7 +1050,7 @@ class Node(SimComponent): def show_nic(self, markdown: bool = False): """Prints a table of the NICs on the Node.""" - table = PrettyTable(["Port", "Type", "MAC Address", "Address", "Speed", "Status"]) + table = PrettyTable(["Port", "Type", "MAC Address", "Address", "Speed", "Status", "NMNE"]) if markdown: table.set_style(MARKDOWN) table.align = "l" @@ -1066,6 +1067,7 @@ class Node(SimComponent): ip_address, network_interface.speed, "Enabled" if network_interface.enabled else "Disabled", + network_interface.nmne if primaite.simulator.network.nmne.CAPTURE_NMNE else "Disabled", ] ) print(table) diff --git a/src/primaite/simulator/network/networks.py b/src/primaite/simulator/network/networks.py index 90146971..cb0965eb 100644 --- a/src/primaite/simulator/network/networks.py +++ b/src/primaite/simulator/network/networks.py @@ -185,7 +185,10 @@ def arcd_uc2_network() -> Network: db_client_2.run() web_browser_2 = client_2.software_manager.software.get("WebBrowser") web_browser_2.target_url = "http://arcd.com/users/" - network.connect(endpoint_b=client_2.network_interface[1], endpoint_a=switch_2.network_interface[2]) + network.connect( + endpoint_b=client_2.network_interface[1], + endpoint_a=switch_2.network_interface[2], + ) # Domain Controller domain_controller = Server( diff --git a/src/primaite/simulator/network/transmission/network_layer.py b/src/primaite/simulator/network/transmission/network_layer.py index b4fe6260..d493cbdf 100644 --- a/src/primaite/simulator/network/transmission/network_layer.py +++ b/src/primaite/simulator/network/transmission/network_layer.py @@ -25,6 +25,10 @@ class IPProtocol(Enum): ICMP = "icmp" """Internet Control Message Protocol.""" + def model_dump(self) -> str: + """Return as JSON-serialisable string.""" + return self.name + class Precedence(Enum): """ diff --git a/src/primaite/simulator/network/transmission/transport_layer.py b/src/primaite/simulator/network/transmission/transport_layer.py index 027c732e..7f0d2d7a 100644 --- a/src/primaite/simulator/network/transmission/transport_layer.py +++ b/src/primaite/simulator/network/transmission/transport_layer.py @@ -72,6 +72,10 @@ class Port(Enum): POSTGRES_SERVER = 5432 "Postgres SQL Server." + def model_dump(self) -> str: + """Return a json-serialisable string.""" + return self.name + class UDPHeader(BaseModel): """ diff --git a/src/primaite/simulator/system/applications/nmap.py b/src/primaite/simulator/system/applications/nmap.py index 77be57e5..d8af1b7b 100644 --- a/src/primaite/simulator/system/applications/nmap.py +++ b/src/primaite/simulator/system/applications/nmap.py @@ -87,7 +87,9 @@ class NMAP(Application): def _init_request_manager(self) -> RequestManager: def _ping_scan_action(request: List[Any], context: Any) -> RequestResponse: - results = self.ping_scan(target_ip_address=request[0]["target_ip_address"], json_serializable=True) + results = self.ping_scan( + target_ip_address=request[0]["target_ip_address"], show=request[0]["show"], json_serializable=True + ) if not self._can_perform_network_action(): return RequestResponse.from_bool(False) return RequestResponse( @@ -311,7 +313,6 @@ class NMAP(Application): self.sys_log.info( f"{self.name}: Responding to port scan request for port {payload.port.value} " f"({payload.port.name}) over {payload.protocol.name}", - True, ) self.software_manager.send_payload_to_session_manager(payload=payload, session_id=session_id) @@ -370,7 +371,8 @@ class NMAP(Application): port_open = self._check_port_open_on_ip_address(ip_address=ip_address, port=port, protocol=protocol) if port_open: - table.add_row([ip_address, port.value, port.name, protocol.name]) + if show: + table.add_row([ip_address, port.value, port.name, protocol.name]) _ip_address = ip_address if not json_serializable else str(ip_address) _protocol = protocol if not json_serializable else protocol.value _port = port if not json_serializable else port.value diff --git a/src/primaite/simulator/system/services/arp/arp.py b/src/primaite/simulator/system/services/arp/arp.py index efadf189..8319b18e 100644 --- a/src/primaite/simulator/system/services/arp/arp.py +++ b/src/primaite/simulator/system/services/arp/arp.py @@ -143,7 +143,7 @@ class ARP(Service): self.sys_log.info(f"Cannot send ARP request to a network address {str(target_ip_address)}") return if target_ip_address == outbound_network_interface.ip_network.broadcast_address: - self.sys_log.info(f"Cannot send ARP request to a broadcast address {str(target_ip_address)}") + self.sys_log.info(f"Cannot send ARP request to a broadcast addresss {str(target_ip_address)}") return self.sys_log.info(f"Sending ARP request from NIC {outbound_network_interface} for ip {target_ip_address}") diff --git a/src/primaite/simulator/system/services/icmp/icmp.py b/src/primaite/simulator/system/services/icmp/icmp.py index eeab80c9..6741d86a 100644 --- a/src/primaite/simulator/system/services/icmp/icmp.py +++ b/src/primaite/simulator/system/services/icmp/icmp.py @@ -61,7 +61,7 @@ class ICMP(Service): if target_ip_address.is_loopback: self.sys_log.info("Pinging loopback address") return any(network_interface.enabled for network_interface in self.network_interfaces.values()) - self.sys_log.info(f"Pinging {target_ip_address}:", to_terminal=True) + self.sys_log.info(f"Pinging {target_ip_address}:", to_terminal=False) sequence, identifier = 0, None while sequence < pings: sequence, identifier = self._send_icmp_echo_request(target_ip_address, sequence, identifier, pings) @@ -77,7 +77,7 @@ class ICMP(Service): f"Received = {request_replies}, " f"Lost = {pings - request_replies} ({(pings - request_replies) / pings * 100}% loss)" ) - self.sys_log.info(output, to_terminal=True) + self.sys_log.info(output, to_terminal=False) return passed @@ -167,7 +167,7 @@ class ICMP(Service): f"bytes={len(frame.payload)}, " f"time={time_str}, " f"TTL={frame.ip.ttl}", - to_terminal=True, + to_terminal=False, ) if not self.request_replies.get(frame.icmp.identifier): self.request_replies[frame.icmp.identifier] = 0 diff --git a/src/primaite/utils/session_metadata_parser.py b/src/primaite/utils/session_metadata_parser.py index acaf45b3..f6594666 100644 --- a/src/primaite/utils/session_metadata_parser.py +++ b/src/primaite/utils/session_metadata_parser.py @@ -3,7 +3,6 @@ raise DeprecationWarning( "Benchmarking depends on deprecated functionality and it has not been updated to primaite v3 yet." ) -# © Crown-owned copyright 2023, Defence Science and Technology Laboratory UK import json from pathlib import Path from typing import Any, Dict, Union diff --git a/tests/assets/configs/bad_primaite_session.yaml b/tests/assets/configs/bad_primaite_session.yaml index 231c69ab..8cbd3ae9 100644 --- a/tests/assets/configs/bad_primaite_session.yaml +++ b/tests/assets/configs/bad_primaite_session.yaml @@ -286,7 +286,7 @@ agents: 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -299,7 +299,7 @@ agents: 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -312,7 +312,7 @@ agents: 24: # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -325,7 +325,7 @@ agents: 25: # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -338,7 +338,7 @@ agents: 26: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -351,7 +351,7 @@ agents: 27: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -364,52 +364,52 @@ agents: 28: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 29: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 30: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 31: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 32: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 33: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 34: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 35: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 36: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 37: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 38: action: "HOST_NIC_DISABLE" diff --git a/tests/assets/configs/eval_only_primaite_session.yaml b/tests/assets/configs/eval_only_primaite_session.yaml index 4cf0e68c..de861dcc 100644 --- a/tests/assets/configs/eval_only_primaite_session.yaml +++ b/tests/assets/configs/eval_only_primaite_session.yaml @@ -298,7 +298,7 @@ agents: 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -311,7 +311,7 @@ agents: 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -324,7 +324,7 @@ agents: 24: # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -337,7 +337,7 @@ agents: 25: # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -350,7 +350,7 @@ agents: 26: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -363,7 +363,7 @@ agents: 27: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -376,52 +376,52 @@ agents: 28: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 29: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 30: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 31: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 32: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 33: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 34: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 35: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 36: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 37: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 38: action: "HOST_NIC_DISABLE" diff --git a/tests/assets/configs/multi_agent_session.yaml b/tests/assets/configs/multi_agent_session.yaml index 0c89bef4..971f36f8 100644 --- a/tests/assets/configs/multi_agent_session.yaml +++ b/tests/assets/configs/multi_agent_session.yaml @@ -289,7 +289,7 @@ agents: 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -302,7 +302,7 @@ agents: 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -315,7 +315,7 @@ agents: 24: # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -328,7 +328,7 @@ agents: 25: # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -341,7 +341,7 @@ agents: 26: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -354,7 +354,7 @@ agents: 27: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -367,52 +367,52 @@ agents: 28: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 29: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 30: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 31: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 32: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 33: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 34: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 35: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 36: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 37: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 38: action: "HOST_NIC_DISABLE" @@ -759,7 +759,7 @@ agents: 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -772,7 +772,7 @@ agents: 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -785,7 +785,7 @@ agents: 24: # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -798,7 +798,7 @@ agents: 25: # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -811,7 +811,7 @@ agents: 26: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -824,7 +824,7 @@ agents: 27: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -837,52 +837,52 @@ agents: 28: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 29: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 30: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 31: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 32: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 33: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 34: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 35: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 36: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 37: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 diff --git a/tests/assets/configs/shared_rewards.yaml b/tests/assets/configs/shared_rewards.yaml index c90e1cc2..81cb85f7 100644 --- a/tests/assets/configs/shared_rewards.yaml +++ b/tests/assets/configs/shared_rewards.yaml @@ -466,7 +466,7 @@ agents: 46: # old action num: 22 # "ACL: ADDRULE - Block outgoing traffic from client 1" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -479,7 +479,7 @@ agents: 47: # old action num: 23 # "ACL: ADDRULE - Block outgoing traffic from client 2" action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -492,7 +492,7 @@ agents: 48: # old action num: 24 # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -505,7 +505,7 @@ agents: 49: # old action num: 25 # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -518,7 +518,7 @@ agents: 50: # old action num: 26 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -531,7 +531,7 @@ agents: 51: # old action num: 27 action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -544,52 +544,52 @@ agents: 52: # old action num: 28 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 53: # old action num: 29 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 54: # old action num: 30 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 55: # old action num: 31 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 56: # old action num: 32 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 57: # old action num: 33 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 58: # old action num: 34 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 59: # old action num: 35 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 60: # old action num: 36 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 61: # old action num: 37 action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 62: # old action num: 38 action: "HOST_NIC_DISABLE" diff --git a/tests/assets/configs/test_primaite_session.yaml b/tests/assets/configs/test_primaite_session.yaml index f41ef475..54143af0 100644 --- a/tests/assets/configs/test_primaite_session.yaml +++ b/tests/assets/configs/test_primaite_session.yaml @@ -307,7 +307,7 @@ agents: 22: # "ACL: ADDRULE - Block outgoing traffic from client 1" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 permission: 2 source_ip_id: 7 # client 1 @@ -320,7 +320,7 @@ agents: 23: # "ACL: ADDRULE - Block outgoing traffic from client 2" (not supported in Primaite) action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 permission: 2 source_ip_id: 8 # client 2 @@ -333,7 +333,7 @@ agents: 24: # block tcp traffic from client 1 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 permission: 2 source_ip_id: 7 # client 1 @@ -346,7 +346,7 @@ agents: 25: # block tcp traffic from client 2 to web app action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 permission: 2 source_ip_id: 8 # client 2 @@ -359,7 +359,7 @@ agents: 26: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 permission: 2 source_ip_id: 7 # client 1 @@ -372,7 +372,7 @@ agents: 27: action: "ROUTER_ACL_ADDRULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 permission: 2 source_ip_id: 8 # client 2 @@ -385,52 +385,52 @@ agents: 28: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 0 29: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 1 30: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 2 31: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 3 32: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 4 33: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 5 34: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 6 35: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 7 36: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 8 37: action: "ROUTER_ACL_REMOVERULE" options: - target_router_nodename: router_1 + target_router: router_1 position: 9 38: action: "HOST_NIC_DISABLE" diff --git a/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py b/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py index 6eadc32f..96ec799c 100644 --- a/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py +++ b/tests/e2e_integration_tests/environments/test_rllib_multi_agent_environment.py @@ -39,3 +39,4 @@ def test_rllib_multi_agent_compatibility(): ), param_space=config, ).fit() + ray.shutdown() diff --git a/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py b/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py index 3caa7e04..d6cacfd2 100644 --- a/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py +++ b/tests/e2e_integration_tests/environments/test_rllib_single_agent_environment.py @@ -41,3 +41,4 @@ def test_rllib_single_agent_compatibility(): assert save_file.exists() save_file.unlink() # clean up + ray.shutdown() diff --git a/tests/integration_tests/configuration_file_parsing/nodes/test_node_config.py b/tests/integration_tests/configuration_file_parsing/nodes/test_node_config.py index f8c7d89f..8526ab78 100644 --- a/tests/integration_tests/configuration_file_parsing/nodes/test_node_config.py +++ b/tests/integration_tests/configuration_file_parsing/nodes/test_node_config.py @@ -45,5 +45,7 @@ def test_basic_config(): client_3: Computer = network.get_node_by_hostname("client_3") assert client_3.operating_state == NodeOperatingState.OFF + # Bandwidth should have non-default values + for link in network.links: assert network.links[link].bandwidth == 200 diff --git a/tests/integration_tests/game_layer/test_actions.py b/tests/integration_tests/game_layer/test_actions.py index 350714e9..0dcf125d 100644 --- a/tests/integration_tests/game_layer/test_actions.py +++ b/tests/integration_tests/game_layer/test_actions.py @@ -123,7 +123,7 @@ def test_router_acl_addrule_integration(game_and_agent: Tuple[PrimaiteGame, Prox action = ( "ROUTER_ACL_ADDRULE", { - "target_router_nodename": "router", + "target_router": "router", "position": 4, # 4th rule "permission": 2, # DENY "source_ip_id": 3, # 10.0.1.2 (client_1) @@ -150,7 +150,7 @@ def test_router_acl_addrule_integration(game_and_agent: Tuple[PrimaiteGame, Prox action = ( "ROUTER_ACL_ADDRULE", { - "target_router_nodename": "router", + "target_router": "router", "position": 5, # 5th rule "permission": 2, # DENY "source_ip_id": 5, # 10.0.2.2 (server_1) @@ -188,7 +188,7 @@ def test_router_acl_removerule_integration(game_and_agent: Tuple[PrimaiteGame, P action = ( "ROUTER_ACL_REMOVERULE", { - "target_router_nodename": "router", + "target_router": "router", "position": 3, # 4th rule }, ) diff --git a/tests/integration_tests/test_simulation/test_request_response.py b/tests/integration_tests/test_simulation/test_request_response.py index 204b9f8c..79c72339 100644 --- a/tests/integration_tests/test_simulation/test_request_response.py +++ b/tests/integration_tests/test_simulation/test_request_response.py @@ -21,7 +21,9 @@ def test_successful_node_file_system_creation_request(example_network): client_1 = example_network.get_node_by_hostname("client_1") assert client_1.file_system.get_file(folder_name="root", file_name="test.txt") is None - response = example_network.apply_request(["node", "client_1", "file_system", "create", "file", "", "test.txt"]) + response = example_network.apply_request( + ["node", "client_1", "file_system", "create", "file", "", "test.txt", "false"] + ) assert response assert client_1.file_system.get_file(folder_name="root", file_name="test.txt") diff --git a/tests/unit_tests/_primaite/_interface/test_request.py b/tests/unit_tests/_primaite/_interface/test_request.py index 07002c99..6067f9e4 100644 --- a/tests/unit_tests/_primaite/_interface/test_request.py +++ b/tests/unit_tests/_primaite/_interface/test_request.py @@ -25,6 +25,10 @@ def test_creating_response_from_boolean(): r2 = RequestResponse.from_bool(False) assert r2.status == "failure" + +@pytest.mark.skip("Disable validation due to performance hit.") +def test_response_from_invalid_options(): + """Test that we get a validation error if a non-boolean is passed.""" with pytest.raises(ValidationError): r3 = RequestResponse.from_bool(1) with pytest.raises(ValidationError): diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system.py index f90b5889..4eb0dd10 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_system.py @@ -108,8 +108,9 @@ def test_create_duplicate_folder(file_system): file_system.create_folder(folder_name="test_folder") assert len(file_system.folders) is 2 - with pytest.raises(Exception): - file_system.create_folder(folder_name="test_folder") + # We no longer through exceptions on making duplicate folders. + # with pytest.raises(Exception): + # file_system.create_folder(folder_name="test_folder") assert len(file_system.folders) is 2