diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c5d152a8..7c397a257 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,13 @@ Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### Added - credentials.json file for storing Monkey Island user login information. #1206 +- The ability to download the Monkey Island logs from the Infection Map page. #1640 ### Changed - "Communicate as Backdoor User" PBA's HTTP requests to request headers only and include a timeout. #1577 - The setup procedure for custom server_config.json files to be simpler. #1576 +- "Logs" page renamed to "Telemetries". #1640 ### Removed - The VSFTPD exploiter. #1533 @@ -32,6 +34,7 @@ Changelog](https://keepachangelog.com/en/1.0.0/). - Hostname system info collector. #1535 - Max iterations and timeout between iterations config options. #1600 - MITRE ATT&CK configuration screen. #1532 +- Island log download button from "Telemetries"(previously called "Logs") page. #1640 ### Fixed - A bug in network map page that caused delay of telemetry log loading. #1545 diff --git a/docs/content/FAQ/_index.md b/docs/content/FAQ/_index.md index 76fedf3a4..4e708186f 100644 --- a/docs/content/FAQ/_index.md +++ b/docs/content/FAQ/_index.md @@ -156,13 +156,23 @@ The Monkey performs queries out to the Internet on two separate occasions: ## Logging and how to find logs -### Monkey Island server logs +### Downloading logs -You can download the Monkey Island's log file directly from the UI. Click the "log" section and choose **Download Monkey Island internal logfile**, like so: +Both Monkey Agent and Monkey Island logs can be found in the Infection Map page. Click on the +machine from which you want to download logs and press the "Download log" button on the side panel. +Note that you can only download the Monkey Island log by clicking on the Monkey Island machine in +the Infection Map. -![How to download Monkey Island internal log file](/images/faq/download_log_monkey_island.png "How to download Monkey Island internal log file") +![How to download logs](/images/faq/log_download.jpg "How to download logs") -It can also be found as a local file on the Monkey Island server system in the specified +### Log locations + +If the logs can't be downloaded through the UI for any reason, you can collect the log files +directly from the machine where an Agent or Monkey Island ran. + +#### Monkey Island server log + +The Monkey Island's log file is located in the [data directory]({{< ref "/reference/data_directory" >}}). The log enables you to see which requests were requested from the server and extra logs from the backend logic. The log will contain entries like these: @@ -177,7 +187,7 @@ It's also possible to change the default log level by editing `log_level` value `log_level` can be set to `info`(default, less verbose) or `debug`(more verbose). -### Infection Monkey agent logs +#### Infection Monkey agent logs The Infection Monkey agent log file can be found in the following paths on machines where it was executed: diff --git a/docs/static/images/faq/download_log_monkey_island.png b/docs/static/images/faq/download_log_monkey_island.png deleted file mode 100644 index 6d352aecc..000000000 Binary files a/docs/static/images/faq/download_log_monkey_island.png and /dev/null differ diff --git a/docs/static/images/faq/log_download.jpg b/docs/static/images/faq/log_download.jpg new file mode 100644 index 000000000..4fd153cbe Binary files /dev/null and b/docs/static/images/faq/log_download.jpg differ diff --git a/monkey/monkey_island/cc/ui/src/components/SideNavComponent.tsx b/monkey/monkey_island/cc/ui/src/components/SideNavComponent.tsx index 6caa6617b..2654f9fc9 100644 --- a/monkey/monkey_island/cc/ui/src/components/SideNavComponent.tsx +++ b/monkey/monkey_island/cc/ui/src/components/SideNavComponent.tsx @@ -91,7 +91,7 @@ const SideNavComponent = ({disabled,
  • - Logs + Telemetries
  • 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 9007194b0..8f3bfe72e 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 @@ -4,8 +4,11 @@ import {faHandPointLeft} from '@fortawesome/free-solid-svg-icons/faHandPointLeft import {faQuestionCircle} from '@fortawesome/free-solid-svg-icons/faQuestionCircle' import Toggle from 'react-toggle'; import {OverlayTrigger, Tooltip} from 'react-bootstrap'; -import download from 'downloadjs' import AuthComponent from '../../AuthComponent'; +import { + AgentLogDownloadButton, + IslandLogDownloadButton +} from '../../ui-components/LogDownloadButtons'; class PreviewPaneComponent extends AuthComponent { @@ -13,7 +16,7 @@ class PreviewPaneComponent extends AuthComponent { return ( {text}} - delay={{ show: 250, hide: 400 }}> + delay={{show: 250, hide: 400}}> ); @@ -94,43 +97,29 @@ class PreviewPaneComponent extends AuthComponent { ); } - unescapeLog(st) { - return st.substr(1, st.length - 2) // remove quotation marks on beginning and end of string. - .replace(/\\n/g, '\n') - .replace(/\\r/g, '\r') - .replace(/\\t/g, '\t') - .replace(/\\b/g, '\b') - .replace(/\\f/g, '\f') - .replace(/\\"/g, '"') - .replace(/\\'/g, '\'') - .replace(/\\&/g, '&'); - } - - downloadLog(asset) { - this.authFetch('/api/log?id=' + asset.id) - .then(res => res.json()) - .then(res => { - let timestamp = res['timestamp']; - timestamp = timestamp.substr(0, timestamp.indexOf('.')); - let filename = res['monkey_label'].split(':').join('-') + ' - ' + timestamp + '.log'; - let logContent = this.unescapeLog(res['log']); - download(logContent, filename, 'text/plain'); - }); - - } - - downloadLogRow(asset) { + downloadLogsRow(asset) { return ( - - - Download Log - - - this.downloadLog(asset)}>Download - - + <> + + + Download Monkey Agent Log + + + + + + {(asset['group'].includes('island')) && + + + Download Island Server Log + + + + + + } + ); } @@ -194,7 +183,7 @@ class PreviewPaneComponent extends AuthComponent { {this.servicesRow(asset)} {this.accessibleRow(asset)} {this.forceKillRow(asset)} - {this.downloadLogRow(asset)} + {this.downloadLogsRow(asset)} {this.exploitsTimeline(asset)} diff --git a/monkey/monkey_island/cc/ui/src/components/pages/TelemetryPage.js b/monkey/monkey_island/cc/ui/src/components/pages/TelemetryPage.js index e0ea0221e..82d27198b 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/TelemetryPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/TelemetryPage.js @@ -1,12 +1,9 @@ import React from 'react'; -import {Button, Col} from 'react-bootstrap'; +import {Col} from 'react-bootstrap'; import AuthService from '../../services/AuthService'; -import download from 'downloadjs'; import TelemetryLogTable from '../ui-components/TelemetryLogTable' -import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; import '../../styles/pages/TelemetryPage.scss'; -import {faDownload} from '@fortawesome/free-solid-svg-icons/faDownload'; class TelemetryPageComponent extends React.Component { @@ -19,35 +16,15 @@ class TelemetryPageComponent extends React.Component { }; } - downloadIslandLog = () => { - this.authFetch('/api/log/island/download') - .then(res => res.json()) - .then(res => { - let filename = 'Island_log'; - let logContent = (res['log_file']); - download(logContent, filename, 'text/plain'); - }); - }; - render() { return (
    -

    Logs

    +

    Agent telemetries

    -
    -

    Monkey Island Logs

    -
    -

    Download Monkey Island internal log file

    - -
    -
    ); } 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 new file mode 100644 index 000000000..0e28973e1 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/LogDownloadButtons.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import AuthComponent from '../AuthComponent'; +import download from 'downloadjs'; +import {Button} from 'react-bootstrap'; + +const authComponent = new AuthComponent({}) + +type Props = { url: string, filename: string, variant?: string} + + + +export const AgentLogDownloadButton = ({ url, variant = 'primary'}: Props) => { + + function unescapeLog(st) { + return st.substr(1, st.length - 2) // remove quotation marks on beginning and end of string. + .replace(/\\n/g, '\n') + .replace(/\\r/g, '\r') + .replace(/\\t/g, '\t') + .replace(/\\b/g, '\b') + .replace(/\\f/g, '\f') + .replace(/\\"/g, '"') + .replace(/\\'/g, '\'') + .replace(/\\&/g, '&'); + } + + function downloadAgentLog() { + authComponent.authFetch(url) + .then(res => res.json()) + .then(res => { + let timestamp = res['timestamp']; + timestamp = timestamp.substr(0, timestamp.indexOf('.')); + let filename = res['monkey_label'].split(':').join('-') + ' - ' + timestamp + '.log'; + let logContent = unescapeLog(res['log']); + download(logContent, filename, 'text/plain'); + }); + } + + return (); +} + + +export const IslandLogDownloadButton = ({ url, variant = 'primary'}: Props) => { + function downloadIslandLog() { + authComponent.authFetch(url) + .then(res => res.json()) + .then(res => { + let filename = 'Island_log'; + let logContent = (res['log_file']); + download(logContent, filename, 'text/plain'); + }); + } + return (); +}