Seperated report into 3 resources (DDR result)
This commit is contained in:
parent
bcc12657a4
commit
683e945506
|
@ -124,7 +124,11 @@ def init_api_resources(api):
|
|||
api.add_resource(Node, '/api/netmap/node', '/api/netmap/node/')
|
||||
|
||||
# report_type: zero_trust or general
|
||||
api.add_resource(Report, '/api/report/<string:report_type>')
|
||||
api.add_resource(
|
||||
Report,
|
||||
'/api/report/<string:report_type>',
|
||||
'/api/report/<string:report_type>/<string:report_data>')
|
||||
|
||||
api.add_resource(TelemetryFeed, '/api/telemetry-feed', '/api/telemetry-feed/')
|
||||
api.add_resource(Log, '/api/log', '/api/log/')
|
||||
api.add_resource(IslandLog, '/api/log/island/download', '/api/log/island/download/')
|
||||
|
|
|
@ -10,50 +10,129 @@ ZERO_TRUST_REPORT_TYPE = "zero_trust"
|
|||
GENERAL_REPORT_TYPE = "general"
|
||||
REPORT_TYPES = [GENERAL_REPORT_TYPE, ZERO_TRUST_REPORT_TYPE]
|
||||
|
||||
REPORT_DATA_PILLARS = "pillars"
|
||||
REPORT_DATA_FINDINGS = "findings"
|
||||
REPORT_DATA_TEST_STATUS = "tests"
|
||||
|
||||
__author__ = ["itay.mizeretz", "shay.nehmad"]
|
||||
|
||||
|
||||
class Report(flask_restful.Resource):
|
||||
|
||||
@jwt_required()
|
||||
def get(self, report_type):
|
||||
def get(self, report_type=GENERAL_REPORT_TYPE, report_data=None):
|
||||
if report_type == GENERAL_REPORT_TYPE:
|
||||
return ReportService.get_report()
|
||||
elif report_type == ZERO_TRUST_REPORT_TYPE:
|
||||
fakedict = {
|
||||
"are_all_monkeys_done": False,
|
||||
"findings": [
|
||||
{
|
||||
"test": "Monkey 8 found a machine with no AV software active.",
|
||||
"conclusive": False,
|
||||
"pillars": ["Devices"],
|
||||
"events": [
|
||||
{
|
||||
"timestamp": "2019-08-01 14:48:46.112000",
|
||||
"title": "Monkey performed an action",
|
||||
"type": "MonkeyAction",
|
||||
"message": "log1"
|
||||
}, {
|
||||
"timestamp": "2019-08-01 14:48:42.112000",
|
||||
"title": "Analysis",
|
||||
"type": "IslandAction",
|
||||
"message": "log2"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"test": "Monkey 6 successfully exploited machine XXX with shellshock.",
|
||||
"conclusive": True,
|
||||
"pillars": ["Devices", "Networks"],
|
||||
"events": [
|
||||
{
|
||||
"timestamp": "2019-08-01 14:48:46.112000",
|
||||
"title": "Analysis",
|
||||
"type": "MonkeyAction",
|
||||
"message": "log3"
|
||||
}]
|
||||
}
|
||||
]
|
||||
}
|
||||
return jsonify(fakedict)
|
||||
if report_data == REPORT_DATA_FINDINGS:
|
||||
return jsonify(get_all_findings())
|
||||
elif report_data == REPORT_DATA_PILLARS:
|
||||
return jsonify(get_pillars_grades())
|
||||
elif report_data == REPORT_DATA_TEST_STATUS:
|
||||
return jsonify(get_tests_status())
|
||||
|
||||
flask_restful.abort(httplib.NOT_FOUND)
|
||||
|
||||
|
||||
def get_all_findings():
|
||||
return [
|
||||
{
|
||||
"test": "Monkey 8 found a machine with no AV software active.",
|
||||
"conclusive": False,
|
||||
"pillars": ["Devices"],
|
||||
"events": [
|
||||
{
|
||||
"timestamp": "2019-08-01 14:48:46.112000",
|
||||
"title": "Monkey performed an action",
|
||||
"type": "MonkeyAction",
|
||||
"message": "log1"
|
||||
}, {
|
||||
"timestamp": "2019-08-01 14:48:42.112000",
|
||||
"title": "Analysis",
|
||||
"type": "IslandAction",
|
||||
"message": "log2"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"test": "Monkey 6 successfully exploited machine XXX with shellshock.",
|
||||
"conclusive": True,
|
||||
"pillars": ["Devices", "Networks"],
|
||||
"events": [
|
||||
{
|
||||
"timestamp": "2019-08-01 14:48:46.112000",
|
||||
"title": "Analysis",
|
||||
"type": "MonkeyAction",
|
||||
"message": "log3"
|
||||
}]
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def get_tests_status():
|
||||
return [
|
||||
{
|
||||
"Test": "Segmentation",
|
||||
"Conclusive": 6,
|
||||
"Inconclusive": 6,
|
||||
"Positive": 6,
|
||||
"Unexecuted": False # There were results meaning the test was executed.
|
||||
},
|
||||
{
|
||||
"Exploit": "network",
|
||||
"Unexecuted": True # There were no results since the test wasn't executed.
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def get_pillars_grades():
|
||||
return [
|
||||
{
|
||||
"Pillar": "data",
|
||||
"Conclusive": 6,
|
||||
"Inconclusive": 6,
|
||||
"Positive": 6,
|
||||
"Unexecuted": 6
|
||||
},
|
||||
{
|
||||
"Pillar": "network",
|
||||
"Conclusive": 6,
|
||||
"Inconclusive": 6,
|
||||
"Positive": 6,
|
||||
"Unexecuted": 6
|
||||
},
|
||||
{
|
||||
"Pillar": "people",
|
||||
"Conclusive": 6,
|
||||
"Inconclusive": 6,
|
||||
"Positive": 6,
|
||||
"Unexecuted": 6
|
||||
},
|
||||
{
|
||||
"Pillar": "workloads",
|
||||
"Conclusive": 6,
|
||||
"Inconclusive": 6,
|
||||
"Positive": 6,
|
||||
"Unexecuted": 6
|
||||
},
|
||||
{
|
||||
"Pillar": "devices",
|
||||
"Conclusive": 6,
|
||||
"Inconclusive": 6,
|
||||
"Positive": 6,
|
||||
"Unexecuted": 6
|
||||
},
|
||||
{
|
||||
"Pillar": "visibility and analytics",
|
||||
"Conclusive": 6,
|
||||
"Inconclusive": 6,
|
||||
"Positive": 6,
|
||||
"Unexecuted": 6
|
||||
},
|
||||
{
|
||||
"Pillar": "automation and analytics",
|
||||
"Conclusive": 6,
|
||||
"Inconclusive": 6,
|
||||
"Positive": 6,
|
||||
"Unexecuted": 6
|
||||
},
|
||||
]
|
||||
|
|
|
@ -11,9 +11,6 @@ class ZeroTrustReportPageComponent extends AuthComponent {
|
|||
super(props);
|
||||
|
||||
this.state = {
|
||||
report: {
|
||||
findings: undefined
|
||||
},
|
||||
allMonkeysAreDead: false,
|
||||
runStarted: false
|
||||
};
|
||||
|
@ -38,14 +35,16 @@ class ZeroTrustReportPageComponent extends AuthComponent {
|
|||
generateReportContent() {
|
||||
let content;
|
||||
|
||||
if (typeof this.state.report.findings === "undefined") {
|
||||
if (typeof this.state.findings === "undefined") {
|
||||
content = "Still empty";
|
||||
} else {
|
||||
content = <div>
|
||||
<h2>Pillars Overview</h2>
|
||||
<PillarGrades findings={this.state.report.findings} />
|
||||
<PillarGrades pillars={this.state.pillars} />
|
||||
<h2>Test Status</h2>
|
||||
TODO
|
||||
<h2>Findings</h2>
|
||||
<FindingsTable findings={this.state.report.findings} />
|
||||
<FindingsTable findings={this.state.findings} />
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
@ -63,9 +62,15 @@ class ZeroTrustReportPageComponent extends AuthComponent {
|
|||
{content}
|
||||
<hr/>
|
||||
THIS IS THE RAW SERVER DATA
|
||||
<pre id="json-report">
|
||||
{JSON.stringify(this.state.report, undefined, 2)}
|
||||
</pre>
|
||||
<br/>
|
||||
PILLARS:
|
||||
<pre>{JSON.stringify(this.state.pillars, undefined, 2)}</pre>
|
||||
<br/>
|
||||
TESTS:
|
||||
<pre>{JSON.stringify(this.state.tests, undefined, 2)}</pre>
|
||||
<br/>
|
||||
FINDINGS:
|
||||
<pre>{JSON.stringify(this.state.findings, undefined, 2)}</pre>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -76,11 +81,26 @@ class ZeroTrustReportPageComponent extends AuthComponent {
|
|||
}
|
||||
|
||||
getZeroTrustReportFromServer() {
|
||||
this.authFetch('/api/report/zero_trust')
|
||||
let res;
|
||||
this.authFetch('/api/report/zero_trust/findings')
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
this.setState({
|
||||
report: res
|
||||
findings: res
|
||||
});
|
||||
});
|
||||
this.authFetch('/api/report/zero_trust/tests')
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
this.setState({
|
||||
tests: res
|
||||
});
|
||||
});
|
||||
this.authFetch('/api/report/zero_trust/pillars')
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
this.setState({
|
||||
pillars: res
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ const columns = [
|
|||
const listItems = pillars.map((pillar) =>
|
||||
<li key={pillar}><PillarLabel pillar={pillar}/></li>
|
||||
);
|
||||
return <ul>{listItems}</ul>
|
||||
return <ul>{listItems}</ul>;
|
||||
}
|
||||
},
|
||||
{ Header: 'Events', id:"events",
|
||||
|
@ -79,19 +79,22 @@ const pageSize = 10;
|
|||
|
||||
class FindingsTable extends Component {
|
||||
render() {
|
||||
let defaultPageSize = this.props.findings.length > pageSize ? pageSize : this.props.findings.length;
|
||||
let showPagination = this.props.findings.length > pageSize;
|
||||
if (this.props.findings.length > 0) {
|
||||
let defaultPageSize = this.props.findings.length > pageSize ? pageSize : this.props.findings.length;
|
||||
let showPagination = this.props.findings.length > pageSize;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ReactTable
|
||||
columns={columns}
|
||||
data={this.props.findings}
|
||||
showPagination={showPagination}
|
||||
defaultPageSize={defaultPageSize}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div>
|
||||
<ReactTable
|
||||
columns={columns}
|
||||
data={this.props.findings}
|
||||
showPagination={showPagination}
|
||||
defaultPageSize={defaultPageSize}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
else { return (<div><pre>BAYAZ</pre></div>);}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,37 +3,13 @@ import ZeroTrustPillars from "./ZeroTrustPillars";
|
|||
|
||||
export class PillarGrades extends Component {
|
||||
render() {
|
||||
let pillarsCounters = {};
|
||||
for(const pillar in ZeroTrustPillars) {
|
||||
pillarsCounters[ZeroTrustPillars[pillar]] = {
|
||||
"conclusive": 0,
|
||||
"possible": 0
|
||||
};
|
||||
}
|
||||
|
||||
if (this.props.findings !== null) {
|
||||
for (const finding of this.props.findings) {
|
||||
if (typeof finding === 'object' && finding !== null) {
|
||||
if (finding.hasOwnProperty("pillars") && finding.hasOwnProperty("conclusive")) {
|
||||
for (const pillar of finding["pillars"]) {
|
||||
if (finding.conclusive) {
|
||||
pillarsCounters[pillar]["conclusive"] += 1;
|
||||
} else {
|
||||
pillarsCounters[pillar]["possible"] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="pillar-grades">
|
||||
<p>
|
||||
TODO: table with conditional colouring.
|
||||
</p>
|
||||
<pre>
|
||||
{JSON.stringify(pillarsCounters, undefined, 2)}
|
||||
{JSON.stringify(this.props.pillars, undefined, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue