forked from p34709852/monkey
UI: add agent and island log download buttons to map
This commit is contained in:
parent
ead3068202
commit
3d25c56a6e
|
@ -4,8 +4,11 @@ import {faHandPointLeft} from '@fortawesome/free-solid-svg-icons/faHandPointLeft
|
||||||
import {faQuestionCircle} from '@fortawesome/free-solid-svg-icons/faQuestionCircle'
|
import {faQuestionCircle} from '@fortawesome/free-solid-svg-icons/faQuestionCircle'
|
||||||
import Toggle from 'react-toggle';
|
import Toggle from 'react-toggle';
|
||||||
import {OverlayTrigger, Tooltip} from 'react-bootstrap';
|
import {OverlayTrigger, Tooltip} from 'react-bootstrap';
|
||||||
import download from 'downloadjs'
|
|
||||||
import AuthComponent from '../../AuthComponent';
|
import AuthComponent from '../../AuthComponent';
|
||||||
|
import {
|
||||||
|
AgentLogDownloadButton,
|
||||||
|
IslandLogDownloadButton
|
||||||
|
} from '../../ui-components/LogDownloadButtons';
|
||||||
|
|
||||||
class PreviewPaneComponent extends AuthComponent {
|
class PreviewPaneComponent extends AuthComponent {
|
||||||
|
|
||||||
|
@ -13,7 +16,7 @@ class PreviewPaneComponent extends AuthComponent {
|
||||||
return (
|
return (
|
||||||
<OverlayTrigger placement="top"
|
<OverlayTrigger placement="top"
|
||||||
overlay={<Tooltip id="tooltip">{text}</Tooltip>}
|
overlay={<Tooltip id="tooltip">{text}</Tooltip>}
|
||||||
delay={{ show: 250, hide: 400 }}>
|
delay={{show: 250, hide: 400}}>
|
||||||
<a><FontAwesomeIcon icon={faQuestionCircle} style={{'marginRight': '0.5em'}}/></a>
|
<a><FontAwesomeIcon icon={faQuestionCircle} style={{'marginRight': '0.5em'}}/></a>
|
||||||
</OverlayTrigger>
|
</OverlayTrigger>
|
||||||
);
|
);
|
||||||
|
@ -94,43 +97,29 @@ class PreviewPaneComponent extends AuthComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
unescapeLog(st) {
|
downloadLogsRow(asset) {
|
||||||
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) {
|
|
||||||
return (
|
return (
|
||||||
<tr>
|
<>
|
||||||
<th>
|
<tr>
|
||||||
Download Log
|
<th>
|
||||||
</th>
|
Download Monkey Agent Log
|
||||||
<td>
|
</th>
|
||||||
<a type='button'
|
<td>
|
||||||
className={asset.has_log ? 'btn btn-primary' : 'btn btn-primary disabled'}
|
<AgentLogDownloadButton url={'/api/log?id=' + asset.id}
|
||||||
onClick={() => this.downloadLog(asset)}>Download</a>
|
variant={asset.has_log ? undefined : 'disabled'}/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{(asset['group'].includes('island')) &&
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Download Island Server Log
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<IslandLogDownloadButton url={'/api/log/island/download'} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +183,7 @@ class PreviewPaneComponent extends AuthComponent {
|
||||||
{this.servicesRow(asset)}
|
{this.servicesRow(asset)}
|
||||||
{this.accessibleRow(asset)}
|
{this.accessibleRow(asset)}
|
||||||
{this.forceKillRow(asset)}
|
{this.forceKillRow(asset)}
|
||||||
{this.downloadLogRow(asset)}
|
{this.downloadLogsRow(asset)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{this.exploitsTimeline(asset)}
|
{this.exploitsTimeline(asset)}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Button, Col} from 'react-bootstrap';
|
import {Col} from 'react-bootstrap';
|
||||||
import AuthService from '../../services/AuthService';
|
import AuthService from '../../services/AuthService';
|
||||||
import download from 'downloadjs';
|
|
||||||
import TelemetryLogTable from '../ui-components/TelemetryLogTable'
|
import TelemetryLogTable from '../ui-components/TelemetryLogTable'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
|
||||||
|
|
||||||
import '../../styles/pages/TelemetryPage.scss';
|
import '../../styles/pages/TelemetryPage.scss';
|
||||||
import {faDownload} from '@fortawesome/free-solid-svg-icons/faDownload';
|
import {IslandLogDownloadButton} from '../ui-components/LogDownloadButtons';
|
||||||
|
|
||||||
|
|
||||||
class TelemetryPageComponent extends React.Component {
|
class TelemetryPageComponent extends React.Component {
|
||||||
|
@ -19,16 +17,6 @@ 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() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Col sm={{offset: 3, span: 9}} md={{offset: 3, span: 9}}
|
<Col sm={{offset: 3, span: 9}} md={{offset: 3, span: 9}}
|
||||||
|
@ -42,10 +30,7 @@ class TelemetryPageComponent extends React.Component {
|
||||||
<h1 className="page-title"> Monkey Island Logs </h1>
|
<h1 className="page-title"> Monkey Island Logs </h1>
|
||||||
<div className="text-center" style={{marginBottom: '20px'}}>
|
<div className="text-center" style={{marginBottom: '20px'}}>
|
||||||
<p style={{'marginBottom': '2em', 'fontSize': '1.2em'}}> Download Monkey Island internal log file </p>
|
<p style={{'marginBottom': '2em', 'fontSize': '1.2em'}}> Download Monkey Island internal log file </p>
|
||||||
<Button bsSize="large" onClick={() => {
|
<IslandLogDownloadButton url={'/api/log/island/download'}/>
|
||||||
this.downloadIslandLog();
|
|
||||||
}}>
|
|
||||||
<FontAwesomeIcon icon={faDownload}/> Download </Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
@ -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 (<Button variant={variant}
|
||||||
|
onClick={downloadAgentLog}>
|
||||||
|
Download Log
|
||||||
|
</Button>);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 (<Button variant={variant}
|
||||||
|
onClick={downloadIslandLog}>
|
||||||
|
Download Log
|
||||||
|
</Button>);
|
||||||
|
}
|
Loading…
Reference in New Issue