forked from p15670423/monkey
Merge pull request #2031 from guardicore/1960-configuration-repository
1960 configuration repository
This commit is contained in:
commit
58733f7572
|
@ -2,3 +2,4 @@ from .agent_configuration import (
|
|||
AgentConfiguration,
|
||||
AgentConfigurationSchema,
|
||||
)
|
||||
from .default_agent_configuration import DEFAULT_AGENT_CONFIGURATION
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
DEFAULT_AGENT_CONFIGURATION = """{
|
||||
"keep_tunnel_open_time": 30,
|
||||
"post_breach_actions": [
|
||||
{
|
||||
"name": "CommunicateAsBackdoorUser",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "ModifyShellStartupFiles",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "HiddenFiles",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "TrapCommand",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "ChangeSetuidSetgid",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "ScheduleJobs",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "Timestomping",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "AccountDiscovery",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "ProcessListCollection",
|
||||
"options": {}
|
||||
}
|
||||
],
|
||||
"credential_collectors": [
|
||||
{
|
||||
"name": "MimikatzCollector",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "SSHCollector",
|
||||
"options": {}
|
||||
}
|
||||
],
|
||||
"payloads": [
|
||||
{
|
||||
"name": "ransomware",
|
||||
"options": {
|
||||
"encryption": {
|
||||
"enabled": true,
|
||||
"directories": {
|
||||
"linux_target_dir": "",
|
||||
"windows_target_dir": ""
|
||||
}
|
||||
},
|
||||
"other_behaviors": {
|
||||
"readme": true
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"custom_pbas": {
|
||||
"linux_command": "",
|
||||
"linux_filename": "",
|
||||
"windows_command": "",
|
||||
"windows_filename": ""
|
||||
},
|
||||
"propagation": {
|
||||
"maximum_depth": 2,
|
||||
"network_scan": {
|
||||
"tcp": {
|
||||
"timeout": 3000,
|
||||
"ports": [
|
||||
22,
|
||||
80,
|
||||
135,
|
||||
443,
|
||||
445,
|
||||
2222,
|
||||
3306,
|
||||
3389,
|
||||
5985,
|
||||
5986,
|
||||
7001,
|
||||
8008,
|
||||
8080,
|
||||
8088,
|
||||
8983,
|
||||
9200,
|
||||
9600
|
||||
]
|
||||
},
|
||||
"icmp": {
|
||||
"timeout": 1000
|
||||
},
|
||||
"fingerprinters": [
|
||||
{
|
||||
"name": "elastic",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "http",
|
||||
"options": {
|
||||
"http_ports": [
|
||||
80,
|
||||
443,
|
||||
7001,
|
||||
8008,
|
||||
8080,
|
||||
8983,
|
||||
9200,
|
||||
9600
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mssql",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "smb",
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"name": "ssh",
|
||||
"options": {}
|
||||
}
|
||||
],
|
||||
"targets": {
|
||||
"blocked_ips": [],
|
||||
"inaccessible_subnets": [],
|
||||
"local_network_scan": true,
|
||||
"subnets": []
|
||||
}
|
||||
},
|
||||
"exploitation": {
|
||||
"options": {
|
||||
"http_ports": [
|
||||
80,
|
||||
443,
|
||||
7001,
|
||||
8008,
|
||||
8080,
|
||||
8983,
|
||||
9200,
|
||||
9600
|
||||
]
|
||||
},
|
||||
"brute_force": [
|
||||
{
|
||||
"name": "MSSQLExploiter",
|
||||
"options": {},
|
||||
"supported_os": [
|
||||
"WINDOWS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PowerShellExploiter",
|
||||
"options": {},
|
||||
"supported_os": [
|
||||
"WINDOWS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "SSHExploiter",
|
||||
"options": {},
|
||||
"supported_os": [
|
||||
"LINUX"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "SmbExploiter",
|
||||
"options": {
|
||||
"smb_download_timeout": 30
|
||||
},
|
||||
"supported_os": [
|
||||
"WINDOWS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "WmiExploiter",
|
||||
"options": {
|
||||
"smb_download_timeout": 30
|
||||
},
|
||||
"supported_os": [
|
||||
"WINDOWS"
|
||||
]
|
||||
}
|
||||
],
|
||||
"vulnerability": [
|
||||
{
|
||||
"name": "HadoopExploiter",
|
||||
"options": {},
|
||||
"supported_os": [
|
||||
"LINUX",
|
||||
"WINDOWS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Log4ShellExploiter",
|
||||
"options": {},
|
||||
"supported_os": [
|
||||
"LINUX",
|
||||
"WINDOWS"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
|
@ -1,3 +1,6 @@
|
|||
from .errors import RetrievalError
|
||||
from .file_storage import FileRetrievalError, IFileRepository, LocalStorageFileRepository
|
||||
from .i_agent_binary_repository import IAgentBinaryRepository, AgentRetrievalError
|
||||
from .agent_binary_repository import AgentBinaryRepository
|
||||
from .i_agent_configuration_repository import IAgentConfigurationRepository
|
||||
from .file_agent_configuration_repository import FileAgentConfigurationRepository
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
class RetrievalError(RuntimeError):
|
||||
pass
|
|
@ -0,0 +1,38 @@
|
|||
import io
|
||||
|
||||
from common.configuration import (
|
||||
DEFAULT_AGENT_CONFIGURATION,
|
||||
AgentConfiguration,
|
||||
AgentConfigurationSchema,
|
||||
)
|
||||
from monkey_island.cc.repository import (
|
||||
IAgentConfigurationRepository,
|
||||
IFileRepository,
|
||||
RetrievalError,
|
||||
)
|
||||
|
||||
AGENT_CONFIGURATION_FILE_NAME = "agent_configuration.json"
|
||||
|
||||
|
||||
class FileAgentConfigurationRepository(IAgentConfigurationRepository):
|
||||
def __init__(self, file_repository: IFileRepository):
|
||||
self._file_repository = file_repository
|
||||
self._schema = AgentConfigurationSchema()
|
||||
|
||||
def get_configuration(self) -> AgentConfiguration:
|
||||
try:
|
||||
with self._file_repository.open_file(AGENT_CONFIGURATION_FILE_NAME) as f:
|
||||
configuration_json = f.read().decode()
|
||||
|
||||
return self._schema.loads(configuration_json)
|
||||
# TODO: Handle FileRetrievalError vs FileNotFoundError
|
||||
# https://github.com/guardicore/monkey/blob/e8001d8cf76340e42bf17ff62523bd2d85fc4841/monkey/monkey_island/cc/repository/file_storage/local_storage_file_repository.py#L47-L50
|
||||
except RetrievalError:
|
||||
return self._schema.loads(DEFAULT_AGENT_CONFIGURATION)
|
||||
|
||||
def store_configuration(self, agent_configuration: AgentConfiguration):
|
||||
configuration_json = self._schema.dumps(agent_configuration)
|
||||
|
||||
self._file_repository.save_file(
|
||||
AGENT_CONFIGURATION_FILE_NAME, io.BytesIO(configuration_json.encode())
|
||||
)
|
|
@ -1,8 +1,10 @@
|
|||
import abc
|
||||
from typing import BinaryIO
|
||||
|
||||
from monkey_island.cc.repository import RetrievalError
|
||||
|
||||
class FileRetrievalError(RuntimeError):
|
||||
|
||||
class FileRetrievalError(RetrievalError):
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
from abc import ABC, abstractmethod
|
||||
|
||||
from common.configuration import AgentConfiguration
|
||||
|
||||
|
||||
class IAgentConfigurationRepository(ABC):
|
||||
"""
|
||||
A repository used to store and retrieve the agent configuration.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def get_configuration(self) -> AgentConfiguration:
|
||||
"""
|
||||
Retrieve the agent configuration from the repository
|
||||
|
||||
:return: The agent configuration as retrieved from the repository, or the default
|
||||
configuration if none could be retrieved.
|
||||
:raises RetrievalError: if the configuration can not be retrieved
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def store_configuration(self, agent_configuration: AgentConfiguration):
|
||||
"""
|
||||
Store the agent configuration in the repository
|
||||
|
||||
:param agent_configuration: The agent configuration to store in the repository
|
||||
"""
|
||||
pass
|
|
@ -1,30 +0,0 @@
|
|||
from abc import ABC
|
||||
from typing import Any, Mapping, Sequence
|
||||
|
||||
|
||||
class IConfigRepository(ABC):
|
||||
|
||||
# Config
|
||||
###############################################
|
||||
|
||||
# This returns the current config
|
||||
# TODO investigate if encryption should be here or where
|
||||
# TODO potentially should be a DTO as well, but it's structure is defined in schema already
|
||||
def get_config(self) -> Mapping:
|
||||
pass
|
||||
|
||||
def set_config(self, config: dict):
|
||||
pass
|
||||
|
||||
# Used when only a subset of config is submitted, for example only PBAFiles
|
||||
# Used by passing keys, like ['monkey', 'post_breach_actions', 'linux_filename']
|
||||
# Using a list is less ambiguous IMO, than using . notation
|
||||
def set_config_field(self, key_list: Sequence[str], value: Any):
|
||||
pass
|
||||
|
||||
# Used when only a subset of config is needed, for example only PBAFiles
|
||||
# Used by passing keys, like ['monkey', 'post_breach_actions', 'linux_filename']
|
||||
# Using a list is less ambiguous IMO, than using . notation
|
||||
# TODO Still in doubt about encryption, this should probably be determined automatically
|
||||
def get_config_field(self, key_list: Sequence[str]) -> Any:
|
||||
pass
|
|
@ -7,7 +7,9 @@ from common.utils.file_utils import get_binary_io_sha256_hash
|
|||
from monkey_island.cc.repository import (
|
||||
AgentBinaryRepository,
|
||||
AgentRetrievalError,
|
||||
FileAgentConfigurationRepository,
|
||||
IAgentBinaryRepository,
|
||||
IAgentConfigurationRepository,
|
||||
IFileRepository,
|
||||
LocalStorageFileRepository,
|
||||
)
|
||||
|
@ -31,11 +33,14 @@ def initialize_services(data_dir: Path) -> DIContainer:
|
|||
container.register_instance(AWSInstance, AWSInstance())
|
||||
|
||||
container.register_instance(
|
||||
IFileRepository, LocalStorageFileRepository(data_dir / "custom_pbas")
|
||||
IFileRepository, LocalStorageFileRepository(data_dir / "runtime_data")
|
||||
)
|
||||
container.register_instance(AWSService, container.resolve(AWSService))
|
||||
container.register_instance(IAgentBinaryRepository, _build_agent_binary_repository())
|
||||
container.register_instance(LocalMonkeyRunService, container.resolve(LocalMonkeyRunService))
|
||||
container.register_instance(
|
||||
IAgentConfigurationRepository, container.resolve(FileAgentConfigurationRepository)
|
||||
)
|
||||
|
||||
# This is temporary until we get DI all worked out.
|
||||
PostBreachFilesService.initialize(container.resolve(IFileRepository))
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
PLUGIN_NAME = "bond"
|
||||
PLUGIN_OPTIONS = {"gun": "Walther PPK", "car": "Aston Martin DB5"}
|
||||
PLUGIN_CONFIGURATION = {"name": PLUGIN_NAME, "options": PLUGIN_OPTIONS}
|
||||
|
||||
LINUX_COMMAND = "a"
|
||||
LINUX_FILENAME = "b"
|
||||
WINDOWS_COMMAND = "c"
|
||||
WINDOWS_FILENAME = "d"
|
||||
CUSTOM_PBA_CONFIGURATION = {
|
||||
"linux_command": LINUX_COMMAND,
|
||||
"linux_filename": LINUX_FILENAME,
|
||||
"windows_command": WINDOWS_COMMAND,
|
||||
"windows_filename": WINDOWS_FILENAME,
|
||||
}
|
||||
|
||||
BLOCKED_IPS = ["10.0.0.1", "192.168.1.1"]
|
||||
INACCESSIBLE_SUBNETS = ["172.0.0.0/24", "172.2.2.0/24", "192.168.56.0/24"]
|
||||
LOCAL_NETWORK_SCAN = True
|
||||
SUBNETS = ["10.0.0.2", "10.0.0.2/16"]
|
||||
SCAN_TARGET_CONFIGURATION = {
|
||||
"blocked_ips": BLOCKED_IPS,
|
||||
"inaccessible_subnets": INACCESSIBLE_SUBNETS,
|
||||
"local_network_scan": LOCAL_NETWORK_SCAN,
|
||||
"subnets": SUBNETS,
|
||||
}
|
||||
|
||||
TIMEOUT = 2.525
|
||||
ICMP_CONFIGURATION = {"timeout": TIMEOUT}
|
||||
|
||||
PORTS = [8080, 443]
|
||||
TCP_SCAN_CONFIGURATION = {"timeout": TIMEOUT, "ports": PORTS}
|
||||
|
||||
FINGERPRINTERS = [{"name": "mssql", "options": {}}]
|
||||
NETWORK_SCAN_CONFIGURATION = {
|
||||
"tcp": TCP_SCAN_CONFIGURATION,
|
||||
"icmp": ICMP_CONFIGURATION,
|
||||
"fingerprinters": FINGERPRINTERS,
|
||||
"targets": SCAN_TARGET_CONFIGURATION,
|
||||
}
|
||||
|
||||
BRUTE_FORCE = [
|
||||
{"name": "ex1", "options": {}, "supported_os": ["LINUX"]},
|
||||
{
|
||||
"name": "ex2",
|
||||
"options": {"smb_download_timeout": 10},
|
||||
"supported_os": ["LINUX", "WINDOWS"],
|
||||
},
|
||||
]
|
||||
VULNERABILITY = [
|
||||
{
|
||||
"name": "ex3",
|
||||
"options": {"smb_download_timeout": 10},
|
||||
"supported_os": ["WINDOWS"],
|
||||
},
|
||||
]
|
||||
EXPLOITATION_CONFIGURATION = {
|
||||
"options": {"http_ports": PORTS},
|
||||
"brute_force": BRUTE_FORCE,
|
||||
"vulnerability": VULNERABILITY,
|
||||
}
|
||||
|
||||
PROPAGATION_CONFIGURATION = {
|
||||
"maximum_depth": 5,
|
||||
"network_scan": NETWORK_SCAN_CONFIGURATION,
|
||||
"exploitation": EXPLOITATION_CONFIGURATION,
|
||||
}
|
||||
|
||||
AGENT_CONFIGURATION = {
|
||||
"keep_tunnel_open_time": 30,
|
||||
"custom_pbas": CUSTOM_PBA_CONFIGURATION,
|
||||
"post_breach_actions": [PLUGIN_CONFIGURATION],
|
||||
"credential_collectors": [PLUGIN_CONFIGURATION],
|
||||
"payloads": [PLUGIN_CONFIGURATION],
|
||||
"propagation": PROPAGATION_CONFIGURATION,
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
from .single_file_repository import SingleFileRepository
|
|
@ -0,0 +1,23 @@
|
|||
import io
|
||||
from typing import BinaryIO
|
||||
|
||||
from monkey_island.cc.repository import FileRetrievalError, IFileRepository
|
||||
|
||||
|
||||
class SingleFileRepository(IFileRepository):
|
||||
def __init__(self):
|
||||
self._file = None
|
||||
|
||||
def save_file(self, unsafe_file_name: str, file_contents: BinaryIO):
|
||||
self._file = io.BytesIO(file_contents.read())
|
||||
|
||||
def open_file(self, unsafe_file_name: str) -> BinaryIO:
|
||||
if self._file is None:
|
||||
raise FileRetrievalError()
|
||||
return self._file
|
||||
|
||||
def delete_file(self, unsafe_file_name: str):
|
||||
self._file = None
|
||||
|
||||
def delete_all_files(self):
|
||||
self.delete_file("")
|
|
@ -1,5 +1,34 @@
|
|||
from tests.common.example_agent_configuration import (
|
||||
AGENT_CONFIGURATION,
|
||||
BLOCKED_IPS,
|
||||
CUSTOM_PBA_CONFIGURATION,
|
||||
EXPLOITATION_CONFIGURATION,
|
||||
FINGERPRINTERS,
|
||||
ICMP_CONFIGURATION,
|
||||
INACCESSIBLE_SUBNETS,
|
||||
LINUX_COMMAND,
|
||||
LINUX_FILENAME,
|
||||
LOCAL_NETWORK_SCAN,
|
||||
NETWORK_SCAN_CONFIGURATION,
|
||||
PLUGIN_CONFIGURATION,
|
||||
PLUGIN_NAME,
|
||||
PLUGIN_OPTIONS,
|
||||
PORTS,
|
||||
PROPAGATION_CONFIGURATION,
|
||||
SCAN_TARGET_CONFIGURATION,
|
||||
SUBNETS,
|
||||
TCP_SCAN_CONFIGURATION,
|
||||
TIMEOUT,
|
||||
WINDOWS_COMMAND,
|
||||
WINDOWS_FILENAME,
|
||||
)
|
||||
|
||||
from common import OperatingSystems
|
||||
from common.configuration import AgentConfiguration, AgentConfigurationSchema
|
||||
from common.configuration import (
|
||||
DEFAULT_AGENT_CONFIGURATION,
|
||||
AgentConfiguration,
|
||||
AgentConfigurationSchema,
|
||||
)
|
||||
from common.configuration.agent_sub_configuration_schemas import (
|
||||
CustomPBAConfigurationSchema,
|
||||
ExploitationConfigurationSchema,
|
||||
|
@ -20,30 +49,14 @@ from common.configuration.agent_sub_configurations import (
|
|||
PropagationConfiguration,
|
||||
)
|
||||
|
||||
NAME = "bond"
|
||||
OPTIONS = {"gun": "Walther PPK", "car": "Aston Martin DB5"}
|
||||
PLUGIN_CONFIGURATION = {"name": NAME, "options": OPTIONS}
|
||||
|
||||
|
||||
def test_build_plugin_configuration():
|
||||
schema = PluginConfigurationSchema()
|
||||
|
||||
config = schema.load(PLUGIN_CONFIGURATION)
|
||||
|
||||
assert config.name == NAME
|
||||
assert config.options == OPTIONS
|
||||
|
||||
|
||||
LINUX_COMMAND = "a"
|
||||
LINUX_FILENAME = "b"
|
||||
WINDOWS_COMMAND = "c"
|
||||
WINDOWS_FILENAME = "d"
|
||||
CUSTOM_PBA_CONFIGURATION = {
|
||||
"linux_command": LINUX_COMMAND,
|
||||
"linux_filename": LINUX_FILENAME,
|
||||
"windows_command": WINDOWS_COMMAND,
|
||||
"windows_filename": WINDOWS_FILENAME,
|
||||
}
|
||||
assert config.name == PLUGIN_NAME
|
||||
assert config.options == PLUGIN_OPTIONS
|
||||
|
||||
|
||||
def test_custom_pba_configuration_schema():
|
||||
|
@ -57,18 +70,6 @@ def test_custom_pba_configuration_schema():
|
|||
assert config.windows_filename == WINDOWS_FILENAME
|
||||
|
||||
|
||||
BLOCKED_IPS = ["10.0.0.1", "192.168.1.1"]
|
||||
INACCESSIBLE_SUBNETS = ["172.0.0.0/24", "172.2.2.0/24", "192.168.56.0/24"]
|
||||
LOCAL_NETWORK_SCAN = True
|
||||
SUBNETS = ["10.0.0.2", "10.0.0.2/16"]
|
||||
SCAN_TARGET_CONFIGURATION = {
|
||||
"blocked_ips": BLOCKED_IPS,
|
||||
"inaccessible_subnets": INACCESSIBLE_SUBNETS,
|
||||
"local_network_scan": LOCAL_NETWORK_SCAN,
|
||||
"subnets": SUBNETS,
|
||||
}
|
||||
|
||||
|
||||
def test_scan_target_configuration():
|
||||
schema = ScanTargetConfigurationSchema()
|
||||
|
||||
|
@ -80,10 +81,6 @@ def test_scan_target_configuration():
|
|||
assert config.subnets == SUBNETS
|
||||
|
||||
|
||||
TIMEOUT = 2.525
|
||||
ICMP_CONFIGURATION = {"timeout": TIMEOUT}
|
||||
|
||||
|
||||
def test_icmp_scan_configuration_schema():
|
||||
schema = ICMPScanConfigurationSchema()
|
||||
|
||||
|
@ -92,11 +89,6 @@ def test_icmp_scan_configuration_schema():
|
|||
assert config.timeout == TIMEOUT
|
||||
|
||||
|
||||
PORTS = [8080, 443]
|
||||
|
||||
TCP_SCAN_CONFIGURATION = {"timeout": TIMEOUT, "ports": PORTS}
|
||||
|
||||
|
||||
def test_tcp_scan_configuration_schema():
|
||||
schema = TCPScanConfigurationSchema()
|
||||
|
||||
|
@ -106,15 +98,6 @@ def test_tcp_scan_configuration_schema():
|
|||
assert config.ports == PORTS
|
||||
|
||||
|
||||
FINGERPRINTERS = [{"name": "mssql", "options": {}}]
|
||||
NETWORK_SCAN_CONFIGURATION = {
|
||||
"tcp": TCP_SCAN_CONFIGURATION,
|
||||
"icmp": ICMP_CONFIGURATION,
|
||||
"fingerprinters": FINGERPRINTERS,
|
||||
"targets": SCAN_TARGET_CONFIGURATION,
|
||||
}
|
||||
|
||||
|
||||
def test_network_scan_configuration():
|
||||
schema = NetworkScanConfigurationSchema()
|
||||
|
||||
|
@ -155,28 +138,6 @@ def test_exploiter_configuration_schema():
|
|||
assert config.supported_os == supported_os
|
||||
|
||||
|
||||
BRUTE_FORCE = [
|
||||
{"name": "ex1", "options": {}, "supported_os": ["LINUX"]},
|
||||
{
|
||||
"name": "ex2",
|
||||
"options": {"smb_download_timeout": 10},
|
||||
"supported_os": ["LINUX", "WINDOWS"],
|
||||
},
|
||||
]
|
||||
VULNERABILITY = [
|
||||
{
|
||||
"name": "ex3",
|
||||
"options": {"smb_download_timeout": 10},
|
||||
"supported_os": ["WINDOWS"],
|
||||
},
|
||||
]
|
||||
EXPLOITATION_CONFIGURATION = {
|
||||
"options": {"http_ports": PORTS},
|
||||
"brute_force": BRUTE_FORCE,
|
||||
"vulnerability": VULNERABILITY,
|
||||
}
|
||||
|
||||
|
||||
def test_exploitation_configuration():
|
||||
schema = ExploitationConfigurationSchema()
|
||||
|
||||
|
@ -187,13 +148,6 @@ def test_exploitation_configuration():
|
|||
assert config_dict == EXPLOITATION_CONFIGURATION
|
||||
|
||||
|
||||
PROPAGATION_CONFIGURATION = {
|
||||
"maximum_depth": 5,
|
||||
"network_scan": NETWORK_SCAN_CONFIGURATION,
|
||||
"exploitation": EXPLOITATION_CONFIGURATION,
|
||||
}
|
||||
|
||||
|
||||
def test_propagation_configuration():
|
||||
schema = PropagationConfigurationSchema()
|
||||
|
||||
|
@ -208,17 +162,9 @@ def test_propagation_configuration():
|
|||
|
||||
|
||||
def test_agent_configuration():
|
||||
agent_configuration = {
|
||||
"keep_tunnel_open_time": 30,
|
||||
"custom_pbas": CUSTOM_PBA_CONFIGURATION,
|
||||
"post_breach_actions": [PLUGIN_CONFIGURATION],
|
||||
"credential_collectors": [PLUGIN_CONFIGURATION],
|
||||
"payloads": [PLUGIN_CONFIGURATION],
|
||||
"propagation": PROPAGATION_CONFIGURATION,
|
||||
}
|
||||
schema = AgentConfigurationSchema()
|
||||
|
||||
config = schema.load(agent_configuration)
|
||||
config = schema.load(AGENT_CONFIGURATION)
|
||||
config_dict = schema.dump(config)
|
||||
|
||||
assert isinstance(config, AgentConfiguration)
|
||||
|
@ -228,4 +174,12 @@ def test_agent_configuration():
|
|||
assert isinstance(config.credential_collectors[0], PluginConfiguration)
|
||||
assert isinstance(config.payloads[0], PluginConfiguration)
|
||||
assert isinstance(config.propagation, PropagationConfiguration)
|
||||
assert config_dict == agent_configuration
|
||||
assert config_dict == AGENT_CONFIGURATION
|
||||
|
||||
|
||||
def test_default_agent_configuration():
|
||||
schema = AgentConfigurationSchema()
|
||||
|
||||
config = schema.loads(DEFAULT_AGENT_CONFIGURATION)
|
||||
|
||||
assert isinstance(config, AgentConfiguration)
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
from tests.common.example_agent_configuration import AGENT_CONFIGURATION
|
||||
from tests.monkey_island import SingleFileRepository
|
||||
|
||||
from common.configuration import DEFAULT_AGENT_CONFIGURATION, AgentConfigurationSchema
|
||||
from monkey_island.cc.repository import FileAgentConfigurationRepository
|
||||
|
||||
|
||||
def test_store_agent_config():
|
||||
repository = FileAgentConfigurationRepository(SingleFileRepository())
|
||||
schema = AgentConfigurationSchema()
|
||||
agent_configuration = schema.load(AGENT_CONFIGURATION)
|
||||
|
||||
repository.store_configuration(agent_configuration)
|
||||
retrieved_agent_configuration = repository.get_configuration()
|
||||
|
||||
assert retrieved_agent_configuration == agent_configuration
|
||||
|
||||
|
||||
def test_get_default_agent_config():
|
||||
repository = FileAgentConfigurationRepository(SingleFileRepository())
|
||||
schema = AgentConfigurationSchema()
|
||||
default_agent_configuration = schema.loads(DEFAULT_AGENT_CONFIGURATION)
|
||||
|
||||
retrieved_agent_configuration = repository.get_configuration()
|
||||
|
||||
assert retrieved_agent_configuration == default_agent_configuration
|
|
@ -1,12 +1,10 @@
|
|||
import io
|
||||
from typing import BinaryIO
|
||||
|
||||
import pytest
|
||||
from tests.common import StubDIContainer
|
||||
from tests.monkey_island import SingleFileRepository
|
||||
from tests.unit_tests.monkey_island.conftest import get_url_for_resource
|
||||
from tests.utils import raise_
|
||||
|
||||
from monkey_island.cc.repository import FileRetrievalError, IFileRepository
|
||||
from monkey_island.cc.repository import IFileRepository
|
||||
from monkey_island.cc.resources.pba_file_upload import LINUX_PBA_TYPE, WINDOWS_PBA_TYPE, FileUpload
|
||||
|
||||
TEST_FILE_CONTENTS = b"m0nk3y"
|
||||
|
@ -40,28 +38,9 @@ def mock_get_config_value(monkeypatch):
|
|||
)
|
||||
|
||||
|
||||
class MockFileRepository(IFileRepository):
|
||||
def __init__(self):
|
||||
self._file = None
|
||||
|
||||
def save_file(self, unsafe_file_name: str, file_contents: BinaryIO):
|
||||
self._file = io.BytesIO(file_contents.read())
|
||||
|
||||
def open_file(self, unsafe_file_name: str) -> BinaryIO:
|
||||
if self._file is None:
|
||||
raise FileRetrievalError()
|
||||
return self._file
|
||||
|
||||
def delete_file(self, unsafe_file_name: str):
|
||||
self._file = None
|
||||
|
||||
def delete_all_files(self):
|
||||
self.delete_file("")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def file_repository():
|
||||
return MockFileRepository()
|
||||
return SingleFileRepository()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
Loading…
Reference in New Issue