From 29e494cfb153e7cbf840c45d6325bb8acde47add Mon Sep 17 00:00:00 2001 From: vakaris_zilius Date: Mon, 14 Mar 2022 13:16:41 +0000 Subject: [PATCH] Island: Fix a ZT multiple findings bug A bug happened in zero trust findings: since multiple exploiters run at the same time, they send telemetries at the same time and those telemetries get parsed at the same time. So multiple threads fetch ZT findings at once, finds none and creates duplicate findings. With this bugfix only one thread can fetch for findings at a time. This means that one thread creates the finding and others fetch it and just add events to it --- .../monkey_zt_finding_service.py | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) 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 6c8063eca..53f3e44a9 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 @@ -1,6 +1,7 @@ from typing import List from bson import ObjectId +from gevent.lock import BoundedSemaphore from common.common_consts import zero_trust_consts from monkey_island.cc.models.zero_trust.event import Event @@ -9,6 +10,10 @@ from monkey_island.cc.models.zero_trust.monkey_finding_details import MonkeyFind class MonkeyZTFindingService: + + # Required to synchronize db state between different threads + _finding_lock = BoundedSemaphore() + @staticmethod def create_or_add_to_existing(test: str, status: str, events: List[Event]): """ @@ -20,16 +25,17 @@ class MonkeyZTFindingService: the query - this is not when this function should be used. """ - existing_findings = list(MonkeyFinding.objects(test=test, status=status)) - assert len(existing_findings) < 2, "More than one finding exists for {}:{}".format( - test, status - ) + with MonkeyZTFindingService._finding_lock: + existing_findings = list(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: - MonkeyZTFindingService.create_new_finding(test, status, events) - else: - # Now we know for sure this is the only one - MonkeyZTFindingService.add_events(existing_findings[0], events) + if len(existing_findings) == 0: + MonkeyZTFindingService.create_new_finding(test, status, events) + else: + # Now we know for sure this is the only one + MonkeyZTFindingService.add_events(existing_findings[0], events) @staticmethod def create_new_finding(test: str, status: str, events: List[Event]):