Removed the storage of subnets that violate segmentation, because this info isn't being used anywhere

This commit is contained in:
VakarisZ 2020-10-14 10:30:13 +03:00
parent 89bdbf946f
commit eb5f809195
5 changed files with 39 additions and 51 deletions

View File

@ -4,7 +4,6 @@ from typing import List
from mongoengine import Document, EmbeddedDocumentListField from mongoengine import Document, EmbeddedDocumentListField
from monkey_island.cc.models.zero_trust.event import Event from monkey_island.cc.models.zero_trust.event import Event
from monkey_island.cc.models.zero_trust.subnet_pair import SubnetPair
class MonkeyFindingDetails(Document): class MonkeyFindingDetails(Document):
@ -15,16 +14,8 @@ class MonkeyFindingDetails(Document):
# SCHEMA # SCHEMA
events = EmbeddedDocumentListField(document_type=Event, required=False) events = EmbeddedDocumentListField(document_type=Event, required=False)
checked_subnet_pairs = EmbeddedDocumentListField(document_type=SubnetPair, required=False)
# LOGIC # LOGIC
def add_events(self, events: List[Event]) -> MonkeyFindingDetails: def add_events(self, events: List[Event]) -> MonkeyFindingDetails:
self.update(push_all__events=events) self.update(push_all__events=events)
return self return self
def add_checked_subnet_pair(self, subnet_pair: SubnetPair) -> MonkeyFindingDetails:
self.update(push__checked_subnet_pairs=subnet_pair)
return self
def is_with_subnet_pair(self, subnet_pair: SubnetPair):
return subnet_pair in self.checked_subnet_pairs

View File

@ -1,19 +0,0 @@
from typing import List
from mongoengine import EmbeddedDocument, StringField
class SubnetPair(EmbeddedDocument):
"""
This model represents a pair of subnets. It is meant to hold details about cross-segmentation check between two
subnets.
"""
# SCHEMA
first_subnet = StringField()
second_subnet = StringField()
# LOGIC
@staticmethod
def create_subnet_pair(subnets: List[str]):
subnets.sort()
return SubnetPair(first_subnet=subnets[0], second_subnet=subnets[1])

View File

@ -28,7 +28,6 @@ def check_segmentation_violation(current_monkey, target_ip):
event = get_segmentation_violation_event(current_monkey, source_subnet, target_ip, target_subnet) event = get_segmentation_violation_event(current_monkey, source_subnet, target_ip, target_subnet)
MonkeyFindingService.create_or_add_to_existing( MonkeyFindingService.create_or_add_to_existing(
test=zero_trust_consts.TEST_SEGMENTATION, test=zero_trust_consts.TEST_SEGMENTATION,
subnet_pairs=[[source_subnet, target_subnet]],
status=zero_trust_consts.STATUS_FAILED, status=zero_trust_consts.STATUS_FAILED,
events=[event] events=[event]
) )
@ -92,7 +91,6 @@ def create_or_add_findings_for_all_pairs(all_subnets, current_monkey):
for subnet_pair in all_subnets_pairs_for_this_monkey: for subnet_pair in all_subnets_pairs_for_this_monkey:
MonkeyFindingService.create_or_add_to_existing( MonkeyFindingService.create_or_add_to_existing(
subnet_pairs=[list(subnet_pair)],
status=zero_trust_consts.STATUS_PASSED, status=zero_trust_consts.STATUS_PASSED,
events=[get_segmentation_done_event(current_monkey, subnet_pair)], events=[get_segmentation_done_event(current_monkey, subnet_pair)],
test=zero_trust_consts.TEST_SEGMENTATION test=zero_trust_consts.TEST_SEGMENTATION

View File

@ -0,0 +1,36 @@
from typing import List
from bson import ObjectId
from monkey_island.cc.models.zero_trust.monkey_finding_details import MonkeyFindingDetails
# How many events of a single finding to return to UI.
# 50 will return 50 latest and 50 oldest events from a finding
EVENT_FETCH_CNT = 50
class MonkeyDetailsService:
@staticmethod
def fetch_details_for_display(finding_id: ObjectId):
pipeline = [{'$match': {'_id': finding_id}},
{'$addFields': {'oldest_events': {'$slice': ['$events', EVENT_FETCH_CNT]},
'latest_events': {'$slice': ['$events', -1 * EVENT_FETCH_CNT]},
'event_count': {'$size': '$events'}}},
{'$unset': ['events', 'checked_subnet_pairs']}]
details = list(MonkeyFindingDetails.objects.aggregate(*pipeline))
if details:
details = details[0]
details['latest_events'] = MonkeyDetailsService._get_events_without_overlap(details['event_count'],
details['latest_events'])
return details
@staticmethod
def _get_events_without_overlap(event_count: int, events: List[object]) -> List[object]:
overlap_count = event_count - EVENT_FETCH_CNT
if overlap_count >= EVENT_FETCH_CNT:
return events
elif overlap_count <= 0:
return []
else:
return events[-1 * overlap_count:]

View File

@ -6,13 +6,12 @@ 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.event import Event
from monkey_island.cc.models.zero_trust.finding import Finding 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.monkey_finding_details import MonkeyFindingDetails
from monkey_island.cc.models.zero_trust.subnet_pair import SubnetPair
class MonkeyFindingService: class MonkeyFindingService:
@staticmethod @staticmethod
def create_or_add_to_existing(test, status, events, subnet_pairs=None): def create_or_add_to_existing(test, status, events):
""" """
Create a new finding or add the events to an existing one if it's the same (same meaning same status and same Create a new finding or add the events to an existing one if it's the same (same meaning same status and same
test). test).
@ -24,18 +23,15 @@ class MonkeyFindingService:
assert (len(existing_findings) < 2), "More than one finding exists for {}:{}".format(test, status) assert (len(existing_findings) < 2), "More than one finding exists for {}:{}".format(test, status)
if len(existing_findings) == 0: if len(existing_findings) == 0:
MonkeyFindingService.create_new_finding(test, status, events, subnet_pairs) MonkeyFindingService.create_new_finding(test, status, events)
else: else:
# Now we know for sure this is the only one # Now we know for sure this is the only one
MonkeyFindingService.add_events(existing_findings[0], events) MonkeyFindingService.add_events(existing_findings[0], events)
if subnet_pairs:
MonkeyFindingService.add_subnet_pairs(existing_findings[0], subnet_pairs)
@staticmethod @staticmethod
def create_new_finding(test: str, status: str, events: List[Event], subnet_pairs: List[SubnetPair]): def create_new_finding(test: str, status: str, events: List[Event]):
details = MonkeyFindingDetails() details = MonkeyFindingDetails()
details.events = events details.events = events
details.subnet_pairs = subnet_pairs
details.save() details.save()
Finding.save_finding(test, status, details) Finding.save_finding(test, status, details)
@ -43,20 +39,6 @@ class MonkeyFindingService:
def add_events(finding: Finding, events: List[Event]): def add_events(finding: Finding, events: List[Event]):
finding.details.fetch().add_events(events).save() finding.details.fetch().add_events(events).save()
@staticmethod
def add_subnet_pairs(finding: Finding, subnet_pairs: List[List[str]]):
finding_details = finding.details.fetch()
for subnet_pair in subnet_pairs:
subnet_pair_document = SubnetPair.create_subnet_pair(subnet_pair)
if not MonkeyFindingService.is_subnet_pair_in_finding(finding, subnet_pair_document):
finding_details.add_checked_subnet_pair(subnet_pair_document)
finding_details.save()
@staticmethod
def is_subnet_pair_in_finding(finding: Finding, subnet_pair: SubnetPair):
details = finding.details.fetch()
return details.is_with_subnet_pair(subnet_pair)
@staticmethod @staticmethod
def get_events_by_finding(finding_id: str) -> List[object]: def get_events_by_finding(finding_id: str) -> List[object]:
finding = Finding.objects.get(id=finding_id) finding = Finding.objects.get(id=finding_id)