Configuration "reset to defaults" added

This commit is contained in:
VakarisZ 2019-03-25 21:37:55 +02:00
parent f5da1bf3b6
commit cce76f37df
4 changed files with 64 additions and 25 deletions

View File

@ -29,7 +29,7 @@ from cc.resources.telemetry import Telemetry
from cc.resources.telemetry_feed import TelemetryFeed from cc.resources.telemetry_feed import TelemetryFeed
from cc.resources.pba_file_download import PBAFileDownload from cc.resources.pba_file_download import PBAFileDownload
from cc.resources.pba_file_upload import FileUpload from cc.resources.pba_file_upload import FileUpload
from cc.resources.attack import AttckConfiguration from cc.resources.attack import AttackConfiguration
from cc.services.config import ConfigService from cc.services.config import ConfigService
__author__ = 'Barak' __author__ = 'Barak'
@ -124,6 +124,6 @@ def init_app(mongo_url):
'/api/fileUpload/<string:file_type>?load=<string:filename>', '/api/fileUpload/<string:file_type>?load=<string:filename>',
'/api/fileUpload/<string:file_type>?restore=<string:filename>') '/api/fileUpload/<string:file_type>?restore=<string:filename>')
api.add_resource(RemoteRun, '/api/remote-monkey', '/api/remote-monkey/') api.add_resource(RemoteRun, '/api/remote-monkey', '/api/remote-monkey/')
api.add_resource(AttckConfiguration, '/api/attack') api.add_resource(AttackConfiguration, '/api/attack')
return app return app

View File

@ -6,13 +6,18 @@ from cc.auth import jwt_required
from cc.services.attack.attack import AttackService from cc.services.attack.attack import AttackService
class AttckConfiguration(flask_restful.Resource): class AttackConfiguration(flask_restful.Resource):
@jwt_required() @jwt_required()
def get(self): def get(self):
return jsonify(configuration=AttackService.get_config()['properties']) return jsonify(configuration=AttackService.get_config()['properties'])
@jwt_required() @jwt_required()
def post(self): def post(self):
AttackService.update_config({'properties': json.loads(request.data)}) config_json = json.loads(request.data)
return {} if 'reset_attack_matrix' in config_json:
AttackService.reset_config()
return jsonify(configuration=AttackService.get_config()['properties'])
else:
AttackService.update_config({'properties': json.loads(request.data)})
return {}

View File

@ -162,7 +162,7 @@ class AppComponent extends AuthComponent {
<hr/> <hr/>
<ul> <ul>
<li><NavLink to="/attck">ATT&CK Configuration</NavLink></li> <li><NavLink to="/attack">ATT&CK Configuration</NavLink></li>
<li><NavLink to="/configure">Configuration</NavLink></li> <li><NavLink to="/configure">Configuration</NavLink></li>
<li><NavLink to="/infection/telemetry">Log</NavLink></li> <li><NavLink to="/infection/telemetry">Log</NavLink></li>
</ul> </ul>
@ -188,7 +188,7 @@ class AppComponent extends AuthComponent {
{this.renderRoute('/start-over', <StartOverPage onStatusChange={this.updateStatus}/>)} {this.renderRoute('/start-over', <StartOverPage onStatusChange={this.updateStatus}/>)}
{this.renderRoute('/report', <ReportPage onStatusChange={this.updateStatus}/>)} {this.renderRoute('/report', <ReportPage onStatusChange={this.updateStatus}/>)}
{this.renderRoute('/license', <LicensePage onStatusChange={this.updateStatus}/>)} {this.renderRoute('/license', <LicensePage onStatusChange={this.updateStatus}/>)}
{this.renderRoute('/attck', <AttckPage onStatusChange={this.updateStatus}/>)} {this.renderRoute('/attack', <AttckPage onStatusChange={this.updateStatus}/>)}
</Col> </Col>
</Row> </Row>
</Grid> </Grid>

View File

@ -46,15 +46,18 @@ let parseTechniques = function (data, maxLen) {
class MatrixComponent extends AuthComponent { class MatrixComponent extends AuthComponent {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = {lastAction: 'none', matrixData: this.props.configuration};
// Copy configuration and parse it for ATT&CK matrix table // Copy configuration and parse it for ATT&CK matrix table
let configCopy = JSON.parse(JSON.stringify(this.props.configuration)); let configCopy = JSON.parse(JSON.stringify(this.props.configuration));
this.maxTechniques = findMaxTechniques(Object.values(configCopy)); this.state = {lastAction: 'none',
this.data = parseTechniques(Object.values(configCopy), this.maxTechniques); configData: this.props.configuration,
} maxTechniques: findMaxTechniques(Object.values(configCopy))};
this.state.matrixTableData = parseTechniques(Object.values(configCopy), this.state.maxTechniques);
this.state.columns = this.getColumns(this.state.matrixTableData)
};
getColumns() {
return Object.keys(this.data[0]).map((key)=>{ getColumns(matrixData) {
return Object.keys(matrixData[0]).map((key)=>{
return { return {
Header: key, Header: key,
id: key, id: key,
@ -84,7 +87,7 @@ class MatrixComponent extends AuthComponent {
{ {
method: 'POST', method: 'POST',
headers: {'Content-Type': 'application/json'}, headers: {'Content-Type': 'application/json'},
body: JSON.stringify(this.state.matrixData) body: JSON.stringify(this.state.configData)
}) })
.then(res => { .then(res => {
if (!res.ok) if (!res.ok)
@ -102,26 +105,54 @@ class MatrixComponent extends AuthComponent {
}); });
}; };
handleTechniqueChange = (technique, value) => { resetConfig = () => {
Object.entries(this.state.matrixData).forEach(techType => { this.authFetch('/api/attack',
if(techType[1].properties.hasOwnProperty(technique)){ {
let tempMatrix = this.state.matrixData; method: 'POST',
tempMatrix[techType[0]].properties[technique].value = value; headers: {'Content-Type': 'application/json'},
this.setState({matrixData: tempMatrix}); body: JSON.stringify('reset_attack_matrix')
} })
.then(res => res.json())
.then(res => {
this.updateStateFromConfig(res.configuration, 'reset')
});
};
updateStateFromConfig = (config, lastAction = '') => {
let configCopy = JSON.parse(JSON.stringify(config));
let maxTechniques = findMaxTechniques(Object.values(configCopy));
let matrixTableData = parseTechniques(Object.values(configCopy), maxTechniques);
let columns = this.getColumns(matrixTableData);
this.setState({
lastAction: lastAction,
configData: config,
maxTechniques: maxTechniques,
matrixTableData: matrixTableData,
columns: columns
}); });
}; };
handleTechniqueChange = (technique, value) => {
// Change value on configuration
Object.entries(this.state.configData).forEach(techType => {
if(techType[1].properties.hasOwnProperty(technique)){
let tempMatrix = this.state.configData;
tempMatrix[techType[0]].properties[technique].value = value;
this.updateStateFromConfig(tempMatrix);
}
});
};
render() { render() {
let columns = this.getColumns();
return ( return (
<div className={"attack-matrix"}> <div className={"attack-matrix"}>
<form onSubmit={this.onSubmit}> <form onSubmit={this.onSubmit}>
<ReactTable <ReactTable
columns={columns} columns={this.state.columns}
data={this.data} data={this.state.matrixTableData}
showPagination={false} showPagination={false}
defaultPageSize={this.maxTechniques} /> defaultPageSize={this.state.maxTechniques} />
<div className={"messages"}> <div className={"messages"}>
{ this.state.lastAction === 'reset' ? { this.state.lastAction === 'reset' ?
<div className="alert alert-success"> <div className="alert alert-success">
@ -146,6 +177,9 @@ class MatrixComponent extends AuthComponent {
<button type="button" onClick={this.onSubmit} className="btn btn-success btn-lg" style={{margin: '5px'}}> <button type="button" onClick={this.onSubmit} className="btn btn-success btn-lg" style={{margin: '5px'}}>
Apply to configuration Apply to configuration
</button> </button>
<button type="button" onClick={this.resetConfig} className="btn btn-danger btn-lg" style={{margin: '5px'}}>
Reset to default matrix
</button>
</div> </div>
</form> </form>
</div>); </div>);