forked from p15670423/monkey
Brought back and refactored run on AWS button.
This commit is contained in:
parent
53f3625172
commit
c6b7f4f0be
|
@ -0,0 +1,75 @@
|
||||||
|
import React, {useEffect, useState} from 'react';
|
||||||
|
import AuthComponent from '../../AuthComponent';
|
||||||
|
import '../../../styles/components/RunOnIslandButton.scss';
|
||||||
|
import {faCloud} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import AWSRunInstances from './AWSRunInstances';
|
||||||
|
import NextSelectionButton from '../../ui-components/inline-selection/NextSelectionButton';
|
||||||
|
import {Alert, Button} from 'react-bootstrap';
|
||||||
|
|
||||||
|
|
||||||
|
function AWSRunButton(props) {
|
||||||
|
|
||||||
|
const authComponent = new AuthComponent({});
|
||||||
|
|
||||||
|
const [isOnAWS, setIsOnAWS] = useState(false);
|
||||||
|
const [AWSInstances, setAWSInstances] = useState([]);
|
||||||
|
const [awsMachineCollectionError, setAwsMachineCollectionError] = useState('');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkIsOnAWS();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function checkIsOnAWS() {
|
||||||
|
authComponent.authFetch('/api/remote-monkey?action=list_aws')
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(res => {
|
||||||
|
let isAws = res['is_aws'];
|
||||||
|
|
||||||
|
if (isAws) {
|
||||||
|
// On AWS!
|
||||||
|
// Checks if there was an error while collecting the aws machines.
|
||||||
|
let isErrorWhileCollectingAwsMachines = (res['error'] != null);
|
||||||
|
if (isErrorWhileCollectingAwsMachines) {
|
||||||
|
// There was an error. Finish loading, and display error message.
|
||||||
|
setIsOnAWS(true);
|
||||||
|
setAwsMachineCollectionError(res['error']);
|
||||||
|
} else {
|
||||||
|
// No error! Finish loading and display machines for user
|
||||||
|
setIsOnAWS(true);
|
||||||
|
setAWSInstances(res['instances']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAWSButton() {
|
||||||
|
return <NextSelectionButton title={'AWS run'}
|
||||||
|
description={'Run on a chosen AWS instance in the cloud.'}
|
||||||
|
icon={faCloud}
|
||||||
|
onButtonClick={() => {
|
||||||
|
props.setComponent(AWSRunInstances,
|
||||||
|
{AWSInstances: AWSInstances, setComponent: props.setComponent})
|
||||||
|
}}/>
|
||||||
|
}
|
||||||
|
|
||||||
|
function getErrorDisplay() {
|
||||||
|
return (
|
||||||
|
<Alert variant={'info'}>Detected ability to run on different AWS instances.
|
||||||
|
To enable this feature, follow the
|
||||||
|
<Button variant={'link'} className={'inline-link'}
|
||||||
|
href={'https://www.guardicore.com/infectionmonkey/docs/usage/integrations/aws-run-on-ec2-machine/'}>
|
||||||
|
Tutorial
|
||||||
|
</Button> and refresh the page. Error received while trying to list AWS instances: {awsMachineCollectionError}
|
||||||
|
</Alert> );
|
||||||
|
}
|
||||||
|
|
||||||
|
let displayed = '';
|
||||||
|
if (awsMachineCollectionError !== '') {
|
||||||
|
displayed = getErrorDisplay();
|
||||||
|
} else if (isOnAWS) {
|
||||||
|
displayed = getAWSButton();
|
||||||
|
}
|
||||||
|
return displayed;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AWSRunButton;
|
|
@ -0,0 +1,108 @@
|
||||||
|
import React, {useEffect, useState} from 'react';
|
||||||
|
import {Button, Nav} from 'react-bootstrap';
|
||||||
|
|
||||||
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||||
|
import {faSync} from '@fortawesome/free-solid-svg-icons/faSync';
|
||||||
|
import '../../../styles/components/RunOnIslandButton.scss';
|
||||||
|
import {faInfoCircle} from '@fortawesome/free-solid-svg-icons/faInfoCircle';
|
||||||
|
import AwsRunTable from './AwsRunTable';
|
||||||
|
import AuthComponent from '../../AuthComponent';
|
||||||
|
|
||||||
|
|
||||||
|
function AWSRunInstances(props) {
|
||||||
|
|
||||||
|
const authComponent = new AuthComponent({});
|
||||||
|
|
||||||
|
let awsTable = null
|
||||||
|
let [allIPs, setAllIPs] = useState([]);
|
||||||
|
let [selectedIp, setSelectedIp] = useState(null);
|
||||||
|
let [AWSClicked, setAWSClicked] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getIps();
|
||||||
|
}, [allIPs]);
|
||||||
|
|
||||||
|
function getIps() {
|
||||||
|
this.authFetch('/api')
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(res => {
|
||||||
|
setAllIPs(res['ip_addresses']);
|
||||||
|
setSelectedIp(res['ip_addresses'][0]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function runOnAws() {
|
||||||
|
setAWSClicked(true);
|
||||||
|
let instances = awsTable.state.selection.map(x => instanceIdToInstance(x));
|
||||||
|
|
||||||
|
authComponent.authFetch('/api/remote-monkey',
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify({type: 'aws', instances: instances, island_ip: selectedIp})
|
||||||
|
}).then(res => res.json())
|
||||||
|
.then(res => {
|
||||||
|
let result = res['result'];
|
||||||
|
|
||||||
|
// update existing state, not run-over
|
||||||
|
let prevRes = awsTable.state.result;
|
||||||
|
for (let key in result) {
|
||||||
|
if (result.hasOwnProperty(key)) {
|
||||||
|
prevRes[key] = result[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
awsTable.setState({
|
||||||
|
result: prevRes,
|
||||||
|
selection: [],
|
||||||
|
selectAll: false
|
||||||
|
});
|
||||||
|
setAWSClicked(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function instanceIdToInstance(instance_id) {
|
||||||
|
let instance = props.AWSInstances.find(
|
||||||
|
function (inst) {
|
||||||
|
return inst['instance_id'] === instance_id;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {'instance_id': instance_id, 'os': instance['os']}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{'marginBottom': '2em'}}>
|
||||||
|
<div style={{'marginTop': '1em', 'marginBottom': '1em'}}>
|
||||||
|
<p className="alert alert-info">
|
||||||
|
<FontAwesomeIcon icon={faInfoCircle} style={{'marginRight': '5px'}}/>
|
||||||
|
Not sure what this is? Not seeing your AWS EC2 instances? <a
|
||||||
|
href="https://github.com/guardicore/monkey/wiki/Monkey-Island:-Running-the-monkey-on-AWS-EC2-instances"
|
||||||
|
rel="noopener noreferrer" target="_blank">Read the documentation</a>!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
allIPs.length > 1 ?
|
||||||
|
<Nav variant="pills" activeKey={selectedIp} onSelect={setSelectedIp}
|
||||||
|
style={{'marginBottom': '2em'}}>
|
||||||
|
{allIPs.map(ip => <Nav.Item key={ip}><Nav.Link eventKey={ip}>{ip}</Nav.Link></Nav.Item>)}
|
||||||
|
</Nav>
|
||||||
|
: <div style={{'marginBottom': '2em'}}/>
|
||||||
|
}
|
||||||
|
<AwsRunTable
|
||||||
|
data={props.AWSInstances}
|
||||||
|
ref={r => (awsTable = r)}
|
||||||
|
/>
|
||||||
|
<div style={{'marginTop': '1em'}}>
|
||||||
|
<Button
|
||||||
|
onClick={runOnAws}
|
||||||
|
className={'btn btn-default btn-md center-block'}
|
||||||
|
disabled={AWSClicked}>
|
||||||
|
Run on selected machines
|
||||||
|
{AWSClicked ?
|
||||||
|
<FontAwesomeIcon icon={faSync} className="text-success" style={{'marginLeft': '5px'}}/> : null}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AWSRunInstances;
|
|
@ -7,6 +7,7 @@ import InlineSelection from '../../ui-components/inline-selection/InlineSelectio
|
||||||
import {cloneDeep} from 'lodash';
|
import {cloneDeep} from 'lodash';
|
||||||
import {faExpandArrowsAlt} from '@fortawesome/free-solid-svg-icons';
|
import {faExpandArrowsAlt} from '@fortawesome/free-solid-svg-icons';
|
||||||
import RunOnIslandButton from './RunOnIslandButton';
|
import RunOnIslandButton from './RunOnIslandButton';
|
||||||
|
import AWSRunButton from './AWSRunButton';
|
||||||
|
|
||||||
function RunOptions(props) {
|
function RunOptions(props) {
|
||||||
|
|
||||||
|
@ -61,6 +62,7 @@ function RunOptions(props) {
|
||||||
setComponent(LocalManualRunOptions,
|
setComponent(LocalManualRunOptions,
|
||||||
{ips: ips, setComponent: setComponent})
|
{ips: ips, setComponent: setComponent})
|
||||||
}}/>
|
}}/>
|
||||||
|
<AWSRunButton setComponent={setComponent}/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
@import 'components/inline-selection/BackButton';
|
@import 'components/inline-selection/BackButton';
|
||||||
@import 'components/inline-selection/CommandDisplay';
|
@import 'components/inline-selection/CommandDisplay';
|
||||||
@import 'components/Icons';
|
@import 'components/Icons';
|
||||||
|
@import 'components/Buttons';
|
||||||
|
|
||||||
|
|
||||||
// Define custom elements after bootstrap import
|
// Define custom elements after bootstrap import
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
a.inline-link {
|
||||||
|
position: relative;
|
||||||
|
top: -1px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
Loading…
Reference in New Issue