From 2c750acc7a2b0097d7aa44e53b3fee74178f1e03 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 12 Sep 2022 13:40:55 -0400 Subject: [PATCH 01/10] Island: Return 204 No Content from ClearSimulationData POST --- monkey/monkey_island/cc/resources/clear_simulation_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey/monkey_island/cc/resources/clear_simulation_data.py b/monkey/monkey_island/cc/resources/clear_simulation_data.py index 342fadd5f..c5a37ec96 100644 --- a/monkey/monkey_island/cc/resources/clear_simulation_data.py +++ b/monkey/monkey_island/cc/resources/clear_simulation_data.py @@ -20,4 +20,4 @@ class ClearSimulationData(AbstractResource): """ self._repository_service.clear_simulation_data() - return make_response({}, HTTPStatus.OK) + return make_response({}, HTTPStatus.NO_CONTENT) From ba724db969258fc1e77a1eb209abd0b403a4a9e2 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 12 Sep 2022 13:41:51 -0400 Subject: [PATCH 02/10] Island: Publish IslandEventTopic.CLEAR_SIMULATION_DATA from resource --- .../cc/resources/clear_simulation_data.py | 8 ++--- .../resources/test_clear_simulation_data.py | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 monkey/tests/unit_tests/monkey_island/cc/resources/test_clear_simulation_data.py diff --git a/monkey/monkey_island/cc/resources/clear_simulation_data.py b/monkey/monkey_island/cc/resources/clear_simulation_data.py index c5a37ec96..e582dbd11 100644 --- a/monkey/monkey_island/cc/resources/clear_simulation_data.py +++ b/monkey/monkey_island/cc/resources/clear_simulation_data.py @@ -2,16 +2,16 @@ from http import HTTPStatus from flask import make_response +from monkey_island.cc.event_queue import IIslandEventQueue, IslandEventTopic from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.request_authentication import jwt_required -from monkey_island.cc.services import RepositoryService class ClearSimulationData(AbstractResource): urls = ["/api/clear-simulation-data"] - def __init__(self, repository_service: RepositoryService): - self._repository_service = repository_service + def __init__(self, island_event_queue: IIslandEventQueue): + self._island_event_queue = island_event_queue @jwt_required def post(self): @@ -19,5 +19,5 @@ class ClearSimulationData(AbstractResource): Clear all data collected during the simulation """ - self._repository_service.clear_simulation_data() + self._island_event_queue.publish(IslandEventTopic.CLEAR_SIMULATION_DATA) return make_response({}, HTTPStatus.NO_CONTENT) diff --git a/monkey/tests/unit_tests/monkey_island/cc/resources/test_clear_simulation_data.py b/monkey/tests/unit_tests/monkey_island/cc/resources/test_clear_simulation_data.py new file mode 100644 index 000000000..3ae081fcb --- /dev/null +++ b/monkey/tests/unit_tests/monkey_island/cc/resources/test_clear_simulation_data.py @@ -0,0 +1,29 @@ +from http import HTTPStatus +from unittest.mock import MagicMock + +import pytest +from tests.common import StubDIContainer + +from monkey_island.cc.event_queue import IIslandEventQueue, IslandEventTopic +from monkey_island.cc.resources import ClearSimulationData + + +@pytest.fixture +def mock_island_event_queue() -> IIslandEventQueue: + return MagicMock(spec=IIslandEventQueue) + + +@pytest.fixture +def flask_client(build_flask_client, mock_island_event_queue): + container = StubDIContainer() + container.register_instance(IIslandEventQueue, mock_island_event_queue) + + with build_flask_client(container) as flask_client: + yield flask_client + + +def test_clear_simulation_data(flask_client, mock_island_event_queue): + resp = flask_client.post(ClearSimulationData.urls[0], follow_redirects=True) + + assert resp.status_code == HTTPStatus.NO_CONTENT + mock_island_event_queue.publish.assert_called_once_with(IslandEventTopic.CLEAR_SIMULATION_DATA) From 7f29e0342dc72323563f3e4773f783b905b7219e Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 12 Sep 2022 13:45:21 -0400 Subject: [PATCH 03/10] Island: Use interface instead of concrete in island_event_handlers --- monkey/monkey_island/cc/setup/island_event_handlers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monkey/monkey_island/cc/setup/island_event_handlers.py b/monkey/monkey_island/cc/setup/island_event_handlers.py index 0fcf2febc..9df1df752 100644 --- a/monkey/monkey_island/cc/setup/island_event_handlers.py +++ b/monkey/monkey_island/cc/setup/island_event_handlers.py @@ -1,10 +1,10 @@ from common import DIContainer -from monkey_island.cc.event_queue import IslandEventTopic, PyPubSubIslandEventQueue +from monkey_island.cc.event_queue import IIslandEventQueue, IslandEventTopic from monkey_island.cc.island_event_handlers import reset_agent_configuration def setup_island_event_handlers(container: DIContainer): - event_queue = container.resolve(PyPubSubIslandEventQueue) + event_queue = container.resolve(IIslandEventQueue) event_queue.subscribe( IslandEventTopic.RESET_AGENT_CONFIGURATION, container.resolve(reset_agent_configuration) From 745027bf93ba4d8fbee27b3fd18b7853c0eff803 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 12 Sep 2022 13:46:45 -0400 Subject: [PATCH 04/10] Island: Wrap island event handler setup in separate function --- monkey/monkey_island/cc/setup/island_event_handlers.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/monkey/monkey_island/cc/setup/island_event_handlers.py b/monkey/monkey_island/cc/setup/island_event_handlers.py index 9df1df752..9f179f315 100644 --- a/monkey/monkey_island/cc/setup/island_event_handlers.py +++ b/monkey/monkey_island/cc/setup/island_event_handlers.py @@ -6,6 +6,12 @@ from monkey_island.cc.island_event_handlers import reset_agent_configuration def setup_island_event_handlers(container: DIContainer): event_queue = container.resolve(IIslandEventQueue) + _handle_reset_agent_configuration_events(event_queue, container) + + +def _handle_reset_agent_configuration_events( + event_queue: IIslandEventQueue, container: DIContainer +): event_queue.subscribe( IslandEventTopic.RESET_AGENT_CONFIGURATION, container.resolve(reset_agent_configuration) ) From 9479b56722c79a03ce42c240e68b333b77635ff9 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 12 Sep 2022 13:51:45 -0400 Subject: [PATCH 05/10] Island: Subscribe ICredentialsRepository to CLEAR_SIMULATION_DATA --- monkey/monkey_island/cc/setup/island_event_handlers.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/monkey/monkey_island/cc/setup/island_event_handlers.py b/monkey/monkey_island/cc/setup/island_event_handlers.py index 9f179f315..3bf01e56f 100644 --- a/monkey/monkey_island/cc/setup/island_event_handlers.py +++ b/monkey/monkey_island/cc/setup/island_event_handlers.py @@ -1,12 +1,14 @@ from common import DIContainer from monkey_island.cc.event_queue import IIslandEventQueue, IslandEventTopic from monkey_island.cc.island_event_handlers import reset_agent_configuration +from monkey_island.cc.repository import ICredentialsRepository def setup_island_event_handlers(container: DIContainer): event_queue = container.resolve(IIslandEventQueue) _handle_reset_agent_configuration_events(event_queue, container) + _handle_clear_simulation_data_events(event_queue, container) def _handle_reset_agent_configuration_events( @@ -15,3 +17,11 @@ def _handle_reset_agent_configuration_events( event_queue.subscribe( IslandEventTopic.RESET_AGENT_CONFIGURATION, container.resolve(reset_agent_configuration) ) + + +def _handle_clear_simulation_data_events(event_queue: IIslandEventQueue, container: DIContainer): + credentials_repository = container.resolve(ICredentialsRepository) + + event_queue.subscribe( + IslandEventTopic.CLEAR_SIMULATION_DATA, credentials_repository.remove_stolen_credentials + ) From 6d297dc201752874e80c7e3aa818077caff151af Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 12 Sep 2022 13:54:29 -0400 Subject: [PATCH 06/10] Island: Subscribe legacy Database.reset_db to CLEAR_SIMULATION_DATA --- monkey/monkey_island/cc/setup/island_event_handlers.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/monkey/monkey_island/cc/setup/island_event_handlers.py b/monkey/monkey_island/cc/setup/island_event_handlers.py index 3bf01e56f..ba7fb9f30 100644 --- a/monkey/monkey_island/cc/setup/island_event_handlers.py +++ b/monkey/monkey_island/cc/setup/island_event_handlers.py @@ -1,7 +1,10 @@ +from functools import partial + from common import DIContainer from monkey_island.cc.event_queue import IIslandEventQueue, IslandEventTopic from monkey_island.cc.island_event_handlers import reset_agent_configuration from monkey_island.cc.repository import ICredentialsRepository +from monkey_island.cc.services.database import Database def setup_island_event_handlers(container: DIContainer): @@ -20,8 +23,10 @@ def _handle_reset_agent_configuration_events( def _handle_clear_simulation_data_events(event_queue: IIslandEventQueue, container: DIContainer): - credentials_repository = container.resolve(ICredentialsRepository) + legacy_database_reset = partial(Database.reset_db, reset_config=False) + event_queue.subscribe(IslandEventTopic.CLEAR_SIMULATION_DATA, legacy_database_reset) + credentials_repository = container.resolve(ICredentialsRepository) event_queue.subscribe( IslandEventTopic.CLEAR_SIMULATION_DATA, credentials_repository.remove_stolen_credentials ) From 4e49e59447f20b2b3049bd1dd9d0bcb8b4a35540 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Mon, 12 Sep 2022 14:21:06 -0400 Subject: [PATCH 07/10] Island: Rename local event_queue -> island_event_queue Disambiguate Island event queues from Agent event queues --- .../cc/setup/island_event_handlers.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/monkey/monkey_island/cc/setup/island_event_handlers.py b/monkey/monkey_island/cc/setup/island_event_handlers.py index ba7fb9f30..a4935fabd 100644 --- a/monkey/monkey_island/cc/setup/island_event_handlers.py +++ b/monkey/monkey_island/cc/setup/island_event_handlers.py @@ -8,25 +8,27 @@ from monkey_island.cc.services.database import Database def setup_island_event_handlers(container: DIContainer): - event_queue = container.resolve(IIslandEventQueue) + island_event_queue = container.resolve(IIslandEventQueue) - _handle_reset_agent_configuration_events(event_queue, container) - _handle_clear_simulation_data_events(event_queue, container) + _handle_reset_agent_configuration_events(island_event_queue, container) + _handle_clear_simulation_data_events(island_event_queue, container) def _handle_reset_agent_configuration_events( - event_queue: IIslandEventQueue, container: DIContainer + island_event_queue: IIslandEventQueue, container: DIContainer ): - event_queue.subscribe( + island_event_queue.subscribe( IslandEventTopic.RESET_AGENT_CONFIGURATION, container.resolve(reset_agent_configuration) ) -def _handle_clear_simulation_data_events(event_queue: IIslandEventQueue, container: DIContainer): +def _handle_clear_simulation_data_events( + island_event_queue: IIslandEventQueue, container: DIContainer +): legacy_database_reset = partial(Database.reset_db, reset_config=False) - event_queue.subscribe(IslandEventTopic.CLEAR_SIMULATION_DATA, legacy_database_reset) + island_event_queue.subscribe(IslandEventTopic.CLEAR_SIMULATION_DATA, legacy_database_reset) credentials_repository = container.resolve(ICredentialsRepository) - event_queue.subscribe( + island_event_queue.subscribe( IslandEventTopic.CLEAR_SIMULATION_DATA, credentials_repository.remove_stolen_credentials ) From f87fb39b0f4b1bda6603e86f231e52463e8f18c9 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 13 Sep 2022 11:30:13 +0200 Subject: [PATCH 08/10] Project: Add clear_simulation_data to vulture_allowlist Remove once #2277 is closed --- vulture_allowlist.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vulture_allowlist.py b/vulture_allowlist.py index a8369b7da..01d3c5b5f 100644 --- a/vulture_allowlist.py +++ b/vulture_allowlist.py @@ -299,6 +299,9 @@ event deserialize serialized_event +# TODO: Remove once #2277 is merged +clear_simulation_data + # pydantic base models underscore_attrs_are_private extra From f944347644d8b1e0069d4d376667783cddf4951b Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 13 Sep 2022 11:41:08 +0200 Subject: [PATCH 09/10] UT: Test ResetAgentConfiguration endpoint --- .../test_reset_agent_configuration.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 monkey/tests/unit_tests/monkey_island/cc/resources/test_reset_agent_configuration.py diff --git a/monkey/tests/unit_tests/monkey_island/cc/resources/test_reset_agent_configuration.py b/monkey/tests/unit_tests/monkey_island/cc/resources/test_reset_agent_configuration.py new file mode 100644 index 000000000..c89cb372b --- /dev/null +++ b/monkey/tests/unit_tests/monkey_island/cc/resources/test_reset_agent_configuration.py @@ -0,0 +1,31 @@ +from http import HTTPStatus +from unittest.mock import MagicMock + +import pytest +from tests.common import StubDIContainer + +from monkey_island.cc.event_queue import IIslandEventQueue, IslandEventTopic +from monkey_island.cc.resources import ResetAgentConfiguration + + +@pytest.fixture +def mock_island_event_queue() -> IIslandEventQueue: + return MagicMock(spec=IIslandEventQueue) + + +@pytest.fixture +def flask_client(build_flask_client, mock_island_event_queue): + container = StubDIContainer() + container.register_instance(IIslandEventQueue, mock_island_event_queue) + + with build_flask_client(container) as flask_client: + yield flask_client + + +def test_reset_agent_configuration(flask_client, mock_island_event_queue): + resp = flask_client.post(ResetAgentConfiguration.urls[0], follow_redirects=True) + + assert resp.status_code == HTTPStatus.OK + mock_island_event_queue.publish.assert_called_once_with( + IslandEventTopic.RESET_AGENT_CONFIGURATION + ) From 7c86bfc18271124b372a2267647029b7218ffaca Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Tue, 13 Sep 2022 07:24:25 -0400 Subject: [PATCH 10/10] Island: Rename _handle_*_events() -> _subscribe_*_events() --- monkey/monkey_island/cc/setup/island_event_handlers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/monkey/monkey_island/cc/setup/island_event_handlers.py b/monkey/monkey_island/cc/setup/island_event_handlers.py index a4935fabd..ab3e856d6 100644 --- a/monkey/monkey_island/cc/setup/island_event_handlers.py +++ b/monkey/monkey_island/cc/setup/island_event_handlers.py @@ -10,11 +10,11 @@ from monkey_island.cc.services.database import Database def setup_island_event_handlers(container: DIContainer): island_event_queue = container.resolve(IIslandEventQueue) - _handle_reset_agent_configuration_events(island_event_queue, container) - _handle_clear_simulation_data_events(island_event_queue, container) + _subscribe_reset_agent_configuration_events(island_event_queue, container) + _subscribe_clear_simulation_data_events(island_event_queue, container) -def _handle_reset_agent_configuration_events( +def _subscribe_reset_agent_configuration_events( island_event_queue: IIslandEventQueue, container: DIContainer ): island_event_queue.subscribe( @@ -22,7 +22,7 @@ def _handle_reset_agent_configuration_events( ) -def _handle_clear_simulation_data_events( +def _subscribe_clear_simulation_data_events( island_event_queue: IIslandEventQueue, container: DIContainer ): legacy_database_reset = partial(Database.reset_db, reset_config=False)