forked from p34709852/monkey
Added show/hide techniques button in attack report, refactored technique dropdowns
This commit is contained in:
parent
1e9c9c196b
commit
4932ddd3d3
|
@ -67,7 +67,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/core": "^10.0.22",
|
"@emotion/core": "^10.0.22",
|
||||||
"@kunukn/react-collapse": "^1.2.7",
|
"@kunukn/react-collapse": "^1.2.7",
|
||||||
"bootstrap": "3.4.1",
|
"bootstrap": "^3.4.1",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"core-js": "^2.6.10",
|
"core-js": "^2.6.10",
|
||||||
"d3": "^5.14.1",
|
"d3": "^5.14.1",
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import {Col} from 'react-bootstrap';
|
import {Col} from 'react-bootstrap';
|
||||||
import {ReactiveGraph} from 'components/reactive-graph/ReactiveGraph';
|
|
||||||
import {edgeGroupToColor, options} from 'components/map/MapOptions';
|
|
||||||
import '../../styles/Collapse.scss';
|
import '../../styles/Collapse.scss';
|
||||||
import '../../styles/report/AttackReport.scss'
|
import '../../styles/report/AttackReport.scss'
|
||||||
import AuthComponent from '../AuthComponent';
|
|
||||||
import {ScanStatus} from '../attack/techniques/Helpers';
|
import {ScanStatus} from '../attack/techniques/Helpers';
|
||||||
import Collapse from '@kunukn/react-collapse';
|
|
||||||
import Matrix from './attack/ReportMatrix';
|
import Matrix from './attack/ReportMatrix';
|
||||||
import SelectedTechnique from './attack/SelectedTechnique';
|
import SelectedTechnique from './attack/SelectedTechnique';
|
||||||
|
import TechniqueDropdowns from './attack/TechniqueDropdowns';
|
||||||
|
|
||||||
import T1210 from '../attack/techniques/T1210';
|
import T1210 from '../attack/techniques/T1210';
|
||||||
import T1197 from '../attack/techniques/T1197';
|
import T1197 from '../attack/techniques/T1197';
|
||||||
|
@ -62,9 +61,8 @@ const techComponents = {
|
||||||
'T1064': T1064
|
'T1064': T1064
|
||||||
};
|
};
|
||||||
|
|
||||||
const classNames = require('classnames');
|
|
||||||
|
|
||||||
class AttackReport extends AuthComponent {
|
class AttackReport extends React.Component {
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -82,9 +80,6 @@ class AttackReport extends AuthComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onToggle = technique =>
|
|
||||||
this.setState(state => ({collapseOpen: state.collapseOpen === technique ? null : technique}));
|
|
||||||
|
|
||||||
onTechniqueSelect = (technique, value, mapped = false) => {
|
onTechniqueSelect = (technique, value, mapped = false) => {
|
||||||
//this.setState({selectedTechnique: technique});
|
//this.setState({selectedTechnique: technique});
|
||||||
let selectedTechnique = this.getTechniqueByTitle(technique);
|
let selectedTechnique = this.getTechniqueByTitle(technique);
|
||||||
|
@ -105,39 +100,6 @@ class AttackReport extends AuthComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getTechniqueCollapse(tech_id) {
|
|
||||||
return (
|
|
||||||
<div key={tech_id} className={classNames('collapse-item', {'item--active': this.state.collapseOpen === tech_id})}>
|
|
||||||
<button className={classNames('btn-collapse', AttackReport.getComponentClass(tech_id, this.state.techniques))}
|
|
||||||
onClick={() => this.onToggle(tech_id)}>
|
|
||||||
<span>{this.state.techniques[tech_id].title}</span>
|
|
||||||
<span>
|
|
||||||
<i className={classNames('fa', this.state.collapseOpen === tech_id ? 'fa-chevron-down' : 'fa-chevron-up')}></i>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
<Collapse
|
|
||||||
className="collapse-comp"
|
|
||||||
isOpen={this.state.collapseOpen === tech_id}
|
|
||||||
onChange={({collapseState}) => {
|
|
||||||
this.setState({tech_id: collapseState});
|
|
||||||
}}
|
|
||||||
onInit={({collapseState}) => {
|
|
||||||
this.setState({tech_id: collapseState});
|
|
||||||
}}
|
|
||||||
render={collapseState => this.createTechniqueContent(collapseState, tech_id)}/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
createTechniqueContent(collapseState, technique) {
|
|
||||||
const TechniqueComponent = techComponents[technique];
|
|
||||||
return (
|
|
||||||
<div className={`content ${collapseState}`}>
|
|
||||||
<TechniqueComponent data={this.state.techniques[technique]}/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderLegend() {
|
renderLegend() {
|
||||||
return (<div id="header" className="row justify-content-between attack-legend">
|
return (<div id="header" className="row justify-content-between attack-legend">
|
||||||
<Col xs={3}>
|
<Col xs={3}>
|
||||||
|
@ -160,10 +122,6 @@ class AttackReport extends AuthComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
generateReportContent() {
|
generateReportContent() {
|
||||||
let content = [];
|
|
||||||
Object.keys(this.state.techniques).forEach((tech_id) => {
|
|
||||||
content.push(this.getTechniqueCollapse(tech_id))
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<div id="attack" className="attack-report">
|
<div id="attack" className="attack-report">
|
||||||
<h3>
|
<h3>
|
||||||
|
@ -177,9 +135,8 @@ class AttackReport extends AuthComponent {
|
||||||
<SelectedTechnique techComponents={techComponents}
|
<SelectedTechnique techComponents={techComponents}
|
||||||
techniques={this.state.techniques}
|
techniques={this.state.techniques}
|
||||||
selected={this.state.selectedTechnique}/>
|
selected={this.state.selectedTechnique}/>
|
||||||
<div>
|
<TechniqueDropdowns techniques={this.state.techniques}
|
||||||
<section className="attack-report">{content}</section>
|
techComponents={techComponents}/>
|
||||||
</div>
|
|
||||||
<br/>
|
<br/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import Checkbox from '../../ui-components/Checkbox';
|
import Checkbox from '../../ui-components/Checkbox';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import 'filepond/dist/filepond.min.css';
|
import 'filepond/dist/filepond.min.css';
|
||||||
|
|
|
@ -17,8 +17,9 @@ class SelectedTechnique extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
if (this.props.selected !== prevProps.selected) {
|
if (this.props.selected !== prevProps.selected || this.props.techniques !== prevProps.techniques) {
|
||||||
this.setState({ selectedTechnique: this.props.selected })
|
this.setState({ selectedTechnique: this.props.selected,
|
||||||
|
techniques: this.props.techniques})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,13 +42,11 @@ class SelectedTechnique extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
let content = {};
|
let content = {};
|
||||||
let selectedTechId = this.state.selectedTechnique;
|
let selectedTechId = this.state.selectedTechnique;
|
||||||
if(selectedTechId === false){
|
if(selectedTechId === false){
|
||||||
content = "Select a technique from attack matrix";
|
content = "None. Select a technique from ATT&CK matrix above.";
|
||||||
} else {
|
} else {
|
||||||
content = this.getSelectedTechniqueComponent(selectedTechId)
|
content = this.getSelectedTechniqueComponent(selectedTechId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
import React from "react";
|
||||||
|
import Collapse from '@kunukn/react-collapse';
|
||||||
|
|
||||||
|
import {Button} from 'react-bootstrap';
|
||||||
|
import AttackReport from '../AttackReport';
|
||||||
|
|
||||||
|
const classNames = require('classnames');
|
||||||
|
|
||||||
|
class TechniqueDropdowns extends React.Component{
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
techniques: this.props.techniques,
|
||||||
|
techComponents: this.props.techComponents,
|
||||||
|
collapseOpen: '',
|
||||||
|
techniquesHidden: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if (this.props.techniques !== prevProps.techniques) {
|
||||||
|
this.setState({ techniques: this.props.techniques })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onToggle = technique =>
|
||||||
|
this.setState(state => ({collapseOpen: state.collapseOpen === technique ? null : technique}));
|
||||||
|
|
||||||
|
getTechniqueCollapse(tech_id) {
|
||||||
|
return (
|
||||||
|
<div key={tech_id} className={classNames('collapse-item', {'item--active': this.state.collapseOpen === tech_id})}>
|
||||||
|
<button className={classNames('btn-collapse', AttackReport.getComponentClass(tech_id, this.state.techniques))}
|
||||||
|
onClick={() => this.onToggle(tech_id)}>
|
||||||
|
<span>{this.state.techniques[tech_id].title}</span>
|
||||||
|
<span>
|
||||||
|
<i className={classNames('fa', this.state.collapseOpen === tech_id ? 'fa-chevron-down' : 'fa-chevron-up')}></i>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<Collapse
|
||||||
|
className="collapse-comp"
|
||||||
|
isOpen={this.state.collapseOpen === tech_id}
|
||||||
|
onChange={({collapseState}) => {
|
||||||
|
this.setState({tech_id: collapseState});
|
||||||
|
}}
|
||||||
|
onInit={({collapseState}) => {
|
||||||
|
this.setState({tech_id: collapseState});
|
||||||
|
}}
|
||||||
|
render={collapseState => this.createTechniqueContent(collapseState, tech_id)}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
createTechniqueContent(collapseState, technique) {
|
||||||
|
const TechniqueComponent = this.state.techComponents[technique];
|
||||||
|
return (
|
||||||
|
<div className={`content ${collapseState}`}>
|
||||||
|
<TechniqueComponent data={this.state.techniques[technique]}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleTechList(){
|
||||||
|
this.setState({techniquesHidden: (! this.state.techniquesHidden)})
|
||||||
|
}
|
||||||
|
|
||||||
|
render(){
|
||||||
|
let listClass = '';
|
||||||
|
let content = [];
|
||||||
|
if (this.state.techniquesHidden){
|
||||||
|
listClass = "hidden-list"
|
||||||
|
} else {
|
||||||
|
Object.keys(this.state.techniques).forEach((tech_id) => {
|
||||||
|
content.push(this.getTechniqueCollapse(tech_id))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="dropdown-list">
|
||||||
|
<Button bsStyle="link"
|
||||||
|
bsSize="large"
|
||||||
|
onClick={() => this.toggleTechList()}>
|
||||||
|
{this.state.techniquesHidden ? "Show all" : "Hide all"}
|
||||||
|
</Button>
|
||||||
|
<section className={`attack-report ${listClass}`}>{content}</section>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TechniqueDropdowns;
|
|
@ -11,3 +11,13 @@
|
||||||
.attack-report div.attack-legend {
|
.attack-report div.attack-legend {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.attack-report .hidden-list{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attack-report .dropdown-list .btn-lg {
|
||||||
|
margin-top: 30px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue