diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index 269b9a5d3..9636a62a0 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -117,19 +117,14 @@ def init_app_url_rules(app): app.add_url_rule("/", "serve_static_file", serve_static_file) -def init_api_resources(api, data_dir): +def init_api_resources(api): api.add_resource(Root, "/api") api.add_resource(Registration, "/api/registration") api.add_resource(Authenticate, "/api/auth") api.add_resource(Environment, "/api/environment") api.add_resource(Monkey, "/api/monkey", "/api/monkey/", "/api/monkey/") api.add_resource(Bootloader, "/api/bootloader/") - api.add_resource( - LocalRun, - "/api/local-monkey", - "/api/local-monkey/", - resource_class_kwargs={"data_dir": data_dir}, - ) + api.add_resource(LocalRun, "/api/local-monkey", "/api/local-monkey/") api.add_resource(ClientRun, "/api/client-monkey", "/api/client-monkey/") api.add_resource( Telemetry, "/api/telemetry", "/api/telemetry/", "/api/telemetry/" @@ -178,7 +173,7 @@ def init_api_resources(api, data_dir): api.add_resource(TelemetryBlackboxEndpoint, "/api/test/telemetry") -def init_app(mongo_url, data_dir): +def init_app(mongo_url): app = Flask(__name__) api = flask_restful.Api(app) @@ -187,6 +182,6 @@ def init_app(mongo_url, data_dir): init_app_config(app, mongo_url) init_app_services(app) init_app_url_rules(app) - init_api_resources(api, data_dir) + init_api_resources(api) return app diff --git a/monkey/monkey_island/cc/main.py b/monkey/monkey_island/cc/main.py index 5b3bfd794..4bdc764c3 100644 --- a/monkey/monkey_island/cc/main.py +++ b/monkey/monkey_island/cc/main.py @@ -48,17 +48,17 @@ def main(should_setup_only=False, server_config_filename=DEFAULT_SERVER_CONFIG_P ) bootloader_server_thread.start() - start_island_server(should_setup_only, data_dir) + start_island_server(should_setup_only) bootloader_server_thread.join() -def start_island_server(should_setup_only, data_dir): +def start_island_server(should_setup_only): mongo_url = os.environ.get("MONGO_URL", env_singleton.env.get_mongo_url()) wait_for_mongo_db_server(mongo_url) assert_mongo_db_version(mongo_url) populate_exporter_list() - app = init_app(mongo_url, data_dir) + app = init_app(mongo_url) crt_path = str(Path(MONKEY_ISLAND_ABS_PATH, "cc", "server.crt")) key_path = str(Path(MONKEY_ISLAND_ABS_PATH, "cc", "server.key")) diff --git a/monkey/monkey_island/cc/resources/local_run.py b/monkey/monkey_island/cc/resources/local_run.py index 91c02a4f7..40a5fb8b0 100644 --- a/monkey/monkey_island/cc/resources/local_run.py +++ b/monkey/monkey_island/cc/resources/local_run.py @@ -1,67 +1,15 @@ import json -import logging -import os -import sys -from shutil import copyfile import flask_restful from flask import jsonify, make_response, request -import monkey_island.cc.environment.environment_singleton as env_singleton from monkey_island.cc.models import Monkey from monkey_island.cc.resources.auth.auth import jwt_required -from monkey_island.cc.resources.monkey_download import get_monkey_executable -from monkey_island.cc.server_utils.consts import MONKEY_ISLAND_ABS_PATH from monkey_island.cc.services.node import NodeService -from monkey_island.cc.services.utils.network_utils import local_ip_addresses - -__author__ = "Barak" - -logger = logging.getLogger(__name__) - - -def run_local_monkey(dest_dir): - import platform - import stat - import subprocess - - # get the monkey executable suitable to run on the server - result = get_monkey_executable(platform.system().lower(), platform.machine().lower()) - if not result: - return False, "OS Type not found" - - src_path = os.path.join(MONKEY_ISLAND_ABS_PATH, "cc", "binaries", result["filename"]) - dest_path = os.path.join(dest_dir, result["filename"]) - - # copy the executable to temp path (don't run the monkey from its current location as it may - # delete itself) - try: - copyfile(src_path, dest_path) - os.chmod(dest_path, stat.S_IRWXU | stat.S_IRWXG) - except Exception as exc: - logger.error("Copy file failed", exc_info=True) - return False, "Copy file failed: %s" % exc - - # run the monkey - try: - args = [ - '"%s" m0nk3y -s %s:%s' - % (dest_path, local_ip_addresses()[0], env_singleton.env.get_island_port()) - ] - if sys.platform == "win32": - args = "".join(args) - subprocess.Popen(args, cwd=dest_dir, shell=True).pid - except Exception as exc: - logger.error("popen failed", exc_info=True) - return False, "popen failed: %s" % exc - - return True, "" +from monkey_island.cc.services.run_local_monkey import RunLocalMonkeyService class LocalRun(flask_restful.Resource): - def __init__(self, data_dir): - self._data_dir = data_dir - @jwt_required def get(self): NodeService.update_dead_monkeys() @@ -77,7 +25,7 @@ class LocalRun(flask_restful.Resource): def post(self): body = json.loads(request.data) if body.get("action") == "run": - local_run = run_local_monkey(self._data_dir) + local_run = RunLocalMonkeyService.run_local_monkey() return jsonify(is_running=local_run[0], error_text=local_run[1]) # default action diff --git a/monkey/monkey_island/cc/services/initialize.py b/monkey/monkey_island/cc/services/initialize.py index 564babcac..93eb66d3f 100644 --- a/monkey/monkey_island/cc/services/initialize.py +++ b/monkey/monkey_island/cc/services/initialize.py @@ -1,9 +1,7 @@ from monkey_island.cc.services.post_breach_files import PostBreachFilesService +from monkey_island.cc.services.run_local_monkey import RunLocalMonkeyService def initialize_services(data_dir): - initialize_post_breach_file_service(data_dir) - - -def initialize_post_breach_file_service(data_dir): PostBreachFilesService.initialize(data_dir) + RunLocalMonkeyService.initialize(data_dir) diff --git a/monkey/monkey_island/cc/services/run_local_monkey.py b/monkey/monkey_island/cc/services/run_local_monkey.py new file mode 100644 index 000000000..ce08ff615 --- /dev/null +++ b/monkey/monkey_island/cc/services/run_local_monkey.py @@ -0,0 +1,59 @@ +import logging +import os +import platform +import stat +import subprocess +import sys +from shutil import copyfile + +import monkey_island.cc.environment.environment_singleton as env_singleton +from monkey_island.cc.resources.monkey_download import get_monkey_executable +from monkey_island.cc.server_utils.consts import MONKEY_ISLAND_ABS_PATH +from monkey_island.cc.services.utils.network_utils import local_ip_addresses + +logger = logging.getLogger(__name__) + + +class RunLocalMonkeyService: + DATA_DIR = None + + # TODO: A number of these services should be instance objects instead of + # static/singleton hybrids. At the moment, this requires invasive refactoring that's + # not a priority. + @classmethod + def initialize(cls, data_dir): + cls.DATA_DIR = data_dir + + @staticmethod + def run_local_monkey(): + # get the monkey executable suitable to run on the server + result = get_monkey_executable(platform.system().lower(), platform.machine().lower()) + if not result: + return False, "OS Type not found" + + src_path = os.path.join(MONKEY_ISLAND_ABS_PATH, "cc", "binaries", result["filename"]) + dest_path = os.path.join(RunLocalMonkeyService.DATA_DIR, result["filename"]) + + # copy the executable to temp path (don't run the monkey from its current location as it may + # delete itself) + try: + copyfile(src_path, dest_path) + os.chmod(dest_path, stat.S_IRWXU | stat.S_IRWXG) + except Exception as exc: + logger.error("Copy file failed", exc_info=True) + return False, "Copy file failed: %s" % exc + + # run the monkey + try: + args = [ + '"%s" m0nk3y -s %s:%s' + % (dest_path, local_ip_addresses()[0], env_singleton.env.get_island_port()) + ] + if sys.platform == "win32": + args = "".join(args) + subprocess.Popen(args, cwd=RunLocalMonkeyService.DATA_DIR, shell=True).pid + except Exception as exc: + logger.error("popen failed", exc_info=True) + return False, "popen failed: %s" % exc + + return True, ""