diff --git a/monkey_island/cc/app.py b/monkey_island/cc/app.py index a5601ba74..4733d5089 100644 --- a/monkey_island/cc/app.py +++ b/monkey_island/cc/app.py @@ -9,7 +9,7 @@ from werkzeug.exceptions import NotFound from cc.auth import init_jwt from cc.database import mongo -from cc.island_config import AUTH_EXPIRATION_TIME +from cc.environment.environment import env from cc.resources.client_run import ClientRun from cc.resources.edge import Edge from cc.resources.local_run import LocalRun @@ -77,7 +77,7 @@ def init_app(mongo_url): app.config['SECRET_KEY'] = os.urandom(32) app.config['JWT_AUTH_URL_RULE'] = '/api/auth' - app.config['JWT_EXPIRATION_DELTA'] = AUTH_EXPIRATION_TIME + app.config['JWT_EXPIRATION_DELTA'] = env.get_auth_expiration_time() init_jwt(app) mongo.init_app(app) diff --git a/monkey_island/cc/auth.py b/monkey_island/cc/auth.py index 7ee787a75..99667d837 100644 --- a/monkey_island/cc/auth.py +++ b/monkey_island/cc/auth.py @@ -4,7 +4,7 @@ from flask import current_app, abort from flask_jwt import JWT, _jwt_required, JWTError from werkzeug.security import safe_str_cmp -from cc.island_config import AUTH_ENABLED +from cc.environment.environment import env __author__ = 'itay.mizeretz' @@ -19,26 +19,21 @@ class User(object): return "User(id='%s')" % self.id -users = [ - User(1, 'monkey', 'infection') -] -username_table = {u.username: u for u in users} -userid_table = {u.id: u for u in users} - - -def authenticate(username, password): - user = username_table.get(username, None) - if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')): - return user - - -def identity(payload): - user_id = payload['identity'] - return userid_table.get(user_id, None) - - def init_jwt(app): - if AUTH_ENABLED: + users = env.get_auth_users() + username_table = {u.username: u for u in users} + userid_table = {u.id: u for u in users} + + def authenticate(username, password): + user = username_table.get(username, None) + if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')): + return user + + def identity(payload): + user_id = payload['identity'] + return userid_table.get(user_id, None) + + if env.is_auth_enabled(): JWT(app, authenticate, identity) @@ -46,7 +41,7 @@ def jwt_required(realm=None): def wrapper(fn): @wraps(fn) def decorator(*args, **kwargs): - if AUTH_ENABLED: + if env.is_auth_enabled(): try: _jwt_required(realm or current_app.config['JWT_DEFAULT_REALM']) except JWTError: diff --git a/monkey_island/cc/environment/__init__.py b/monkey_island/cc/environment/__init__.py new file mode 100644 index 000000000..712ba232a --- /dev/null +++ b/monkey_island/cc/environment/__init__.py @@ -0,0 +1,33 @@ +import abc +from datetime import timedelta + +__author__ = 'itay.mizeretz' + + +class Environment(object): + __metaclass__ = abc.ABCMeta + + _ISLAND_PORT = 5000 + _MONGO_URL = "mongodb://localhost:27017/monkeyisland" + _DEBUG_SERVER = False + _AUTH_EXPIRATION_TIME = timedelta(hours=1) + + def get_island_port(self): + return self._ISLAND_PORT + + def get_mongo_url(self): + return self._MONGO_URL + + def is_debug(self): + return self._DEBUG_SERVER + + def get_auth_expiration_time(self): + return self._AUTH_EXPIRATION_TIME + + @abc.abstractmethod + def is_auth_enabled(self): + return + + @abc.abstractmethod + def get_auth_users(self): + return diff --git a/monkey_island/cc/environment/aws.py b/monkey_island/cc/environment/aws.py new file mode 100644 index 000000000..b85a7d2e4 --- /dev/null +++ b/monkey_island/cc/environment/aws.py @@ -0,0 +1,24 @@ +import urllib2 + +import cc.auth +from cc.environment import Environment + +__author__ = 'itay.mizeretz' + + +class AwsEnvironment(Environment): + def __init__(self): + super(AwsEnvironment, self).__init__() + self._instance_id = AwsEnvironment._get_instance_id() + + @staticmethod + def _get_instance_id(): + return urllib2.urlopen('http://169.254.169.254/latest/meta-data/instance-id').read() + + def is_auth_enabled(self): + return True + + def get_auth_users(self): + return [ + cc.auth.User(1, 'monkey', self._instance_id) + ] diff --git a/monkey_island/cc/environment/environment.py b/monkey_island/cc/environment/environment.py new file mode 100644 index 000000000..5cb992c7c --- /dev/null +++ b/monkey_island/cc/environment/environment.py @@ -0,0 +1,18 @@ +import json +import standard +import aws + +ENV_DICT = { + 'standard': standard.StandardEnvironment, + 'aws': aws.AwsEnvironment +} + + +def load_env_from_file(): + with open('server_config.json', 'r') as f: + config_content = f.read() + config_json = json.loads(config_content) + return config_json['server_config'] + + +env = ENV_DICT[load_env_from_file()]() diff --git a/monkey_island/cc/environment/standard.py b/monkey_island/cc/environment/standard.py new file mode 100644 index 000000000..8df00a2c3 --- /dev/null +++ b/monkey_island/cc/environment/standard.py @@ -0,0 +1,12 @@ +from cc.environment import Environment + +__author__ = 'itay.mizeretz' + + +class StandardEnvironment(Environment): + + def is_auth_enabled(self): + return False + + def get_auth_users(self): + return [] diff --git a/monkey_island/cc/island_config.py b/monkey_island/cc/island_config.py deleted file mode 100644 index 87fe97263..000000000 --- a/monkey_island/cc/island_config.py +++ /dev/null @@ -1,9 +0,0 @@ -from datetime import timedelta - -__author__ = 'itay.mizeretz' - -ISLAND_PORT = 5000 -DEFAULT_MONGO_URL = "mongodb://localhost:27017/monkeyisland" -DEBUG_SERVER = False -AUTH_ENABLED = True -AUTH_EXPIRATION_TIME = timedelta(hours=1) diff --git a/monkey_island/cc/main.py b/monkey_island/cc/main.py index bb1ed9eaf..c36b564e7 100644 --- a/monkey_island/cc/main.py +++ b/monkey_island/cc/main.py @@ -11,7 +11,7 @@ if BASE_PATH not in sys.path: from cc.app import init_app from cc.utils import local_ip_addresses -from cc.island_config import DEFAULT_MONGO_URL, ISLAND_PORT, DEBUG_SERVER +from cc.environment.environment import env from cc.database import is_db_server_up if __name__ == '__main__': @@ -19,20 +19,20 @@ if __name__ == '__main__': from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop - mongo_url = os.environ.get('MONGO_URL', DEFAULT_MONGO_URL) + mongo_url = os.environ.get('MONGO_URL', env.get_mongo_url()) while not is_db_server_up(mongo_url): print('Waiting for MongoDB server') time.sleep(1) app = init_app(mongo_url) - if DEBUG_SERVER: + if env.is_debug(): app.run(host='0.0.0.0', debug=True, ssl_context=('server.crt', 'server.key')) else: http_server = HTTPServer(WSGIContainer(app), ssl_options={'certfile': os.environ.get('SERVER_CRT', 'server.crt'), 'keyfile': os.environ.get('SERVER_KEY', 'server.key')}) - http_server.listen(ISLAND_PORT) - print('Monkey Island C&C Server is running on https://{}:{}'.format(local_ip_addresses()[0], ISLAND_PORT)) + http_server.listen(env.get_island_port()) + print('Monkey Island C&C Server is running on https://{}:{}'.format(local_ip_addresses()[0], env.get_island_port())) IOLoop.instance().start() diff --git a/monkey_island/cc/resources/local_run.py b/monkey_island/cc/resources/local_run.py index 3d18b49e6..c588eaf80 100644 --- a/monkey_island/cc/resources/local_run.py +++ b/monkey_island/cc/resources/local_run.py @@ -6,8 +6,8 @@ import sys from flask import request, jsonify, make_response import flask_restful +from cc.environment.environment import env from cc.resources.monkey_download import get_monkey_executable -from cc.island_config import ISLAND_PORT from cc.services.node import NodeService from cc.utils import local_ip_addresses @@ -36,7 +36,7 @@ def run_local_monkey(): # run the monkey try: - args = ['"%s" m0nk3y -s %s:%s' % (target_path, local_ip_addresses()[0], ISLAND_PORT)] + args = ['"%s" m0nk3y -s %s:%s' % (target_path, local_ip_addresses()[0], env.get_island_port())] if sys.platform == "win32": args = "".join(args) pid = subprocess.Popen(args, shell=True).pid diff --git a/monkey_island/cc/server_config.json b/monkey_island/cc/server_config.json new file mode 100644 index 000000000..2d1a5995b --- /dev/null +++ b/monkey_island/cc/server_config.json @@ -0,0 +1,3 @@ +{ + "server_config": "standard" +} \ No newline at end of file diff --git a/monkey_island/cc/services/config.py b/monkey_island/cc/services/config.py index ea755312f..cd2999a49 100644 --- a/monkey_island/cc/services/config.py +++ b/monkey_island/cc/services/config.py @@ -1,7 +1,7 @@ from cc.database import mongo from jsonschema import Draft4Validator, validators -from cc.island_config import ISLAND_PORT +from cc.environment.environment import env from cc.utils import local_ip_addresses __author__ = "itay.mizeretz" @@ -885,8 +885,8 @@ class ConfigService: @staticmethod def set_server_ips_in_config(config): ips = local_ip_addresses() - config["cnc"]["servers"]["command_servers"] = ["%s:%d" % (ip, ISLAND_PORT) for ip in ips] - config["cnc"]["servers"]["current_server"] = "%s:%d" % (ips[0], ISLAND_PORT) + config["cnc"]["servers"]["command_servers"] = ["%s:%d" % (ip, env.get_island_port()) for ip in ips] + config["cnc"]["servers"]["current_server"] = "%s:%d" % (ips[0], env.get_island_port()) @staticmethod def save_initial_config_if_needed(): diff --git a/monkey_island/cc/ui/src/server_config/AwsConfig.js b/monkey_island/cc/ui/src/server_config/AwsConfig.js new file mode 100644 index 000000000..1c5814b5a --- /dev/null +++ b/monkey_island/cc/ui/src/server_config/AwsConfig.js @@ -0,0 +1,9 @@ +import BaseConfig from './BaseConfig'; + +class AwsConfig extends BaseConfig{ + isAuthEnabled() { + return true; + } +} + +export default AwsConfig; diff --git a/monkey_island/cc/ui/src/server_config/BaseConfig.js b/monkey_island/cc/ui/src/server_config/BaseConfig.js new file mode 100644 index 000000000..1ca82506d --- /dev/null +++ b/monkey_island/cc/ui/src/server_config/BaseConfig.js @@ -0,0 +1,8 @@ +class BaseConfig { + + isAuthEnabled() { + throw new Error('Abstract function'); + } +} + +export default BaseConfig; diff --git a/monkey_island/cc/ui/src/server_config/ServerConfig.js b/monkey_island/cc/ui/src/server_config/ServerConfig.js new file mode 100644 index 000000000..faff47abc --- /dev/null +++ b/monkey_island/cc/ui/src/server_config/ServerConfig.js @@ -0,0 +1,12 @@ +import StandardConfig from './StandardConfig'; +import AwsConfig from './AwsConfig'; + +const SERVER_CONFIG_JSON = require('json-loader!../../../server_config.json'); + +const CONFIG_DICT = + { + 'standard': StandardConfig, + 'aws': AwsConfig + }; + +export const SERVER_CONFIG = new CONFIG_DICT[SERVER_CONFIG_JSON['server_config']](); diff --git a/monkey_island/cc/ui/src/server_config/StandardConfig.js b/monkey_island/cc/ui/src/server_config/StandardConfig.js new file mode 100644 index 000000000..f549f7112 --- /dev/null +++ b/monkey_island/cc/ui/src/server_config/StandardConfig.js @@ -0,0 +1,10 @@ +import BaseConfig from './BaseConfig'; + +class StandardConfig extends BaseConfig { + + isAuthEnabled () { + return false; + } +} + +export default StandardConfig; diff --git a/monkey_island/cc/ui/src/services/AuthService.js b/monkey_island/cc/ui/src/services/AuthService.js index 25e214088..ea5db3b8b 100644 --- a/monkey_island/cc/ui/src/services/AuthService.js +++ b/monkey_island/cc/ui/src/services/AuthService.js @@ -1,7 +1,8 @@ import decode from 'jwt-decode'; +import {SERVER_CONFIG} from '../server_config/ServerConfig'; export default class AuthService { - AUTH_ENABLED = true; + AUTH_ENABLED = SERVER_CONFIG.isAuthEnabled(); login = (username, password) => { if (this.AUTH_ENABLED) { @@ -96,5 +97,4 @@ export default class AuthService { return localStorage.getItem('jwt') } - }