From fe1d9b8f721034fd656de93d142a27370bf2701f Mon Sep 17 00:00:00 2001 From: itay Date: Mon, 22 Apr 2019 18:08:58 +0300 Subject: [PATCH] Add version update service+resource Add routing to update resource Split app initializing to functions --- monkey/monkey_island/cc/app.py | 28 ++++++--- .../cc/resources/version_update.py | 23 ++++++++ .../cc/services/version_update.py | 57 +++++++++++++++++++ 3 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 monkey/monkey_island/cc/resources/version_update.py create mode 100644 monkey/monkey_island/cc/services/version_update.py diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index 4f055fec6..781640b0d 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -28,6 +28,7 @@ from monkey_island.cc.resources.root import Root from monkey_island.cc.resources.telemetry import Telemetry from monkey_island.cc.resources.telemetry_feed import TelemetryFeed from monkey_island.cc.resources.pba_file_download import PBAFileDownload +from monkey_island.cc.resources.version_update import VersionUpdate from monkey_island.cc.services.config import ConfigService from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH from monkey_island.cc.resources.pba_file_upload import FileUpload @@ -82,18 +83,14 @@ def output_json(obj, code, headers=None): return resp -def init_app(mongo_url): - app = Flask(__name__) - - api = flask_restful.Api(app) - api.representations = {'application/json': output_json} - +def init_app_config(app, mongo_url): app.config['MONGO_URI'] = mongo_url - app.config['SECRET_KEY'] = str(uuid.getnode()) app.config['JWT_AUTH_URL_RULE'] = '/api/auth' app.config['JWT_EXPIRATION_DELTA'] = env.get_auth_expiration_time() + +def init_app_services(app): init_jwt(app) mongo.init_app(app) @@ -101,9 +98,13 @@ def init_app(mongo_url): database.init() ConfigService.init_config() + +def init_app_url_rules(app): app.add_url_rule('/', 'serve_home', serve_home) app.add_url_rule('/', 'serve_static_file', serve_static_file) + +def init_api_resources(api): api.add_resource(Root, '/api') api.add_resource(Monkey, '/api/monkey', '/api/monkey/', '/api/monkey/') api.add_resource(LocalRun, '/api/local-monkey', '/api/local-monkey/') @@ -126,5 +127,18 @@ def init_app(mongo_url): '/api/fileUpload/?restore=') api.add_resource(RemoteRun, '/api/remote-monkey', '/api/remote-monkey/') api.add_resource(AttackTelem, '/api/attack/') + api.add_resource(VersionUpdate, '/api/version-update', '/api/version-update/') + + +def init_app(mongo_url): + app = Flask(__name__) + + api = flask_restful.Api(app) + api.representations = {'application/json': output_json} + + init_app_config(app, mongo_url) + init_app_services(app) + init_app_url_rules(app) + init_api_resources(api) return app diff --git a/monkey/monkey_island/cc/resources/version_update.py b/monkey/monkey_island/cc/resources/version_update.py new file mode 100644 index 000000000..e9cb8ffb0 --- /dev/null +++ b/monkey/monkey_island/cc/resources/version_update.py @@ -0,0 +1,23 @@ +import flask_restful +import logging + +from monkey_island.cc.environment.environment import env +from monkey_island.cc.auth import jwt_required +from monkey_island.cc.services.version_update import VersionUpdateService + +__author__ = 'itay.mizeretz' + +logger = logging.getLogger(__name__) + + +class VersionUpdate(flask_restful.Resource): + def __init__(self): + super(VersionUpdate, self).__init__() + + @jwt_required() + def get(self): + return { + 'current_version': env.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 new file mode 100644 index 000000000..127e39f57 --- /dev/null +++ b/monkey/monkey_island/cc/services/version_update.py @@ -0,0 +1,57 @@ +import logging + +import requests + +from monkey_island.cc.environment.environment import env + +__author__ = "itay.mizeretz" + +logger = logging.getLogger(__name__) + + +class VersionUpdateService: + VERSION_SERVER_URL_PREF = 'https://monkey.guardicore.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' + + newer_version = None + + def __init__(self): + pass + + @staticmethod + def get_newer_version(): + """ + Checks for newer version if never checked before. + :return: None if failed checking for newer version, result of '_check_new_version' otherwise + """ + if VersionUpdateService.newer_version is None: + try: + VersionUpdateService.newer_version = VersionUpdateService._check_new_version() + except Exception: + logger.exception('Failed updating version number') + + return VersionUpdateService.newer_version + + @staticmethod + def _check_new_version(): + """ + 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()) + + reply = requests.get(url, timeout=15) + + res = reply.json().get('newer_version', None) + + if res is False: + return res + + [int(x) for x in res.split('.')] # raises value error if version is invalid format + return res + + @staticmethod + def get_download_link(): + return VersionUpdateService.VERSION_SERVER_DOWNLOAD_URL % (env.get_deployment(), env.get_version()) +