From 80e743557256a2a7e49347a5d24e918acacb28fb Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Mon, 8 Feb 2021 17:38:45 +0200 Subject: [PATCH] Refactored Finding DTO into ScoutSuiteFinding and MonkeyFinding DTO which inherit from more abstract Finding. --- .../common/common_consts/zero_trust_consts.py | 4 -- .../cc/models/zero_trust/finding.py | 40 +++++------------- .../cc/models/zero_trust/monkey_finding.py | 18 ++++++++ .../models/zero_trust/scoutsuite_finding.py | 18 ++++++++ ...test_finding.py => test_monkey_finding.py} | 25 +++++------ .../zero_trust/test_scoutsuite_finding.py | 41 +++++++++++++++++++ .../resources/zero_trust/zero_trust_report.py | 2 +- .../monkey_zt_finding_service.py | 12 +++--- .../test_monkey_zt_finding_service.py | 3 +- .../scoutsuite_zt_finding_service.py | 16 ++++---- .../test_scoutsuite_zt_finding_service.py | 9 ++-- .../zero_trust/test_common/finding_data.py | 20 ++++----- .../zero_trust_report/finding_service.py | 18 ++++---- .../zero_trust_report/pillar_service.py | 6 +-- .../zero_trust_report/test_finding_service.py | 9 ++-- .../zerotrust/FindingsTable.js | 4 +- 16 files changed, 150 insertions(+), 95 deletions(-) create mode 100644 monkey/monkey_island/cc/models/zero_trust/monkey_finding.py create mode 100644 monkey/monkey_island/cc/models/zero_trust/scoutsuite_finding.py rename monkey/monkey_island/cc/models/zero_trust/{test_finding.py => test_monkey_finding.py} (56%) create mode 100644 monkey/monkey_island/cc/models/zero_trust/test_scoutsuite_finding.py diff --git a/monkey/common/common_consts/zero_trust_consts.py b/monkey/common/common_consts/zero_trust_consts.py index 3d3602b80..f0a624bdf 100644 --- a/monkey/common/common_consts/zero_trust_consts.py +++ b/monkey/common/common_consts/zero_trust_consts.py @@ -22,10 +22,6 @@ STATUS_FAILED = "Failed" # Don't change order! The statuses are ordered by importance/severity. ORDERED_TEST_STATUSES = [STATUS_FAILED, STATUS_VERIFY, STATUS_PASSED, STATUS_UNEXECUTED] -MONKEY_FINDING = "monkey_finding" -SCOUTSUITE_FINDING = "scoutsuite_finding" -FINDING_TYPES = [MONKEY_FINDING, SCOUTSUITE_FINDING] - TEST_DATA_ENDPOINT_ELASTIC = "unencrypted_data_endpoint_elastic" TEST_DATA_ENDPOINT_HTTP = "unencrypted_data_endpoint_http" TEST_MACHINE_EXPLOITED = "machine_exploited" diff --git a/monkey/monkey_island/cc/models/zero_trust/finding.py b/monkey/monkey_island/cc/models/zero_trust/finding.py index b9aefb42a..4d108ddde 100644 --- a/monkey/monkey_island/cc/models/zero_trust/finding.py +++ b/monkey/monkey_island/cc/models/zero_trust/finding.py @@ -4,7 +4,8 @@ Define a Document Schema for Zero Trust findings. """ from __future__ import annotations -from typing import Union + +import abc from mongoengine import Document, GenericLazyReferenceField, StringField @@ -12,7 +13,6 @@ import common.common_consts.zero_trust_consts as zero_trust_consts # Dummy import for mongoengine. # noinspection PyUnresolvedReferences from monkey_island.cc.models.zero_trust.monkey_finding_details import MonkeyFindingDetails -from monkey_island.cc.models.zero_trust.scoutsuite_finding_details import ScoutSuiteFindingDetails class Finding(Document): @@ -33,39 +33,21 @@ class Finding(Document): * The logic section defines complex questions we can ask about a single document which are asked multiple times, or complex action we will perform - somewhat like an API. """ - # SCHEMA - test = StringField(required=True, choices=zero_trust_consts.TESTS) - status = StringField(required=True, choices=zero_trust_consts.ORDERED_TEST_STATUSES) - finding_type = StringField(required=True, choices=zero_trust_consts.FINDING_TYPES) - - # Details are in a separate document in order to discourage pulling them when not needed - # due to performance. - details = GenericLazyReferenceField(choices=[MonkeyFindingDetails, ScoutSuiteFindingDetails], required=True) # http://docs.mongoengine.org/guide/defining-documents.html#document-inheritance meta = {'allow_inheritance': True} - # LOGIC - def get_test_explanation(self): - return zero_trust_consts.TESTS_MAP[self.test][zero_trust_consts.TEST_EXPLANATION_KEY] + # SCHEMA + test = StringField(required=True, choices=zero_trust_consts.TESTS) + status = StringField(required=True, choices=zero_trust_consts.ORDERED_TEST_STATUSES) - def get_pillars(self): - return zero_trust_consts.TESTS_MAP[self.test][zero_trust_consts.PILLARS_KEY] + # Details are in a separate document in order to discourage pulling them when not needed + # due to performance. + details = GenericLazyReferenceField(required=True) # Creation methods @staticmethod + @abc.abstractmethod def save_finding(test: str, status: str, - detail_ref: Union[MonkeyFindingDetails, ScoutSuiteFindingDetails]) -> Finding: - finding = Finding(test=test, - status=status, - details=detail_ref, - finding_type=Finding._get_finding_type_by_details(detail_ref)) - finding.save() - return finding - - @staticmethod - def _get_finding_type_by_details(details: Union[MonkeyFindingDetails, ScoutSuiteFindingDetails]) -> str: - if type(details) == MonkeyFindingDetails: - return zero_trust_consts.MONKEY_FINDING - else: - return zero_trust_consts.SCOUTSUITE_FINDING + detail_ref) -> Finding: + pass diff --git a/monkey/monkey_island/cc/models/zero_trust/monkey_finding.py b/monkey/monkey_island/cc/models/zero_trust/monkey_finding.py new file mode 100644 index 000000000..e063ea5c1 --- /dev/null +++ b/monkey/monkey_island/cc/models/zero_trust/monkey_finding.py @@ -0,0 +1,18 @@ +from mongoengine import LazyReferenceField + +from monkey_island.cc.models.zero_trust.finding import Finding +from monkey_island.cc.models.zero_trust.monkey_finding_details import MonkeyFindingDetails + + +class MonkeyFinding(Finding): + details = LazyReferenceField(MonkeyFindingDetails, required=True) + + @staticmethod + def save_finding(test: str, + status: str, + detail_ref: MonkeyFindingDetails) -> Finding: + monkey_finding = MonkeyFinding(test=test, + status=status, + details=detail_ref) + monkey_finding.save() + return monkey_finding diff --git a/monkey/monkey_island/cc/models/zero_trust/scoutsuite_finding.py b/monkey/monkey_island/cc/models/zero_trust/scoutsuite_finding.py new file mode 100644 index 000000000..8adeef2e9 --- /dev/null +++ b/monkey/monkey_island/cc/models/zero_trust/scoutsuite_finding.py @@ -0,0 +1,18 @@ +from mongoengine import LazyReferenceField + +from monkey_island.cc.models.zero_trust.finding import Finding +from monkey_island.cc.models.zero_trust.scoutsuite_finding_details import ScoutSuiteFindingDetails + + +class ScoutSuiteFinding(Finding): + details = LazyReferenceField(ScoutSuiteFindingDetails, required=True) + + @staticmethod + def save_finding(test: str, + status: str, + detail_ref: ScoutSuiteFindingDetails) -> Finding: + scoutsuite_finding = ScoutSuiteFinding(test=test, + status=status, + details=detail_ref) + scoutsuite_finding.save() + return scoutsuite_finding diff --git a/monkey/monkey_island/cc/models/zero_trust/test_finding.py b/monkey/monkey_island/cc/models/zero_trust/test_monkey_finding.py similarity index 56% rename from monkey/monkey_island/cc/models/zero_trust/test_finding.py rename to monkey/monkey_island/cc/models/zero_trust/test_monkey_finding.py index 4df4b7bab..56a4066e1 100644 --- a/monkey/monkey_island/cc/models/zero_trust/test_finding.py +++ b/monkey/monkey_island/cc/models/zero_trust/test_monkey_finding.py @@ -4,29 +4,22 @@ from mongoengine import ValidationError import common.common_consts.zero_trust_consts as zero_trust_consts from monkey_island.cc.models.zero_trust.event import Event from monkey_island.cc.models.zero_trust.finding import Finding +from monkey_island.cc.models.zero_trust.monkey_finding import MonkeyFinding from monkey_island.cc.models.zero_trust.monkey_finding_details import MonkeyFindingDetails -from monkey_island.cc.models.zero_trust.scoutsuite_finding_details import ScoutSuiteFindingDetails from monkey_island.cc.test_common.fixtures import FixtureEnum MONKEY_FINDING_DETAIL_MOCK = MonkeyFindingDetails() MONKEY_FINDING_DETAIL_MOCK.events = ['mock1', 'mock2'] -SCOUTSUITE_FINDING_DETAIL_MOCK = ScoutSuiteFindingDetails() -SCOUTSUITE_FINDING_DETAIL_MOCK.scoutsuite_rules = [] -class TestFinding: +class TestMonkeyFinding: @pytest.mark.usefixtures(FixtureEnum.USES_DATABASE) def test_save_finding_validation(self): with pytest.raises(ValidationError): - _ = Finding.save_finding(test="bla bla", - status=zero_trust_consts.STATUS_FAILED, - detail_ref=MONKEY_FINDING_DETAIL_MOCK) - - with pytest.raises(ValidationError): - _ = Finding.save_finding(test=zero_trust_consts.TEST_SEGMENTATION, - status="bla bla", - detail_ref=SCOUTSUITE_FINDING_DETAIL_MOCK) + _ = MonkeyFinding.save_finding(test="bla bla", + status=zero_trust_consts.STATUS_FAILED, + detail_ref=MONKEY_FINDING_DETAIL_MOCK) @pytest.mark.usefixtures(FixtureEnum.USES_DATABASE) def test_save_finding_sanity(self): @@ -37,8 +30,10 @@ class TestFinding: monkey_details_example = MonkeyFindingDetails() monkey_details_example.events.append(event_example) monkey_details_example.save() - Finding.save_finding(test=zero_trust_consts.TEST_SEGMENTATION, - status=zero_trust_consts.STATUS_FAILED, detail_ref=monkey_details_example) + MonkeyFinding.save_finding(test=zero_trust_consts.TEST_SEGMENTATION, + status=zero_trust_consts.STATUS_FAILED, + detail_ref=monkey_details_example) - assert len(Finding.objects(test=zero_trust_consts.TEST_SEGMENTATION)) == 1 + assert len(MonkeyFinding.objects(test=zero_trust_consts.TEST_SEGMENTATION)) == 1 + assert len(MonkeyFinding.objects(status=zero_trust_consts.STATUS_FAILED)) == 1 assert len(Finding.objects(status=zero_trust_consts.STATUS_FAILED)) == 1 diff --git a/monkey/monkey_island/cc/models/zero_trust/test_scoutsuite_finding.py b/monkey/monkey_island/cc/models/zero_trust/test_scoutsuite_finding.py new file mode 100644 index 000000000..723b428ff --- /dev/null +++ b/monkey/monkey_island/cc/models/zero_trust/test_scoutsuite_finding.py @@ -0,0 +1,41 @@ +import pytest +from mongoengine import ValidationError + +import common.common_consts.zero_trust_consts as zero_trust_consts +from monkey_island.cc.models.zero_trust.finding import Finding +from monkey_island.cc.models.zero_trust.monkey_finding_details import MonkeyFindingDetails +from monkey_island.cc.models.zero_trust.scoutsuite_finding import ScoutSuiteFinding +from monkey_island.cc.models.zero_trust.scoutsuite_finding_details import ScoutSuiteFindingDetails +from monkey_island.cc.services.zero_trust.test_common.scoutsuite_finding_data import RULES +from monkey_island.cc.test_common.fixtures import FixtureEnum + +MONKEY_FINDING_DETAIL_MOCK = MonkeyFindingDetails() +MONKEY_FINDING_DETAIL_MOCK.events = ['mock1', 'mock2'] +SCOUTSUITE_FINDING_DETAIL_MOCK = ScoutSuiteFindingDetails() +SCOUTSUITE_FINDING_DETAIL_MOCK.scoutsuite_rules = [] + + +class TestScoutSuiteFinding: + + @pytest.mark.usefixtures(FixtureEnum.USES_DATABASE) + def test_save_finding_validation(self): + with pytest.raises(ValidationError): + _ = ScoutSuiteFinding.save_finding(test=zero_trust_consts.TEST_SEGMENTATION, + status="bla bla", + detail_ref=SCOUTSUITE_FINDING_DETAIL_MOCK) + + @pytest.mark.usefixtures(FixtureEnum.USES_DATABASE) + def test_save_finding_sanity(self): + assert len(Finding.objects(test=zero_trust_consts.TEST_SEGMENTATION)) == 0 + + rule_example = RULES[0] + scoutsuite_details_example = ScoutSuiteFindingDetails() + scoutsuite_details_example.scoutsuite_rules.append(rule_example) + scoutsuite_details_example.save() + ScoutSuiteFinding.save_finding(test=zero_trust_consts.TEST_SEGMENTATION, + status=zero_trust_consts.STATUS_FAILED, + detail_ref=scoutsuite_details_example) + + assert len(ScoutSuiteFinding.objects(test=zero_trust_consts.TEST_SEGMENTATION)) == 1 + assert len(ScoutSuiteFinding.objects(status=zero_trust_consts.STATUS_FAILED)) == 1 + assert len(Finding.objects(status=zero_trust_consts.STATUS_FAILED)) == 1 diff --git a/monkey/monkey_island/cc/resources/zero_trust/zero_trust_report.py b/monkey/monkey_island/cc/resources/zero_trust/zero_trust_report.py index a69ea50c0..433bf4631 100644 --- a/monkey/monkey_island/cc/resources/zero_trust/zero_trust_report.py +++ b/monkey/monkey_island/cc/resources/zero_trust/zero_trust_report.py @@ -24,7 +24,7 @@ class ZeroTrustReport(flask_restful.Resource): elif report_data == REPORT_DATA_PRINCIPLES_STATUS: return jsonify(PrincipleService.get_principles_status()) elif report_data == REPORT_DATA_FINDINGS: - return jsonify(FindingService.get_all_findings()) + return jsonify(FindingService.get_all_findings_for_ui()) elif report_data == REPORT_DATA_SCOUTSUITE: # Raw ScoutSuite data is already solved as json, no need to jsonify return Response(ScoutSuiteRawDataService.get_scoutsuite_data_json(), diff --git a/monkey/monkey_island/cc/services/zero_trust/monkey_findings/monkey_zt_finding_service.py b/monkey/monkey_island/cc/services/zero_trust/monkey_findings/monkey_zt_finding_service.py index 7ed184559..72e9f7861 100644 --- a/monkey/monkey_island/cc/services/zero_trust/monkey_findings/monkey_zt_finding_service.py +++ b/monkey/monkey_island/cc/services/zero_trust/monkey_findings/monkey_zt_finding_service.py @@ -4,14 +4,14 @@ from bson import ObjectId from common.common_consts import zero_trust_consts from monkey_island.cc.models.zero_trust.event import Event -from monkey_island.cc.models.zero_trust.finding import Finding +from monkey_island.cc.models.zero_trust.monkey_finding import MonkeyFinding from monkey_island.cc.models.zero_trust.monkey_finding_details import MonkeyFindingDetails class MonkeyZTFindingService: @staticmethod - def create_or_add_to_existing(test: str, status: str, events: str): + def create_or_add_to_existing(test: str, status: str, events: List[Event]): """ Create a new finding or add the events to an existing one if it's the same (same meaning same status and same test). @@ -19,7 +19,7 @@ class MonkeyZTFindingService: :raises: Assertion error if this is used when there's more then one finding which fits the query - this is not when this function should be used. """ - existing_findings = Finding.objects(test=test, status=status) + existing_findings = MonkeyFinding.objects(test=test, status=status) assert (len(existing_findings) < 2), "More than one finding exists for {}:{}".format(test, status) if len(existing_findings) == 0: @@ -33,15 +33,15 @@ class MonkeyZTFindingService: details = MonkeyFindingDetails() details.events = events details.save() - Finding.save_finding(test, status, details) + MonkeyFinding.save_finding(test, status, details) @staticmethod - def add_events(finding: Finding, events: List[Event]): + def add_events(finding: MonkeyFinding, events: List[Event]): finding.details.fetch().add_events(events).save() @staticmethod def get_events_by_finding(finding_id: str) -> List[object]: - finding = Finding.objects.get(id=finding_id) + finding = MonkeyFinding.objects.get(id=finding_id) pipeline = [{'$match': {'_id': ObjectId(finding.details.id)}}, {'$unwind': '$events'}, {'$project': {'events': '$events'}}, diff --git a/monkey/monkey_island/cc/services/zero_trust/monkey_findings/test_monkey_zt_finding_service.py b/monkey/monkey_island/cc/services/zero_trust/monkey_findings/test_monkey_zt_finding_service.py index c3db9ea39..80df71786 100644 --- a/monkey/monkey_island/cc/services/zero_trust/monkey_findings/test_monkey_zt_finding_service.py +++ b/monkey/monkey_island/cc/services/zero_trust/monkey_findings/test_monkey_zt_finding_service.py @@ -5,6 +5,7 @@ import pytest from common.common_consts import zero_trust_consts from monkey_island.cc.models.zero_trust.event import Event from monkey_island.cc.models.zero_trust.finding import Finding +from monkey_island.cc.models.zero_trust.monkey_finding import MonkeyFinding from monkey_island.cc.services.zero_trust.monkey_findings.monkey_zt_finding_service import MonkeyZTFindingService from monkey_island.cc.test_common.fixtures import FixtureEnum @@ -67,4 +68,4 @@ class TestMonkeyZTFindingService: # Create new finding MonkeyZTFindingService.create_or_add_to_existing(test=TESTS[1], status=STATUS[1], events=[EVENTS[1]]) # Assert there was a new finding created, because test and status is different - assert len(Finding.objects()) == 2 + assert len(MonkeyFinding.objects()) == 2 diff --git a/monkey/monkey_island/cc/services/zero_trust/scoutsuite/scoutsuite_zt_finding_service.py b/monkey/monkey_island/cc/services/zero_trust/scoutsuite/scoutsuite_zt_finding_service.py index 27b1b82b3..63befc808 100644 --- a/monkey/monkey_island/cc/services/zero_trust/scoutsuite/scoutsuite_zt_finding_service.py +++ b/monkey/monkey_island/cc/services/zero_trust/scoutsuite/scoutsuite_zt_finding_service.py @@ -1,18 +1,18 @@ from typing import List from common.common_consts import zero_trust_consts -from monkey_island.cc.models.zero_trust.finding import Finding +from monkey_island.cc.models.zero_trust.scoutsuite_finding import ScoutSuiteFinding from monkey_island.cc.models.zero_trust.scoutsuite_finding_details import ScoutSuiteFindingDetails from monkey_island.cc.models.zero_trust.scoutsuite_rule import ScoutSuiteRule -from monkey_island.cc.services.zero_trust.scoutsuite.consts.scoutsuite_findings import ScoutSuiteFinding +from monkey_island.cc.services.zero_trust.scoutsuite.consts.scoutsuite_finding_maps import ScoutSuiteFindingMap from monkey_island.cc.services.zero_trust.scoutsuite.scoutsuite_rule_service import ScoutSuiteRuleService class ScoutSuiteZTFindingService: @staticmethod - def process_rule(finding: ScoutSuiteFinding, rule: ScoutSuiteRule): - existing_findings = Finding.objects(test=finding.test, finding_type=zero_trust_consts.SCOUTSUITE_FINDING) + def process_rule(finding: ScoutSuiteFindingMap, rule: ScoutSuiteRule): + existing_findings = ScoutSuiteFinding.objects(test=finding.test) assert (len(existing_findings) < 2), "More than one finding exists for {}".format(finding.test) if len(existing_findings) == 0: @@ -21,12 +21,12 @@ class ScoutSuiteZTFindingService: ScoutSuiteZTFindingService.add_rule(existing_findings[0], rule) @staticmethod - def _create_new_finding_from_rule(finding: ScoutSuiteFinding, rule: ScoutSuiteRule): + def _create_new_finding_from_rule(finding: ScoutSuiteFindingMap, rule: ScoutSuiteRule): details = ScoutSuiteFindingDetails() details.scoutsuite_rules = [rule] details.save() status = ScoutSuiteZTFindingService.get_finding_status_from_rules(details.scoutsuite_rules) - Finding.save_finding(finding.test, status, details) + ScoutSuiteFinding.save_finding(finding.test, status, details) @staticmethod def get_finding_status_from_rules(rules: List[ScoutSuiteRule]) -> str: @@ -40,13 +40,13 @@ class ScoutSuiteZTFindingService: return zero_trust_consts.STATUS_PASSED @staticmethod - def add_rule(finding: Finding, rule: ScoutSuiteRule): + def add_rule(finding: ScoutSuiteFinding, rule: ScoutSuiteRule): ScoutSuiteZTFindingService.change_finding_status_by_rule(finding, rule) finding.save() finding.details.fetch().add_rule(rule) @staticmethod - def change_finding_status_by_rule(finding: Finding, rule: ScoutSuiteRule): + def change_finding_status_by_rule(finding: ScoutSuiteFinding, rule: ScoutSuiteRule): rule_status = ScoutSuiteZTFindingService.get_finding_status_from_rules([rule]) finding_status = finding.status new_finding_status = ScoutSuiteZTFindingService.get_finding_status_from_rule_status(finding_status, rule_status) diff --git a/monkey/monkey_island/cc/services/zero_trust/scoutsuite/test_scoutsuite_zt_finding_service.py b/monkey/monkey_island/cc/services/zero_trust/scoutsuite/test_scoutsuite_zt_finding_service.py index 0350bd2f3..00e9d1e32 100644 --- a/monkey/monkey_island/cc/services/zero_trust/scoutsuite/test_scoutsuite_zt_finding_service.py +++ b/monkey/monkey_island/cc/services/zero_trust/scoutsuite/test_scoutsuite_zt_finding_service.py @@ -2,6 +2,7 @@ import pytest from common.common_consts import zero_trust_consts from monkey_island.cc.models.zero_trust.finding import Finding +from monkey_island.cc.models.zero_trust.scoutsuite_finding import ScoutSuiteFinding from monkey_island.cc.services.zero_trust.scoutsuite.scoutsuite_zt_finding_service import ScoutSuiteZTFindingService from monkey_island.cc.services.zero_trust.test_common.scoutsuite_finding_data import RULES, SCOUTSUITE_FINDINGS from monkey_island.cc.test_common.fixtures import FixtureEnum @@ -15,7 +16,7 @@ class TestScoutSuiteZTFindingService: ScoutSuiteZTFindingService.process_rule(SCOUTSUITE_FINDINGS[0], RULES[0]) findings = list(Finding.objects()) assert len(findings) == 1 - assert findings[0].finding_type == zero_trust_consts.SCOUTSUITE_FINDING + assert type(findings[0]) == ScoutSuiteFinding # Assert that details were created properly details = findings[0].details.fetch() assert len(details.scoutsuite_rules) == 1 @@ -23,9 +24,9 @@ class TestScoutSuiteZTFindingService: # Rule processing should add rule to an already existing finding ScoutSuiteZTFindingService.process_rule(SCOUTSUITE_FINDINGS[0], RULES[1]) - findings = list(Finding.objects()) + findings = list(ScoutSuiteFinding.objects()) assert len(findings) == 1 - assert findings[0].finding_type == zero_trust_consts.SCOUTSUITE_FINDING + assert type(findings[0]) == ScoutSuiteFinding # Assert that details were created properly details = findings[0].details.fetch() assert len(details.scoutsuite_rules) == 2 @@ -35,7 +36,7 @@ class TestScoutSuiteZTFindingService: ScoutSuiteZTFindingService.process_rule(SCOUTSUITE_FINDINGS[1], RULES[1]) findings = list(Finding.objects()) assert len(findings) == 2 - assert findings[1].finding_type == zero_trust_consts.SCOUTSUITE_FINDING + assert type(findings[0]) == ScoutSuiteFinding # Assert that details were created properly details = findings[1].details.fetch() assert len(details.scoutsuite_rules) == 1 diff --git a/monkey/monkey_island/cc/services/zero_trust/test_common/finding_data.py b/monkey/monkey_island/cc/services/zero_trust/test_common/finding_data.py index 0b8de9221..aaea95031 100644 --- a/monkey/monkey_island/cc/services/zero_trust/test_common/finding_data.py +++ b/monkey/monkey_island/cc/services/zero_trust/test_common/finding_data.py @@ -1,6 +1,8 @@ -from common.common_consts.zero_trust_consts import TEST_SCOUTSUITE_SERVICE_SECURITY, STATUS_FAILED, SCOUTSUITE_FINDING, \ - TEST_ENDPOINT_SECURITY_EXISTS, STATUS_PASSED, MONKEY_FINDING +from common.common_consts.zero_trust_consts import TEST_SCOUTSUITE_SERVICE_SECURITY, STATUS_FAILED, \ + TEST_ENDPOINT_SECURITY_EXISTS, STATUS_PASSED from monkey_island.cc.models.zero_trust.finding import Finding +from monkey_island.cc.models.zero_trust.monkey_finding import MonkeyFinding +from monkey_island.cc.models.zero_trust.scoutsuite_finding import ScoutSuiteFinding from monkey_island.cc.services.zero_trust.test_common.monkey_finding_data import get_monkey_details_dto from monkey_island.cc.services.zero_trust.test_common.scoutsuite_finding_data import get_scoutsuite_details_dto @@ -8,16 +10,14 @@ from monkey_island.cc.services.zero_trust.test_common.scoutsuite_finding_data im def get_scoutsuite_finding_dto() -> Finding: scoutsuite_details = get_scoutsuite_details_dto() scoutsuite_details.save() - return Finding(test=TEST_SCOUTSUITE_SERVICE_SECURITY, - status=STATUS_FAILED, - finding_type=SCOUTSUITE_FINDING, - details=scoutsuite_details) + return ScoutSuiteFinding(test=TEST_SCOUTSUITE_SERVICE_SECURITY, + status=STATUS_FAILED, + details=scoutsuite_details) def get_monkey_finding_dto() -> Finding: monkey_details = get_monkey_details_dto() monkey_details.save() - return Finding(test=TEST_ENDPOINT_SECURITY_EXISTS, - status=STATUS_PASSED, - finding_type=MONKEY_FINDING, - details=monkey_details) + return MonkeyFinding(test=TEST_ENDPOINT_SECURITY_EXISTS, + status=STATUS_PASSED, + details=monkey_details) diff --git a/monkey/monkey_island/cc/services/zero_trust/zero_trust_report/finding_service.py b/monkey/monkey_island/cc/services/zero_trust/zero_trust_report/finding_service.py index 3f972bb4c..5b69d6ad9 100644 --- a/monkey/monkey_island/cc/services/zero_trust/zero_trust_report/finding_service.py +++ b/monkey/monkey_island/cc/services/zero_trust/zero_trust_report/finding_service.py @@ -6,6 +6,8 @@ from bson import SON from common.common_consts import zero_trust_consts from common.utils.exceptions import UnknownFindingError from monkey_island.cc.models.zero_trust.finding import Finding +from monkey_island.cc.models.zero_trust.monkey_finding import MonkeyFinding +from monkey_island.cc.models.zero_trust.scoutsuite_finding import ScoutSuiteFinding from monkey_island.cc.services.zero_trust.monkey_findings.monkey_zt_details_service import MonkeyZTDetailsService @@ -16,15 +18,18 @@ class EnrichedFinding: test_key: str pillars: List[str] status: str - finding_type: str details: Union[dict, None] class FindingService: @staticmethod - def get_all_findings() -> List[EnrichedFinding]: - findings = list(Finding.objects) + def get_all_findings_from_db() -> List[Finding]: + return list(Finding.objects) + + @staticmethod + def get_all_findings_for_ui() -> List[EnrichedFinding]: + findings = FindingService.get_all_findings_from_db() for i in range(len(findings)): details = FindingService._get_finding_details(findings[i]) findings[i] = findings[i].to_mongo() @@ -41,16 +46,15 @@ class FindingService: test_key=finding['test'], pillars=test_info[zero_trust_consts.PILLARS_KEY], status=finding['status'], - finding_type=finding['finding_type'], details=None ) return enriched_finding @staticmethod def _get_finding_details(finding: Finding) -> Union[dict, SON]: - if finding.finding_type == zero_trust_consts.MONKEY_FINDING: + if type(finding) == MonkeyFinding: return MonkeyZTDetailsService.fetch_details_for_display(finding.details.id) - elif finding.finding_type == zero_trust_consts.SCOUTSUITE_FINDING: + elif type(finding) == ScoutSuiteFinding: return finding.details.fetch().to_mongo() else: - raise UnknownFindingError(f"Unknown finding type {finding.finding_type}") + raise UnknownFindingError(f"Unknown finding type {str(type(finding))}") diff --git a/monkey/monkey_island/cc/services/zero_trust/zero_trust_report/pillar_service.py b/monkey/monkey_island/cc/services/zero_trust/zero_trust_report/pillar_service.py index 9ec584571..4f9c067f6 100644 --- a/monkey/monkey_island/cc/services/zero_trust/zero_trust_report/pillar_service.py +++ b/monkey/monkey_island/cc/services/zero_trust/zero_trust_report/pillar_service.py @@ -1,5 +1,5 @@ import common.common_consts.zero_trust_consts as zero_trust_consts -from monkey_island.cc.models.zero_trust.finding import Finding +from monkey_island.cc.services.zero_trust.zero_trust_report.finding_service import FindingService class PillarService: @@ -13,7 +13,7 @@ class PillarService: @staticmethod def _get_pillars_grades(): pillars_grades = [] - all_findings = Finding.objects() + all_findings = FindingService.get_all_findings_from_db() for pillar in zero_trust_consts.PILLARS: pillars_grades.append(PillarService.__get_pillar_grade(pillar, all_findings)) return pillars_grades @@ -67,7 +67,7 @@ class PillarService: @staticmethod def __get_status_of_single_pillar(pillar): - all_findings = Finding.objects() + all_findings = FindingService.get_all_findings_from_db() grade = PillarService.__get_pillar_grade(pillar, all_findings) for status in zero_trust_consts.ORDERED_TEST_STATUSES: if grade[status] > 0: diff --git a/monkey/monkey_island/cc/services/zero_trust/zero_trust_report/test_finding_service.py b/monkey/monkey_island/cc/services/zero_trust/zero_trust_report/test_finding_service.py index 36ef060fd..fdbe6df39 100644 --- a/monkey/monkey_island/cc/services/zero_trust/zero_trust_report/test_finding_service.py +++ b/monkey/monkey_island/cc/services/zero_trust/zero_trust_report/test_finding_service.py @@ -3,9 +3,10 @@ from unittest.mock import MagicMock import pytest from common.common_consts.zero_trust_consts import TESTS_MAP, TEST_SCOUTSUITE_SERVICE_SECURITY, STATUS_FAILED, \ - SCOUTSUITE_FINDING, DEVICES, NETWORKS, MONKEY_FINDING, STATUS_PASSED, TEST_ENDPOINT_SECURITY_EXISTS + DEVICES, NETWORKS, STATUS_PASSED, TEST_ENDPOINT_SECURITY_EXISTS from monkey_island.cc.services.zero_trust.monkey_findings.monkey_zt_details_service import MonkeyZTDetailsService -from monkey_island.cc.services.zero_trust.test_common.finding_data import get_scoutsuite_finding_dto, get_monkey_finding_dto +from monkey_island.cc.services.zero_trust.test_common.finding_data import get_scoutsuite_finding_dto, \ + get_monkey_finding_dto from monkey_island.cc.services.zero_trust.zero_trust_report.finding_service import FindingService, EnrichedFinding from monkey_island.cc.test_common.fixtures.fixture_enum import FixtureEnum @@ -18,11 +19,10 @@ def test_get_all_findings(): # This method fails due to mongomock not being able to simulate $unset, so don't test details MonkeyZTDetailsService.fetch_details_for_display = MagicMock(return_value=None) - findings = FindingService.get_all_findings() + findings = FindingService.get_all_findings_for_ui() description = TESTS_MAP[TEST_SCOUTSUITE_SERVICE_SECURITY]['finding_explanation'][STATUS_FAILED] expected_finding0 = EnrichedFinding(finding_id=findings[0].finding_id, - finding_type=SCOUTSUITE_FINDING, pillars=[DEVICES, NETWORKS], status=STATUS_FAILED, test=description, @@ -31,7 +31,6 @@ def test_get_all_findings(): description = TESTS_MAP[TEST_ENDPOINT_SECURITY_EXISTS]['finding_explanation'][STATUS_PASSED] expected_finding1 = EnrichedFinding(finding_id=findings[1].finding_id, - finding_type=MONKEY_FINDING, pillars=[DEVICES], status=STATUS_PASSED, test=description, diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/FindingsTable.js b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/FindingsTable.js index efd5a6ac4..657ad741e 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/FindingsTable.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/FindingsTable.js @@ -36,10 +36,10 @@ export class FindingsTable extends Component { ]; getFindingDetails(finding) { - if (finding.finding_type === 'scoutsuite_finding') { + if ('scoutsuite_rules' in finding.details) { return ; - } else if (finding.finding_type === 'monkey_finding') { + } else { return