ATT&CK report page UI implemented

This commit is contained in:
VakarisZ 2019-04-04 17:21:02 +03:00
parent 4d6f403710
commit 5ff7eba12f
7 changed files with 134 additions and 118 deletions

View File

@ -1,6 +1,6 @@
from monkey_island.cc.database import mongo
from cc.database import mongo
from common.utils.attack_status_enum import ScanStatus
from monkey_island.cc.services.attack.attack_config import get_technique
from cc.services.attack.attack_config import get_technique
__author__ = "VakarisZ"

View File

@ -126,18 +126,23 @@
}
},
"@babel/runtime-corejs2": {
"version": "7.1.5",
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.1.5.tgz",
"integrity": "sha512-WsYRwQsFhVmxkAqwypPTZyV9GpkqMEaAr2zOItOmqSX2GBFaI+eq98CN81e13o0zaUKJOQGYyjhNVqj56nnkYg==",
"version": "7.4.3",
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.4.3.tgz",
"integrity": "sha512-anTLTF7IK8Hd5f73zpPzt875I27UaaTWARJlfMGgnmQhvEe1uNHQRKBUbXL0Gc0VEYiVzsHsTPso5XdK8NGvFg==",
"requires": {
"core-js": "2.5.7",
"regenerator-runtime": "0.12.1"
"core-js": "2.6.5",
"regenerator-runtime": "0.13.2"
},
"dependencies": {
"core-js": {
"version": "2.6.5",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz",
"integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A=="
},
"regenerator-runtime": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
"integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
"version": "0.13.2",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz",
"integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA=="
}
}
},
@ -13923,7 +13928,7 @@
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-0.32.4.tgz",
"integrity": "sha512-xj+JfaPOvnvr3ow0aHC7Y3HaBKZNR1mm361hVxVzVX3fcdJNIrfiodbQ0m9nLBpNxiKG6FTU2lq/SbTDYT2vew==",
"requires": {
"@babel/runtime-corejs2": "7.1.5",
"@babel/runtime-corejs2": "7.4.3",
"classnames": "2.2.6",
"dom-helpers": "3.4.0",
"invariant": "2.2.4",
@ -13932,7 +13937,7 @@
"prop-types-extra": "1.1.0",
"react-overlays": "0.8.3",
"react-prop-types": "0.4.0",
"react-transition-group": "2.5.0",
"react-transition-group": "2.8.0",
"uncontrollable": "5.1.0",
"warning": "3.0.0"
},
@ -14106,7 +14111,7 @@
"dom-helpers": "3.4.0",
"prop-types": "15.6.2",
"prop-types-extra": "1.1.0",
"react-transition-group": "2.5.0",
"react-transition-group": "2.8.0",
"warning": "3.0.0"
}
},
@ -14247,9 +14252,9 @@
}
},
"react-transition-group": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.5.0.tgz",
"integrity": "sha512-qYB3JBF+9Y4sE4/Mg/9O6WFpdoYjeeYqx0AFb64PTazVy8RPMiE3A47CG9QmM4WJ/mzDiZYslV+Uly6O1Erlgw==",
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.8.0.tgz",
"integrity": "sha512-So23a1MPn8CGoW5WNU4l0tLiVkOFmeXSS1K4Roe+dxxqqHvI/2XBmj76jx+u96LHnQddWG7LX8QovPAainSmWQ==",
"requires": {
"dom-helpers": "3.4.0",
"loose-envify": "1.4.0",

View File

@ -65,7 +65,7 @@
},
"dependencies": {
"@kunukn/react-collapse": "^1.0.5",
"bootstrap": "3.3.7",
"bootstrap": "^3.3.7",
"classnames": "^2.2.6",
"core-js": "^2.5.7",
"downloadjs": "^1.4.7",

View File

@ -21,7 +21,6 @@ class T1210 extends React.Component {
super(props);
}
render() {
console.log(this.props);
return (
<Collapse isOpen={true || false}>
<div>{this.props.data.message}</div>

View File

@ -1,5 +1,5 @@
import React from 'react';
import {Button, Col} from 'react-bootstrap';
import {Button, Col, Row, TabContainer} from 'react-bootstrap';
import {ReactiveGraph} from 'components/reactive-graph/ReactiveGraph';
import {edgeGroupToColor, options} from 'components/map/MapOptions';
import AuthComponent from '../AuthComponent';
@ -20,7 +20,8 @@ class AttackReportPageComponent extends AuthComponent {
this.state = {
report: {},
allMonkeysAreDead: false,
runStarted: true
runStarted: true,
index: 1
};
}
@ -53,40 +54,56 @@ class AttackReportPageComponent extends AuthComponent {
}
}
state = {
index: 1,
};
onToggle = index =>
this.setState(state => ({ index: state.index === index ? null : index }));
onToggle = () => {
this.setState(state => ({ isOpen: !state.isOpen }));
};
getTechniqueCollapse(tech_id){
switch (this.state.report[tech_id].status) {
case 'SCANNED':
var className = 'collapse-info';
break;
case 'USED':
var className = 'collapse-danger';
break;
default:
var className = 'collapse-default';
}
getTechniqueCollapse(technique){
const TechniqueComponent = tech_components[technique];
return (
<div className={classNames("item", { "item--active": this.state.index === 1 })}>
<button className="btn" onClick={() => this.onToggle(1)}>
<span>select 1</span> <span>{this.state.item1}</span>
<div className={classNames("collapse-item", { "item--active": this.state.index === 1 })}>
<button className={classNames("btn-collapse", className)} onClick={() => this.onToggle(1)}>
<span>{this.state.report[tech_id].title}</span>
<span>
<i className={classNames("fa", this.state.index === 1 ? "fa-chevron-down" : "fa-chevron-up")}></i>
</span>
</button>
<Collapse
className="collapse"
className="collapse-comp"
isOpen={this.state.index === 1}
onChange={({ collapseState }) => {
this.setState({ item1: collapseState });
}}
onInit={({ collapseState }) => {
this.setState({ item1: collapseState });
}}>
<TechniqueComponent data={this.state.report[technique]} />
</Collapse>
}}
render={collapseState => this.createTechniqueContent(collapseState, tech_id)}/>
</div>
);
}
createTechniqueContent(collapseState, technique) {
const TechniqueComponent = tech_components[technique];
return (
<div className={`content ${collapseState}`}>
<TechniqueComponent data={this.state.report[technique]} />
</div>
);
}
generateReportContent(){
let content = '';
Object.keys(this.state.report).forEach((technique) => {
content = this.getTechniqueCollapse(technique)
Object.keys(this.state.report).forEach((tech_id) => {
content = this.getTechniqueCollapse(tech_id)
});
return <section className="app">{content}</section>
}
@ -109,6 +126,20 @@ class AttackReportPageComponent extends AuthComponent {
return (
<Col xs={12} lg={8}>
<h1 className="page-title no-print">5. ATT&CK Report</h1>
<div id="header" className="row justify-content-between attack-legend">
<Col xs={4}>
<i className="fa fa-circle icon-default"></i>
<span> - Unscanned</span>
</Col>
<Col xs={4}>
<i className="fa fa-circle icon-info"></i>
<span> - Scanned</span>
</Col>
<Col xs={4}>
<i className="fa fa-circle icon-danger"></i>
<span> - Used</span>
</Col>
</div>
<div style={{'fontSize': '1.2em'}}>
{content}
</div>

View File

@ -516,7 +516,28 @@ body {
}
/* Attack config page */
/* Attack pages */
.attack-matrix .messages {
margin-bottom: 30px;
}
.icon-info {
color: #ade3eb !important;
}
.icon-warning {
color: #f0ad4e !important;
}
.icon-danger {
color: #d9acac !important;
}
.icon-default {
color: #e0ddde !important;
}
.attack-legend {
text-align: center;
margin-bottom: 20px;
}

View File

@ -1,26 +1,10 @@
$transition: 350ms cubic-bezier(0.4, 0, 0.2, 1);
$transition: 500ms cubic-bezier(0.4, 0.1, 0.1, 0.5);
* {
box-sizing: border-box;
}
$danger-color: #d9acac;
$info-color: #ade3eb;
$default-color: #e0ddde;
:root {
font-size: 10px;
}
body {
font: 1.6rem / 1.5 "Montserrat", sans-serif;
margin: 0;
min-height: 100vh;
font-size: 1.6rem;
overflow-y: scroll;
}
p {
margin: 0;
}
button {
.collapse-item button {
font-size: inherit;
margin: 0;
padding: 1rem;
@ -30,62 +14,59 @@ button {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
img {
vertical-align: bottom;
max-width: 100%;
height: auto;
.collapse-item button span:first-child{
text-align:left;
}
a {
color: black;
font-size: inherit;
}
h2 {
margin: 0.5rem;
}
.info {
margin-bottom: 3rem;
text-align: center;
padding: 1rem;
}
.app {
min-height: 100vh;
max-width: 500px;
margin: 0 auto;
padding: 1rem;
}
.btn {
.collapse-item button {
width: 100%;
box-shadow: 0 2px 6px #ccc;
border: none;
transition: background-color $transition;
font-family: inherit;
display: flex;
justify-content: space-between;
align-items: center;
> span {
font-family: inherit;
> span {
display: inline-block;
flex: 4;
text-align: right;
&:nth-child(2) {
flex: 3;
}
}
}
.item {
.collapse-danger {
background-color: $danger-color !important;
}
.collapse-info {
background-color: $info-color !important;
}
.collapse-default {
background-color: $default-color !important;
}
.collapse-item {
padding: 0.5rem;
&--active {
.btn {
.btn-collapse {
background-color: #f7f7f7;
}
}
}
.collapse {
.collapse-item .collapse-comp {
padding: 0 7px 7px 7px;
border: 2px solid rgb(232, 228, 228);
border-top: 0;
display:block !important;
transition: height $transition;
overflow: hidden;
}
.content {
.collapse-item .content {
padding: 2rem 0;
transition: transform $transition;
will-change: transform;
@ -94,7 +75,7 @@ h2 {
&.collapsing {
transform: translateY(-$offset);
}
&.collapsed {
&.collapse-comp {
transform: translateY(-$offset);
}
&.expanding {
@ -105,32 +86,11 @@ h2 {
}
}
.text {
.collapse-item .text {
margin-bottom: 1rem;
}
.state {
.collapse-item .state {
display: inline-block;
min-width: 6em;
}
.image-wrapper {
position: relative;
max-width: 500px;
height: 0;
padding-bottom: 40%;
margin-bottom: 1rem;
background: #eee;
&__img {
object-fit: cover;
width: 100%;
position: absolute;
}
}
.collapse-css-transition {
transition: height 300ms cubic-bezier(0.4, 0, 0.2, 1);
overflow: hidden;
}