diff --git a/CHANGELOG.md b/CHANGELOG.md index 37052cb2..7a96b27c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,7 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Order of service health state - Starting a node didn't start the services on it - Fixed an issue where the services were still able to run even though the node the service is installed on is turned off - +- The use of NODE_FILE_CHECKHASH and NODE_FOLDER_CHECKHASH in the current release is marked as 'Not Implemented'. ### Added diff --git a/src/primaite/config/_package_data/data_manipulation.yaml b/src/primaite/config/_package_data/data_manipulation.yaml index 9dea1b14..e3d68706 100644 --- a/src/primaite/config/_package_data/data_manipulation.yaml +++ b/src/primaite/config/_package_data/data_manipulation.yaml @@ -313,7 +313,7 @@ agents: folder_id: 0 file_id: 0 10: - action: "NODE_FILE_SCAN" # CHECKHASH replaced by SCAN - but the behaviour is the same in this context. + action: "NODE_FILE_CHECKHASH" # CHECKHASH replaced by SCAN - but the behaviour is the same in this context. options: node_id: 2 folder_id: 0 @@ -341,7 +341,7 @@ agents: node_id: 2 folder_id: 0 15: - action: "NODE_FOLDER_SCAN" # CHECKHASH replaced by SCAN - but the behaviour is the same in this context. + action: "NODE_FOLDER_CHECKHASH" # CHECKHASH replaced by SCAN - but the behaviour is the same in this context. options: node_id: 2 folder_id: 0 diff --git a/src/primaite/notebooks/Data-Manipulation-E2E-Demonstration.ipynb b/src/primaite/notebooks/Data-Manipulation-E2E-Demonstration.ipynb index a958aa0a..2a5ec16f 100644 --- a/src/primaite/notebooks/Data-Manipulation-E2E-Demonstration.ipynb +++ b/src/primaite/notebooks/Data-Manipulation-E2E-Demonstration.ipynb @@ -477,7 +477,8 @@ "source": [ "obs, reward, terminated, truncated, info = env.step(9) # scan database file\n", "obs, reward, terminated, truncated, info = env.step(1) # scan webapp service\n", - "pprint(obs['NODES'])" + "\n", + "pprint(obs['NODES'])\n" ] }, { @@ -492,7 +493,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Also, the NMNE outbound of either client 1 (node 6) or client 2 (node 7) increased from 0 to 1, but only right after the red attack, so we probably cannot see it now." + "Also, the NMNE outbound of either client 1 (node 6) or client 2 (node 7) has increased from 0 to 1. This tells us which client is being used by the red agent." ] }, { @@ -647,7 +648,6 @@ "metadata": {}, "outputs": [], "source": [ - "\n", "for step in range(40):\n", " obs, reward, terminated, truncated, info = env.step(0) # do nothing\n", " print(f\"step: {env.game.step_counter}, Red action: {info['agent_actions']['data_manipulation_attacker'].action}, Blue reward:{reward:.2f}\" )" @@ -668,13 +668,6 @@ "source": [ "env.reset()" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -693,7 +686,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.10.11" } }, "nbformat": 4, diff --git a/src/primaite/simulator/file_system/file.py b/src/primaite/simulator/file_system/file.py index 3a1c24df..a4d54e79 100644 --- a/src/primaite/simulator/file_system/file.py +++ b/src/primaite/simulator/file_system/file.py @@ -3,6 +3,7 @@ from __future__ import annotations import hashlib import json import os.path +import warnings from pathlib import Path from typing import Dict, Optional @@ -145,6 +146,10 @@ class File(FileSystemItemABC): Return False if corruption is detected, otherwise True """ + warnings.warn("NODE_FILE_CHECKHASH is currently not implemented.") + self.sys_log.warning("NODE_FILE_CHECKHASH is currently not implemented.") + return False + if self.deleted: self.sys_log.error(f"Unable to check hash of deleted file {self.folder_name}/{self.name}") return False diff --git a/src/primaite/simulator/file_system/file_system_item_abc.py b/src/primaite/simulator/file_system/file_system_item_abc.py index 32f5f6be..c89152b4 100644 --- a/src/primaite/simulator/file_system/file_system_item_abc.py +++ b/src/primaite/simulator/file_system/file_system_item_abc.py @@ -156,7 +156,7 @@ class FileSystemItemABC(SimComponent): @abstractmethod def check_hash(self) -> bool: """ - Checks the has of the file to detect any changes. + Checks the hash of the file to detect any changes. For current implementation, any change in file hash means it is compromised. diff --git a/src/primaite/simulator/file_system/folder.py b/src/primaite/simulator/file_system/folder.py index 51b7a819..90ad4425 100644 --- a/src/primaite/simulator/file_system/folder.py +++ b/src/primaite/simulator/file_system/folder.py @@ -1,5 +1,6 @@ from __future__ import annotations +import warnings from typing import Dict, Optional from prettytable import MARKDOWN, PrettyTable @@ -380,6 +381,10 @@ class Folder(FileSystemItemABC): Return False if corruption is detected, otherwise True """ + warnings.warn("NODE_FOLDER_CHECKHASH is currently not implemented.") + self.sys_log.error("NODE_FOLDER_CHECKHASH is currently not implemented.") + return False + if self.deleted: self.sys_log.error(f"Unable to check hash of deleted folder {self.name}") return False diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_file.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_file.py index 32efe029..9d9228d8 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_file.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_file.py @@ -1,3 +1,7 @@ +import warnings + +import pytest + from primaite.simulator.file_system.file import File from primaite.simulator.file_system.file_system_item_abc import FileSystemItemHealthStatus from primaite.simulator.file_system.file_type import FileType @@ -41,6 +45,7 @@ def test_file_reveal_to_red_scan(file_system): assert file.revealed_to_red is True +@pytest.mark.skip(reason="NODE_FILE_CHECKHASH not implemented") def test_simulated_file_check_hash(file_system): file: File = file_system.create_file(file_name="test_file.txt", folder_name="test_folder") @@ -52,6 +57,7 @@ def test_simulated_file_check_hash(file_system): assert file.health_status == FileSystemItemHealthStatus.CORRUPT +@pytest.mark.skip(reason="NODE_FILE_CHECKHASH not implemented") def test_real_file_check_hash(file_system): file: File = file_system.create_file(file_name="test_file.txt", real=True) @@ -80,3 +86,14 @@ def test_file_corrupt_repair_restore(file_system): file.restore() assert file.health_status == FileSystemItemHealthStatus.GOOD + + +def test_file_warning_triggered(file_system): + file: File = file_system.create_file(file_name="test_file.txt", folder_name="test_folder") + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + file.check_hash() + # Check warning issued + assert len(w) == 1 + assert "not implemented" in str(w[-1].message) diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py index 658b1b09..efa49134 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_file_actions.py @@ -31,6 +31,7 @@ def test_file_scan_request(populated_file_system): assert file.visible_health_status == FileSystemItemHealthStatus.CORRUPT +@pytest.mark.skip(reason="NODE_FILE_CHECKHASH not implemented") def test_file_checkhash_request(populated_file_system): """Test that an agent can request a file hash check.""" fs, folder, file = populated_file_system diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder.py index bada2dab..e00c002d 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder.py @@ -119,6 +119,7 @@ def test_folder_corrupt_repair(file_system): assert file.health_status == FileSystemItemHealthStatus.GOOD +@pytest.mark.skip(reason="NODE_FILE_CHECKHASH not implemented") def test_simulated_folder_check_hash(file_system): folder: Folder = file_system.create_folder(folder_name="test_folder") file_system.create_file(file_name="test_file.txt", folder_name="test_folder") @@ -133,6 +134,7 @@ def test_simulated_folder_check_hash(file_system): assert folder.health_status == FileSystemItemHealthStatus.CORRUPT +@pytest.mark.skip(reason="NODE_FILE_CHECKHASH not implemented") def test_real_folder_check_hash(file_system): folder: Folder = file_system.create_folder(folder_name="test_folder") file_system.create_file(file_name="test_file.txt", folder_name="test_folder", real=True) diff --git a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py index 6e904f2a..11043844 100644 --- a/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py +++ b/tests/unit_tests/_primaite/_simulator/_file_system/test_folder_actions.py @@ -1,3 +1,4 @@ +import warnings from typing import Tuple import pytest @@ -49,6 +50,7 @@ def test_folder_scan_request(populated_file_system): assert file2.visible_health_status == FileSystemItemHealthStatus.CORRUPT +@pytest.mark.skip(reason="NODE_FOLDER_CHECKHASH not implemented") def test_folder_checkhash_request(populated_file_system): """Test that an agent can request a folder hash check.""" fs, folder, file = populated_file_system @@ -62,6 +64,16 @@ def test_folder_checkhash_request(populated_file_system): assert folder.health_status == FileSystemItemHealthStatus.CORRUPT +def test_folder_warning_triggered(populated_file_system): + fs, folder, _ = populated_file_system + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + fs.apply_request(request=["folder", folder.name, "checkhash"]) + # Check warning issued + assert len(w) == 1 + assert "not implemented" in str(w[-1].message) + + def test_folder_repair_request(populated_file_system): """Test that an agent can request a folder repair.""" fs, folder, file = populated_file_system