forked from p15670423/monkey
Merge pull request #1335 from guardicore/ransomware-mode-default-config-values
Ransomware mode default config values
This commit is contained in:
commit
2bc0f739dc
|
@ -5,10 +5,11 @@ import flask_restful
|
||||||
from flask import make_response, request
|
from flask import make_response, request
|
||||||
|
|
||||||
from monkey_island.cc.resources.auth.auth import jwt_required
|
from monkey_island.cc.resources.auth.auth import jwt_required
|
||||||
|
from monkey_island.cc.services.config_manipulator import update_config_on_mode_set
|
||||||
from monkey_island.cc.services.mode.island_mode_service import ModeNotSetError, get_mode, set_mode
|
from monkey_island.cc.services.mode.island_mode_service import ModeNotSetError, get_mode, set_mode
|
||||||
from monkey_island.cc.services.mode.mode_enum import IslandModeEnum
|
from monkey_island.cc.services.mode.mode_enum import IslandModeEnum
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class IslandMode(flask_restful.Resource):
|
class IslandMode(flask_restful.Resource):
|
||||||
|
@ -21,6 +22,12 @@ class IslandMode(flask_restful.Resource):
|
||||||
mode = IslandModeEnum(mode_str)
|
mode = IslandModeEnum(mode_str)
|
||||||
set_mode(mode)
|
set_mode(mode)
|
||||||
|
|
||||||
|
if not update_config_on_mode_set(mode):
|
||||||
|
LOG.error(
|
||||||
|
"Could not apply configuration changes per mode. "
|
||||||
|
"Using default advanced configuration."
|
||||||
|
)
|
||||||
|
|
||||||
return make_response({}, 200)
|
return make_response({}, 200)
|
||||||
except (AttributeError, json.decoder.JSONDecodeError):
|
except (AttributeError, json.decoder.JSONDecodeError):
|
||||||
return make_response({}, 400)
|
return make_response({}, 400)
|
||||||
|
|
|
@ -8,7 +8,9 @@ from jsonschema import Draft4Validator, validators
|
||||||
import monkey_island.cc.environment.environment_singleton as env_singleton
|
import monkey_island.cc.environment.environment_singleton as env_singleton
|
||||||
from monkey_island.cc.database import mongo
|
from monkey_island.cc.database import mongo
|
||||||
from monkey_island.cc.server_utils.encryptor import get_encryptor
|
from monkey_island.cc.server_utils.encryptor import get_encryptor
|
||||||
|
from monkey_island.cc.services.config_manipulator import update_config_per_mode
|
||||||
from monkey_island.cc.services.config_schema.config_schema import SCHEMA
|
from monkey_island.cc.services.config_schema.config_schema import SCHEMA
|
||||||
|
from monkey_island.cc.services.mode.island_mode_service import ModeNotSetError, get_mode
|
||||||
from monkey_island.cc.services.post_breach_files import PostBreachFilesService
|
from monkey_island.cc.services.post_breach_files import PostBreachFilesService
|
||||||
from monkey_island.cc.services.utils.network_utils import local_ip_addresses
|
from monkey_island.cc.services.utils.network_utils import local_ip_addresses
|
||||||
|
|
||||||
|
@ -235,9 +237,12 @@ class ConfigService:
|
||||||
def get_default_config(should_encrypt=False):
|
def get_default_config(should_encrypt=False):
|
||||||
ConfigService.init_default_config()
|
ConfigService.init_default_config()
|
||||||
config = copy.deepcopy(ConfigService.default_config)
|
config = copy.deepcopy(ConfigService.default_config)
|
||||||
|
|
||||||
if should_encrypt:
|
if should_encrypt:
|
||||||
ConfigService.encrypt_config(config)
|
ConfigService.encrypt_config(config)
|
||||||
|
|
||||||
logger.info("Default config was called")
|
logger.info("Default config was called")
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -251,7 +256,11 @@ class ConfigService:
|
||||||
PostBreachFilesService.remove_PBA_files()
|
PostBreachFilesService.remove_PBA_files()
|
||||||
config = ConfigService.get_default_config(True)
|
config = ConfigService.get_default_config(True)
|
||||||
ConfigService.set_server_ips_in_config(config)
|
ConfigService.set_server_ips_in_config(config)
|
||||||
ConfigService.update_config(config, should_encrypt=False)
|
try:
|
||||||
|
mode = get_mode()
|
||||||
|
update_config_per_mode(mode, config, should_encrypt=False)
|
||||||
|
except ModeNotSetError:
|
||||||
|
ConfigService.update_config(config, should_encrypt=False)
|
||||||
logger.info("Monkey config reset was called")
|
logger.info("Monkey config reset was called")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
import dpath.util
|
||||||
|
|
||||||
|
import monkey_island.cc.services.config as config_service
|
||||||
|
from monkey_island.cc.services.config_manipulators import MANIPULATOR_PER_MODE
|
||||||
|
from monkey_island.cc.services.mode.mode_enum import IslandModeEnum
|
||||||
|
|
||||||
|
|
||||||
|
def update_config_on_mode_set(mode: IslandModeEnum) -> bool:
|
||||||
|
config = config_service.ConfigService.get_config()
|
||||||
|
return update_config_per_mode(mode.value, config, True)
|
||||||
|
|
||||||
|
|
||||||
|
def update_config_per_mode(mode: str, config: Dict, should_encrypt: bool) -> bool:
|
||||||
|
config = _set_default_config_values_per_mode(mode, config)
|
||||||
|
return config_service.ConfigService.update_config(
|
||||||
|
config_json=config, should_encrypt=should_encrypt
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _set_default_config_values_per_mode(mode: str, config: Dict) -> Dict:
|
||||||
|
config_manipulator = MANIPULATOR_PER_MODE[mode]
|
||||||
|
config = _apply_config_manipulator(config, config_manipulator)
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
def _apply_config_manipulator(config: Dict, config_manipulator: Dict):
|
||||||
|
for path, value in config_manipulator.items():
|
||||||
|
dpath.util.set(config, path, value, ".")
|
||||||
|
return config
|
|
@ -0,0 +1,6 @@
|
||||||
|
from monkey_island.cc.services.mode.mode_enum import IslandModeEnum
|
||||||
|
|
||||||
|
MANIPULATOR_PER_MODE = {
|
||||||
|
IslandModeEnum.ADVANCED.value: {},
|
||||||
|
IslandModeEnum.RANSOMWARE.value: {"monkey.post_breach.post_breach_actions": []},
|
||||||
|
}
|
|
@ -1,6 +1,10 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
from monkey_island.cc.models.island_mode_model import IslandMode
|
from monkey_island.cc.models.island_mode_model import IslandMode
|
||||||
from monkey_island.cc.services.mode.mode_enum import IslandModeEnum
|
from monkey_island.cc.services.mode.mode_enum import IslandModeEnum
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def set_mode(mode: IslandModeEnum):
|
def set_mode(mode: IslandModeEnum):
|
||||||
island_mode_model = IslandMode()
|
island_mode_model = IslandMode()
|
||||||
|
|
|
@ -13,7 +13,11 @@ def uses_database():
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("mode", ["ransomware", "advanced"])
|
@pytest.mark.parametrize("mode", ["ransomware", "advanced"])
|
||||||
def test_island_mode_post(flask_client, mode):
|
def test_island_mode_post(flask_client, mode, monkeypatch):
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"monkey_island.cc.resources.island_mode.update_config_on_mode_set",
|
||||||
|
lambda _: None,
|
||||||
|
)
|
||||||
resp = flask_client.post(
|
resp = flask_client.post(
|
||||||
"/api/island-mode", data=json.dumps({"mode": mode}), follow_redirects=True
|
"/api/island-mode", data=json.dumps({"mode": mode}), follow_redirects=True
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from monkey_island.cc.environment import Environment
|
||||||
|
from monkey_island.cc.services.config import ConfigService
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def IPS():
|
||||||
|
return ["0.0.0.0", "9.9.9.9"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def PORT():
|
||||||
|
return 9999
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def config(monkeypatch, IPS, PORT):
|
||||||
|
monkeypatch.setattr("monkey_island.cc.services.config.local_ip_addresses", lambda: IPS)
|
||||||
|
monkeypatch.setattr(Environment, "_ISLAND_PORT", PORT)
|
||||||
|
config = ConfigService.get_default_config(True)
|
||||||
|
return config
|
|
@ -1,43 +1,30 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from monkey_island.cc.environment import Environment
|
|
||||||
from monkey_island.cc.services.config import ConfigService
|
from monkey_island.cc.services.config import ConfigService
|
||||||
|
|
||||||
IPS = ["0.0.0.0", "9.9.9.9"]
|
|
||||||
PORT = 9999
|
|
||||||
|
|
||||||
|
|
||||||
# If tests fail because config path is changed, sync with
|
# If tests fail because config path is changed, sync with
|
||||||
# monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js
|
# monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def config(monkeypatch):
|
|
||||||
monkeypatch.setattr("monkey_island.cc.services.config.local_ip_addresses", lambda: IPS)
|
|
||||||
monkeypatch.setattr(Environment, "_ISLAND_PORT", PORT)
|
|
||||||
config = ConfigService.get_default_config(True)
|
|
||||||
return config
|
|
||||||
|
|
||||||
|
|
||||||
class MockClass:
|
class MockClass:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="function", autouse=True)
|
@pytest.fixture(scope="function", autouse=True)
|
||||||
def mock_port_in_env_singleton(monkeypatch):
|
def mock_port_in_env_singleton(monkeypatch, PORT):
|
||||||
mock_singleton = MockClass()
|
mock_singleton = MockClass()
|
||||||
mock_singleton.env = MockClass()
|
mock_singleton.env = MockClass()
|
||||||
mock_singleton.env.get_island_port = lambda: PORT
|
mock_singleton.env.get_island_port = lambda: PORT
|
||||||
monkeypatch.setattr("monkey_island.cc.services.config.env_singleton", mock_singleton)
|
monkeypatch.setattr("monkey_island.cc.services.config.env_singleton", mock_singleton)
|
||||||
|
|
||||||
|
|
||||||
def test_set_server_ips_in_config_command_servers(config):
|
def test_set_server_ips_in_config_command_servers(config, IPS, PORT):
|
||||||
ConfigService.set_server_ips_in_config(config)
|
ConfigService.set_server_ips_in_config(config)
|
||||||
expected_config_command_servers = [f"{ip}:{PORT}" for ip in IPS]
|
expected_config_command_servers = [f"{ip}:{PORT}" for ip in IPS]
|
||||||
assert config["internal"]["island_server"]["command_servers"] == expected_config_command_servers
|
assert config["internal"]["island_server"]["command_servers"] == expected_config_command_servers
|
||||||
|
|
||||||
|
|
||||||
def test_set_server_ips_in_config_current_server(config):
|
def test_set_server_ips_in_config_current_server(config, IPS, PORT):
|
||||||
ConfigService.set_server_ips_in_config(config)
|
ConfigService.set_server_ips_in_config(config)
|
||||||
expected_config_current_server = f"{IPS[0]}:{PORT}"
|
expected_config_current_server = f"{IPS[0]}:{PORT}"
|
||||||
assert config["internal"]["island_server"]["current_server"] == expected_config_current_server
|
assert config["internal"]["island_server"]["current_server"] == expected_config_current_server
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
from monkey_island.cc.services.config_manipulator import update_config_on_mode_set
|
||||||
|
from monkey_island.cc.services.mode.mode_enum import IslandModeEnum
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_config_on_mode_set_advanced(config, monkeypatch):
|
||||||
|
monkeypatch.setattr("monkey_island.cc.services.config.ConfigService.get_config", lambda: config)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"monkey_island.cc.services.config.ConfigService.update_config",
|
||||||
|
lambda config_json, should_encrypt: config_json,
|
||||||
|
)
|
||||||
|
|
||||||
|
mode = IslandModeEnum.ADVANCED
|
||||||
|
manipulated_config = update_config_on_mode_set(mode)
|
||||||
|
assert manipulated_config == config
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_config_on_mode_set_ransomware(config, monkeypatch):
|
||||||
|
monkeypatch.setattr("monkey_island.cc.services.config.ConfigService.get_config", lambda: config)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"monkey_island.cc.services.config.ConfigService.update_config",
|
||||||
|
lambda config_json, should_encrypt: config_json,
|
||||||
|
)
|
||||||
|
|
||||||
|
mode = IslandModeEnum.RANSOMWARE
|
||||||
|
manipulated_config = update_config_on_mode_set(mode)
|
||||||
|
assert manipulated_config["monkey"]["post_breach"]["post_breach_actions"] == []
|
Loading…
Reference in New Issue