From 0846258bbd99544a0998605610a3ce3a585a7155 Mon Sep 17 00:00:00 2001 From: Barak Argaman Date: Sat, 16 Sep 2017 04:37:39 +0300 Subject: [PATCH] ui improvements post review --- monkey_island/cc/resources/edge.py | 3 - monkey_island/cc/resources/node.py | 3 - monkey_island/cc/services/edge.py | 6 +- monkey_island/cc/services/node.py | 5 +- monkey_island/cc/ui/package.json | 2 - monkey_island/cc/ui/src/components/Main.js | 45 ++++---- .../ui/src/components/pages/ConfigurePage.js | 24 +++-- .../ui/src/components/pages/FullLogsPage.js | 8 +- .../cc/ui/src/components/pages/MapPage.js | 64 +++++------ .../ui/src/components/pages/RunMonkeyPage.js | 85 +++++++++------ .../ui/src/components/pages/RunServerPage.js | 5 +- .../components/preview-pane/PreviewPane.js | 100 ++++++++++++++++++ .../cc/ui/src/images/guardicore-logo.png | Bin 0 -> 9855 bytes monkey_island/cc/ui/src/styles/App.css | 54 +++++++++- 14 files changed, 278 insertions(+), 126 deletions(-) create mode 100644 monkey_island/cc/ui/src/components/preview-pane/PreviewPane.js create mode 100644 monkey_island/cc/ui/src/images/guardicore-logo.png diff --git a/monkey_island/cc/resources/edge.py b/monkey_island/cc/resources/edge.py index 8aee77638..2ef0c15bc 100644 --- a/monkey_island/cc/resources/edge.py +++ b/monkey_island/cc/resources/edge.py @@ -1,8 +1,6 @@ -from bson import ObjectId from flask import request import flask_restful -from cc.database import mongo from cc.services.edge import EdgeService __author__ = 'Barak' @@ -11,7 +9,6 @@ __author__ = 'Barak' class Edge(flask_restful.Resource): def get(self): edge_id = request.args.get('id') - if edge_id: return {"edge": EdgeService.get_displayed_edge_by_id(edge_id)} diff --git a/monkey_island/cc/resources/node.py b/monkey_island/cc/resources/node.py index d3c61f76f..5a6c52e1b 100644 --- a/monkey_island/cc/resources/node.py +++ b/monkey_island/cc/resources/node.py @@ -1,9 +1,6 @@ -from bson import ObjectId from flask import request import flask_restful -from cc.database import mongo -from cc.services.edge import EdgeService from cc.services.node import NodeService __author__ = 'Barak' diff --git a/monkey_island/cc/services/edge.py b/monkey_island/cc/services/edge.py index edadb1322..7f93205f4 100644 --- a/monkey_island/cc/services/edge.py +++ b/monkey_island/cc/services/edge.py @@ -169,11 +169,11 @@ class EdgeService: @staticmethod def get_edge_group(edge): - if edge["exploited"]: + if edge.get("exploited"): return "exploited" - if edge["tunnel"]: + if edge.get("tunnel"): return "tunnel" - if (len(edge["scans"]) > 0) or (len(edge["exploits"]) > 0): + if (len(edge.get("scans", [])) > 0) or (len(edge.get("exploits", [])) > 0): return "scan" return "empty" diff --git a/monkey_island/cc/services/node.py b/monkey_island/cc/services/node.py index ed626eb5c..ca2288974 100644 --- a/monkey_island/cc/services/node.py +++ b/monkey_island/cc/services/node.py @@ -101,10 +101,7 @@ class NodeService: @staticmethod def get_node_group(node): - if node["exploited"]: - return "exploited" - else: - return "clean" + return "exploited" if node.get("exploited") else "clean" @staticmethod def monkey_to_net_node(monkey): diff --git a/monkey_island/cc/ui/package.json b/monkey_island/cc/ui/package.json index a7375ab3a..73d84fa6b 100644 --- a/monkey_island/cc/ui/package.json +++ b/monkey_island/cc/ui/package.json @@ -70,8 +70,6 @@ "react-bootstrap": "^0.31.2", "react-copy-to-clipboard": "^5.0.0", "react-data-components": "^1.1.1", - "react-data-grid": "^2.0.58", - "react-data-grid-addons": "^2.0.58", "react-dom": "^15.6.1", "react-fa": "^4.2.0", "react-graph-vis": "^0.1.3", diff --git a/monkey_island/cc/ui/src/components/Main.js b/monkey_island/cc/ui/src/components/Main.js index 11c7f1115..598f0e1a6 100644 --- a/monkey_island/cc/ui/src/components/Main.js +++ b/monkey_island/cc/ui/src/components/Main.js @@ -14,6 +14,7 @@ require('react-data-components/css/table-twbs.css'); require('styles/App.css'); let logoImage = require('../images/monkey-logo.png'); +let guardicoreLogoImage = require('../images/guardicore-logo.png'); class AppComponent extends React.Component { render() { @@ -24,52 +25,56 @@ class AppComponent extends React.Component {
Infection Monkey - by GuardiCore

+ +
+
+ Powered by + + GuardiCore + +
+ diff --git a/monkey_island/cc/ui/src/components/pages/ConfigurePage.js b/monkey_island/cc/ui/src/components/pages/ConfigurePage.js index 94359d967..16b5ef4a3 100644 --- a/monkey_island/cc/ui/src/components/pages/ConfigurePage.js +++ b/monkey_island/cc/ui/src/components/pages/ConfigurePage.js @@ -1,6 +1,6 @@ import React from 'react'; import Form from 'react-jsonschema-form'; -import {Col} from 'react-bootstrap'; +import {Col, Nav, NavItem} from 'react-bootstrap'; class ConfigurePageComponent extends React.Component { constructor(props) { @@ -47,9 +47,9 @@ class ConfigurePageComponent extends React.Component { }); }; - setSelectedSection = (event) => { + setSelectedSection = (key) => { this.setState({ - selectedSection: event.target.value + selectedSection: key }); }; @@ -57,17 +57,14 @@ class ConfigurePageComponent extends React.Component { return (

Monkey Configuration

-
- - This configuration will only apply on new infections. -
- + { this.state.selectedSection ?
: ''} +
+ + This configuration will only apply to new infections. +
+ { this.state.saved ?

Configuration saved successfully.

: ''} diff --git a/monkey_island/cc/ui/src/components/pages/FullLogsPage.js b/monkey_island/cc/ui/src/components/pages/FullLogsPage.js index 837e12c1f..dbdc618ac 100644 --- a/monkey_island/cc/ui/src/components/pages/FullLogsPage.js +++ b/monkey_island/cc/ui/src/components/pages/FullLogsPage.js @@ -3,13 +3,13 @@ import {Col} from 'react-bootstrap'; import JSONTree from 'react-json-tree' import {DataTable} from 'react-data-components'; -const renderJson = (val, row) => ; -const renderTime = (val, row) => val.split('.')[0]; +const renderJson = (val) => ; +const renderTime = (val) => val.split('.')[0]; const columns = [ - { title: 'Type', prop: 'telem_type' }, - { title: 'Monkey ID', prop: 'monkey_guid' }, { title: 'Time', prop: 'timestamp', render: renderTime}, + { title: 'Monkey ID', prop: 'monkey_guid' }, + { title: 'Type', prop: 'telem_type' }, { title: 'More Info', prop: 'data', render: renderJson, width: '40%' } ]; diff --git a/monkey_island/cc/ui/src/components/pages/MapPage.js b/monkey_island/cc/ui/src/components/pages/MapPage.js index fb236d857..57d88eba7 100644 --- a/monkey_island/cc/ui/src/components/pages/MapPage.js +++ b/monkey_island/cc/ui/src/components/pages/MapPage.js @@ -1,8 +1,9 @@ import React from 'react'; import {Col} from 'react-bootstrap'; import Graph from 'react-graph-vis'; -import {Icon} from 'react-fa' - +import PreviewPane from 'components/preview-pane/PreviewPane'; +import {Link} from 'react-router-dom'; +import {Icon} from 'react-fa'; let options = { layout: { @@ -44,7 +45,9 @@ class MapPageComponent extends React.Component { constructor(props) { super(props); this.state = { - graph: {nodes: [], edges: []} + graph: {nodes: [], edges: []}, + selected: null, + selectedType: null }; } @@ -60,13 +63,19 @@ class MapPageComponent extends React.Component { selectionChanged(event) { if (event.nodes.length === 1) { - console.log('selected node:', event.nodes[0]); + console.log('selected node:', event.nodes[0]); // eslint-disable-line no-console + fetch('/api/netmap/node?id='+event.nodes[0]) + .then(res => res.json()) + .then(res => this.setState({selected: res, selectedType: 'node'})); } else if (event.edges.length === 1) { - console.log('selected edge:', event.edges[0]); + fetch('/api/netmap/edge?id='+event.edges[0]) + .then(res => res.json()) + .then(res => this.setState({selected: res.edge, selectedType: 'edge'})); } else { - console.log('no preview.'); + console.log('selection cleared.'); // eslint-disable-line no-console + this.setState({selected: null, selectedType: null}); } } @@ -77,44 +86,21 @@ class MapPageComponent extends React.Component {

Infection Map

-
- -
-
-
-

- - vm4 - Infected Asset -

-
+ -
-

Machine Info

-

...

+ -

Exploit Method

-

...

- -

Timeline

-
    -
  • -
    - failed attempt1 -
  • -
  • -
    - failed attempt2 -
  • -
  • -
    - Infection! -
  • -
-
+
+ Monkey Telemetry +
diff --git a/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js b/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js index 46bbdc115..cc708afeb 100644 --- a/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js +++ b/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js @@ -2,6 +2,7 @@ import React from 'react'; import {Button, Col, Well} from 'react-bootstrap'; import CopyToClipboard from 'react-copy-to-clipboard'; import {Icon} from 'react-fa'; +import {Link} from "react-router-dom"; class RunMonkeyPageComponent extends React.Component { constructor(props) { @@ -9,7 +10,8 @@ class RunMonkeyPageComponent extends React.Component { this.state = { ips: [], selectedIp: '0.0.0.0', - isRunning: true + isRunningOnIsland: false, + isRunningLocally: false }; } @@ -17,14 +19,13 @@ class RunMonkeyPageComponent extends React.Component { fetch('/api') .then(res => res.json()) .then(res => this.setState({ - ips: res['ip_addresses'], - selectedIp: res['ip_addresses'][0] + ips: res['ip_addresses'] })); fetch('/api/local-monkey') .then(res => res.json()) .then(res => this.setState({ - isRunning: res['is_running'] + isRunningOnIsland: res['is_running'] })); } @@ -37,50 +38,64 @@ class RunMonkeyPageComponent extends React.Component { { method: 'POST', headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({action: 'run', ip: this.state.selectedIp}) + body: JSON.stringify({action: 'run'}) }) .then(res => res.json()) .then(res => { this.setState({ - isRunning: res['is_running'] + isRunningOnIsland: res['is_running'] }); }); }; - setSelectedIp = (event) => { - this.setState({selectedIp: event.target.value}); - }; - render() { return (

Run the Monkey

-

- Select one of the server's IP addresses: - -
That address will be used as the monkey's C&C address. +

+ You can run the monkey on the C&C server, on your local machine and basically everywhere. + The more the merrier 😄

-

Run this snippet on a host for manually infecting it with a Monkey:

- - - - - {this.generateCmd(this.state.selectedIp)} - -

- Or simply click here to Run on {this.state.selectedIp} - { this.state.isRunning ? - Running... - : ''} +

+ + + Download and run locally + { !this.state.isRunningLocally ? + + : ''} + +

+
+

+ Run one of those snippets on a host for infecting it with a Monkey: +
+ (The IP address is used as the monkey's C&C address) +

+ + {this.state.ips.map(ip => +
+ + + + {this.generateCmd(ip)} +
+ )} +
+
+

+ Go ahead and monitor the ongoing infection in the Infection Map view.

); diff --git a/monkey_island/cc/ui/src/components/pages/RunServerPage.js b/monkey_island/cc/ui/src/components/pages/RunServerPage.js index c94f78b9c..1c8f6580e 100644 --- a/monkey_island/cc/ui/src/components/pages/RunServerPage.js +++ b/monkey_island/cc/ui/src/components/pages/RunServerPage.js @@ -21,7 +21,10 @@ class RunServerPageComponent extends React.Component {

Your Monkey Island server is up and running on {this.state.ip} 👏 👏

- Now configure the monkey (or just stick with the default configuration) and run the monkey. + Go ahead and run the monkey. +

+

+ (You can make further adjustments by configuring the monkey)

diff --git a/monkey_island/cc/ui/src/components/preview-pane/PreviewPane.js b/monkey_island/cc/ui/src/components/preview-pane/PreviewPane.js new file mode 100644 index 000000000..2f49f6257 --- /dev/null +++ b/monkey_island/cc/ui/src/components/preview-pane/PreviewPane.js @@ -0,0 +1,100 @@ +import React from 'react'; +import {Icon} from "react-fa"; + +class PreviewPaneComponent extends React.Component { + assetInfo(asset) { + return ( +
+ + + + + + + + + + + + + + + + + + + +
Operating System{asset.os}
IP Addresses{asset.ip_addresses.map(val =>
{val}
)}
Services{asset.services.map(val =>
{val}
)}
Accessible From{asset.accessible_from_nodes.map(val =>
{val.id}
)}
+
+ ); + } + + infectedAssetInfo(asset) { + return ( +
+ {this.assetInfo(asset)} + +

Timeline

+
    + { asset.exploits.map(exploit => +
  • +
    +
    {exploit.start_timestamp}
    +
    {exploit.origin}
    +
    {exploit.exploiter}
    +
  • + )} +
+
+ ); + } + + infectionInfo(edge) { + return ( +
+ +
+ ); + } + + scanInfo(edge) { + return ( +
+ +
+ ); + } + + render() { + let info = null; + switch (this.props.type) { + case 'edge': + info = this.props.item.exploits.length ? + this.infectionInfo(this.props.item) : this.scanInfo(this.props.item); + case 'node': + info = this.props.item.exploits.some(exploit => exploit.result) ? + this.infectedAssetInfo(this.props.item) : this.assetInfo(this.props.item); + } + return ( +
+ { !this.props.item ? + + + Select an item on the map for a preview + + : +
+

+ {this.props.item.label} +

+ +
+ {info} +
+ } +
+ ); + } +} + +export default PreviewPaneComponent; diff --git a/monkey_island/cc/ui/src/images/guardicore-logo.png b/monkey_island/cc/ui/src/images/guardicore-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f02d006c5a152367c9abf6cbedec6603cbb99f GIT binary patch literal 9855 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 literal 0 HcmV?d00001 diff --git a/monkey_island/cc/ui/src/styles/App.css b/monkey_island/cc/ui/src/styles/App.css index 01dc1a8b0..72b3dbf76 100644 --- a/monkey_island/cc/ui/src/styles/App.css +++ b/monkey_island/cc/ui/src/styles/App.css @@ -91,6 +91,22 @@ body { li .checkmark { font-size: 1.3em; + margin-right: -15px; + } + + hr { + border-top-color: #ccc !important; + } + + .guardicore-link span { + color: #999; + vertical-align: middle; + } + + .guardicore-link img { + height: 24px; + margin-left: 8px; + vertical-align: middle; } } @@ -162,6 +178,10 @@ body { margin-left: 1em; } +.run-monkey-snippets .well { + margin-bottom: 0; +} + /* * Map Preview Pane */ @@ -172,10 +192,16 @@ body { border-bottom: 3px solid #e8e8e8; padding: 1.5em 1em; border-radius: 8px; + margin-bottom: 2em; +} + +.preview-pane hr { + margin: 10px 0; } .preview-pane h3 { margin: 0; + font-size: 20px; } .preview-pane h3 small { @@ -191,6 +217,15 @@ body { font-size: 1em; margin-top: 0; } + +.preview-pane .table tr:first-child th , .preview-pane .table tr:first-child td { + border-top: 0; +} + +.preview-pane .table th { + text-align: left; +} + .preview-pane p, .preview-pane .timeline { margin-left: 1em; } @@ -220,6 +255,7 @@ body { .timeline .bullet { width: 16px; + height: 16px; background: #ccc; position: absolute; right: 100%; @@ -247,8 +283,16 @@ body { padding: 15px 8px; } -#search-field , #page-menu { +.data-table-container > .container > .row:first-child > div:first-child > div { + display: inline-block; +} + +.data-table-container > .container > .row:first-child > div:first-child > div:last-child { margin-left: 1em; +} + +#search-field , #page-menu { + margin-left: 0.5em; margin-bottom: 1em; height: 34px; padding: 6px 12px; @@ -265,3 +309,11 @@ body { -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; } + +#search-field { + width: 100px; +} + +.data-table-container .pagination { + margin: 0 !important; +}