diff --git a/monkey/monkey_island/cc/resources/ransomware_report.py b/monkey/monkey_island/cc/resources/ransomware_report.py index 55da76b06..cb5923468 100644 --- a/monkey/monkey_island/cc/resources/ransomware_report.py +++ b/monkey/monkey_island/cc/resources/ransomware_report.py @@ -2,9 +2,12 @@ import flask_restful from flask import jsonify from monkey_island.cc.resources.auth.auth import jwt_required +from monkey_island.cc.services.ransomware import ransomware_report class RansomwareReport(flask_restful.Resource): @jwt_required def get(self): - return jsonify({"report": None}) + return jsonify( + {"report": None, "propagation_stats": ransomware_report.get_propagation_stats()} + ) diff --git a/monkey/monkey_island/cc/services/ransomware/ransomware_report.py b/monkey/monkey_island/cc/services/ransomware/ransomware_report.py new file mode 100644 index 000000000..0e0f1c299 --- /dev/null +++ b/monkey/monkey_island/cc/services/ransomware/ransomware_report.py @@ -0,0 +1,24 @@ +from typing import Dict, List + +from monkey_island.cc.services.reporting.report import ReportService + + +def get_propagation_stats() -> Dict: + scanned = ReportService.get_scanned() + exploited = ReportService.get_exploited() + + return { + "num_scanned_nodes": len(scanned), + "num_exploited_nodes": len(exploited), + "num_exploited_per_exploit": _get_exploit_counts(exploited), + } + + +def _get_exploit_counts(exploited: List[Dict]) -> Dict: + exploit_counts = {} + + for node in exploited: + for exploit in node["exploits"]: + exploit_counts[exploit] = exploit_counts.get(exploit, 0) + 1 + + return exploit_counts diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/ransomware/test_ransomware_report.py b/monkey/tests/unit_tests/monkey_island/cc/services/ransomware/test_ransomware_report.py new file mode 100644 index 000000000..4c586aa81 --- /dev/null +++ b/monkey/tests/unit_tests/monkey_island/cc/services/ransomware/test_ransomware_report.py @@ -0,0 +1,37 @@ +import pytest + +from monkey_island.cc.services.ransomware import ransomware_report +from monkey_island.cc.services.reporting.report import ReportService + + +@pytest.fixture +def patch_report_service_for_stats(monkeypatch): + TEST_SCANNED_RESULTS = [{}, {}, {}, {}] + TEST_EXPLOITED_RESULTS = [ + {"exploits": ["SSH Exploiter"]}, + {"exploits": ["SSH Exploiter", "SMB Exploiter"]}, + {"exploits": ["WMI Exploiter"]}, + ] + + monkeypatch.setattr(ReportService, "get_scanned", lambda: TEST_SCANNED_RESULTS) + monkeypatch.setattr(ReportService, "get_exploited", lambda: TEST_EXPLOITED_RESULTS) + + +def test_get_propagation_stats__num_scanned(patch_report_service_for_stats): + stats = ransomware_report.get_propagation_stats() + + assert stats["num_scanned_nodes"] == 4 + + +def test_get_propagation_stats__num_exploited(patch_report_service_for_stats): + stats = ransomware_report.get_propagation_stats() + + assert stats["num_exploited_nodes"] == 3 + + +def test_get_propagation_stats__num_exploited_per_exploit(patch_report_service_for_stats): + stats = ransomware_report.get_propagation_stats() + + assert stats["num_exploited_per_exploit"]["SSH Exploiter"] == 2 + assert stats["num_exploited_per_exploit"]["SMB Exploiter"] == 1 + assert stats["num_exploited_per_exploit"]["WMI Exploiter"] == 1