From 6438afbcd59d6bb0218f1b5219fa1fdc987c8b75 Mon Sep 17 00:00:00 2001 From: vakarisz Date: Wed, 18 May 2022 13:02:48 +0300 Subject: [PATCH] Island: Add a bunch of IRepository interfaces for data entities --- .../monkey_island/cc/dal/IAgentRepository.py | 15 ++++++++++ .../monkey_island/cc/dal/IAttackRepository.py | 24 +++++++++++++++ .../monkey_island/cc/dal/IConfigRepository.py | 30 +++++++++++++++++++ .../monkey_island/cc/dal/IEdgeRepository.py | 30 +++++++++++++++++++ .../cc/dal/IMachineRepository.py | 19 ++++++++++++ .../monkey_island/cc/dal/IReportRepository.py | 14 +++++++++ .../cc/dal/ISimulationRepository.py | 11 +++++++ .../cc/dal/ITelemetryRepository.py | 20 +++++++++++++ 8 files changed, 163 insertions(+) create mode 100644 monkey/monkey_island/cc/dal/IAgentRepository.py create mode 100644 monkey/monkey_island/cc/dal/IAttackRepository.py create mode 100644 monkey/monkey_island/cc/dal/IConfigRepository.py create mode 100644 monkey/monkey_island/cc/dal/IEdgeRepository.py create mode 100644 monkey/monkey_island/cc/dal/IMachineRepository.py create mode 100644 monkey/monkey_island/cc/dal/IReportRepository.py create mode 100644 monkey/monkey_island/cc/dal/ISimulationRepository.py create mode 100644 monkey/monkey_island/cc/dal/ITelemetryRepository.py diff --git a/monkey/monkey_island/cc/dal/IAgentRepository.py b/monkey/monkey_island/cc/dal/IAgentRepository.py new file mode 100644 index 000000000..5a784e5d2 --- /dev/null +++ b/monkey/monkey_island/cc/dal/IAgentRepository.py @@ -0,0 +1,15 @@ +from abc import ABC +from typing import Optional, Sequence + +from monkey_island.cc.models import Monkey + + +class IAgentRepository(ABC): + # TODO rename Monkey document to Agent + def save_agent(self, agent: Monkey): + pass + + def get_agents( + self, id: Optional[str] = None, running: Optional[bool] = None + ) -> Sequence[Monkey]: + pass diff --git a/monkey/monkey_island/cc/dal/IAttackRepository.py b/monkey/monkey_island/cc/dal/IAttackRepository.py new file mode 100644 index 000000000..f1c6c0213 --- /dev/null +++ b/monkey/monkey_island/cc/dal/IAttackRepository.py @@ -0,0 +1,24 @@ +from abc import ABC +from typing import Sequence + +from monkey_island.cc.models.attack import Mitigation + + +class IRepository(ABC): + # Att&ck just add not implemented raises + ###################################### + # This will likely stay the same as mitigations are external data + def save_mitigations(self, mitigations: Sequence[Mitigation]): + pass + + # This will likely remain if we plan to keep the report actionable + def get_mitigation_by_technique(self, technique_id: str) -> Mitigation: + pass + + # This could go away, since attack report is not costly to generate and we'll refactor it + def save_attack_report(self, attack_report: dict): + raise NotImplementedError + + # This will probably go away once we use endpoints instead + def get_attack_report(self): + raise NotImplementedError diff --git a/monkey/monkey_island/cc/dal/IConfigRepository.py b/monkey/monkey_island/cc/dal/IConfigRepository.py new file mode 100644 index 000000000..70e59a89f --- /dev/null +++ b/monkey/monkey_island/cc/dal/IConfigRepository.py @@ -0,0 +1,30 @@ +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 diff --git a/monkey/monkey_island/cc/dal/IEdgeRepository.py b/monkey/monkey_island/cc/dal/IEdgeRepository.py new file mode 100644 index 000000000..3b1393f31 --- /dev/null +++ b/monkey/monkey_island/cc/dal/IEdgeRepository.py @@ -0,0 +1,30 @@ +from abc import ABC +from typing import Optional, Sequence + +from monkey_island.cc.models.edge import Edge + + +class IEdgeRepository(ABC): + def get_all_edges(self): + pass + + def get_edges(self, src_machine_id: str, dst_machine_id: str) -> Sequence[Edge]: + pass + + def save_edge(self, edge: Edge): + pass + + def get_by_dst(self, dst_machine_id: str) -> Sequence[Edge]: + pass + + # If tunnel is None then it gets all edges, if True/False then gets only + # tunneling/non-tunneling edges + def get_by_src(self, src_machine_id: str, tunnel: Optional[bool] = None) -> Sequence[Edge]: + pass + + def get_by_id(self, edge_id: str) -> Edge: + pass + + # Scan telemetries might change the label once we know more about the target system + def set_label(self, edge_id: str, label: str): + pass diff --git a/monkey/monkey_island/cc/dal/IMachineRepository.py b/monkey/monkey_island/cc/dal/IMachineRepository.py new file mode 100644 index 000000000..99e7f49dc --- /dev/null +++ b/monkey/monkey_island/cc/dal/IMachineRepository.py @@ -0,0 +1,19 @@ +from abc import ABC +from typing import Optional, Sequence + + +class IMachineRepository(ABC): + # TODO define Machine object(ORM model) + def save_machine(self, machine: Machine): + pass + + # TODO define Machine object(ORM model) + # TODO define or re-use machine state. + def get_machines( + self, + id: Optional[str] = None, + ips: Optional[Sequence[str]] = None, + state: Optional[MachineState] = None, + is_island: Optional[bool] = None, + ) -> Sequence[Machine]: + pass diff --git a/monkey/monkey_island/cc/dal/IReportRepository.py b/monkey/monkey_island/cc/dal/IReportRepository.py new file mode 100644 index 000000000..6891c3c50 --- /dev/null +++ b/monkey/monkey_island/cc/dal/IReportRepository.py @@ -0,0 +1,14 @@ +from abc import ABC + +from monkey_island.cc.models import Report + + +class IReportRepository(ABC): + # Report (potentially should go away if split up into proper endpoints/services) + ################################# + def save_report(self, report: Report): + pass + + # Should return only one + def get_report(self) -> Report: + pass diff --git a/monkey/monkey_island/cc/dal/ISimulationRepository.py b/monkey/monkey_island/cc/dal/ISimulationRepository.py new file mode 100644 index 000000000..96cc3dc17 --- /dev/null +++ b/monkey/monkey_island/cc/dal/ISimulationRepository.py @@ -0,0 +1,11 @@ +from abc import ABC + + +class ISimulationRepository(ABC): + # TODO define simulation object. It should contain metadata about simulation, + # like start, end times, mode and last forced stop of all monkeys + def save_simulation(self, simulation: Simulation): + pass + + def get_simulation(self): + pass diff --git a/monkey/monkey_island/cc/dal/ITelemetryRepository.py b/monkey/monkey_island/cc/dal/ITelemetryRepository.py new file mode 100644 index 000000000..69aa2ff35 --- /dev/null +++ b/monkey/monkey_island/cc/dal/ITelemetryRepository.py @@ -0,0 +1,20 @@ +from abc import ABC +from typing import Optional, Sequence + +from monkey_island.cc.models.telemetries.telemetry import Telemetry + + +class ITelemetryRepository(ABC): + def save_telemetry(self, telemetry: Telemetry): + pass + + # TODO define all telemetry types + # Potentially we'll need to define each telem type separately. As it stands there's no way to + # get exploit telemetries by exploiter for example + def get_telemetries( + self, + id: Optional[str] = None, + type: Optional[TelemetryType] = None, + monkey_id: Optional[str] = None, + ) -> Sequence[Telemetry]: + pass