forked from p15670423/monkey
Merge pull request #2142 from guardicore/2107-refactor-api-log-endpoint
Refactor Island log endpoint
This commit is contained in:
commit
30166880bb
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
|
|
@ -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>
|
||||||
}
|
}
|
||||||
|
|
|
@ -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');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue