From 20be94d6064bbb5d33920152b08c3503f52023ab Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Sun, 23 Feb 2020 15:24:44 +0200 Subject: [PATCH] WIP trying to get the BB test to work --- .../monkey_zoo/blackbox/analyzers/analyzer.py | 8 +++++ .../analyzers/communication_analyzer.py | 3 +- .../analyzers/performance_analyzer.py | 36 +++++++++++++++++++ .../island_client/monkey_island_client.py | 23 +++++++++++- .../blackbox/island_configs/STRUTS2.conf | 13 ++----- envs/monkey_zoo/blackbox/test_blackbox.py | 19 ++++++++++ .../cc/resources/test/clear_caches.py | 2 +- 7 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 envs/monkey_zoo/blackbox/analyzers/analyzer.py create mode 100644 envs/monkey_zoo/blackbox/analyzers/performance_analyzer.py diff --git a/envs/monkey_zoo/blackbox/analyzers/analyzer.py b/envs/monkey_zoo/blackbox/analyzers/analyzer.py new file mode 100644 index 000000000..d6043feeb --- /dev/null +++ b/envs/monkey_zoo/blackbox/analyzers/analyzer.py @@ -0,0 +1,8 @@ +from abc import ABCMeta, abstractmethod + + +class Analyzer(object, metaclass=ABCMeta): + + @abstractmethod + def analyze_test_results(self): + raise NotImplementedError() diff --git a/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py b/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py index 491b534b8..22841f783 100644 --- a/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py +++ b/envs/monkey_zoo/blackbox/analyzers/communication_analyzer.py @@ -1,7 +1,8 @@ +from envs.monkey_zoo.blackbox.analyzers.analyzer import Analyzer from envs.monkey_zoo.blackbox.analyzers.analyzer_log import AnalyzerLog -class CommunicationAnalyzer(object): +class CommunicationAnalyzer(Analyzer): def __init__(self, island_client, machine_ips): self.island_client = island_client diff --git a/envs/monkey_zoo/blackbox/analyzers/performance_analyzer.py b/envs/monkey_zoo/blackbox/analyzers/performance_analyzer.py new file mode 100644 index 000000000..23bb5b0ae --- /dev/null +++ b/envs/monkey_zoo/blackbox/analyzers/performance_analyzer.py @@ -0,0 +1,36 @@ +from datetime import timedelta + +from envs.monkey_zoo.blackbox.analyzers.analyzer import Analyzer +from envs.monkey_zoo.blackbox.analyzers.analyzer_log import AnalyzerLog +from envs.monkey_zoo.blackbox.island_client.monkey_island_client import MonkeyIslandClient + +MAX_ALLOWED_SINGLE_PAGE_TIME = timedelta(seconds=1) +MAX_ALLOWED_TOTAL_TIME = timedelta(seconds=3) + + +class PerformanceAnalyzer(Analyzer): + + def __init__(self, island_client: MonkeyIslandClient): + self.island_client = island_client + self.log = AnalyzerLog(self.__class__.__name__) + + def analyze_test_results(self) -> bool: + self.log.clear() + total_time = timedelta() + + self.island_client.clear_caches() + timings = self.island_client.time_all_report_pages() + + single_page_time_less_then_max = True + + for page, elapsed in timings: + self.log.add_entry(f"page {page} took {str(elapsed)}") + total_time += elapsed + if elapsed > MAX_ALLOWED_SINGLE_PAGE_TIME: + single_page_time_less_then_max = False + + total_time_less_then_max = total_time < MAX_ALLOWED_TOTAL_TIME + + self.log.add_entry(f"total time is {str(total_time)}") + + return total_time_less_then_max and single_page_time_less_then_max diff --git a/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py b/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py index 53f102a72..ea68f391f 100644 --- a/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py +++ b/envs/monkey_zoo/blackbox/island_client/monkey_island_client.py @@ -92,6 +92,27 @@ class MonkeyIslandClient(object): :raises: If error (by error code), raises the error :return: The response """ - response = self.requests.delete("api/test/clear_caches") + response = self.requests.get("api/test/clear_caches") response.raise_for_status() return response + + def time_all_report_pages(self): + REPORT_URLS = [ + "api/report/security", + "api/attack/report", + "api/report/zero_trust/findings", + "api/report/zero_trust/principles", + "api/report/zero_trust/pillars" + ] + + report_resource_to_response_time = {} + + for url in REPORT_URLS: + response = self.requests.get(url) + if response: + report_resource_to_response_time[url] = response.elapsed + else: + LOGGER.error(f"Trying to get {url} but got unexpected {str(response)}") + response.raise_for_status() + + return report_resource_to_response_time diff --git a/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf b/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf index ea53f3b0b..2f9e765a9 100644 --- a/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf +++ b/envs/monkey_zoo/blackbox/island_configs/STRUTS2.conf @@ -46,17 +46,8 @@ "exploits": { "general": { "exploiter_classes": [ - "SmbExploiter", - "WmiExploiter", - "SSHExploiter", - "ShellShockExploiter", - "SambaCryExploiter", - "ElasticGroovyExploiter", - "Struts2Exploiter", - "WebLogicExploiter", - "HadoopExploiter", - "VSFTPDExploiter" - ], + "Struts2Exploiter" + ], "skip_exploit_if_file_exist": false }, "ms08_067": { diff --git a/envs/monkey_zoo/blackbox/test_blackbox.py b/envs/monkey_zoo/blackbox/test_blackbox.py index 8581b6fbe..2d8a96dae 100644 --- a/envs/monkey_zoo/blackbox/test_blackbox.py +++ b/envs/monkey_zoo/blackbox/test_blackbox.py @@ -4,6 +4,7 @@ import logging import pytest from time import sleep +from envs.monkey_zoo.blackbox.analyzers.performance_analyzer import PerformanceAnalyzer from envs.monkey_zoo.blackbox.island_client.monkey_island_client import MonkeyIslandClient from envs.monkey_zoo.blackbox.analyzers.communication_analyzer import CommunicationAnalyzer from envs.monkey_zoo.blackbox.island_client.island_config_parser import IslandConfigParser @@ -65,6 +66,21 @@ class TestMonkeyBlackbox(object): timeout_in_seconds, log_handler).run() + @staticmethod + def run_performance_test(island_client, conf_filename, test_name, timeout_in_seconds=DEFAULT_TIMEOUT_SECONDS): + config_parser = IslandConfigParser(conf_filename) + analyzers = [ + CommunicationAnalyzer(island_client, config_parser.get_ips_of_targets()), + PerformanceAnalyzer(island_client), + ] + log_handler = TestLogsHandler(test_name, island_client, TestMonkeyBlackbox.get_log_dir_path()) + BasicTest(test_name, + island_client, + config_parser, + analyzers, + timeout_in_seconds, + log_handler).run() + @staticmethod def get_log_dir_path(): return os.path.abspath(LOG_DIR_PATH) @@ -108,3 +124,6 @@ class TestMonkeyBlackbox(object): def test_wmi_pth(self, island_client): TestMonkeyBlackbox.run_basic_test(island_client, "WMI_PTH.conf", "WMI_PTH") + + def test_performance(self, island_client): + TestMonkeyBlackbox.run_performance_test(island_client, "STRUTS2.conf", "Report_timing") diff --git a/monkey/monkey_island/cc/resources/test/clear_caches.py b/monkey/monkey_island/cc/resources/test/clear_caches.py index 1d12fb32e..f17193821 100644 --- a/monkey/monkey_island/cc/resources/test/clear_caches.py +++ b/monkey/monkey_island/cc/resources/test/clear_caches.py @@ -18,7 +18,7 @@ class ClearCaches(flask_restful.Resource): :note: DO NOT CALL THIS IN PRODUCTION CODE as this will slow down the user experience. """ @jwt_required() - def delete(self, **kw): + def get(self, **kw): try: logger.warning("Trying to clear caches! Make sure this is not production") ReportService.delete_saved_report_if_exists()