Merge pull request #2159 from guardicore/2109-version-object

2109 version object
This commit is contained in:
Mike Salvatore 2022-08-03 13:22:35 -04:00 committed by GitHub
commit 3aafa60e53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 118 additions and 5 deletions

View File

@ -32,6 +32,7 @@ marshmallow-enum = "*"
readerwriterlock = "*"
pymongo = "*"
cryptography = "*"
semantic-version = "*"
[dev-packages]
virtualenv = ">=20.0.26"

View File

@ -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": {

View File

@ -0,0 +1,16 @@
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"
DOCKER = "docker"

View File

@ -0,0 +1,83 @@
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:
"""
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):
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)

View File

@ -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)