From 84c78c4d8fbadb73e639a01fd1f73dad6b87d3cb Mon Sep 17 00:00:00 2001 From: vakarisz Date: Wed, 25 May 2022 11:19:24 +0300 Subject: [PATCH] Island: Reduce coupling between resources and flask --- monkey/monkey_island/cc/app.py | 6 ++++-- .../cc/resources/AbstractResource.py | 6 ++++++ .../agent_controls/stop_agent_check.py | 6 ++---- .../resources/agent_controls/stop_all_agents.py | 5 ++--- .../cc/resources/attack/attack_report.py | 5 ++--- monkey/monkey_island/cc/resources/auth/auth.py | 8 ++------ .../cc/resources/auth/registration.py | 5 ++--- .../cc/resources/blackbox/clear_caches.py | 4 ++-- .../resources/blackbox/log_blackbox_endpoint.py | 5 ++--- .../blackbox/monkey_blackbox_endpoint.py | 5 ++--- .../blackbox/telemetry_blackbox_endpoint.py | 5 ++--- .../cc/resources/configuration_export.py | 5 ++--- .../cc/resources/configuration_import.py | 5 ++--- monkey/monkey_island/cc/resources/edge.py | 5 ++--- .../exploitations/manual_exploitation.py | 6 ++---- .../exploitations/monkey_exploitation.py | 6 ++---- monkey/monkey_island/cc/resources/i_resource.py | 17 ----------------- .../cc/resources/island_configuration.py | 5 ++--- .../monkey_island/cc/resources/island_logs.py | 6 ++---- .../monkey_island/cc/resources/island_mode.py | 5 ++--- monkey/monkey_island/cc/resources/local_run.py | 5 ++--- monkey/monkey_island/cc/resources/log.py | 5 ++--- monkey/monkey_island/cc/resources/monkey.py | 5 ++--- .../cc/resources/monkey_download.py | 5 ++--- monkey/monkey_island/cc/resources/netmap.py | 6 ++---- monkey/monkey_island/cc/resources/node.py | 5 ++--- .../monkey_island/cc/resources/node_states.py | 6 ++---- .../cc/resources/pba_file_download.py | 5 ++--- .../cc/resources/pba_file_upload.py | 5 ++--- .../cc/resources/propagation_credentials.py | 6 ++---- .../cc/resources/ransomware_report.py | 5 ++--- monkey/monkey_island/cc/resources/remote_run.py | 5 ++--- monkey/monkey_island/cc/resources/root.py | 5 ++--- .../cc/resources/security_report.py | 6 ++---- monkey/monkey_island/cc/resources/telemetry.py | 5 ++--- .../cc/resources/telemetry_feed.py | 5 ++--- .../cc/resources/version_update.py | 6 ++---- .../cc/resources/zero_trust/finding_event.py | 6 ++---- .../resources/zero_trust/zero_trust_report.py | 4 ++-- .../unit_tests/monkey_island/cc/test_app.py | 5 ++--- .../tests/unit_tests/monkey_island/conftest.py | 4 ++-- 41 files changed, 86 insertions(+), 143 deletions(-) create mode 100644 monkey/monkey_island/cc/resources/AbstractResource.py delete mode 100644 monkey/monkey_island/cc/resources/i_resource.py diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index 13035bebd..c973eb2fb 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -11,6 +11,7 @@ from werkzeug.exceptions import NotFound from common import DIContainer from monkey_island.cc.database import database, mongo from monkey_island.cc.resources import RemoteRun +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.agent_controls import StopAgentCheck, StopAllAgents from monkey_island.cc.resources.attack.attack_report import AttackReport from monkey_island.cc.resources.auth.auth import Authenticate, init_jwt @@ -26,7 +27,6 @@ from monkey_island.cc.resources.configuration_import import ConfigurationImport 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.i_resource import IResource from monkey_island.cc.resources.island_configuration import IslandConfiguration from monkey_island.cc.resources.island_logs import IslandLog from monkey_island.cc.resources.island_mode import IslandMode @@ -121,7 +121,9 @@ class FlaskDIWrapper: self._container = container self._reserved_urls = set() - def add_resource(self, resource: Type[IResource]): + def add_resource(self, resource: Type[AbstractResource]): + assert "urls" in resource.__dict__, f"Resource {resource} has no defined URLs" + self._reserve_urls(resource.urls) dependencies = self._container.resolve_dependencies(resource) diff --git a/monkey/monkey_island/cc/resources/AbstractResource.py b/monkey/monkey_island/cc/resources/AbstractResource.py new file mode 100644 index 000000000..1788c641d --- /dev/null +++ b/monkey/monkey_island/cc/resources/AbstractResource.py @@ -0,0 +1,6 @@ +import flask_restful + + +# The purpose of this class is to decouple resources from flask +class AbstractResource(flask_restful.Resource): + pass diff --git a/monkey/monkey_island/cc/resources/agent_controls/stop_agent_check.py b/monkey/monkey_island/cc/resources/agent_controls/stop_agent_check.py index d92992b27..e26b2d172 100644 --- a/monkey/monkey_island/cc/resources/agent_controls/stop_agent_check.py +++ b/monkey/monkey_island/cc/resources/agent_controls/stop_agent_check.py @@ -1,10 +1,8 @@ -import flask_restful - -from monkey_island.cc.resources.i_resource import IResource +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.services.infection_lifecycle import should_agent_die -class StopAgentCheck(flask_restful.Resource, IResource): +class StopAgentCheck(AbstractResource): urls = ["/api/monkey-control/needs-to-stop/"] def get(self, monkey_guid: int): diff --git a/monkey/monkey_island/cc/resources/agent_controls/stop_all_agents.py b/monkey/monkey_island/cc/resources/agent_controls/stop_all_agents.py index 3d43eeba4..c843a3d79 100644 --- a/monkey/monkey_island/cc/resources/agent_controls/stop_all_agents.py +++ b/monkey/monkey_island/cc/resources/agent_controls/stop_all_agents.py @@ -1,15 +1,14 @@ import json -import flask_restful from flask import make_response, request +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.resources.utils.semaphores import agent_killing_mutex from monkey_island.cc.services.infection_lifecycle import set_stop_all, should_agent_die -class StopAllAgents(flask_restful.Resource, IResource): +class StopAllAgents(AbstractResource): urls = ["/api/monkey-control/stop-all-agents"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/attack/attack_report.py b/monkey/monkey_island/cc/resources/attack/attack_report.py index b35355d41..95675e5b6 100644 --- a/monkey/monkey_island/cc/resources/attack/attack_report.py +++ b/monkey/monkey_island/cc/resources/attack/attack_report.py @@ -1,13 +1,12 @@ -import flask_restful from flask import current_app, json +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.attack.attack_report import AttackReportService from monkey_island.cc.services.attack.attack_schema import SCHEMA -class AttackReport(flask_restful.Resource, IResource): +class AttackReport(AbstractResource): urls = ["/api/report/attack"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/auth/auth.py b/monkey/monkey_island/cc/resources/auth/auth.py index d683b4d65..e7a2d742e 100644 --- a/monkey/monkey_island/cc/resources/auth/auth.py +++ b/monkey/monkey_island/cc/resources/auth/auth.py @@ -1,15 +1,11 @@ import logging -from functools import wraps import flask_jwt_extended -import flask_restful from flask import make_response, request -from flask_jwt_extended.exceptions import JWTExtendedException -from jwt import PyJWTError from common.utils.exceptions import IncorrectCredentialsError +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.credential_utils import get_username_password_from_request -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services import AuthenticationService logger = logging.getLogger(__name__) @@ -22,7 +18,7 @@ def init_jwt(app): ) -class Authenticate(flask_restful.Resource, IResource): +class Authenticate(AbstractResource): """ Resource for user authentication. The user provides the username and password and we give them a JWT. diff --git a/monkey/monkey_island/cc/resources/auth/registration.py b/monkey/monkey_island/cc/resources/auth/registration.py index 66d7e3bb0..1625de62b 100644 --- a/monkey/monkey_island/cc/resources/auth/registration.py +++ b/monkey/monkey_island/cc/resources/auth/registration.py @@ -1,17 +1,16 @@ import logging -import flask_restful from flask import make_response, request from common.utils.exceptions import AlreadyRegisteredError, InvalidRegistrationCredentialsError +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.credential_utils import get_username_password_from_request -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services import AuthenticationService logger = logging.getLogger(__name__) -class Registration(flask_restful.Resource, IResource): +class Registration(AbstractResource): urls = ["/api/registration"] diff --git a/monkey/monkey_island/cc/resources/blackbox/clear_caches.py b/monkey/monkey_island/cc/resources/blackbox/clear_caches.py index 426e3f450..289a85d04 100644 --- a/monkey/monkey_island/cc/resources/blackbox/clear_caches.py +++ b/monkey/monkey_island/cc/resources/blackbox/clear_caches.py @@ -2,8 +2,8 @@ import logging import flask_restful +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.attack.attack_report import AttackReportService from monkey_island.cc.services.reporting.report import ReportService @@ -12,7 +12,7 @@ NOT_ALL_REPORTS_DELETED = "Not all reports have been cleared from the DB!" logger = logging.getLogger(__name__) -class ClearCaches(flask_restful.Resource, IResource): +class ClearCaches(AbstractResource): urls = ["/api/test/clear-caches"] """ Used for timing tests - we want to get actual execution time of functions in BlackBox without diff --git a/monkey/monkey_island/cc/resources/blackbox/log_blackbox_endpoint.py b/monkey/monkey_island/cc/resources/blackbox/log_blackbox_endpoint.py index 577830c2e..aa8f168b2 100644 --- a/monkey/monkey_island/cc/resources/blackbox/log_blackbox_endpoint.py +++ b/monkey/monkey_island/cc/resources/blackbox/log_blackbox_endpoint.py @@ -1,13 +1,12 @@ -import flask_restful from bson import json_util from flask import request from monkey_island.cc.database import database, mongo +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource -class LogBlackboxEndpoint(flask_restful.Resource, IResource): +class LogBlackboxEndpoint(AbstractResource): urls = ["/api/test/log"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/blackbox/monkey_blackbox_endpoint.py b/monkey/monkey_island/cc/resources/blackbox/monkey_blackbox_endpoint.py index cf47f3637..ac8790e6a 100644 --- a/monkey/monkey_island/cc/resources/blackbox/monkey_blackbox_endpoint.py +++ b/monkey/monkey_island/cc/resources/blackbox/monkey_blackbox_endpoint.py @@ -1,13 +1,12 @@ -import flask_restful from bson import json_util from flask import request from monkey_island.cc.database import mongo +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource -class MonkeyBlackboxEndpoint(flask_restful.Resource, IResource): +class MonkeyBlackboxEndpoint(AbstractResource): urls = ["/api/test/monkey"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/blackbox/telemetry_blackbox_endpoint.py b/monkey/monkey_island/cc/resources/blackbox/telemetry_blackbox_endpoint.py index ca0493b38..f20b5f474 100644 --- a/monkey/monkey_island/cc/resources/blackbox/telemetry_blackbox_endpoint.py +++ b/monkey/monkey_island/cc/resources/blackbox/telemetry_blackbox_endpoint.py @@ -1,13 +1,12 @@ -import flask_restful from bson import json_util from flask import request from monkey_island.cc.models.telemetries import get_telemetry_by_query +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource -class TelemetryBlackboxEndpoint(flask_restful.Resource, IResource): +class TelemetryBlackboxEndpoint(AbstractResource): urls = ["/api/test/telemetry"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/configuration_export.py b/monkey/monkey_island/cc/resources/configuration_export.py index 99b03c442..8a7726ff6 100644 --- a/monkey/monkey_island/cc/resources/configuration_export.py +++ b/monkey/monkey_island/cc/resources/configuration_export.py @@ -1,15 +1,14 @@ import json -import flask_restful from flask import request +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.server_utils.encryption import PasswordBasedStringEncryptor from monkey_island.cc.services.config import ConfigService -class ConfigurationExport(flask_restful.Resource, IResource): +class ConfigurationExport(AbstractResource): urls = ["/api/configuration/export"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/configuration_import.py b/monkey/monkey_island/cc/resources/configuration_import.py index fc52dcf97..7843a03da 100644 --- a/monkey/monkey_island/cc/resources/configuration_import.py +++ b/monkey/monkey_island/cc/resources/configuration_import.py @@ -3,12 +3,11 @@ import logging from dataclasses import dataclass from json.decoder import JSONDecodeError -import flask_restful from flask import request from common.utils.exceptions import InvalidConfigurationError +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.server_utils.encryption import ( InvalidCiphertextError, InvalidCredentialsError, @@ -39,7 +38,7 @@ class ResponseContents: return self.__dict__ -class ConfigurationImport(flask_restful.Resource, IResource): +class ConfigurationImport(AbstractResource): urls = ["/api/configuration/import"] SUCCESS = False diff --git a/monkey/monkey_island/cc/resources/edge.py b/monkey/monkey_island/cc/resources/edge.py index c9133cc0f..9798e116a 100644 --- a/monkey/monkey_island/cc/resources/edge.py +++ b/monkey/monkey_island/cc/resources/edge.py @@ -1,11 +1,10 @@ -import flask_restful from flask import request -from monkey_island.cc.resources.i_resource import IResource +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.services.edge.displayed_edge import DisplayedEdgeService -class Edge(flask_restful.Resource, IResource): +class Edge(AbstractResource): urls = ["/api/netmap/edge"] def get(self): diff --git a/monkey/monkey_island/cc/resources/exploitations/manual_exploitation.py b/monkey/monkey_island/cc/resources/exploitations/manual_exploitation.py index 6e14bdb61..d15a3a0f0 100644 --- a/monkey/monkey_island/cc/resources/exploitations/manual_exploitation.py +++ b/monkey/monkey_island/cc/resources/exploitations/manual_exploitation.py @@ -1,13 +1,11 @@ -import flask_restful - +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.reporting.exploitations.manual_exploitation import ( get_manual_exploitations, ) -class ManualExploitation(flask_restful.Resource, IResource): +class ManualExploitation(AbstractResource): urls = ["/api/exploitations/manual"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/exploitations/monkey_exploitation.py b/monkey/monkey_island/cc/resources/exploitations/monkey_exploitation.py index b1a93831e..70468a057 100644 --- a/monkey/monkey_island/cc/resources/exploitations/monkey_exploitation.py +++ b/monkey/monkey_island/cc/resources/exploitations/monkey_exploitation.py @@ -1,13 +1,11 @@ -import flask_restful - +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.reporting.exploitations.monkey_exploitation import ( get_monkey_exploited, ) -class MonkeyExploitation(flask_restful.Resource, IResource): +class MonkeyExploitation(AbstractResource): urls = ["/api/exploitations/monkey"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/i_resource.py b/monkey/monkey_island/cc/resources/i_resource.py deleted file mode 100644 index 239b37854..000000000 --- a/monkey/monkey_island/cc/resources/i_resource.py +++ /dev/null @@ -1,17 +0,0 @@ -from abc import ABCMeta, abstractmethod -from typing import Sequence - -from flask.views import MethodViewType - - -# Flask resources inherit from flask_restful.Resource, so custom interface -# must implement both metaclasses -class AbstractResource(ABCMeta, MethodViewType): - pass - - -class IResource(metaclass=AbstractResource): - @property - @abstractmethod - def urls(self) -> Sequence[str]: - pass diff --git a/monkey/monkey_island/cc/resources/island_configuration.py b/monkey/monkey_island/cc/resources/island_configuration.py index 2289cd722..fb9aff16c 100644 --- a/monkey/monkey_island/cc/resources/island_configuration.py +++ b/monkey/monkey_island/cc/resources/island_configuration.py @@ -1,14 +1,13 @@ import json -import flask_restful from flask import abort, jsonify, request +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.config import ConfigService -class IslandConfiguration(flask_restful.Resource, IResource): +class IslandConfiguration(AbstractResource): urls = ["/api/configuration/island"] diff --git a/monkey/monkey_island/cc/resources/island_logs.py b/monkey/monkey_island/cc/resources/island_logs.py index e85ec9bfc..7c9da657d 100644 --- a/monkey/monkey_island/cc/resources/island_logs.py +++ b/monkey/monkey_island/cc/resources/island_logs.py @@ -1,15 +1,13 @@ import logging -import flask_restful - +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.island_logs import IslandLogService logger = logging.getLogger(__name__) -class IslandLog(flask_restful.Resource, IResource): +class IslandLog(AbstractResource): urls = ["/api/log/island/download"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/island_mode.py b/monkey/monkey_island/cc/resources/island_mode.py index 781682784..4fa666ca7 100644 --- a/monkey/monkey_island/cc/resources/island_mode.py +++ b/monkey/monkey_island/cc/resources/island_mode.py @@ -1,11 +1,10 @@ import json import logging -import flask_restful from flask import make_response, request +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource 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.mode_enum import IslandModeEnum @@ -13,7 +12,7 @@ from monkey_island.cc.services.mode.mode_enum import IslandModeEnum logger = logging.getLogger(__name__) -class IslandMode(flask_restful.Resource, IResource): +class IslandMode(AbstractResource): urls = ["/api/island-mode"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/local_run.py b/monkey/monkey_island/cc/resources/local_run.py index ecfc32ad6..320b064eb 100644 --- a/monkey/monkey_island/cc/resources/local_run.py +++ b/monkey/monkey_island/cc/resources/local_run.py @@ -1,16 +1,15 @@ import json -import flask_restful from flask import jsonify, make_response, request from monkey_island.cc.models import Monkey +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.node import NodeService from monkey_island.cc.services.run_local_monkey import LocalMonkeyRunService -class LocalRun(flask_restful.Resource, IResource): +class LocalRun(AbstractResource): urls = ["/api/local-monkey"] diff --git a/monkey/monkey_island/cc/resources/log.py b/monkey/monkey_island/cc/resources/log.py index 4b3e860fd..5499e8ac9 100644 --- a/monkey/monkey_island/cc/resources/log.py +++ b/monkey/monkey_island/cc/resources/log.py @@ -1,18 +1,17 @@ import json -import flask_restful from bson import ObjectId from flask import request from monkey_island.cc.database import mongo +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required from monkey_island.cc.resources.blackbox.utils.telem_store import TestTelemStore -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.log import LogService from monkey_island.cc.services.node import NodeService -class Log(flask_restful.Resource, IResource): +class Log(AbstractResource): urls = ["/api/log"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/monkey.py b/monkey/monkey_island/cc/resources/monkey.py index 811f8f24b..f4fe9de90 100644 --- a/monkey/monkey_island/cc/resources/monkey.py +++ b/monkey/monkey_island/cc/resources/monkey.py @@ -1,13 +1,12 @@ import json from datetime import datetime -import flask_restful from flask import request from monkey_island.cc.database import mongo from monkey_island.cc.models.monkey_ttl import create_monkey_ttl_document +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.blackbox.utils.telem_store import TestTelemStore -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.resources.utils.semaphores import agent_killing_mutex from monkey_island.cc.server_utils.consts import DEFAULT_MONKEY_TTL_EXPIRY_DURATION_IN_SECONDS from monkey_island.cc.services.config import ConfigService @@ -17,7 +16,7 @@ from monkey_island.cc.services.node import NodeService # TODO: separate logic from interface -class Monkey(flask_restful.Resource, IResource): +class Monkey(AbstractResource): urls = [ "/api/agent", "/api/agent/", diff --git a/monkey/monkey_island/cc/resources/monkey_download.py b/monkey/monkey_island/cc/resources/monkey_download.py index 99060a84b..9c19b70dc 100644 --- a/monkey/monkey_island/cc/resources/monkey_download.py +++ b/monkey/monkey_island/cc/resources/monkey_download.py @@ -2,10 +2,9 @@ import hashlib import logging from pathlib import Path -import flask_restful from flask import make_response, send_from_directory -from monkey_island.cc.resources.i_resource import IResource +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.server_utils.consts import MONKEY_ISLAND_ABS_PATH logger = logging.getLogger(__name__) @@ -20,7 +19,7 @@ class UnsupportedOSError(Exception): pass -class MonkeyDownload(flask_restful.Resource, IResource): +class MonkeyDownload(AbstractResource): urls = ["/api/agent/download/"] # Used by monkey. can't secure. diff --git a/monkey/monkey_island/cc/resources/netmap.py b/monkey/monkey_island/cc/resources/netmap.py index 370f23483..a5f08901b 100644 --- a/monkey/monkey_island/cc/resources/netmap.py +++ b/monkey/monkey_island/cc/resources/netmap.py @@ -1,12 +1,10 @@ -import flask_restful - +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.netmap.net_edge import NetEdgeService from monkey_island.cc.services.netmap.net_node import NetNodeService -class NetMap(flask_restful.Resource, IResource): +class NetMap(AbstractResource): urls = ["/api/netmap"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/node.py b/monkey/monkey_island/cc/resources/node.py index ce87248a5..1dfa83f45 100644 --- a/monkey/monkey_island/cc/resources/node.py +++ b/monkey/monkey_island/cc/resources/node.py @@ -1,12 +1,11 @@ -import flask_restful from flask import request +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.node import NodeService -class Node(flask_restful.Resource, IResource): +class Node(AbstractResource): urls = ["/api/netmap/node"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/node_states.py b/monkey/monkey_island/cc/resources/node_states.py index aa7138b2d..484c2497a 100644 --- a/monkey/monkey_island/cc/resources/node_states.py +++ b/monkey/monkey_island/cc/resources/node_states.py @@ -1,11 +1,9 @@ -import flask_restful - +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.utils.node_states import NodeStates as NodeStateList -class NodeStates(flask_restful.Resource, IResource): +class NodeStates(AbstractResource): urls = ["/api/netmap/node-states"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/pba_file_download.py b/monkey/monkey_island/cc/resources/pba_file_download.py index 3ad69bb57..73658d0ad 100644 --- a/monkey/monkey_island/cc/resources/pba_file_download.py +++ b/monkey/monkey_island/cc/resources/pba_file_download.py @@ -1,15 +1,14 @@ import logging -import flask_restful from flask import make_response, send_file -from monkey_island.cc.resources.i_resource import IResource +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.services import FileRetrievalError, IFileStorageService logger = logging.getLogger(__file__) -class PBAFileDownload(flask_restful.Resource, IResource): +class PBAFileDownload(AbstractResource): urls = ["/api/pba/download/"] """ File download endpoint used by monkey to download user's PBA file diff --git a/monkey/monkey_island/cc/resources/pba_file_upload.py b/monkey/monkey_island/cc/resources/pba_file_upload.py index f03ee998d..2dada0f71 100644 --- a/monkey/monkey_island/cc/resources/pba_file_upload.py +++ b/monkey/monkey_island/cc/resources/pba_file_upload.py @@ -1,13 +1,12 @@ import logging from http import HTTPStatus -import flask_restful from flask import Response, make_response, request, send_file from werkzeug.utils import secure_filename as sanitize_filename from common.config_value_paths import PBA_LINUX_FILENAME_PATH, PBA_WINDOWS_FILENAME_PATH +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services import FileRetrievalError, IFileStorageService from monkey_island.cc.services.config import ConfigService @@ -18,7 +17,7 @@ LINUX_PBA_TYPE = "PBAlinux" WINDOWS_PBA_TYPE = "PBAwindows" -class FileUpload(flask_restful.Resource, IResource): +class FileUpload(AbstractResource): """ File upload endpoint used to send/receive Custom PBA files """ diff --git a/monkey/monkey_island/cc/resources/propagation_credentials.py b/monkey/monkey_island/cc/resources/propagation_credentials.py index 99ff5a6af..340f473b3 100644 --- a/monkey/monkey_island/cc/resources/propagation_credentials.py +++ b/monkey/monkey_island/cc/resources/propagation_credentials.py @@ -1,11 +1,9 @@ -import flask_restful - from monkey_island.cc.database import mongo -from monkey_island.cc.resources.i_resource import IResource +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.services.config import ConfigService -class PropagationCredentials(flask_restful.Resource, IResource): +class PropagationCredentials(AbstractResource): urls = ["/api/propagation-credentials/"] def get(self, guid: str): diff --git a/monkey/monkey_island/cc/resources/ransomware_report.py b/monkey/monkey_island/cc/resources/ransomware_report.py index 7c017a3ae..676652542 100644 --- a/monkey/monkey_island/cc/resources/ransomware_report.py +++ b/monkey/monkey_island/cc/resources/ransomware_report.py @@ -1,12 +1,11 @@ -import flask_restful from flask import jsonify +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.ransomware import ransomware_report -class RansomwareReport(flask_restful.Resource, IResource): +class RansomwareReport(AbstractResource): urls = ["/api/report/ransomware"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/remote_run.py b/monkey/monkey_island/cc/resources/remote_run.py index 434bcedf8..8b57d0e3d 100644 --- a/monkey/monkey_island/cc/resources/remote_run.py +++ b/monkey/monkey_island/cc/resources/remote_run.py @@ -1,12 +1,11 @@ import json from typing import Sequence -import flask_restful from botocore.exceptions import ClientError, NoCredentialsError from flask import jsonify, make_response, request +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services import AWSService from monkey_island.cc.services.aws import AWSCommandResults @@ -20,7 +19,7 @@ NO_CREDS_ERROR_FORMAT = ( ) -class RemoteRun(flask_restful.Resource, IResource): +class RemoteRun(AbstractResource): urls = ["/api/remote-monkey"] def __init__(self, aws_service: AWSService): diff --git a/monkey/monkey_island/cc/resources/root.py b/monkey/monkey_island/cc/resources/root.py index a2de10927..6994fee62 100644 --- a/monkey/monkey_island/cc/resources/root.py +++ b/monkey/monkey_island/cc/resources/root.py @@ -1,11 +1,10 @@ import logging -import flask_restful from flask import jsonify, make_response, request from monkey_island.cc.database import mongo +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.database import Database from monkey_island.cc.services.infection_lifecycle import get_completed_steps from monkey_island.cc.services.utils.network_utils import local_ip_addresses @@ -13,7 +12,7 @@ from monkey_island.cc.services.utils.network_utils import local_ip_addresses logger = logging.getLogger(__name__) -class Root(IResource, flask_restful.Resource): +class Root(AbstractResource): urls = ["/api"] diff --git a/monkey/monkey_island/cc/resources/security_report.py b/monkey/monkey_island/cc/resources/security_report.py index 55e9cdfee..afcf43add 100644 --- a/monkey/monkey_island/cc/resources/security_report.py +++ b/monkey/monkey_island/cc/resources/security_report.py @@ -1,11 +1,9 @@ -import flask_restful - +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.reporting.report import ReportService -class SecurityReport(flask_restful.Resource, IResource): +class SecurityReport(AbstractResource): urls = ["/api/report/security"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/telemetry.py b/monkey/monkey_island/cc/resources/telemetry.py index 865f2c9a0..971f39a96 100644 --- a/monkey/monkey_island/cc/resources/telemetry.py +++ b/monkey/monkey_island/cc/resources/telemetry.py @@ -3,22 +3,21 @@ import logging from datetime import datetime import dateutil -import flask_restful from flask import request from monkey_island.cc.database import mongo from monkey_island.cc.models.monkey import Monkey from monkey_island.cc.models.telemetries import get_telemetry_by_query +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required from monkey_island.cc.resources.blackbox.utils.telem_store import TestTelemStore -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.node import NodeService from monkey_island.cc.services.telemetry.processing.processing import process_telemetry logger = logging.getLogger(__name__) -class Telemetry(flask_restful.Resource, IResource): +class Telemetry(AbstractResource): urls = ["/api/telemetry", "/api/telemetry/"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/telemetry_feed.py b/monkey/monkey_island/cc/resources/telemetry_feed.py index 51388d8e6..8314f6576 100644 --- a/monkey/monkey_island/cc/resources/telemetry_feed.py +++ b/monkey/monkey_island/cc/resources/telemetry_feed.py @@ -3,19 +3,18 @@ from datetime import datetime import dateutil import flask_pymongo -import flask_restful from flask import request from common.common_consts.telem_categories import TelemCategoryEnum from monkey_island.cc.database import mongo +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.node import NodeService logger = logging.getLogger(__name__) -class TelemetryFeed(flask_restful.Resource, IResource): +class TelemetryFeed(AbstractResource): urls = ["/api/telemetry-feed"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/version_update.py b/monkey/monkey_island/cc/resources/version_update.py index 2b76c5346..0544cea4c 100644 --- a/monkey/monkey_island/cc/resources/version_update.py +++ b/monkey/monkey_island/cc/resources/version_update.py @@ -1,15 +1,13 @@ import logging -import flask_restful - from common.version import get_version -from monkey_island.cc.resources.i_resource import IResource +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.services.version_update import VersionUpdateService logger = logging.getLogger(__name__) -class VersionUpdate(flask_restful.Resource, IResource): +class VersionUpdate(AbstractResource): urls = ["/api/version-update"] def __init__(self): diff --git a/monkey/monkey_island/cc/resources/zero_trust/finding_event.py b/monkey/monkey_island/cc/resources/zero_trust/finding_event.py index 3bccb2989..d232e83d7 100644 --- a/monkey/monkey_island/cc/resources/zero_trust/finding_event.py +++ b/monkey/monkey_island/cc/resources/zero_trust/finding_event.py @@ -1,15 +1,13 @@ import json -import flask_restful - +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.zero_trust.monkey_findings.monkey_zt_finding_service import ( MonkeyZTFindingService, ) -class ZeroTrustFindingEvent(flask_restful.Resource, IResource): +class ZeroTrustFindingEvent(AbstractResource): urls = ["/api/zero-trust/finding-event/"] @jwt_required diff --git a/monkey/monkey_island/cc/resources/zero_trust/zero_trust_report.py b/monkey/monkey_island/cc/resources/zero_trust/zero_trust_report.py index b80224f8e..9e32b72bd 100644 --- a/monkey/monkey_island/cc/resources/zero_trust/zero_trust_report.py +++ b/monkey/monkey_island/cc/resources/zero_trust/zero_trust_report.py @@ -3,8 +3,8 @@ import http.client import flask_restful from flask import jsonify +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.zero_trust.zero_trust_report.finding_service import FindingService from monkey_island.cc.services.zero_trust.zero_trust_report.pillar_service import PillarService from monkey_island.cc.services.zero_trust.zero_trust_report.principle_service import ( @@ -16,7 +16,7 @@ REPORT_DATA_FINDINGS = "findings" REPORT_DATA_PRINCIPLES_STATUS = "principles" -class ZeroTrustReport(flask_restful.Resource, IResource): +class ZeroTrustReport(AbstractResource): urls = ["/api/report/zero-trust/"] @jwt_required diff --git a/monkey/tests/unit_tests/monkey_island/cc/test_app.py b/monkey/tests/unit_tests/monkey_island/cc/test_app.py index 8befc3b22..225f87ff8 100644 --- a/monkey/tests/unit_tests/monkey_island/cc/test_app.py +++ b/monkey/tests/unit_tests/monkey_island/cc/test_app.py @@ -1,14 +1,13 @@ -import flask_restful import pytest from tests.common import StubDIContainer from tests.unit_tests.monkey_island.conftest import mock_flask_resource_manager from monkey_island.cc.app import FlaskDIWrapper -from monkey_island.cc.resources.i_resource import IResource +from monkey_island.cc.resources.AbstractResource import AbstractResource def get_mock_resource(name, urls): - class MockResource(flask_restful.Resource, IResource): + class MockResource(AbstractResource): urls = [] def get(self, something=None): diff --git a/monkey/tests/unit_tests/monkey_island/conftest.py b/monkey/tests/unit_tests/monkey_island/conftest.py index d3c986df3..094bbb2aa 100644 --- a/monkey/tests/unit_tests/monkey_island/conftest.py +++ b/monkey/tests/unit_tests/monkey_island/conftest.py @@ -8,7 +8,7 @@ import pytest from flask import Flask import monkey_island -from monkey_island.cc.resources.i_resource import IResource +from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.services.representations import output_json @@ -47,7 +47,7 @@ def mock_flask_resource_manager(container): return flask_resource_manager -def get_url_for_resource(resource: IResource, **kwargs): +def get_url_for_resource(resource: AbstractResource, **kwargs): chosen_url = None for url in resource.urls: if _get_url_keywords(url) == set(kwargs.keys()):