From f0a613eb751b6ac537eb0162297011b5fa67150b Mon Sep 17 00:00:00 2001 From: vakarisz Date: Fri, 20 May 2022 18:20:37 +0300 Subject: [PATCH] Island: Move URL definitions to resource classes --- monkey/monkey_island/cc/app.py | 88 ++++++++----------- .../agent_controls/stop_agent_check.py | 5 +- .../agent_controls/stop_all_agents.py | 5 +- .../cc/resources/attack/attack_report.py | 5 +- .../monkey_island/cc/resources/auth/auth.py | 5 +- .../cc/resources/auth/registration.py | 6 +- .../cc/resources/blackbox/clear_caches.py | 4 +- .../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 | 4 +- monkey/monkey_island/cc/resources/edge.py | 5 +- .../exploitations/manual_exploitation.py | 5 +- .../exploitations/monkey_exploitation.py | 5 +- .../cc/resources/island_configuration.py | 6 +- .../monkey_island/cc/resources/island_logs.py | 5 +- .../monkey_island/cc/resources/island_mode.py | 5 +- .../monkey_island/cc/resources/local_run.py | 6 +- monkey/monkey_island/cc/resources/log.py | 5 +- monkey/monkey_island/cc/resources/monkey.py | 8 +- .../cc/resources/monkey_download.py | 4 +- monkey/monkey_island/cc/resources/netmap.py | 5 +- monkey/monkey_island/cc/resources/node.py | 5 +- .../monkey_island/cc/resources/node_states.py | 5 +- .../cc/resources/pba_file_download.py | 4 +- .../cc/resources/pba_file_upload.py | 10 ++- .../cc/resources/propagation_credentials.py | 5 +- .../cc/resources/ransomware_report.py | 5 +- .../monkey_island/cc/resources/remote_run.py | 5 +- monkey/monkey_island/cc/resources/root.py | 6 +- .../cc/resources/security_report.py | 5 +- .../monkey_island/cc/resources/telemetry.py | 5 +- .../cc/resources/telemetry_feed.py | 5 +- .../cc/resources/version_update.py | 5 +- .../cc/resources/zero_trust/finding_event.py | 5 +- .../resources/zero_trust/zero_trust_report.py | 5 +- 37 files changed, 187 insertions(+), 89 deletions(-) diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index be135b494..4ef9233c2 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -143,65 +143,49 @@ class FlaskDIWrapper: def init_api_resources(api: FlaskDIWrapper): - api.add_resource(Root, "/api") - api.add_resource(Registration, "/api/registration") - api.add_resource(Authenticate, "/api/auth") - api.add_resource( - Monkey, - "/api/agent", - "/api/agent/", - "/api/agent//", - ) - api.add_resource(LocalRun, "/api/local-monkey") - api.add_resource(Telemetry, "/api/telemetry", "/api/telemetry/") + api.add_resource(Root) + api.add_resource(Registration) + api.add_resource(Authenticate) + api.add_resource(Monkey) + api.add_resource(LocalRun) + api.add_resource(Telemetry) - api.add_resource(IslandMode, "/api/island-mode") - api.add_resource(IslandConfiguration, "/api/configuration/island") - api.add_resource(ConfigurationExport, "/api/configuration/export") - api.add_resource(ConfigurationImport, "/api/configuration/import") - api.add_resource( - MonkeyDownload, - "/api/agent/download/", - ) - api.add_resource(NetMap, "/api/netmap") - api.add_resource(Edge, "/api/netmap/edge") - api.add_resource(Node, "/api/netmap/node") - api.add_resource(NodeStates, "/api/netmap/node-states") + api.add_resource(IslandMode) + api.add_resource(IslandConfiguration) + api.add_resource(ConfigurationExport) + api.add_resource(ConfigurationImport) + api.add_resource(MonkeyDownload) + api.add_resource(NetMap) + api.add_resource(Edge) + api.add_resource(Node) + api.add_resource(NodeStates) - api.add_resource(SecurityReport, "/api/report/security") - api.add_resource(ZeroTrustReport, "/api/report/zero-trust/") - api.add_resource(AttackReport, "/api/report/attack") - api.add_resource(RansomwareReport, "/api/report/ransomware") - api.add_resource(ManualExploitation, "/api/exploitations/manual") - api.add_resource(MonkeyExploitation, "/api/exploitations/monkey") + api.add_resource(SecurityReport) + api.add_resource(ZeroTrustReport) + api.add_resource(AttackReport) + api.add_resource(RansomwareReport) + api.add_resource(ManualExploitation) + api.add_resource(MonkeyExploitation) - api.add_resource(ZeroTrustFindingEvent, "/api/zero-trust/finding-event/") - api.add_resource(TelemetryFeed, "/api/telemetry-feed") - api.add_resource(Log, "/api/log") - api.add_resource(IslandLog, "/api/log/island/download") + api.add_resource(ZeroTrustFindingEvent) + api.add_resource(TelemetryFeed) + api.add_resource(Log) + api.add_resource(IslandLog) - api.add_resource( - PBAFileDownload, - "/api/pba/download/", - ) - api.add_resource( - FileUpload, - "/api/file-upload/", - "/api/file-upload/?load=", - "/api/file-upload/?restore=", - ) + api.add_resource(PBAFileDownload) + api.add_resource(FileUpload) - api.add_resource(PropagationCredentials, "/api/propagation-credentials/") - api.add_resource(RemoteRun, "/api/remote-monkey") - api.add_resource(VersionUpdate, "/api/version-update") - api.add_resource(StopAgentCheck, "/api/monkey-control/needs-to-stop/") - api.add_resource(StopAllAgents, "/api/monkey-control/stop-all-agents") + api.add_resource(PropagationCredentials) + api.add_resource(RemoteRun) + api.add_resource(VersionUpdate) + api.add_resource(StopAgentCheck) + api.add_resource(StopAllAgents) # Resources used by black box tests - api.add_resource(MonkeyBlackboxEndpoint, "/api/test/monkey") - api.add_resource(ClearCaches, "/api/test/clear-caches") - api.add_resource(LogBlackboxEndpoint, "/api/test/log") - api.add_resource(TelemetryBlackboxEndpoint, "/api/test/telemetry") + api.add_resource(MonkeyBlackboxEndpoint) + api.add_resource(ClearCaches) + api.add_resource(LogBlackboxEndpoint) + api.add_resource(TelemetryBlackboxEndpoint) def init_app(mongo_url: str, container: DIContainer): 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 3fb948a68..d92992b27 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,8 +1,11 @@ import flask_restful +from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.infection_lifecycle import should_agent_die -class StopAgentCheck(flask_restful.Resource): +class StopAgentCheck(flask_restful.Resource, IResource): + urls = ["/api/monkey-control/needs-to-stop/"] + def get(self, monkey_guid: int): return {"stop_agent": should_agent_die(monkey_guid)} 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 a8819243b..3d43eeba4 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 @@ -4,11 +4,14 @@ import flask_restful from flask import make_response, request 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): +class StopAllAgents(flask_restful.Resource, IResource): + urls = ["/api/monkey-control/stop-all-agents"] + @jwt_required def post(self): with agent_killing_mutex: diff --git a/monkey/monkey_island/cc/resources/attack/attack_report.py b/monkey/monkey_island/cc/resources/attack/attack_report.py index 502538990..b35355d41 100644 --- a/monkey/monkey_island/cc/resources/attack/attack_report.py +++ b/monkey/monkey_island/cc/resources/attack/attack_report.py @@ -2,11 +2,14 @@ import flask_restful from flask import current_app, json 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): +class AttackReport(flask_restful.Resource, IResource): + urls = ["/api/report/attack"] + @jwt_required def get(self): response_content = { diff --git a/monkey/monkey_island/cc/resources/auth/auth.py b/monkey/monkey_island/cc/resources/auth/auth.py index f5b73e062..d683b4d65 100644 --- a/monkey/monkey_island/cc/resources/auth/auth.py +++ b/monkey/monkey_island/cc/resources/auth/auth.py @@ -9,6 +9,7 @@ from jwt import PyJWTError from common.utils.exceptions import IncorrectCredentialsError 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__) @@ -21,13 +22,15 @@ def init_jwt(app): ) -class Authenticate(flask_restful.Resource): +class Authenticate(flask_restful.Resource, IResource): """ Resource for user authentication. The user provides the username and password and we give them a JWT. See `AuthService.js` file for the frontend counterpart for this code. """ + urls = ["/api/auth"] + def post(self): """ Example request: diff --git a/monkey/monkey_island/cc/resources/auth/registration.py b/monkey/monkey_island/cc/resources/auth/registration.py index 175582733..66d7e3bb0 100644 --- a/monkey/monkey_island/cc/resources/auth/registration.py +++ b/monkey/monkey_island/cc/resources/auth/registration.py @@ -5,12 +5,16 @@ from flask import make_response, request from common.utils.exceptions import AlreadyRegisteredError, InvalidRegistrationCredentialsError 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): +class Registration(flask_restful.Resource, IResource): + + urls = ["/api/registration"] + def get(self): return {"needs_registration": AuthenticationService.needs_registration()} diff --git a/monkey/monkey_island/cc/resources/blackbox/clear_caches.py b/monkey/monkey_island/cc/resources/blackbox/clear_caches.py index b8ebeb056..426e3f450 100644 --- a/monkey/monkey_island/cc/resources/blackbox/clear_caches.py +++ b/monkey/monkey_island/cc/resources/blackbox/clear_caches.py @@ -3,6 +3,7 @@ import logging import flask_restful 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 @@ -11,7 +12,8 @@ NOT_ALL_REPORTS_DELETED = "Not all reports have been cleared from the DB!" logger = logging.getLogger(__name__) -class ClearCaches(flask_restful.Resource): +class ClearCaches(flask_restful.Resource, IResource): + urls = ["/api/test/clear-caches"] """ Used for timing tests - we want to get actual execution time of functions in BlackBox without caching - 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 c101b567a..577830c2e 100644 --- a/monkey/monkey_island/cc/resources/blackbox/log_blackbox_endpoint.py +++ b/monkey/monkey_island/cc/resources/blackbox/log_blackbox_endpoint.py @@ -4,9 +4,12 @@ from flask import request from monkey_island.cc.database import database, mongo from monkey_island.cc.resources.auth.auth import jwt_required +from monkey_island.cc.resources.i_resource import IResource -class LogBlackboxEndpoint(flask_restful.Resource): +class LogBlackboxEndpoint(flask_restful.Resource, IResource): + urls = ["/api/test/log"] + @jwt_required def get(self): find_query = json_util.loads(request.args.get("find_query")) 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 2957fd4b9..cf47f3637 100644 --- a/monkey/monkey_island/cc/resources/blackbox/monkey_blackbox_endpoint.py +++ b/monkey/monkey_island/cc/resources/blackbox/monkey_blackbox_endpoint.py @@ -4,9 +4,12 @@ from flask import request from monkey_island.cc.database import mongo from monkey_island.cc.resources.auth.auth import jwt_required +from monkey_island.cc.resources.i_resource import IResource -class MonkeyBlackboxEndpoint(flask_restful.Resource): +class MonkeyBlackboxEndpoint(flask_restful.Resource, IResource): + urls = ["/api/test/monkey"] + @jwt_required def get(self, **kw): find_query = json_util.loads(request.args.get("find_query")) 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 f1e958e3e..ca0493b38 100644 --- a/monkey/monkey_island/cc/resources/blackbox/telemetry_blackbox_endpoint.py +++ b/monkey/monkey_island/cc/resources/blackbox/telemetry_blackbox_endpoint.py @@ -4,9 +4,12 @@ from flask import request from monkey_island.cc.models.telemetries import get_telemetry_by_query from monkey_island.cc.resources.auth.auth import jwt_required +from monkey_island.cc.resources.i_resource import IResource -class TelemetryBlackboxEndpoint(flask_restful.Resource): +class TelemetryBlackboxEndpoint(flask_restful.Resource, IResource): + urls = ["/api/test/telemetry"] + @jwt_required def get(self, **kw): find_query = json_util.loads(request.args.get("find_query")) diff --git a/monkey/monkey_island/cc/resources/configuration_export.py b/monkey/monkey_island/cc/resources/configuration_export.py index 111cfa177..99b03c442 100644 --- a/monkey/monkey_island/cc/resources/configuration_export.py +++ b/monkey/monkey_island/cc/resources/configuration_export.py @@ -4,11 +4,14 @@ import flask_restful from flask import request 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): +class ConfigurationExport(flask_restful.Resource, IResource): + urls = ["/api/configuration/export"] + @jwt_required def post(self): data = json.loads(request.data) diff --git a/monkey/monkey_island/cc/resources/configuration_import.py b/monkey/monkey_island/cc/resources/configuration_import.py index 3a66a2ed0..fc52dcf97 100644 --- a/monkey/monkey_island/cc/resources/configuration_import.py +++ b/monkey/monkey_island/cc/resources/configuration_import.py @@ -8,6 +8,7 @@ from flask import request from common.utils.exceptions import InvalidConfigurationError 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, @@ -38,7 +39,8 @@ class ResponseContents: return self.__dict__ -class ConfigurationImport(flask_restful.Resource): +class ConfigurationImport(flask_restful.Resource, IResource): + urls = ["/api/configuration/import"] SUCCESS = False @jwt_required diff --git a/monkey/monkey_island/cc/resources/edge.py b/monkey/monkey_island/cc/resources/edge.py index 9eb0d5943..c9133cc0f 100644 --- a/monkey/monkey_island/cc/resources/edge.py +++ b/monkey/monkey_island/cc/resources/edge.py @@ -1,10 +1,13 @@ import flask_restful from flask import request +from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.edge.displayed_edge import DisplayedEdgeService -class Edge(flask_restful.Resource): +class Edge(flask_restful.Resource, IResource): + urls = ["/api/netmap/edge"] + def get(self): edge_id = request.args.get("id") displayed_edge = DisplayedEdgeService.get_displayed_edge_by_id(edge_id) diff --git a/monkey/monkey_island/cc/resources/exploitations/manual_exploitation.py b/monkey/monkey_island/cc/resources/exploitations/manual_exploitation.py index 7c5db2f75..6e14bdb61 100644 --- a/monkey/monkey_island/cc/resources/exploitations/manual_exploitation.py +++ b/monkey/monkey_island/cc/resources/exploitations/manual_exploitation.py @@ -1,12 +1,15 @@ import flask_restful 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): +class ManualExploitation(flask_restful.Resource, IResource): + urls = ["/api/exploitations/manual"] + @jwt_required def get(self): manual_exploitations = [ diff --git a/monkey/monkey_island/cc/resources/exploitations/monkey_exploitation.py b/monkey/monkey_island/cc/resources/exploitations/monkey_exploitation.py index 5e00a51a0..b1a93831e 100644 --- a/monkey/monkey_island/cc/resources/exploitations/monkey_exploitation.py +++ b/monkey/monkey_island/cc/resources/exploitations/monkey_exploitation.py @@ -1,12 +1,15 @@ import flask_restful 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): +class MonkeyExploitation(flask_restful.Resource, IResource): + urls = ["/api/exploitations/monkey"] + @jwt_required def get(self): monkey_exploitations = [exploitation.__dict__ for exploitation in get_monkey_exploited()] diff --git a/monkey/monkey_island/cc/resources/island_configuration.py b/monkey/monkey_island/cc/resources/island_configuration.py index 42730e477..2289cd722 100644 --- a/monkey/monkey_island/cc/resources/island_configuration.py +++ b/monkey/monkey_island/cc/resources/island_configuration.py @@ -4,10 +4,14 @@ import flask_restful from flask import abort, jsonify, request 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): +class IslandConfiguration(flask_restful.Resource, IResource): + + urls = ["/api/configuration/island"] + @jwt_required def get(self): return jsonify( diff --git a/monkey/monkey_island/cc/resources/island_logs.py b/monkey/monkey_island/cc/resources/island_logs.py index ae5bb1398..e85ec9bfc 100644 --- a/monkey/monkey_island/cc/resources/island_logs.py +++ b/monkey/monkey_island/cc/resources/island_logs.py @@ -3,12 +3,15 @@ import logging import flask_restful 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): +class IslandLog(flask_restful.Resource, IResource): + urls = ["/api/log/island/download"] + @jwt_required def get(self): try: diff --git a/monkey/monkey_island/cc/resources/island_mode.py b/monkey/monkey_island/cc/resources/island_mode.py index 389d79dea..781682784 100644 --- a/monkey/monkey_island/cc/resources/island_mode.py +++ b/monkey/monkey_island/cc/resources/island_mode.py @@ -5,6 +5,7 @@ import flask_restful from flask import make_response, request 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 @@ -12,7 +13,9 @@ from monkey_island.cc.services.mode.mode_enum import IslandModeEnum logger = logging.getLogger(__name__) -class IslandMode(flask_restful.Resource): +class IslandMode(flask_restful.Resource, IResource): + urls = ["/api/island-mode"] + @jwt_required def post(self): try: diff --git a/monkey/monkey_island/cc/resources/local_run.py b/monkey/monkey_island/cc/resources/local_run.py index 5645557da..ecfc32ad6 100644 --- a/monkey/monkey_island/cc/resources/local_run.py +++ b/monkey/monkey_island/cc/resources/local_run.py @@ -5,11 +5,15 @@ from flask import jsonify, make_response, request from monkey_island.cc.models import Monkey 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): +class LocalRun(flask_restful.Resource, IResource): + + urls = ["/api/local-monkey"] + @jwt_required def get(self): island_monkey = NodeService.get_monkey_island_monkey() diff --git a/monkey/monkey_island/cc/resources/log.py b/monkey/monkey_island/cc/resources/log.py index 63e4d44f1..4b3e860fd 100644 --- a/monkey/monkey_island/cc/resources/log.py +++ b/monkey/monkey_island/cc/resources/log.py @@ -7,11 +7,14 @@ from flask import request from monkey_island.cc.database import mongo 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): +class Log(flask_restful.Resource, IResource): + urls = ["/api/log"] + @jwt_required def get(self): monkey_id = request.args.get("id") diff --git a/monkey/monkey_island/cc/resources/monkey.py b/monkey/monkey_island/cc/resources/monkey.py index a11f9ffb8..811f8f24b 100644 --- a/monkey/monkey_island/cc/resources/monkey.py +++ b/monkey/monkey_island/cc/resources/monkey.py @@ -7,6 +7,7 @@ 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.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 @@ -16,7 +17,12 @@ from monkey_island.cc.services.node import NodeService # TODO: separate logic from interface -class Monkey(flask_restful.Resource): +class Monkey(flask_restful.Resource, IResource): + urls = [ + "/api/agent", + "/api/agent/", + "/api/agent//", + ] # Used by monkey. can't secure. def get(self, guid=None, config_format=None, **kw): diff --git a/monkey/monkey_island/cc/resources/monkey_download.py b/monkey/monkey_island/cc/resources/monkey_download.py index a5750769f..99060a84b 100644 --- a/monkey/monkey_island/cc/resources/monkey_download.py +++ b/monkey/monkey_island/cc/resources/monkey_download.py @@ -5,6 +5,7 @@ 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.server_utils.consts import MONKEY_ISLAND_ABS_PATH logger = logging.getLogger(__name__) @@ -19,7 +20,8 @@ class UnsupportedOSError(Exception): pass -class MonkeyDownload(flask_restful.Resource): +class MonkeyDownload(flask_restful.Resource, IResource): + urls = ["/api/agent/download/"] # Used by monkey. can't secure. def get(self, host_os): diff --git a/monkey/monkey_island/cc/resources/netmap.py b/monkey/monkey_island/cc/resources/netmap.py index a649fff76..370f23483 100644 --- a/monkey/monkey_island/cc/resources/netmap.py +++ b/monkey/monkey_island/cc/resources/netmap.py @@ -1,11 +1,14 @@ import flask_restful 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): +class NetMap(flask_restful.Resource, IResource): + urls = ["/api/netmap"] + @jwt_required def get(self, **kw): net_nodes = NetNodeService.get_all_net_nodes() diff --git a/monkey/monkey_island/cc/resources/node.py b/monkey/monkey_island/cc/resources/node.py index d4252354c..ce87248a5 100644 --- a/monkey/monkey_island/cc/resources/node.py +++ b/monkey/monkey_island/cc/resources/node.py @@ -2,10 +2,13 @@ import flask_restful from flask import request 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): +class Node(flask_restful.Resource, IResource): + urls = ["/api/netmap/node"] + @jwt_required def get(self): node_id = request.args.get("id") diff --git a/monkey/monkey_island/cc/resources/node_states.py b/monkey/monkey_island/cc/resources/node_states.py index 073aafffd..aa7138b2d 100644 --- a/monkey/monkey_island/cc/resources/node_states.py +++ b/monkey/monkey_island/cc/resources/node_states.py @@ -1,10 +1,13 @@ import flask_restful 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): +class NodeStates(flask_restful.Resource, IResource): + urls = ["/api/netmap/node-states"] + @jwt_required def get(self): return {"node_states": [state.value for state in NodeStateList]} diff --git a/monkey/monkey_island/cc/resources/pba_file_download.py b/monkey/monkey_island/cc/resources/pba_file_download.py index a11e964b1..3ad69bb57 100644 --- a/monkey/monkey_island/cc/resources/pba_file_download.py +++ b/monkey/monkey_island/cc/resources/pba_file_download.py @@ -3,12 +3,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.services import FileRetrievalError, IFileStorageService logger = logging.getLogger(__file__) -class PBAFileDownload(flask_restful.Resource): +class PBAFileDownload(flask_restful.Resource, IResource): + 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 233cf9e67..f03ee998d 100644 --- a/monkey/monkey_island/cc/resources/pba_file_upload.py +++ b/monkey/monkey_island/cc/resources/pba_file_upload.py @@ -7,22 +7,28 @@ 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.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 logger = logging.getLogger(__file__) - # Front end uses these strings to identify which files to work with (linux or windows) LINUX_PBA_TYPE = "PBAlinux" WINDOWS_PBA_TYPE = "PBAwindows" -class FileUpload(flask_restful.Resource): +class FileUpload(flask_restful.Resource, IResource): """ File upload endpoint used to send/receive Custom PBA files """ + urls = [ + "/api/file-upload/", + "/api/file-upload/?load=", + "/api/file-upload/?restore=", + ] + def __init__(self, file_storage_service: IFileStorageService): self._file_storage_service = file_storage_service diff --git a/monkey/monkey_island/cc/resources/propagation_credentials.py b/monkey/monkey_island/cc/resources/propagation_credentials.py index 532501658..99ff5a6af 100644 --- a/monkey/monkey_island/cc/resources/propagation_credentials.py +++ b/monkey/monkey_island/cc/resources/propagation_credentials.py @@ -1,10 +1,13 @@ import flask_restful from monkey_island.cc.database import mongo +from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.config import ConfigService -class PropagationCredentials(flask_restful.Resource): +class PropagationCredentials(flask_restful.Resource, IResource): + urls = ["/api/propagation-credentials/"] + def get(self, guid: str): monkey_json = mongo.db.monkey.find_one_or_404({"guid": guid}) ConfigService.decrypt_flat_config(monkey_json["config"]) diff --git a/monkey/monkey_island/cc/resources/ransomware_report.py b/monkey/monkey_island/cc/resources/ransomware_report.py index af86e75a1..7c017a3ae 100644 --- a/monkey/monkey_island/cc/resources/ransomware_report.py +++ b/monkey/monkey_island/cc/resources/ransomware_report.py @@ -2,10 +2,13 @@ import flask_restful from flask import jsonify 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): +class RansomwareReport(flask_restful.Resource, IResource): + urls = ["/api/report/ransomware"] + @jwt_required def get(self): return jsonify( diff --git a/monkey/monkey_island/cc/resources/remote_run.py b/monkey/monkey_island/cc/resources/remote_run.py index 8bb0752aa..434bcedf8 100644 --- a/monkey/monkey_island/cc/resources/remote_run.py +++ b/monkey/monkey_island/cc/resources/remote_run.py @@ -6,6 +6,7 @@ from botocore.exceptions import ClientError, NoCredentialsError from flask import jsonify, make_response, request 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 @@ -19,7 +20,9 @@ NO_CREDS_ERROR_FORMAT = ( ) -class RemoteRun(flask_restful.Resource): +class RemoteRun(flask_restful.Resource, IResource): + urls = ["/api/remote-monkey"] + def __init__(self, aws_service: AWSService): self._aws_service = aws_service diff --git a/monkey/monkey_island/cc/resources/root.py b/monkey/monkey_island/cc/resources/root.py index aa2087913..a2de10927 100644 --- a/monkey/monkey_island/cc/resources/root.py +++ b/monkey/monkey_island/cc/resources/root.py @@ -5,6 +5,7 @@ from flask import jsonify, make_response, request from monkey_island.cc.database import mongo 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 @@ -12,7 +13,10 @@ from monkey_island.cc.services.utils.network_utils import local_ip_addresses logger = logging.getLogger(__name__) -class Root(flask_restful.Resource): +class Root(IResource, flask_restful.Resource): + + urls = ["/api"] + def get(self, action=None): if not action: action = request.args.get("action") diff --git a/monkey/monkey_island/cc/resources/security_report.py b/monkey/monkey_island/cc/resources/security_report.py index b2ce0704e..55e9cdfee 100644 --- a/monkey/monkey_island/cc/resources/security_report.py +++ b/monkey/monkey_island/cc/resources/security_report.py @@ -1,10 +1,13 @@ import flask_restful 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): +class SecurityReport(flask_restful.Resource, IResource): + urls = ["/api/report/security"] + @jwt_required def get(self): return ReportService.get_report() diff --git a/monkey/monkey_island/cc/resources/telemetry.py b/monkey/monkey_island/cc/resources/telemetry.py index 3358788f3..865f2c9a0 100644 --- a/monkey/monkey_island/cc/resources/telemetry.py +++ b/monkey/monkey_island/cc/resources/telemetry.py @@ -11,13 +11,16 @@ from monkey_island.cc.models.monkey import Monkey from monkey_island.cc.models.telemetries import get_telemetry_by_query 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): +class Telemetry(flask_restful.Resource, IResource): + urls = ["/api/telemetry", "/api/telemetry/"] + @jwt_required def get(self, **kw): monkey_guid = request.args.get("monkey_guid") diff --git a/monkey/monkey_island/cc/resources/telemetry_feed.py b/monkey/monkey_island/cc/resources/telemetry_feed.py index d880d964d..51388d8e6 100644 --- a/monkey/monkey_island/cc/resources/telemetry_feed.py +++ b/monkey/monkey_island/cc/resources/telemetry_feed.py @@ -9,12 +9,15 @@ from flask import request from common.common_consts.telem_categories import TelemCategoryEnum from monkey_island.cc.database import mongo 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): +class TelemetryFeed(flask_restful.Resource, IResource): + urls = ["/api/telemetry-feed"] + @jwt_required def get(self, **kw): timestamp = request.args.get("timestamp") diff --git a/monkey/monkey_island/cc/resources/version_update.py b/monkey/monkey_island/cc/resources/version_update.py index 9346bfce4..2b76c5346 100644 --- a/monkey/monkey_island/cc/resources/version_update.py +++ b/monkey/monkey_island/cc/resources/version_update.py @@ -3,12 +3,15 @@ import logging import flask_restful from common.version import get_version +from monkey_island.cc.resources.i_resource import IResource from monkey_island.cc.services.version_update import VersionUpdateService logger = logging.getLogger(__name__) -class VersionUpdate(flask_restful.Resource): +class VersionUpdate(flask_restful.Resource, IResource): + urls = ["/api/version-update"] + def __init__(self): super(VersionUpdate, self).__init__() 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 ce99390da..3bccb2989 100644 --- a/monkey/monkey_island/cc/resources/zero_trust/finding_event.py +++ b/monkey/monkey_island/cc/resources/zero_trust/finding_event.py @@ -3,12 +3,15 @@ import json import flask_restful 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): +class ZeroTrustFindingEvent(flask_restful.Resource, IResource): + urls = ["/api/zero-trust/finding-event/"] + @jwt_required def get(self, finding_id: str): return { 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 491b109dc..b80224f8e 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 @@ -4,6 +4,7 @@ import flask_restful from flask import jsonify 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 ( @@ -15,7 +16,9 @@ REPORT_DATA_FINDINGS = "findings" REPORT_DATA_PRINCIPLES_STATUS = "principles" -class ZeroTrustReport(flask_restful.Resource): +class ZeroTrustReport(flask_restful.Resource, IResource): + urls = ["/api/report/zero-trust/"] + @jwt_required def get(self, report_data=None): if report_data == REPORT_DATA_PILLARS: