diff --git a/CHANGELOG.md b/CHANGELOG.md index 66259a5a1..a1974f561 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Changelog](https://keepachangelog.com/en/1.0.0/). - `/api/island-mode` to accept and return new "unset" mode. #2036 - `/api/version-update` to `api/island/version`. #2109 - The `/api/island-mode` to `/api/island/mode`. #2106 +- The `/api/log/island/download` endpoint to `/api/island/log`. #2107 ### Removed - VSFTPD exploiter. #1533 diff --git a/monkey/monkey_island/cc/resources/island_logs.py b/monkey/monkey_island/cc/resources/island_logs.py index 24162ba3e..e9eb7ea63 100644 --- a/monkey/monkey_island/cc/resources/island_logs.py +++ b/monkey/monkey_island/cc/resources/island_logs.py @@ -1,19 +1,22 @@ import logging +from pathlib import Path from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.request_authentication import jwt_required -from monkey_island.cc.services.island_logs import IslandLogService +from monkey_island.cc.server_utils.island_logger import get_log_file_contents logger = logging.getLogger(__name__) class IslandLog(AbstractResource): - # API Spec: Why the inconsistency in endpoints of IslandLog and Log? - urls = ["/api/log/island/download"] + urls = ["/api/island/log"] + + def __init__(self, island_log_file_path: Path): + self._island_log_file_path = island_log_file_path @jwt_required def get(self): try: - return IslandLogService.get_log_file() + return get_log_file_contents(self._island_log_file_path) except Exception: logger.error("Monkey Island logs failed to download", exc_info=True) diff --git a/monkey/monkey_island/cc/server_utils/island_logger.py b/monkey/monkey_island/cc/server_utils/island_logger.py index 513d5031c..07090214a 100644 --- a/monkey/monkey_island/cc/server_utils/island_logger.py +++ b/monkey/monkey_island/cc/server_utils/island_logger.py @@ -23,12 +23,22 @@ def setup_logging(data_dir: Path, log_level: str): formatter = _get_log_formatter() - log_file_path = data_dir / ISLAND_LOG_FILENAME + log_file_path = get_log_file_path(data_dir) _add_file_handler(logger, formatter, log_file_path) _add_console_handler(logger, formatter) +def get_log_file_path(data_dir: Path) -> Path: + return data_dir / ISLAND_LOG_FILENAME + + +def get_log_file_contents(log_file_path: Path) -> str: + with open(log_file_path, "rt") as f: + log_file = f.read() + return log_file + + def setup_default_failsafe_logging(): logger = logging.getLogger() logger.setLevel(logging.DEBUG) diff --git a/monkey/monkey_island/cc/services/initialize.py b/monkey/monkey_island/cc/services/initialize.py index c3623e716..2d2678ac3 100644 --- a/monkey/monkey_island/cc/services/initialize.py +++ b/monkey/monkey_island/cc/services/initialize.py @@ -32,6 +32,7 @@ from monkey_island.cc.repository import ( ) from monkey_island.cc.server_utils.consts import MONKEY_ISLAND_ABS_PATH from monkey_island.cc.server_utils.encryption import ILockableEncryptor, RepositoryEncryptor +from monkey_island.cc.server_utils.island_logger import get_log_file_path from monkey_island.cc.services import AWSService, IslandModeService, RepositoryService from monkey_island.cc.services.attack.technique_reports.T1003 import T1003, T1003GetReportData from monkey_island.cc.services.run_local_monkey import LocalMonkeyRunService @@ -87,6 +88,7 @@ def _register_conventions(container: DIContainer, data_dir: Path): "default_ransomware_agent_configuration", DEFAULT_RANSOMWARE_AGENT_CONFIGURATION, ) + container.register_convention(Path, "island_log_file_path", get_log_file_path(data_dir)) def _register_repositories(container: DIContainer, data_dir: Path): diff --git a/monkey/monkey_island/cc/services/island_logs.py b/monkey/monkey_island/cc/services/island_logs.py deleted file mode 100644 index 0bbf4ec0b..000000000 --- a/monkey/monkey_island/cc/services/island_logs.py +++ /dev/null @@ -1,30 +0,0 @@ -import logging - -logger = logging.getLogger(__name__) - - -class IslandLogService: - def __init__(self): - pass - - @staticmethod - def get_log_file(): - """ - This static function is a helper function for the monkey island log download function. - It finds the logger handlers and checks if one of them is a fileHandler of any kind by - checking if the handler - has the property handler.baseFilename. - :return: - a dict with the log file content. - """ - logger_handlers = logger.parent.handlers - for handler in logger_handlers: - if hasattr(handler, "baseFilename"): - logger.info("Log file found: {0}".format(handler.baseFilename)) - log_file_path = handler.baseFilename - with open(log_file_path, "rt") as f: - log_file = f.read() - return {"log_file": log_file} - - logger.warning("No log file could be found, check logger config.") - return None diff --git a/monkey/monkey_island/cc/ui/src/components/map/preview-pane/PreviewPane.js b/monkey/monkey_island/cc/ui/src/components/map/preview-pane/PreviewPane.js index f9a09bb4c..cc2074107 100644 --- a/monkey/monkey_island/cc/ui/src/components/map/preview-pane/PreviewPane.js +++ b/monkey/monkey_island/cc/ui/src/components/map/preview-pane/PreviewPane.js @@ -87,7 +87,7 @@ class PreviewPaneComponent extends AuthComponent { Download Island Server Log - + } diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/LogDownloadButtons.tsx b/monkey/monkey_island/cc/ui/src/components/ui-components/LogDownloadButtons.tsx index 0e28973e1..1cca8d09b 100644 --- a/monkey/monkey_island/cc/ui/src/components/ui-components/LogDownloadButtons.tsx +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/LogDownloadButtons.tsx @@ -48,7 +48,7 @@ export const IslandLogDownloadButton = ({ url, variant = 'primary'}: Props) => { .then(res => res.json()) .then(res => { let filename = 'Island_log'; - let logContent = (res['log_file']); + let logContent = res; download(logContent, filename, 'text/plain'); }); }