Merge pull request #2142 from guardicore/2107-refactor-api-log-endpoint

Refactor Island log endpoint
This commit is contained in:
Shreya Malviya 2022-08-02 13:14:32 +05:30 committed by GitHub
commit 30166880bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 23 additions and 37 deletions

View File

@ -47,6 +47,7 @@ Changelog](https://keepachangelog.com/en/1.0.0/).
- `/api/island-mode` to accept and return new "unset" mode. #2036 - `/api/island-mode` to accept and return new "unset" mode. #2036
- `/api/version-update` to `api/island/version`. #2109 - `/api/version-update` to `api/island/version`. #2109
- The `/api/island-mode` to `/api/island/mode`. #2106 - The `/api/island-mode` to `/api/island/mode`. #2106
- The `/api/log/island/download` endpoint to `/api/island/log`. #2107
### Removed ### Removed
- VSFTPD exploiter. #1533 - VSFTPD exploiter. #1533

View File

@ -1,19 +1,22 @@
import logging import logging
from pathlib import Path
from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.AbstractResource import AbstractResource
from monkey_island.cc.resources.request_authentication import jwt_required 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__) logger = logging.getLogger(__name__)
class IslandLog(AbstractResource): class IslandLog(AbstractResource):
# API Spec: Why the inconsistency in endpoints of IslandLog and Log? urls = ["/api/island/log"]
urls = ["/api/log/island/download"]
def __init__(self, island_log_file_path: Path):
self._island_log_file_path = island_log_file_path
@jwt_required @jwt_required
def get(self): def get(self):
try: try:
return IslandLogService.get_log_file() return get_log_file_contents(self._island_log_file_path)
except Exception: except Exception:
logger.error("Monkey Island logs failed to download", exc_info=True) logger.error("Monkey Island logs failed to download", exc_info=True)

View File

@ -23,12 +23,22 @@ def setup_logging(data_dir: Path, log_level: str):
formatter = _get_log_formatter() 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_file_handler(logger, formatter, log_file_path)
_add_console_handler(logger, formatter) _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(): def setup_default_failsafe_logging():
logger = logging.getLogger() logger = logging.getLogger()
logger.setLevel(logging.DEBUG) logger.setLevel(logging.DEBUG)

View File

@ -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.consts import MONKEY_ISLAND_ABS_PATH
from monkey_island.cc.server_utils.encryption import ILockableEncryptor, RepositoryEncryptor 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 import AWSService, IslandModeService, RepositoryService
from monkey_island.cc.services.attack.technique_reports.T1003 import T1003, T1003GetReportData from monkey_island.cc.services.attack.technique_reports.T1003 import T1003, T1003GetReportData
from monkey_island.cc.services.run_local_monkey import LocalMonkeyRunService 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",
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): def _register_repositories(container: DIContainer, data_dir: Path):

View File

@ -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

View File

@ -87,7 +87,7 @@ class PreviewPaneComponent extends AuthComponent {
Download Island Server Log Download Island Server Log
</th> </th>
<td> <td>
<IslandLogDownloadButton url={'/api/log/island/download'} /> <IslandLogDownloadButton url={'/api/island/log'} />
</td> </td>
</tr> </tr>
} }

View File

@ -48,7 +48,7 @@ export const IslandLogDownloadButton = ({ url, variant = 'primary'}: Props) => {
.then(res => res.json()) .then(res => res.json())
.then(res => { .then(res => {
let filename = 'Island_log'; let filename = 'Island_log';
let logContent = (res['log_file']); let logContent = res;
download(logContent, filename, 'text/plain'); download(logContent, filename, 'text/plain');
}); });
} }