From d189a94e9c6e0faca0ee29fab690624e7219daaf Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 4 Aug 2022 12:31:21 +0530 Subject: [PATCH 01/17] Island: Rename local_ip_addresses() -> get_local_ip_addresses() --- monkey/monkey_island/cc/models/monkey.py | 4 ++-- monkey/monkey_island/cc/resources/ip_addresses.py | 4 ++-- monkey/monkey_island/cc/resources/root.py | 4 ++-- monkey/monkey_island/cc/server_setup.py | 6 ++++-- monkey/monkey_island/cc/services/node.py | 10 +++++----- monkey/monkey_island/cc/services/reporting/report.py | 4 ++-- monkey/monkey_island/cc/services/run_local_monkey.py | 4 ++-- .../monkey_island/cc/services/utils/network_utils.py | 2 +- 8 files changed, 20 insertions(+), 18 deletions(-) diff --git a/monkey/monkey_island/cc/models/monkey.py b/monkey/monkey_island/cc/models/monkey.py index a106f9965..3e518444d 100644 --- a/monkey/monkey_island/cc/models/monkey.py +++ b/monkey/monkey_island/cc/models/monkey.py @@ -19,7 +19,7 @@ from mongoengine import ( from monkey_island.cc.models.command_control_channel import CommandControlChannel from monkey_island.cc.models.monkey_ttl import MonkeyTtl, create_monkey_ttl_document from monkey_island.cc.server_utils.consts import DEFAULT_MONKEY_TTL_EXPIRY_DURATION_IN_SECONDS -from monkey_island.cc.services.utils.network_utils import local_ip_addresses +from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses class ParentNotFoundError(Exception): @@ -123,7 +123,7 @@ class Monkey(Document): def get_label_by_id(object_id): current_monkey = Monkey.get_single_monkey_by_id(object_id) label = Monkey.get_hostname_by_id(object_id) + " : " + current_monkey.ip_addresses[0] - if len(set(current_monkey.ip_addresses).intersection(local_ip_addresses())) > 0: + if len(set(current_monkey.ip_addresses).intersection(get_local_ip_addresses())) > 0: label = "MonkeyIsland - " + label return label diff --git a/monkey/monkey_island/cc/resources/ip_addresses.py b/monkey/monkey_island/cc/resources/ip_addresses.py index ef0e0fa4b..9b61d3e45 100644 --- a/monkey/monkey_island/cc/resources/ip_addresses.py +++ b/monkey/monkey_island/cc/resources/ip_addresses.py @@ -2,7 +2,7 @@ from typing import Mapping, Sequence from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.request_authentication import jwt_required -from monkey_island.cc.services.utils.network_utils import local_ip_addresses +from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses class IpAddresses(AbstractResource): @@ -15,6 +15,6 @@ class IpAddresses(AbstractResource): :return: a dictionary with "ip_addresses" key that points to a list of IP's """ - local_ips = local_ip_addresses() + local_ips = get_local_ip_addresses() return {"ip_addresses": local_ips} diff --git a/monkey/monkey_island/cc/resources/root.py b/monkey/monkey_island/cc/resources/root.py index ef53ff788..0bfc94a8c 100644 --- a/monkey/monkey_island/cc/resources/root.py +++ b/monkey/monkey_island/cc/resources/root.py @@ -6,7 +6,7 @@ from monkey_island.cc.database import mongo from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.request_authentication import jwt_required from monkey_island.cc.services.infection_lifecycle import get_completed_steps -from monkey_island.cc.services.utils.network_utils import local_ip_addresses +from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses logger = logging.getLogger(__name__) @@ -29,7 +29,7 @@ class Root(AbstractResource): @jwt_required def get_server_info(self): return jsonify( - ip_addresses=local_ip_addresses(), + ip_addresses=get_local_ip_addresses(), mongo=str(mongo.db), completed_steps=get_completed_steps(), ) diff --git a/monkey/monkey_island/cc/server_setup.py b/monkey/monkey_island/cc/server_setup.py index 3b08cd2f2..9dce509ef 100644 --- a/monkey/monkey_island/cc/server_setup.py +++ b/monkey/monkey_island/cc/server_setup.py @@ -27,7 +27,7 @@ from monkey_island.cc.server_utils.consts import ( # noqa: E402 ) from monkey_island.cc.server_utils.island_logger import reset_logger, setup_logging # noqa: E402 from monkey_island.cc.services.initialize import initialize_services # noqa: E402 -from monkey_island.cc.services.utils.network_utils import local_ip_addresses # noqa: E402 +from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses # noqa: E402 from monkey_island.cc.setup import PyWSGILoggingFilter # noqa: E402 from monkey_island.cc.setup import island_config_options_validator # noqa: E402 from monkey_island.cc.setup.data_dir import IncompatibleDataDirectory, setup_data_dir # noqa: E402 @@ -168,7 +168,9 @@ def _log_init_info(): def _log_web_interface_access_urls(): - web_interface_urls = ", ".join([f"https://{ip}:{ISLAND_PORT}" for ip in local_ip_addresses()]) + web_interface_urls = ", ".join( + [f"https://{ip}:{ISLAND_PORT}" for ip in get_local_ip_addresses()] + ) logger.info( "To access the web interface, navigate to one of the the following URLs using your " f"browser: {web_interface_urls}" diff --git a/monkey/monkey_island/cc/services/node.py b/monkey/monkey_island/cc/services/node.py index 4ffb3935d..e65a410fd 100644 --- a/monkey/monkey_island/cc/services/node.py +++ b/monkey/monkey_island/cc/services/node.py @@ -9,7 +9,7 @@ from monkey_island.cc.database import mongo from monkey_island.cc.models import Monkey from monkey_island.cc.services.edge.displayed_edge import DisplayedEdgeService from monkey_island.cc.services.edge.edge import EdgeService -from monkey_island.cc.services.utils.network_utils import local_ip_addresses +from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses from monkey_island.cc.services.utils.node_states import NodeStates @@ -110,7 +110,7 @@ class NodeService: def get_monkey_label(monkey): # todo label = monkey["hostname"] + " : " + monkey["ip_addresses"][0] - ip_addresses = local_ip_addresses() + ip_addresses = get_local_ip_addresses() if len(set(monkey["ip_addresses"]).intersection(ip_addresses)) > 0: label = "MonkeyIsland - " + label return label @@ -118,7 +118,7 @@ class NodeService: @staticmethod def get_monkey_group(monkey): keywords = [] - if len(set(monkey["ip_addresses"]).intersection(local_ip_addresses())) != 0: + if len(set(monkey["ip_addresses"]).intersection(get_local_ip_addresses())) != 0: keywords.extend(["island", "monkey"]) else: monkey_type = "manual" if NodeService.get_monkey_manual_run(monkey) else "monkey" @@ -275,7 +275,7 @@ class NodeService: # It's better to just initialize the island machine on reset I think @staticmethod def get_monkey_island_monkey(): - ip_addresses = local_ip_addresses() + ip_addresses = get_local_ip_addresses() for ip_address in ip_addresses: monkey = NodeService.get_monkey_by_ip(ip_address) if monkey is not None: @@ -297,7 +297,7 @@ class NodeService: @staticmethod def get_monkey_island_node(): island_node = NodeService.get_monkey_island_pseudo_net_node() - island_node["ip_addresses"] = local_ip_addresses() + island_node["ip_addresses"] = get_local_ip_addresses() island_node["domain_name"] = socket.gethostname() return island_node diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index 89c6d2a78..c21be0efb 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -19,7 +19,7 @@ from monkey_island.cc.services.reporting.pth_report import PTHReportService from monkey_island.cc.services.reporting.report_generation_synchronisation import ( safe_generate_regular_report, ) -from monkey_island.cc.services.utils.network_utils import get_subnets, local_ip_addresses +from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses, get_subnets from .. import AWSService from . import aws_exporter @@ -175,7 +175,7 @@ class ReportService: @staticmethod def get_island_cross_segment_issues(): issues = [] - island_ips = local_ip_addresses() + island_ips = get_local_ip_addresses() for monkey in mongo.db.monkey.find( {"tunnel": {"$exists": False}}, {"tunnel": 1, "guid": 1, "hostname": 1} ): diff --git a/monkey/monkey_island/cc/services/run_local_monkey.py b/monkey/monkey_island/cc/services/run_local_monkey.py index a56642e2c..529b67926 100644 --- a/monkey/monkey_island/cc/services/run_local_monkey.py +++ b/monkey/monkey_island/cc/services/run_local_monkey.py @@ -7,7 +7,7 @@ from shutil import copyfileobj from monkey_island.cc.repository import IAgentBinaryRepository, RetrievalError from monkey_island.cc.server_utils.consts import ISLAND_PORT -from monkey_island.cc.services.utils.network_utils import local_ip_addresses +from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses logger = logging.getLogger(__name__) @@ -59,7 +59,7 @@ class LocalMonkeyRunService: # run the monkey try: - ip = local_ip_addresses()[0] + ip = get_local_ip_addresses()[0] port = ISLAND_PORT args = [str(dest_path), "m0nk3y", "-s", f"{ip}:{port}"] diff --git a/monkey/monkey_island/cc/services/utils/network_utils.py b/monkey/monkey_island/cc/services/utils/network_utils.py index e68a68748..e25d50708 100644 --- a/monkey/monkey_island/cc/services/utils/network_utils.py +++ b/monkey/monkey_island/cc/services/utils/network_utils.py @@ -58,7 +58,7 @@ else: # lot of times during the report generation. This means that if the interfaces of the Island machine # change, the Island process needs to be restarted. @lru(maxsize=1) -def local_ip_addresses() -> Sequence[str]: +def get_local_ip_addresses() -> Sequence[str]: ip_list = [] for interface in interfaces(): addresses = ifaddresses(interface).get(AF_INET, []) From 1466fccc5feeff5036aabd9dfc2f9c08277157d4 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 4 Aug 2022 12:32:13 +0530 Subject: [PATCH 02/17] Island: Register convention 'local_ip_addresses' --- monkey/monkey_island/cc/services/initialize.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/monkey/monkey_island/cc/services/initialize.py b/monkey/monkey_island/cc/services/initialize.py index f8056cebc..5c989adfb 100644 --- a/monkey/monkey_island/cc/services/initialize.py +++ b/monkey/monkey_island/cc/services/initialize.py @@ -1,6 +1,7 @@ import json import logging from pathlib import Path +from typing import Sequence from pymongo import MongoClient @@ -14,6 +15,7 @@ from common.aws import AWSInstance from common.common_consts.telem_categories import TelemCategoryEnum from common.utils.file_utils import get_binary_io_sha256_hash from common.version import get_version +from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses from monkey_island.cc.deployment import Deployment from monkey_island.cc.repository import ( AgentBinaryRepository, @@ -96,6 +98,7 @@ def _register_conventions(container: DIContainer, data_dir: Path): ) container.register_convention(Path, "island_log_file_path", get_log_file_path(data_dir)) container.register_convention(str, "version_number", get_version()) + container.register_convention(Sequence[str], "local_ip_addresses", get_local_ip_addresses()) def _register_repositories(container: DIContainer, data_dir: Path): From 637c466822a94cc100fab9d670146c30ec8b28b8 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 4 Aug 2022 12:35:47 +0530 Subject: [PATCH 03/17] Island: Pass local_ip_addresses in IpAddresses resource constructor --- monkey/monkey_island/cc/resources/ip_addresses.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/monkey/monkey_island/cc/resources/ip_addresses.py b/monkey/monkey_island/cc/resources/ip_addresses.py index 9b61d3e45..653aaf93d 100644 --- a/monkey/monkey_island/cc/resources/ip_addresses.py +++ b/monkey/monkey_island/cc/resources/ip_addresses.py @@ -2,12 +2,14 @@ from typing import Mapping, Sequence from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.request_authentication import jwt_required -from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses class IpAddresses(AbstractResource): urls = ["/api/island/ip-addresses"] + def __init__(self, local_ip_addresses: Sequence[str]): + self._local_ips = local_ip_addresses + @jwt_required def get(self) -> Mapping[str, Sequence[str]]: """ @@ -15,6 +17,5 @@ class IpAddresses(AbstractResource): :return: a dictionary with "ip_addresses" key that points to a list of IP's """ - local_ips = get_local_ip_addresses() - return {"ip_addresses": local_ips} + return {"ip_addresses": self._local_ips} From 860eb1b65c9c2be0f9a18c0d46ab4daee810eac7 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 4 Aug 2022 12:43:24 +0530 Subject: [PATCH 04/17] Island: Simply return IPs list instead of mapping in IpAddresses resource --- monkey/monkey_island/cc/resources/ip_addresses.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/monkey/monkey_island/cc/resources/ip_addresses.py b/monkey/monkey_island/cc/resources/ip_addresses.py index 653aaf93d..b64a032f9 100644 --- a/monkey/monkey_island/cc/resources/ip_addresses.py +++ b/monkey/monkey_island/cc/resources/ip_addresses.py @@ -1,4 +1,4 @@ -from typing import Mapping, Sequence +from typing import Sequence from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.request_authentication import jwt_required @@ -11,11 +11,11 @@ class IpAddresses(AbstractResource): self._local_ips = local_ip_addresses @jwt_required - def get(self) -> Mapping[str, Sequence[str]]: + def get(self) -> Sequence[str]: """ Gets the IP addresses of the Island network interfaces :return: a dictionary with "ip_addresses" key that points to a list of IP's """ - return {"ip_addresses": self._local_ips} + return self._local_ips From e2702ffacba088ca5c58e5199b4143f1fb78c4ca Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 4 Aug 2022 12:49:47 +0530 Subject: [PATCH 05/17] UI: Modify RunOptions page to correctly display IPs in manual run option --- .../cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js index 99f7f92b7..87a872c5f 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js @@ -23,8 +23,7 @@ function RunOptions(props) { if (initialized === false) { authComponent.authFetch(IP_ADDRESSES_URL) .then(res => res.json()) - .then(res => { - let ipAddresses = res.ip_addresses; + .then(ipAddresses => { setIps(ipAddresses); setInitialized(true); }); From 6b89f38f876430863abf315900e2d1200f2e1435 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 4 Aug 2022 12:52:25 +0530 Subject: [PATCH 06/17] Island: Fix docstrings in IpAddresses resource --- monkey/monkey_island/cc/resources/ip_addresses.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/monkey/monkey_island/cc/resources/ip_addresses.py b/monkey/monkey_island/cc/resources/ip_addresses.py index b64a032f9..85e88b094 100644 --- a/monkey/monkey_island/cc/resources/ip_addresses.py +++ b/monkey/monkey_island/cc/resources/ip_addresses.py @@ -5,6 +5,10 @@ from monkey_island.cc.resources.request_authentication import jwt_required class IpAddresses(AbstractResource): + """ + Endpoint for the Monkey Island's local IP addresses + """ + urls = ["/api/island/ip-addresses"] def __init__(self, local_ip_addresses: Sequence[str]): @@ -13,9 +17,9 @@ class IpAddresses(AbstractResource): @jwt_required def get(self) -> Sequence[str]: """ - Gets the IP addresses of the Island network interfaces + Sends the local IP addresses of the Island - :return: a dictionary with "ip_addresses" key that points to a list of IP's + :return: Local IPs """ return self._local_ips From e4d7f36985c7d15f4124846a3fe22d5d0c51d6d1 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 4 Aug 2022 12:53:36 +0530 Subject: [PATCH 07/17] Island: Rename IpAddresses -> IPAddresses --- monkey/monkey_island/cc/app.py | 4 ++-- monkey/monkey_island/cc/resources/ip_addresses.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index cd7d46018..cf8e5b4cd 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -33,7 +33,7 @@ from monkey_island.cc.resources.blackbox.telemetry_blackbox_endpoint import ( from monkey_island.cc.resources.edge import Edge from monkey_island.cc.resources.exploitations.manual_exploitation import ManualExploitation from monkey_island.cc.resources.exploitations.monkey_exploitation import MonkeyExploitation -from monkey_island.cc.resources.ip_addresses import IpAddresses +from monkey_island.cc.resources.ip_addresses import IPAddresses from monkey_island.cc.resources.island_mode import IslandMode from monkey_island.cc.resources.local_run import LocalRun from monkey_island.cc.resources.log import Log @@ -179,7 +179,7 @@ def init_restful_endpoints(api: FlaskDIWrapper): api.add_resource(TelemetryFeed) api.add_resource(Log) api.add_resource(IslandLog) - api.add_resource(IpAddresses) + api.add_resource(IPAddresses) # API Spec: These two should be the same resource, GET for download and POST for upload api.add_resource(PBAFileDownload) diff --git a/monkey/monkey_island/cc/resources/ip_addresses.py b/monkey/monkey_island/cc/resources/ip_addresses.py index 85e88b094..981adfb8d 100644 --- a/monkey/monkey_island/cc/resources/ip_addresses.py +++ b/monkey/monkey_island/cc/resources/ip_addresses.py @@ -4,7 +4,7 @@ from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.request_authentication import jwt_required -class IpAddresses(AbstractResource): +class IPAddresses(AbstractResource): """ Endpoint for the Monkey Island's local IP addresses """ From 80c6ee88051af5a64d8dd288e54d0ad78c0cf059 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 4 Aug 2022 12:59:18 +0530 Subject: [PATCH 08/17] Island: Inject local_ip_addresses into LocalMonkeyRunService's constructor --- monkey/monkey_island/cc/services/run_local_monkey.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/monkey/monkey_island/cc/services/run_local_monkey.py b/monkey/monkey_island/cc/services/run_local_monkey.py index 529b67926..f47a73a74 100644 --- a/monkey/monkey_island/cc/services/run_local_monkey.py +++ b/monkey/monkey_island/cc/services/run_local_monkey.py @@ -4,10 +4,10 @@ import stat import subprocess from pathlib import Path from shutil import copyfileobj +from typing import Sequence from monkey_island.cc.repository import IAgentBinaryRepository, RetrievalError from monkey_island.cc.server_utils.consts import ISLAND_PORT -from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses logger = logging.getLogger(__name__) @@ -15,9 +15,15 @@ AGENT_NAMES = {"linux": "monkey-linux-64", "windows": "monkey-windows-64.exe"} class LocalMonkeyRunService: - def __init__(self, data_dir: Path, agent_binary_repository: IAgentBinaryRepository): + def __init__( + self, + data_dir: Path, + agent_binary_repository: IAgentBinaryRepository, + local_ip_addresses: Sequence[str], + ): self._data_dir = data_dir self._agent_binary_repository = agent_binary_repository + self._local_ips = local_ip_addresses def run_local_monkey(self): # get the monkey executable suitable to run on the server @@ -59,7 +65,7 @@ class LocalMonkeyRunService: # run the monkey try: - ip = get_local_ip_addresses()[0] + ip = self._local_ips[0] port = ISLAND_PORT args = [str(dest_path), "m0nk3y", "-s", f"{ip}:{port}"] From 4ee1450001cf6d79b807ce350c0de511108f2b5d Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 4 Aug 2022 13:03:04 +0530 Subject: [PATCH 09/17] Island: Inject local_ip_addresses into Root resource's constructor --- monkey/monkey_island/cc/resources/root.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/monkey/monkey_island/cc/resources/root.py b/monkey/monkey_island/cc/resources/root.py index 0bfc94a8c..dcf07c9aa 100644 --- a/monkey/monkey_island/cc/resources/root.py +++ b/monkey/monkey_island/cc/resources/root.py @@ -1,4 +1,5 @@ import logging +from typing import Sequence from flask import jsonify, make_response, request @@ -6,7 +7,6 @@ from monkey_island.cc.database import mongo from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.request_authentication import jwt_required from monkey_island.cc.services.infection_lifecycle import get_completed_steps -from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses logger = logging.getLogger(__name__) @@ -15,6 +15,9 @@ class Root(AbstractResource): urls = ["/api"] + def __init__(self, local_ip_addresses: Sequence[str]): + self._local_ips = local_ip_addresses + def get(self, action=None): if not action: action = request.args.get("action") @@ -29,7 +32,7 @@ class Root(AbstractResource): @jwt_required def get_server_info(self): return jsonify( - ip_addresses=get_local_ip_addresses(), + ip_addresses=self._local_ips, mongo=str(mongo.db), completed_steps=get_completed_steps(), ) From 144268187f35446070b4881deb7df5b77b932d46 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 4 Aug 2022 13:06:08 +0530 Subject: [PATCH 10/17] Island: Add IPAddresses to cc/resources/__init__.py and shorten imports --- monkey/monkey_island/cc/app.py | 2 +- monkey/monkey_island/cc/resources/__init__.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index cf8e5b4cd..570d1bee8 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -13,6 +13,7 @@ from monkey_island.cc.database import database, mongo from monkey_island.cc.resources import ( AgentBinaries, ClearSimulationData, + IPAddresses, IslandLog, PropagationCredentials, RemoteRun, @@ -33,7 +34,6 @@ from monkey_island.cc.resources.blackbox.telemetry_blackbox_endpoint import ( from monkey_island.cc.resources.edge import Edge from monkey_island.cc.resources.exploitations.manual_exploitation import ManualExploitation from monkey_island.cc.resources.exploitations.monkey_exploitation import MonkeyExploitation -from monkey_island.cc.resources.ip_addresses import IPAddresses from monkey_island.cc.resources.island_mode import IslandMode from monkey_island.cc.resources.local_run import LocalRun from monkey_island.cc.resources.log import Log diff --git a/monkey/monkey_island/cc/resources/__init__.py b/monkey/monkey_island/cc/resources/__init__.py index 28a55cd09..91024a6e3 100644 --- a/monkey/monkey_island/cc/resources/__init__.py +++ b/monkey/monkey_island/cc/resources/__init__.py @@ -4,3 +4,4 @@ from .clear_simulation_data import ClearSimulationData from .island_log import IslandLog from .reset_agent_configuration import ResetAgentConfiguration from .propagation_credentials import PropagationCredentials +from .ip_addresses import IPAddresses From eb4f704597d6707e8babbd48dc9257bc42ff3ea0 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 4 Aug 2022 13:41:55 +0530 Subject: [PATCH 11/17] UT: Hacky workaround in StubDIContainer to get the tests passing for now --- monkey/tests/common/stub_di_container.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/monkey/tests/common/stub_di_container.py b/monkey/tests/common/stub_di_container.py index bed434145..85034fc79 100644 --- a/monkey/tests/common/stub_di_container.py +++ b/monkey/tests/common/stub_di_container.py @@ -7,6 +7,10 @@ T = TypeVar("T") class StubDIContainer(DIContainer): + def __init__(self): + super().__init__() + self._convention_registry[(Sequence[str], "local_ip_addresses")] = [] + def resolve(self, type_: Type[T]) -> T: try: return super().resolve(type_) From 407bf892e54caff9c2dfcae62ae7171a3a04c6e2 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 4 Aug 2022 16:55:59 +0530 Subject: [PATCH 12/17] Island: Fix import order in cc/services/initialize.py --- monkey/monkey_island/cc/services/initialize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monkey/monkey_island/cc/services/initialize.py b/monkey/monkey_island/cc/services/initialize.py index 5c989adfb..a03f2f6c0 100644 --- a/monkey/monkey_island/cc/services/initialize.py +++ b/monkey/monkey_island/cc/services/initialize.py @@ -15,7 +15,6 @@ from common.aws import AWSInstance from common.common_consts.telem_categories import TelemCategoryEnum from common.utils.file_utils import get_binary_io_sha256_hash from common.version import get_version -from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses from monkey_island.cc.deployment import Deployment from monkey_island.cc.repository import ( AgentBinaryRepository, @@ -47,6 +46,7 @@ from monkey_island.cc.services.telemetry.processing.credentials.credentials_pars from monkey_island.cc.services.telemetry.processing.processing import ( TELEMETRY_CATEGORY_TO_PROCESSING_FUNC, ) +from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses from monkey_island.cc.setup.mongo.mongo_setup import MONGO_URL from monkey_island.cc.version import Version From 5f91e39b39420f75b59e42ba8613d6d90457ed0e Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Thu, 4 Aug 2022 10:44:08 -0400 Subject: [PATCH 13/17] Common: Handle classes without __name__ in DIContainer --- monkey/common/di_container.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/monkey/common/di_container.py b/monkey/common/di_container.py index c1c740e39..9220864c3 100644 --- a/monkey/common/di_container.py +++ b/monkey/common/di_container.py @@ -35,13 +35,14 @@ class DIContainer: if not inspect.isclass(concrete_type): raise TypeError( "Expected a class, but received an instance of type " - f'"{concrete_type.__class__.__name__}"; Pass a class, not an instance, to ' - "register(), or use register_instance() instead" + f'"{DIContainer._format_type_name(concrete_type.__class__)}"; Pass a class, not an ' + "instance, to register(), or use register_instance() instead" ) if not issubclass(concrete_type, interface): raise TypeError( - f'Class "{concrete_type.__name__}" is not a subclass of {interface.__name__}' + f'Class "{DIContainer._format_type_name(concrete_type)}" is not a subclass of ' + f"{DIContainer._format_type_name(interface)}" ) self._type_registry[interface] = concrete_type @@ -56,8 +57,9 @@ class DIContainer: """ if not isinstance(instance, interface): raise TypeError( - f'The provided instance of type "{instance.__class__.__name__}" ' - f"is not an instance of {interface.__name__}" + "The provided instance of type " + f'"{DIContainer._format_type_name(instance.__class__)}" ' + f"is not an instance of {DIContainer._format_type_name(interface)}" ) self._instance_registry[interface] = instance @@ -151,7 +153,9 @@ class DIContainer: elif type_ in self._instance_registry: return self._retrieve_registered_instance(type_) - raise UnregisteredTypeError(f'Failed to resolve unregistered type "{type_.__name__}"') + raise UnregisteredTypeError( + f'Failed to resolve unregistered type "{DIContainer._format_type_name(type)}"' + ) def _construct_new_instance(self, arg_type: Type[T]) -> T: try: @@ -182,3 +186,13 @@ class DIContainer: """ convention_identifier = (type_, name) del_key(self._convention_registry, convention_identifier) + + @staticmethod + def _format_type_name(type_: Type) -> str: + try: + return type_.__name__ + except AttributeError: + # Some Types, like typing.Sequence, don't have a __name__ attribute in python3.7. When + # we upgrade to a later version of Python, this exception handler may no longer be + # necessary. + return str(type_) From 2e05987e7e9c7ce46c3c299c14ede9b9492b5b87 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Thu, 4 Aug 2022 10:49:08 -0400 Subject: [PATCH 14/17] Revert "UT: Hacky workaround in StubDIContainer to get the tests passing for now" This reverts commit eb4f704597d6707e8babbd48dc9257bc42ff3ea0. This was resolved by 5f91e39 instead. --- monkey/tests/common/stub_di_container.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/monkey/tests/common/stub_di_container.py b/monkey/tests/common/stub_di_container.py index 85034fc79..bed434145 100644 --- a/monkey/tests/common/stub_di_container.py +++ b/monkey/tests/common/stub_di_container.py @@ -7,10 +7,6 @@ T = TypeVar("T") class StubDIContainer(DIContainer): - def __init__(self): - super().__init__() - self._convention_registry[(Sequence[str], "local_ip_addresses")] = [] - def resolve(self, type_: Type[T]) -> T: try: return super().resolve(type_) From 3f14b96b71689399404f17581c4ed2d67ad6e4ae Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Fri, 5 Aug 2022 13:13:51 +0530 Subject: [PATCH 15/17] UI: Get IP addresses from /api/island/ip-addresses instead of /api in AWSRunOptions.js --- .../pages/RunMonkeyPage/RunOnAWS/AWSRunOptions.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSRunOptions.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSRunOptions.js index e6c2290b2..a91da1c36 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSRunOptions.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOnAWS/AWSRunOptions.js @@ -32,11 +32,11 @@ const getContents = (props) => { }, []); function getIps() { - authComponent.authFetch('/api') + authComponent.authFetch('/api/island/ip-addresses') .then(res => res.json()) - .then(res => { - setAllIPs(res['ip_addresses']); - setSelectedIp(res['ip_addresses'][0]); + .then(ip_addresses => { + setAllIPs(ip_addresses); + setSelectedIp(ip_addresses[0]); }); } From 4095e130f9f17622a75e82151d7fccc6f414538e Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Fri, 5 Aug 2022 13:17:00 +0530 Subject: [PATCH 16/17] Island: Don't return IP addresses from Root resource's GET --- monkey/monkey_island/cc/resources/root.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/monkey/monkey_island/cc/resources/root.py b/monkey/monkey_island/cc/resources/root.py index dcf07c9aa..4200029a4 100644 --- a/monkey/monkey_island/cc/resources/root.py +++ b/monkey/monkey_island/cc/resources/root.py @@ -1,5 +1,4 @@ import logging -from typing import Sequence from flask import jsonify, make_response, request @@ -15,9 +14,6 @@ class Root(AbstractResource): urls = ["/api"] - def __init__(self, local_ip_addresses: Sequence[str]): - self._local_ips = local_ip_addresses - def get(self, action=None): if not action: action = request.args.get("action") @@ -32,7 +28,6 @@ class Root(AbstractResource): @jwt_required def get_server_info(self): return jsonify( - ip_addresses=self._local_ips, mongo=str(mongo.db), completed_steps=get_completed_steps(), ) From 2be0e088e0162d340055e76a78f3fe72f65bb9db Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Fri, 5 Aug 2022 13:35:39 +0530 Subject: [PATCH 17/17] Island: Fix all references to 'local' IPs which may not always be local --- monkey/monkey_island/cc/models/monkey.py | 4 ++-- monkey/monkey_island/cc/resources/ip_addresses.py | 12 ++++++------ monkey/monkey_island/cc/server_setup.py | 6 ++---- monkey/monkey_island/cc/services/initialize.py | 4 ++-- monkey/monkey_island/cc/services/node.py | 10 +++++----- monkey/monkey_island/cc/services/reporting/report.py | 4 ++-- monkey/monkey_island/cc/services/run_local_monkey.py | 6 +++--- .../monkey_island/cc/services/utils/network_utils.py | 2 +- 8 files changed, 23 insertions(+), 25 deletions(-) diff --git a/monkey/monkey_island/cc/models/monkey.py b/monkey/monkey_island/cc/models/monkey.py index 3e518444d..003e14509 100644 --- a/monkey/monkey_island/cc/models/monkey.py +++ b/monkey/monkey_island/cc/models/monkey.py @@ -19,7 +19,7 @@ from mongoengine import ( from monkey_island.cc.models.command_control_channel import CommandControlChannel from monkey_island.cc.models.monkey_ttl import MonkeyTtl, create_monkey_ttl_document from monkey_island.cc.server_utils.consts import DEFAULT_MONKEY_TTL_EXPIRY_DURATION_IN_SECONDS -from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses +from monkey_island.cc.services.utils.network_utils import get_ip_addresses class ParentNotFoundError(Exception): @@ -123,7 +123,7 @@ class Monkey(Document): def get_label_by_id(object_id): current_monkey = Monkey.get_single_monkey_by_id(object_id) label = Monkey.get_hostname_by_id(object_id) + " : " + current_monkey.ip_addresses[0] - if len(set(current_monkey.ip_addresses).intersection(get_local_ip_addresses())) > 0: + if len(set(current_monkey.ip_addresses).intersection(get_ip_addresses())) > 0: label = "MonkeyIsland - " + label return label diff --git a/monkey/monkey_island/cc/resources/ip_addresses.py b/monkey/monkey_island/cc/resources/ip_addresses.py index 981adfb8d..3ba7d6123 100644 --- a/monkey/monkey_island/cc/resources/ip_addresses.py +++ b/monkey/monkey_island/cc/resources/ip_addresses.py @@ -6,20 +6,20 @@ from monkey_island.cc.resources.request_authentication import jwt_required class IPAddresses(AbstractResource): """ - Endpoint for the Monkey Island's local IP addresses + Endpoint for the Monkey Island's IP addresses """ urls = ["/api/island/ip-addresses"] - def __init__(self, local_ip_addresses: Sequence[str]): - self._local_ips = local_ip_addresses + def __init__(self, ip_addresses: Sequence[str]): + self._ips = ip_addresses @jwt_required def get(self) -> Sequence[str]: """ - Sends the local IP addresses of the Island + Sends the IP addresses of the Island - :return: Local IPs + :return: IP addresses """ - return self._local_ips + return self._ips diff --git a/monkey/monkey_island/cc/server_setup.py b/monkey/monkey_island/cc/server_setup.py index 9dce509ef..eed949a02 100644 --- a/monkey/monkey_island/cc/server_setup.py +++ b/monkey/monkey_island/cc/server_setup.py @@ -27,7 +27,7 @@ from monkey_island.cc.server_utils.consts import ( # noqa: E402 ) from monkey_island.cc.server_utils.island_logger import reset_logger, setup_logging # noqa: E402 from monkey_island.cc.services.initialize import initialize_services # noqa: E402 -from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses # noqa: E402 +from monkey_island.cc.services.utils.network_utils import get_ip_addresses # noqa: E402 from monkey_island.cc.setup import PyWSGILoggingFilter # noqa: E402 from monkey_island.cc.setup import island_config_options_validator # noqa: E402 from monkey_island.cc.setup.data_dir import IncompatibleDataDirectory, setup_data_dir # noqa: E402 @@ -168,9 +168,7 @@ def _log_init_info(): def _log_web_interface_access_urls(): - web_interface_urls = ", ".join( - [f"https://{ip}:{ISLAND_PORT}" for ip in get_local_ip_addresses()] - ) + web_interface_urls = ", ".join([f"https://{ip}:{ISLAND_PORT}" for ip in get_ip_addresses()]) logger.info( "To access the web interface, navigate to one of the the following URLs using your " f"browser: {web_interface_urls}" diff --git a/monkey/monkey_island/cc/services/initialize.py b/monkey/monkey_island/cc/services/initialize.py index a03f2f6c0..d89d931a0 100644 --- a/monkey/monkey_island/cc/services/initialize.py +++ b/monkey/monkey_island/cc/services/initialize.py @@ -46,7 +46,7 @@ from monkey_island.cc.services.telemetry.processing.credentials.credentials_pars from monkey_island.cc.services.telemetry.processing.processing import ( TELEMETRY_CATEGORY_TO_PROCESSING_FUNC, ) -from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses +from monkey_island.cc.services.utils.network_utils import get_ip_addresses from monkey_island.cc.setup.mongo.mongo_setup import MONGO_URL from monkey_island.cc.version import Version @@ -98,7 +98,7 @@ def _register_conventions(container: DIContainer, data_dir: Path): ) container.register_convention(Path, "island_log_file_path", get_log_file_path(data_dir)) container.register_convention(str, "version_number", get_version()) - container.register_convention(Sequence[str], "local_ip_addresses", get_local_ip_addresses()) + container.register_convention(Sequence[str], "ip_addresses", get_ip_addresses()) def _register_repositories(container: DIContainer, data_dir: Path): diff --git a/monkey/monkey_island/cc/services/node.py b/monkey/monkey_island/cc/services/node.py index e65a410fd..faac42539 100644 --- a/monkey/monkey_island/cc/services/node.py +++ b/monkey/monkey_island/cc/services/node.py @@ -9,7 +9,7 @@ from monkey_island.cc.database import mongo from monkey_island.cc.models import Monkey from monkey_island.cc.services.edge.displayed_edge import DisplayedEdgeService from monkey_island.cc.services.edge.edge import EdgeService -from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses +from monkey_island.cc.services.utils.network_utils import get_ip_addresses from monkey_island.cc.services.utils.node_states import NodeStates @@ -110,7 +110,7 @@ class NodeService: def get_monkey_label(monkey): # todo label = monkey["hostname"] + " : " + monkey["ip_addresses"][0] - ip_addresses = get_local_ip_addresses() + ip_addresses = get_ip_addresses() if len(set(monkey["ip_addresses"]).intersection(ip_addresses)) > 0: label = "MonkeyIsland - " + label return label @@ -118,7 +118,7 @@ class NodeService: @staticmethod def get_monkey_group(monkey): keywords = [] - if len(set(monkey["ip_addresses"]).intersection(get_local_ip_addresses())) != 0: + if len(set(monkey["ip_addresses"]).intersection(get_ip_addresses())) != 0: keywords.extend(["island", "monkey"]) else: monkey_type = "manual" if NodeService.get_monkey_manual_run(monkey) else "monkey" @@ -275,7 +275,7 @@ class NodeService: # It's better to just initialize the island machine on reset I think @staticmethod def get_monkey_island_monkey(): - ip_addresses = get_local_ip_addresses() + ip_addresses = get_ip_addresses() for ip_address in ip_addresses: monkey = NodeService.get_monkey_by_ip(ip_address) if monkey is not None: @@ -297,7 +297,7 @@ class NodeService: @staticmethod def get_monkey_island_node(): island_node = NodeService.get_monkey_island_pseudo_net_node() - island_node["ip_addresses"] = get_local_ip_addresses() + island_node["ip_addresses"] = get_ip_addresses() island_node["domain_name"] = socket.gethostname() return island_node diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index c21be0efb..32761c7a6 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -19,7 +19,7 @@ from monkey_island.cc.services.reporting.pth_report import PTHReportService from monkey_island.cc.services.reporting.report_generation_synchronisation import ( safe_generate_regular_report, ) -from monkey_island.cc.services.utils.network_utils import get_local_ip_addresses, get_subnets +from monkey_island.cc.services.utils.network_utils import get_ip_addresses, get_subnets from .. import AWSService from . import aws_exporter @@ -175,7 +175,7 @@ class ReportService: @staticmethod def get_island_cross_segment_issues(): issues = [] - island_ips = get_local_ip_addresses() + island_ips = get_ip_addresses() for monkey in mongo.db.monkey.find( {"tunnel": {"$exists": False}}, {"tunnel": 1, "guid": 1, "hostname": 1} ): diff --git a/monkey/monkey_island/cc/services/run_local_monkey.py b/monkey/monkey_island/cc/services/run_local_monkey.py index f47a73a74..36c348b85 100644 --- a/monkey/monkey_island/cc/services/run_local_monkey.py +++ b/monkey/monkey_island/cc/services/run_local_monkey.py @@ -19,11 +19,11 @@ class LocalMonkeyRunService: self, data_dir: Path, agent_binary_repository: IAgentBinaryRepository, - local_ip_addresses: Sequence[str], + ip_addresses: Sequence[str], ): self._data_dir = data_dir self._agent_binary_repository = agent_binary_repository - self._local_ips = local_ip_addresses + self._ips = ip_addresses def run_local_monkey(self): # get the monkey executable suitable to run on the server @@ -65,7 +65,7 @@ class LocalMonkeyRunService: # run the monkey try: - ip = self._local_ips[0] + ip = self._ips[0] port = ISLAND_PORT args = [str(dest_path), "m0nk3y", "-s", f"{ip}:{port}"] diff --git a/monkey/monkey_island/cc/services/utils/network_utils.py b/monkey/monkey_island/cc/services/utils/network_utils.py index e25d50708..8af255ee0 100644 --- a/monkey/monkey_island/cc/services/utils/network_utils.py +++ b/monkey/monkey_island/cc/services/utils/network_utils.py @@ -58,7 +58,7 @@ else: # lot of times during the report generation. This means that if the interfaces of the Island machine # change, the Island process needs to be restarted. @lru(maxsize=1) -def get_local_ip_addresses() -> Sequence[str]: +def get_ip_addresses() -> Sequence[str]: ip_list = [] for interface in interfaces(): addresses = ifaddresses(interface).get(AF_INET, [])