From bd9400403df9ee9834914d89df0d2c623f445fb6 Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Sun, 9 Feb 2020 11:20:12 +0200 Subject: [PATCH 1/6] Added version file to common. It's also executable so it's accessible from shell. --- monkey/common/version.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 monkey/common/version.py diff --git a/monkey/common/version.py b/monkey/common/version.py new file mode 100644 index 000000000..317afe99a --- /dev/null +++ b/monkey/common/version.py @@ -0,0 +1,22 @@ +# To get the version from shell, run `python ./version.py` (see `python ./version.py -h` for details). +import argparse + +MAJOR = "1" +MINOR = "8" +PATCH = "0" +BUILD = "dev" + + +def get_version(build=BUILD): + return f"{MAJOR}.{MINOR}.{PATCH}+{build}" + + +def print_version(): + parser = argparse.ArgumentParser() + parser.add_argument("-b", "--build", default=BUILD, help="Choose the build string for this version.", type=str) + args = parser.parse_args() + print(get_version(args.build)) + + +if __name__ == '__main__': + print_version() From cea33d4540539fca664ad23cee65028488dbc5b5 Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Sun, 9 Feb 2020 11:20:29 +0200 Subject: [PATCH 2/6] Logging version when initializing Monkey and Island. --- monkey/infection_monkey/main.py | 3 +++ monkey/monkey_island/cc/main.py | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/monkey/infection_monkey/main.py b/monkey/infection_monkey/main.py index 928425535..21871d857 100644 --- a/monkey/infection_monkey/main.py +++ b/monkey/infection_monkey/main.py @@ -12,6 +12,7 @@ from infection_monkey.config import WormConfiguration, EXTERNAL_CONFIG_FILE from infection_monkey.dropper import MonkeyDrops from infection_monkey.model import MONKEY_ARG, DROPPER_ARG from infection_monkey.monkey import InfectionMonkey +from common.version import get_version # noinspection PyUnresolvedReferences import infection_monkey.post_breach # dummy import for pyinstaller @@ -117,6 +118,8 @@ def main(): LOG.info(">>>>>>>>>> Initializing monkey (%s): PID %s <<<<<<<<<<", monkey_cls.__name__, os.getpid()) + LOG.info(f"version: {get_version()}") + monkey = monkey_cls(monkey_args) monkey.initialize() diff --git a/monkey/monkey_island/cc/main.py b/monkey/monkey_island/cc/main.py index 17c537aeb..f06d36ea3 100644 --- a/monkey/monkey_island/cc/main.py +++ b/monkey/monkey_island/cc/main.py @@ -25,6 +25,7 @@ from monkey_island.cc.utils import local_ip_addresses from monkey_island.cc.environment.environment import env from monkey_island.cc.database import is_db_server_up, get_db_version from monkey_island.cc.resources.monkey_download import MonkeyDownload +from common.version import get_version def main(): @@ -54,8 +55,9 @@ def main(): def log_init_info(): - logger.info( - 'Monkey Island Server is running. Listening on the following URLs: {}'.format( + logger.info('Monkey Island Server is running!') + logger.info(f"version: {get_version()}") + logger.info('Listening on the following URLs: {}'.format( ", ".join(["https://{}:{}".format(x, env.get_island_port()) for x in local_ip_addresses()]) ) ) From a7aeb7d7ffeebd8f678410d2f975fbfa0f77ef44 Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Sun, 9 Feb 2020 11:28:47 +0200 Subject: [PATCH 3/6] Report version as part of state telem and log it in island. --- monkey/infection_monkey/monkey.py | 5 +++-- monkey/infection_monkey/telemetry/state_telem.py | 8 ++++++-- .../cc/services/telemetry/processing/state.py | 8 ++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/monkey/infection_monkey/monkey.py b/monkey/infection_monkey/monkey.py index 06a08f131..6b8803a9f 100644 --- a/monkey/infection_monkey/monkey.py +++ b/monkey/infection_monkey/monkey.py @@ -30,6 +30,7 @@ from infection_monkey.network.tools import get_interface_to_target from infection_monkey.exploit.tools.exceptions import ExploitingVulnerableMachineError, FailedExploitationError from infection_monkey.telemetry.attack.t1106_telem import T1106Telem from common.utils.attack_utils import ScanStatus, UsageEnum +from common.version import get_version from infection_monkey.exploit.HostExploiter import HostExploiter MAX_DEPTH_REACHED_MESSAGE = "Reached max depth, shutting down" @@ -121,7 +122,7 @@ class InfectionMonkey(object): if monkey_tunnel: monkey_tunnel.start() - StateTelem(is_done=False).send() + StateTelem(is_done=False, version=get_version()).send() TunnelTelem().send() LOG.debug("Starting the post-breach phase.") @@ -254,7 +255,7 @@ class InfectionMonkey(object): InfectionMonkey.close_tunnel() firewall.close() else: - StateTelem(is_done=True).send() # Signal the server (before closing the tunnel) + StateTelem(is_done=True, version=get_version()).send() # Signal the server (before closing the tunnel) InfectionMonkey.close_tunnel() firewall.close() if WormConfiguration.send_log_to_server: diff --git a/monkey/infection_monkey/telemetry/state_telem.py b/monkey/infection_monkey/telemetry/state_telem.py index 3bd63d2f9..4d4224288 100644 --- a/monkey/infection_monkey/telemetry/state_telem.py +++ b/monkey/infection_monkey/telemetry/state_telem.py @@ -5,15 +5,19 @@ __author__ = "itay.mizeretz" class StateTelem(BaseTelem): - def __init__(self, is_done): + def __init__(self, is_done, version="Unknown"): """ Default state telemetry constructor :param is_done: Whether the state of monkey is done. """ super(StateTelem, self).__init__() self.is_done = is_done + self.version = version telem_category = 'state' def get_data(self): - return {'done': self.is_done} + return { + 'done': self.is_done, + 'version': self.version + } diff --git a/monkey/monkey_island/cc/services/telemetry/processing/state.py b/monkey/monkey_island/cc/services/telemetry/processing/state.py index 4e164e900..b7e341483 100644 --- a/monkey/monkey_island/cc/services/telemetry/processing/state.py +++ b/monkey/monkey_island/cc/services/telemetry/processing/state.py @@ -1,9 +1,14 @@ +import logging + from monkey_island.cc.models import Monkey from monkey_island.cc.services.node import NodeService from monkey_island.cc.services.telemetry.zero_trust_tests.segmentation import \ test_passed_findings_for_unreached_segments +logger = logging.getLogger(__name__) + + def process_state_telemetry(telemetry_json): monkey = NodeService.get_monkey_by_guid(telemetry_json['monkey_guid']) NodeService.add_communication_info(monkey, telemetry_json['command_control_channel']) @@ -15,3 +20,6 @@ def process_state_telemetry(telemetry_json): if telemetry_json['data']['done']: current_monkey = Monkey.get_single_monkey_by_guid(telemetry_json['monkey_guid']) test_passed_findings_for_unreached_segments(current_monkey) + + if telemetry_json['data']['version']: + logger.info(f"monkey {telemetry_json['monkey_guid']} has version {telemetry_json['data']['version']}") From fcef4f154f8d02a83a39e4484d656c742aa036a3 Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Sun, 9 Feb 2020 11:32:41 +0200 Subject: [PATCH 4/6] Delete old Monkey Island-centric version and replace with common.version --- monkey/monkey_island/cc/environment/__init__.py | 5 ----- monkey/monkey_island/cc/resources/version_update.py | 4 ++-- monkey/monkey_island/cc/services/version_update.py | 5 +++-- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/monkey/monkey_island/cc/environment/__init__.py b/monkey/monkey_island/cc/environment/__init__.py index 26d33f78c..ec7c7a0f4 100644 --- a/monkey/monkey_island/cc/environment/__init__.py +++ b/monkey/monkey_island/cc/environment/__init__.py @@ -26,8 +26,6 @@ class Environment(object, metaclass=ABCMeta): def testing(self, value): self._testing = value - _MONKEY_VERSION = "1.7.0" - def __init__(self): self.config = None self._testing = False # Assume env is not for unit testing. @@ -58,9 +56,6 @@ class Environment(object, metaclass=ABCMeta): def is_develop(self): return self.get_deployment() == 'develop' - def get_version(self): - return self._MONKEY_VERSION + ('-dev' if self.is_develop() else '') - def _get_from_config(self, key, default_value=None): val = default_value if self.config is not None: diff --git a/monkey/monkey_island/cc/resources/version_update.py b/monkey/monkey_island/cc/resources/version_update.py index b1fbfdf82..a88f8830c 100644 --- a/monkey/monkey_island/cc/resources/version_update.py +++ b/monkey/monkey_island/cc/resources/version_update.py @@ -1,7 +1,7 @@ import flask_restful import logging -from monkey_island.cc.environment.environment import env +from common.version import get_version from monkey_island.cc.services.version_update import VersionUpdateService __author__ = 'itay.mizeretz' @@ -17,7 +17,7 @@ class VersionUpdate(flask_restful.Resource): # even when not authenticated def get(self): return { - 'current_version': env.get_version(), + 'current_version': get_version(), 'newer_version': VersionUpdateService.get_newer_version(), 'download_link': VersionUpdateService.get_download_link() } diff --git a/monkey/monkey_island/cc/services/version_update.py b/monkey/monkey_island/cc/services/version_update.py index c1dab52a9..ddd60d5c0 100644 --- a/monkey/monkey_island/cc/services/version_update.py +++ b/monkey/monkey_island/cc/services/version_update.py @@ -2,6 +2,7 @@ import logging import requests +from common.version import get_version from monkey_island.cc.environment.environment import env __author__ = "itay.mizeretz" @@ -39,7 +40,7 @@ class VersionUpdateService: Checks if newer monkey version is available :return: False if not, version in string format ('1.6.2') otherwise """ - url = VersionUpdateService.VERSION_SERVER_CHECK_NEW_URL % (env.get_deployment(), env.get_version()) + url = VersionUpdateService.VERSION_SERVER_CHECK_NEW_URL % (env.get_deployment(), get_version()) reply = requests.get(url, timeout=15) @@ -53,4 +54,4 @@ class VersionUpdateService: @staticmethod def get_download_link(): - return VersionUpdateService.VERSION_SERVER_DOWNLOAD_URL % (env.get_deployment(), env.get_version()) + return VersionUpdateService.VERSION_SERVER_DOWNLOAD_URL % (env.get_deployment(), get_version()) From 46952ed0aeef53f1625781b416fe8d841738baa9 Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Sun, 9 Feb 2020 11:51:00 +0200 Subject: [PATCH 5/6] Changed build to static file so that build scripts can change it dynamically --- monkey/common/BUILD | 1 + monkey/common/version.py | 5 ++++- monkey/infection_monkey/monkey.spec | 4 +++- monkey/monkey_island/monkey_island.spec | 4 +++- 4 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 monkey/common/BUILD diff --git a/monkey/common/BUILD b/monkey/common/BUILD new file mode 100644 index 000000000..90012116c --- /dev/null +++ b/monkey/common/BUILD @@ -0,0 +1 @@ +dev \ No newline at end of file diff --git a/monkey/common/version.py b/monkey/common/version.py index 317afe99a..9d60e636c 100644 --- a/monkey/common/version.py +++ b/monkey/common/version.py @@ -1,10 +1,13 @@ # To get the version from shell, run `python ./version.py` (see `python ./version.py -h` for details). import argparse +from pathlib import Path MAJOR = "1" MINOR = "8" PATCH = "0" -BUILD = "dev" +build_file_path = Path(__file__).parent.joinpath("BUILD") +with open(build_file_path, "r") as build_file: + BUILD = build_file.read() def get_version(build=BUILD): diff --git a/monkey/infection_monkey/monkey.spec b/monkey/infection_monkey/monkey.spec index 2157b697c..4baa205e2 100644 --- a/monkey/infection_monkey/monkey.spec +++ b/monkey/infection_monkey/monkey.spec @@ -19,7 +19,9 @@ def main(): hookspath=['./pyinstaller_hooks'], runtime_hooks=None, binaries=None, - datas=None, + datas=[ + ("../common/BUILD", "../common/BUILD") + ], excludes=None, win_no_prefer_redirects=None, win_private_assemblies=None, diff --git a/monkey/monkey_island/monkey_island.spec b/monkey/monkey_island/monkey_island.spec index 342df5ab3..e74763160 100644 --- a/monkey/monkey_island/monkey_island.spec +++ b/monkey/monkey_island/monkey_island.spec @@ -15,7 +15,9 @@ def main(): hookspath=None, runtime_hooks=None, binaries=None, - datas=None, + datas=[ + ("../common/BUILD", "../common/BUILD") + ], excludes=None, win_no_prefer_redirects=None, win_private_assemblies=None, From 0859050a654bdbde1d4de317cc6a5f6580d43394 Mon Sep 17 00:00:00 2001 From: Shay Nehmad Date: Sun, 9 Feb 2020 15:20:34 +0200 Subject: [PATCH 6/6] Added version argument to monkey build scripts --- monkey/infection_monkey/build_linux.sh | 15 +++++++++++++++ monkey/infection_monkey/build_windows.bat | 11 +++++++++++ 2 files changed, 26 insertions(+) diff --git a/monkey/infection_monkey/build_linux.sh b/monkey/infection_monkey/build_linux.sh index fcaf4c75d..68abd4758 100644 --- a/monkey/infection_monkey/build_linux.sh +++ b/monkey/infection_monkey/build_linux.sh @@ -1,2 +1,17 @@ #!/bin/bash + +# Allow custom build ID +# If the first argument is not empty... +if [[ -n "$1" ]] +then + # Validate argument is a valid build string + if [[ "$1" =~ ^[\da-zA-Z]*$ ]] + then + # And put it in the BUILD file + echo "$1" > ../common/BUILD + else + echo "Build ID $1 invalid!" + fi +fi + pyinstaller -F --log-level=DEBUG --clean monkey.spec diff --git a/monkey/infection_monkey/build_windows.bat b/monkey/infection_monkey/build_windows.bat index f763bda6b..93e4e4a42 100644 --- a/monkey/infection_monkey/build_windows.bat +++ b/monkey/infection_monkey/build_windows.bat @@ -1 +1,12 @@ +REM Check if build ID was passed to the build script. +if "%1"=="" GOTO START_BUILD + +REM Validate build ID +echo %1|findstr /r "^[0-9a-zA-Z]*$" +if %errorlevel% neq 0 (exit /b %errorlevel%) + +REM replace build ID +echo %1> ../common/BUILD + +:START_BUILD pyinstaller -F --log-level=DEBUG --clean --upx-dir=.\bin monkey.spec