From cce76f37dfc174b5e0d1641956ad612e196a649c Mon Sep 17 00:00:00 2001
From: VakarisZ <vakarisz@yahoo.com>
Date: Mon, 25 Mar 2019 21:37:55 +0200
Subject: [PATCH] Configuration "reset to defaults" added

---
 monkey/monkey_island/cc/app.py                |  4 +-
 monkey/monkey_island/cc/resources/attack.py   | 11 ++-
 .../cc/ui/src/components/Main.js              |  4 +-
 .../src/components/attack/MatrixComponent.js  | 70 ++++++++++++++-----
 4 files changed, 64 insertions(+), 25 deletions(-)

diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py
index c313cea50..f43492713 100644
--- a/monkey/monkey_island/cc/app.py
+++ b/monkey/monkey_island/cc/app.py
@@ -29,7 +29,7 @@ from cc.resources.telemetry import Telemetry
 from cc.resources.telemetry_feed import TelemetryFeed
 from cc.resources.pba_file_download import PBAFileDownload
 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
 
 __author__ = 'Barak'
@@ -124,6 +124,6 @@ def init_app(mongo_url):
                      '/api/fileUpload/<string:file_type>?load=<string:filename>',
                      '/api/fileUpload/<string:file_type>?restore=<string:filename>')
     api.add_resource(RemoteRun, '/api/remote-monkey', '/api/remote-monkey/')
-    api.add_resource(AttckConfiguration, '/api/attack')
+    api.add_resource(AttackConfiguration, '/api/attack')
 
     return app
diff --git a/monkey/monkey_island/cc/resources/attack.py b/monkey/monkey_island/cc/resources/attack.py
index dd8be055e..25af9100c 100644
--- a/monkey/monkey_island/cc/resources/attack.py
+++ b/monkey/monkey_island/cc/resources/attack.py
@@ -6,13 +6,18 @@ from cc.auth import jwt_required
 from cc.services.attack.attack import AttackService
 
 
-class AttckConfiguration(flask_restful.Resource):
+class AttackConfiguration(flask_restful.Resource):
     @jwt_required()
     def get(self):
         return jsonify(configuration=AttackService.get_config()['properties'])
 
     @jwt_required()
     def post(self):
-        AttackService.update_config({'properties': json.loads(request.data)})
-        return {}
+        config_json = json.loads(request.data)
+        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 {}
 
diff --git a/monkey/monkey_island/cc/ui/src/components/Main.js b/monkey/monkey_island/cc/ui/src/components/Main.js
index 7fc9bbb80..291cfde58 100644
--- a/monkey/monkey_island/cc/ui/src/components/Main.js
+++ b/monkey/monkey_island/cc/ui/src/components/Main.js
@@ -162,7 +162,7 @@ class AppComponent extends AuthComponent {
 
               <hr/>
               <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="/infection/telemetry">Log</NavLink></li>
               </ul>
@@ -188,7 +188,7 @@ class AppComponent extends AuthComponent {
               {this.renderRoute('/start-over', <StartOverPage onStatusChange={this.updateStatus}/>)}
               {this.renderRoute('/report', <ReportPage 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>
           </Row>
         </Grid>
diff --git a/monkey/monkey_island/cc/ui/src/components/attack/MatrixComponent.js b/monkey/monkey_island/cc/ui/src/components/attack/MatrixComponent.js
index 309e2bbea..818a5b8e6 100644
--- a/monkey/monkey_island/cc/ui/src/components/attack/MatrixComponent.js
+++ b/monkey/monkey_island/cc/ui/src/components/attack/MatrixComponent.js
@@ -46,15 +46,18 @@ let parseTechniques = function (data, maxLen) {
 class MatrixComponent extends AuthComponent {
   constructor(props) {
     super(props);
-    this.state = {lastAction: 'none', matrixData: this.props.configuration};
     // Copy configuration and parse it for ATT&CK matrix table
     let configCopy = JSON.parse(JSON.stringify(this.props.configuration));
-    this.maxTechniques = findMaxTechniques(Object.values(configCopy));
-    this.data = parseTechniques(Object.values(configCopy), this.maxTechniques);
-  }
+    this.state = {lastAction: 'none',
+                  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 {
         Header: key,
         id: key,
@@ -84,7 +87,7 @@ class MatrixComponent extends AuthComponent {
       {
         method: 'POST',
         headers: {'Content-Type': 'application/json'},
-        body: JSON.stringify(this.state.matrixData)
+        body: JSON.stringify(this.state.configData)
       })
       .then(res => {
         if (!res.ok)
@@ -102,26 +105,54 @@ class MatrixComponent extends AuthComponent {
       });
   };
 
-  handleTechniqueChange = (technique, value) => {
-    Object.entries(this.state.matrixData).forEach(techType => {
-      if(techType[1].properties.hasOwnProperty(technique)){
-        let tempMatrix = this.state.matrixData;
-        tempMatrix[techType[0]].properties[technique].value = value;
-        this.setState({matrixData: tempMatrix});
-      }
+  resetConfig = () => {
+    this.authFetch('/api/attack',
+      {
+        method: 'POST',
+        headers: {'Content-Type': 'application/json'},
+        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() {
-    let columns = this.getColumns();
     return (
       <div className={"attack-matrix"}>
         <form onSubmit={this.onSubmit}>
           <ReactTable
-                  columns={columns}
-                  data={this.data}
+                  columns={this.state.columns}
+                  data={this.state.matrixTableData}
                   showPagination={false}
-                  defaultPageSize={this.maxTechniques} />
+                  defaultPageSize={this.state.maxTechniques} />
           <div className={"messages"}>
             { this.state.lastAction === 'reset' ?
               <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'}}>
               Apply to configuration
             </button>
+            <button type="button" onClick={this.resetConfig} className="btn btn-danger btn-lg" style={{margin: '5px'}}>
+              Reset to default matrix
+            </button>
           </div>
         </form>
       </div>);