From 8c1afcc2b42ca9d8ff5a049f19153346bfd1ff62 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 29 Sep 2021 19:31:35 +0200 Subject: [PATCH] Island: Add import attack mitigations Also UTs for reset_database from setup mongo. --- .../cc/setup/mongo/database_initializer.py | 20 +++++- .../mongo_mitigations/attack_mitigations.json | 1 + .../mongo_mitigations/invalid_mitigation | 1 + .../attack/test_mitre_api_interface.py | 18 ------ .../setup/mongo/test_database_initializer.py | 61 +++++++++++++++++++ 5 files changed, 80 insertions(+), 21 deletions(-) create mode 100644 monkey/tests/data_for_tests/mongo_mitigations/attack_mitigations.json create mode 100644 monkey/tests/data_for_tests/mongo_mitigations/invalid_mitigation delete mode 100644 monkey/tests/unit_tests/monkey_island/cc/services/attack/test_mitre_api_interface.py create mode 100644 monkey/tests/unit_tests/monkey_island/cc/setup/mongo/test_database_initializer.py diff --git a/monkey/monkey_island/cc/setup/mongo/database_initializer.py b/monkey/monkey_island/cc/setup/mongo/database_initializer.py index 4e339aad7..761617a08 100644 --- a/monkey/monkey_island/cc/setup/mongo/database_initializer.py +++ b/monkey/monkey_island/cc/setup/mongo/database_initializer.py @@ -1,14 +1,23 @@ +import json import logging +from pathlib import Path from pymongo import errors from monkey_island.cc.database import mongo from monkey_island.cc.models.attack.attack_mitigations import AttackMitigations -from monkey_island.cc.services.attack.mitre_api_interface import MitreApiInterface from monkey_island.cc.services.database import Database +from monkey_island.cc.server_utils.consts import MONKEY_ISLAND_ABS_PATH logger = logging.getLogger(__name__) +ATTACK_MITIGATION_PATH = ( + Path(MONKEY_ISLAND_ABS_PATH) + / "cc" + / "setup" + / "mongo" + / f"{AttackMitigations.COLLECTION_NAME}.json" +) def reset_database(): Database.reset_db() @@ -35,5 +44,10 @@ def _try_store_mitigations_on_mongo(): def _store_mitigations_on_mongo(): - # TODO: import attack mitigations - pass + try: + with open(ATTACK_MITIGATION_PATH) as f: + file_data = json.load(f) + mongodb_collection = mongo.db[AttackMitigations.COLLECTION_NAME] + mongodb_collection.insert_many(file_data) + except json.decoder.JSONDecodeError as e: + raise Exception(f"Invalid attack mitigations {ATTACK_MITIGATION_PATH} file: {e}") diff --git a/monkey/tests/data_for_tests/mongo_mitigations/attack_mitigations.json b/monkey/tests/data_for_tests/mongo_mitigations/attack_mitigations.json new file mode 100644 index 000000000..dace1ebec --- /dev/null +++ b/monkey/tests/data_for_tests/mongo_mitigations/attack_mitigations.json @@ -0,0 +1 @@ +[{"_id": "T1066", "mitigations": [{"name": "Indicator Removal from Tools Mitigation", "description": "Mitigation is difficult in instances like this because the adversary may have access to the system through another channel and can learn what techniques or tools are blocked by resident defenses. Exercising best practices with configuration and security as well as ensuring that proper process is followed during investigation of potential compromise is essential to detecting a larger intrusion through discrete alerts.", "url": ""}]}, {"_id": "T1047", "mitigations": [{"name": "Privileged Account Management", "description": "Manage the creation, modification, use, and permissions associated to privileged accounts, including SYSTEM and root.", "url": "https://attack.mitre.org/mitigations/M1026"}, {"name": "User Account Management", "description": "Manage the creation, modification, use, and permissions associated to user accounts.", "url": "https://attack.mitre.org/mitigations/M1018"}]}, {"_id": "T1156", "mitigations": [{"name": "Restrict File and Directory Permissions", "description": "Restrict access by setting directory and file permissions that are not specific to users or privileged accounts.", "url": "https://attack.mitre.org/mitigations/M1022"}]}] diff --git a/monkey/tests/data_for_tests/mongo_mitigations/invalid_mitigation b/monkey/tests/data_for_tests/mongo_mitigations/invalid_mitigation new file mode 100644 index 000000000..3f18637dc --- /dev/null +++ b/monkey/tests/data_for_tests/mongo_mitigations/invalid_mitigation @@ -0,0 +1 @@ +[{"_id": "T1066", "mitigations": [} diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/attack/test_mitre_api_interface.py b/monkey/tests/unit_tests/monkey_island/cc/services/attack/test_mitre_api_interface.py deleted file mode 100644 index 24f516198..000000000 --- a/monkey/tests/unit_tests/monkey_island/cc/services/attack/test_mitre_api_interface.py +++ /dev/null @@ -1,18 +0,0 @@ -import json -from pathlib import Path - -from monkey_island.cc.server_utils.consts import MONKEY_ISLAND_ABS_PATH - - -def test_get_all_mitigations(): - attack_mitigation_path = ( - Path(MONKEY_ISLAND_ABS_PATH) / "cc" / "setup" / "mongo" / "attack_mitigations.json" - ) - - with open(attack_mitigation_path) as mitigations: - mitigations = json.load(mitigations) - assert len(mitigations) >= 266 - mitigation = next(iter(mitigations))["mitigations"][0] - assert mitigation["name"] is not None - assert mitigation["description"] is not None - assert mitigation["url"] is not None diff --git a/monkey/tests/unit_tests/monkey_island/cc/setup/mongo/test_database_initializer.py b/monkey/tests/unit_tests/monkey_island/cc/setup/mongo/test_database_initializer.py new file mode 100644 index 000000000..5388bdd8e --- /dev/null +++ b/monkey/tests/unit_tests/monkey_island/cc/setup/mongo/test_database_initializer.py @@ -0,0 +1,61 @@ +import json.decoder +from pathlib import Path +from unittest.mock import MagicMock + +import mongomock +import pytest + +from monkey_island.cc.server_utils.consts import MONKEY_ISLAND_ABS_PATH +from monkey_island.cc.setup.mongo.database_initializer import reset_database + + +@pytest.fixture +def fake_mongo(monkeypatch): + mongo = mongomock.MongoClient() + monkeypatch.setattr("monkey_island.cc.setup.mongo.database_initializer.mongo", mongo) + monkeypatch.setattr("monkey_island.cc.services.database.mongo", mongo) + return mongo + + +@pytest.fixture +def fake_config(monkeypatch): + monkeypatch.setattr("monkey_island.cc.services.config.ConfigService.init_config", lambda: None) + monkeypatch.setattr("monkey_island.cc.services.attack.attack_config.AttackConfig.reset_config", lambda: None) + monkeypatch.setattr("monkey_island.cc.services.database.jsonify", MagicMock(return_value=True)) + + +def test_store_mitigations_on_mongo(monkeypatch, data_for_tests_dir, fake_mongo, fake_config): + monkeypatch.setattr( + "monkey_island.cc.setup.mongo.database_initializer.ATTACK_MITIGATION_PATH", + Path(data_for_tests_dir) / "mongo_mitigations" / "attack_mitigations.json", + ) + fake_mongo.db.validate_collection = MagicMock(return_value=True) + reset_database() + + assert len(list(fake_mongo.db.attack_mitigations.find({}))) == 3 + + +def test_store_mitigations_on_mongo__invalid_mitigation( + monkeypatch, data_for_tests_dir, fake_mongo, fake_config +): + monkeypatch.setattr( + "monkey_island.cc.setup.mongo.database_initializer.ATTACK_MITIGATION_PATH", + Path(data_for_tests_dir) / "mongo_mitigations" / "invalid_mitigation", + ) + fake_mongo.db.validate_collection = MagicMock(return_value=True) + with pytest.raises(Exception): + reset_database() + + +def test_get_all_mitigations(): + attack_mitigation_path = ( + Path(MONKEY_ISLAND_ABS_PATH) / "cc" / "setup" / "mongo" / "attack_mitigations.json" + ) + + with open(attack_mitigation_path) as mitigations: + mitigations = json.load(mitigations) + assert len(mitigations) >= 266 + mitigation = next(iter(mitigations))["mitigations"][0] + assert mitigation["name"] is not None + assert mitigation["description"] is not None + assert mitigation["url"] is not None