From 117b1ebe5acf19025fea957afe0a434165ca2776 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 3 Aug 2022 16:26:22 +0200 Subject: [PATCH 1/5] Island: Add Deployment Enum --- monkey/monkey_island/cc/deployment.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 monkey/monkey_island/cc/deployment.py diff --git a/monkey/monkey_island/cc/deployment.py b/monkey/monkey_island/cc/deployment.py new file mode 100644 index 000000000..0ab378f95 --- /dev/null +++ b/monkey/monkey_island/cc/deployment.py @@ -0,0 +1,8 @@ +from enum import Enum + + +class Deployment(Enum): + DEVELOP = "develop" + WINDOWS = "windows" + APPIMAGE = "appimage" + DOCKER = "docker" From 3c1653d87236f2c3f37f4ca2fd2f7049078fd3a8 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 3 Aug 2022 16:28:18 +0200 Subject: [PATCH 2/5] Island: Add semantic_version to Pipfile Used to validate version string --- monkey/monkey_island/Pipfile | 1 + monkey/monkey_island/Pipfile.lock | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/monkey/monkey_island/Pipfile b/monkey/monkey_island/Pipfile index d95999cba..af867d904 100644 --- a/monkey/monkey_island/Pipfile +++ b/monkey/monkey_island/Pipfile @@ -32,6 +32,7 @@ marshmallow-enum = "*" readerwriterlock = "*" pymongo = "*" cryptography = "*" +semantic-version = "*" [dev-packages] virtualenv = ">=20.0.26" diff --git a/monkey/monkey_island/Pipfile.lock b/monkey/monkey_island/Pipfile.lock index babf8a552..52894413a 100644 --- a/monkey/monkey_island/Pipfile.lock +++ b/monkey/monkey_island/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "09e1b190955d23328ac5e2de385904f7b109eb6b748e7ae9b2b5c7bfd62f690c" + "sha256": "2af80b266ceacbce17f2f3a7bfbc08dbf2429ebb5901357c93b1fb17b380ca4b" }, "pipfile-spec": 6, "requires": { @@ -797,6 +797,14 @@ "markers": "python_version >= '3.6'", "version": "==0.5.2" }, + "semantic-version": { + "hashes": [ + "sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c", + "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177" + ], + "index": "pypi", + "version": "==2.10.0" + }, "setuptools": { "hashes": [ "sha256:0d33c374d41c7863419fc8f6c10bfe25b7b498aa34164d135c622e52580c6b16", @@ -944,7 +952,7 @@ "sha256:7614553711ee97490f732126dc077f8d0ae084ebc6a96e23db1482afabdb2c51", "sha256:ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb" ], - "markers": "python_full_version >= '3.6.0'", + "markers": "python_version >= '3.6'", "version": "==2.10.3" }, "black": { @@ -1236,7 +1244,7 @@ "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159", "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3" ], - "markers": "python_full_version >= '3.6.0'", + "markers": "python_version >= '3.6'", "version": "==1.0.0" }, "py": { @@ -1268,7 +1276,7 @@ "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb", "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519" ], - "markers": "python_full_version >= '3.6.0'", + "markers": "python_version >= '3.6'", "version": "==2.12.0" }, "pyparsing": { @@ -1392,7 +1400,7 @@ "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07", "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2" ], - "markers": "python_full_version >= '3.6.0'", + "markers": "python_version >= '3.6'", "version": "==2.0.0" }, "sphinxcontrib-jsmath": { From 8586d8906293991d7bf9800d01a0b72d3c2d5d4d Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 3 Aug 2022 16:29:19 +0200 Subject: [PATCH 3/5] Island: Implement Version object --- monkey/monkey_island/cc/version.py | 81 ++++++++++++++++++++++++++++++ vulture_allowlist.py | 5 ++ 2 files changed, 86 insertions(+) create mode 100644 monkey/monkey_island/cc/version.py diff --git a/monkey/monkey_island/cc/version.py b/monkey/monkey_island/cc/version.py new file mode 100644 index 000000000..ed944a4a2 --- /dev/null +++ b/monkey/monkey_island/cc/version.py @@ -0,0 +1,81 @@ +import logging +from threading import Event, Thread + +import requests +import semantic_version + +from .deployment import Deployment + +VERSION_SERVER_URL_PREF = "https://updates.infectionmonkey.com" +VERSION_SERVER_CHECK_NEW_URL = VERSION_SERVER_URL_PREF + "?deployment=%s&monkey_version=%s" +VERSION_SERVER_DOWNLOAD_URL = VERSION_SERVER_CHECK_NEW_URL + "&is_download=true" + +LATEST_VERSION_TIMEOUT = 7 + +logger = logging.getLogger(__name__) + + +class Version: + """ + Class which get current version, latest version and download link for the latest version + """ + + def __init__(self, version_number: str, deployment: Deployment): + self._version_number = version_number + self._latest_version = None + self._download_url = None + self._deployment = deployment + self._initialization_complete = Event() + + Thread(target=self._set_version_metadata, daemon=True).start() + + @property + def version_number(self): + """ + The current version of the island + """ + return self._version_number + + @property + def latest_version(self): + """ + Latest available version of the island + """ + self._initialization_complete.wait() + return self._latest_version + + @property + def download_url(self): + """ + URL for the latest available version + """ + self._initialization_complete.wait() + return self._download_url + + def _set_version_metadata(self): + self._latest_version = self._get_latest_version() + self._download_url = self._get_download_link() + self._initialization_complete.set() + + def _get_latest_version(self) -> str: + url = VERSION_SERVER_CHECK_NEW_URL % (self._deployment.value, self._version_number) + + try: + reply = requests.get(url, timeout=LATEST_VERSION_TIMEOUT) + except requests.exceptions.RequestsException as err: + logger.warning(f"Failed to connect to {VERSION_SERVER_URL_PREF}: {err}") + return self._version_number + + res = reply.json().get("newer_version", None) + + if res is False: + return self._version_number + + if not semantic_version.validate(res): + logger.warning(f"Recieved invalid version {res} from {VERSION_SERVER_URL_PREF}") + return self._version_number + + return res.strip() + + def _get_download_link(self): + return VERSION_SERVER_DOWNLOAD_URL % (self._deployment.value, self._version_number) diff --git a/vulture_allowlist.py b/vulture_allowlist.py index d512f51eb..287619b44 100644 --- a/vulture_allowlist.py +++ b/vulture_allowlist.py @@ -160,6 +160,11 @@ get_file_sha256_hash strict_slashes # unused attribute (monkey/monkey_island/cc/app.py:96) post_breach_actions # unused variable (monkey\infection_monkey\config.py:95) +# Deployments +DEVELOP # unused variable (monkey/monkey/monkey_island/cc/deployment.py:5) +APPIMAGE # unused variable (monkey/monkey/monkey_island/cc/deployment.py:7) +DOCKER # unused variable (monkey/monkey/monkey_island/cc/deployment.py:8) + # these are not needed for it to work, but may be useful extra information to understand what's going on WINDOWS_PBA_TYPE # unused variable (monkey/monkey_island/cc/resources/pba_file_upload.py:23) WINDOWS_TTL # unused variable (monkey/infection_monkey/network/ping_scanner.py:17) From 89c24232c026534d8b5d1b0af15aafa8bfb3d4b2 Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Wed, 3 Aug 2022 11:57:03 -0400 Subject: [PATCH 4/5] Island: Improve docstring for Version --- monkey/monkey_island/cc/version.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/monkey/monkey_island/cc/version.py b/monkey/monkey_island/cc/version.py index ed944a4a2..54924f9c1 100644 --- a/monkey/monkey_island/cc/version.py +++ b/monkey/monkey_island/cc/version.py @@ -17,7 +17,9 @@ logger = logging.getLogger(__name__) class Version: """ - Class which get current version, latest version and download link for the latest version + Information about the Island's version + + Provides the current version, latest version, and download link for the latest version. """ def __init__(self, version_number: str, deployment: Deployment): From 3512ed0b2693807b9428035c3c6a9481157352eb Mon Sep 17 00:00:00 2001 From: Mike Salvatore Date: Wed, 3 Aug 2022 13:16:15 -0400 Subject: [PATCH 5/5] Island: Add docstring to Deployment --- monkey/monkey_island/cc/deployment.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/monkey/monkey_island/cc/deployment.py b/monkey/monkey_island/cc/deployment.py index 0ab378f95..b5bee88a4 100644 --- a/monkey/monkey_island/cc/deployment.py +++ b/monkey/monkey_island/cc/deployment.py @@ -2,6 +2,14 @@ from enum import Enum class Deployment(Enum): + """ + An Enum representing the different ways the Island can be deployed + + The Infection Monkey Island can be deployed on a variety of different platforms via different + packaging mechanisms. This Enum represents the different ways that the Island can be deployed. + The value of each member is the member's name in all lower-case characters. + """ + DEVELOP = "develop" WINDOWS = "windows" APPIMAGE = "appimage"