forked from p15670423/monkey
Merge pull request #1620 from guardicore/1506-remove-environments
Remove environments
This commit is contained in:
commit
f457635507
|
@ -1,5 +0,0 @@
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
|
|
||||||
class Environment(Enum):
|
|
||||||
AWS = "AWS"
|
|
|
@ -1,11 +1,11 @@
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
import flask_restful
|
import flask_restful
|
||||||
from flask import Flask, Response, send_from_directory
|
from flask import Flask, Response, send_from_directory
|
||||||
from werkzeug.exceptions import NotFound
|
from werkzeug.exceptions import NotFound
|
||||||
|
|
||||||
import monkey_island.cc.environment.environment_singleton as env_singleton
|
|
||||||
from common.common_consts.api_url_consts import T1216_PBA_FILE_DOWNLOAD_PATH
|
from common.common_consts.api_url_consts import T1216_PBA_FILE_DOWNLOAD_PATH
|
||||||
from monkey_island.cc.database import database, mongo
|
from monkey_island.cc.database import database, mongo
|
||||||
from monkey_island.cc.resources.attack.attack_report import AttackReport
|
from monkey_island.cc.resources.attack.attack_report import AttackReport
|
||||||
|
@ -57,6 +57,7 @@ from monkey_island.cc.services.remote_run_aws import RemoteRunAwsService
|
||||||
from monkey_island.cc.services.representations import output_json
|
from monkey_island.cc.services.representations import output_json
|
||||||
|
|
||||||
HOME_FILE = "index.html"
|
HOME_FILE = "index.html"
|
||||||
|
AUTH_EXPIRATION_TIME = timedelta(minutes=30)
|
||||||
|
|
||||||
|
|
||||||
def serve_static_file(static_path):
|
def serve_static_file(static_path):
|
||||||
|
@ -86,7 +87,7 @@ def init_app_config(app, mongo_url):
|
||||||
app.config["MONGO_URI"] = mongo_url
|
app.config["MONGO_URI"] = mongo_url
|
||||||
|
|
||||||
# See https://flask-jwt-extended.readthedocs.io/en/stable/options
|
# See https://flask-jwt-extended.readthedocs.io/en/stable/options
|
||||||
app.config["JWT_ACCESS_TOKEN_EXPIRES"] = env_singleton.env.get_auth_expiration_time()
|
app.config["JWT_ACCESS_TOKEN_EXPIRES"] = AUTH_EXPIRATION_TIME
|
||||||
# Invalidate the signature of JWTs if the server process restarts. This avoids the edge case
|
# Invalidate the signature of JWTs if the server process restarts. This avoids the edge case
|
||||||
# of getting a JWT,
|
# of getting a JWT,
|
||||||
# deciding to reset credentials and then still logging in with the old JWT.
|
# deciding to reset credentials and then still logging in with the old JWT.
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
import logging
|
|
||||||
from abc import ABCMeta, abstractmethod
|
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
from common.utils.exceptions import (
|
|
||||||
AlreadyRegisteredError,
|
|
||||||
InvalidRegistrationCredentialsError,
|
|
||||||
)
|
|
||||||
from monkey_island.cc.environment.environment_config import EnvironmentConfig
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class Environment(object, metaclass=ABCMeta):
|
|
||||||
_ISLAND_PORT = 5000
|
|
||||||
_DEBUG_SERVER = False
|
|
||||||
_AUTH_EXPIRATION_TIME = timedelta(minutes=30)
|
|
||||||
|
|
||||||
_testing = False
|
|
||||||
|
|
||||||
def __init__(self, config: EnvironmentConfig):
|
|
||||||
self._config = config
|
|
||||||
self._testing = False # Assume env is not for unit testing.
|
|
||||||
|
|
||||||
@property
|
|
||||||
def testing(self):
|
|
||||||
return self._testing
|
|
||||||
|
|
||||||
@testing.setter
|
|
||||||
def testing(self, value):
|
|
||||||
self._testing = value
|
|
||||||
|
|
||||||
def get_config(self) -> EnvironmentConfig:
|
|
||||||
return self._config
|
|
||||||
|
|
||||||
def get_island_port(self):
|
|
||||||
return self._ISLAND_PORT
|
|
||||||
|
|
||||||
def is_debug(self):
|
|
||||||
return self._DEBUG_SERVER
|
|
||||||
|
|
||||||
def get_auth_expiration_time(self):
|
|
||||||
return self._AUTH_EXPIRATION_TIME
|
|
|
@ -1,9 +0,0 @@
|
||||||
from common.cloud.aws.aws_instance import AwsInstance
|
|
||||||
from monkey_island.cc.environment import Environment
|
|
||||||
|
|
||||||
|
|
||||||
class AwsEnvironment(Environment):
|
|
||||||
def __init__(self, config):
|
|
||||||
super(AwsEnvironment, self).__init__(config)
|
|
||||||
# Not suppressing error here on purpose. This is critical if we're on AWS env.
|
|
||||||
self.aws_info = AwsInstance()
|
|
|
@ -1,49 +0,0 @@
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
from typing import Dict
|
|
||||||
|
|
||||||
|
|
||||||
class EnvironmentConfig:
|
|
||||||
def __init__(self, file_path):
|
|
||||||
self._server_config_path = os.path.expanduser(file_path)
|
|
||||||
self.server_config = None
|
|
||||||
self.aws = None
|
|
||||||
|
|
||||||
self._load_from_file(self._server_config_path)
|
|
||||||
|
|
||||||
def _load_from_file(self, file_path):
|
|
||||||
file_path = os.path.expanduser(file_path)
|
|
||||||
|
|
||||||
with open(file_path, "r") as f:
|
|
||||||
config_content = f.read()
|
|
||||||
|
|
||||||
self._load_from_json(config_content)
|
|
||||||
|
|
||||||
def _load_from_json(self, config_json: str):
|
|
||||||
data = json.loads(config_json)
|
|
||||||
self._load_from_dict(data["environment"])
|
|
||||||
|
|
||||||
def _load_from_dict(self, dict_data: Dict):
|
|
||||||
aws = dict_data["aws"] if "aws" in dict_data else None
|
|
||||||
|
|
||||||
self.server_config = dict_data["server_config"]
|
|
||||||
self.aws = aws
|
|
||||||
|
|
||||||
def save_to_file(self):
|
|
||||||
with open(self._server_config_path, "r") as f:
|
|
||||||
config = json.load(f)
|
|
||||||
|
|
||||||
config["environment"] = self.to_dict()
|
|
||||||
|
|
||||||
with open(self._server_config_path, "w") as f:
|
|
||||||
f.write(json.dumps(config, indent=2))
|
|
||||||
|
|
||||||
def to_dict(self) -> Dict:
|
|
||||||
config_dict = {
|
|
||||||
"server_config": self.server_config,
|
|
||||||
}
|
|
||||||
if self.aws:
|
|
||||||
config_dict.update({"aws": self.aws})
|
|
||||||
return config_dict
|
|
|
@ -1,34 +0,0 @@
|
||||||
import logging
|
|
||||||
|
|
||||||
from monkey_island.cc.environment import EnvironmentConfig, aws, password
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
AWS = "aws"
|
|
||||||
PASSWORD = "password"
|
|
||||||
|
|
||||||
ENV_DICT = {
|
|
||||||
AWS: aws.AwsEnvironment,
|
|
||||||
PASSWORD: password.PasswordEnvironment,
|
|
||||||
}
|
|
||||||
|
|
||||||
env = None
|
|
||||||
|
|
||||||
|
|
||||||
def set_env(env_type: str, env_config: EnvironmentConfig):
|
|
||||||
global env
|
|
||||||
if env_type in ENV_DICT:
|
|
||||||
env = ENV_DICT[env_type](env_config)
|
|
||||||
|
|
||||||
|
|
||||||
def initialize_from_file(file_path):
|
|
||||||
try:
|
|
||||||
config = EnvironmentConfig(file_path)
|
|
||||||
|
|
||||||
__env_type = config.server_config
|
|
||||||
set_env(__env_type, config)
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
logger.info("Monkey's env is: {0}".format(env.__class__.__name__))
|
|
||||||
except Exception:
|
|
||||||
logger.error("Failed initializing environment", exc_info=True)
|
|
||||||
raise
|
|
|
@ -1,7 +0,0 @@
|
||||||
from monkey_island.cc.environment import Environment
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: We can probably remove these Environment subclasses, but the
|
|
||||||
# AwsEnvironment class still does something unique in its constructor.
|
|
||||||
class PasswordEnvironment(Environment):
|
|
||||||
pass
|
|
|
@ -10,13 +10,14 @@ from typing import Tuple
|
||||||
import gevent.hub
|
import gevent.hub
|
||||||
from gevent.pywsgi import WSGIServer
|
from gevent.pywsgi import WSGIServer
|
||||||
|
|
||||||
|
from monkey_island.cc.server_utils.consts import ISLAND_PORT
|
||||||
|
|
||||||
# Add the monkey_island directory to the path, to make sure imports that don't start with
|
# Add the monkey_island directory to the path, to make sure imports that don't start with
|
||||||
# "monkey_island." work.
|
# "monkey_island." work.
|
||||||
MONKEY_ISLAND_DIR_BASE_PATH = str(Path(__file__).parent.parent)
|
MONKEY_ISLAND_DIR_BASE_PATH = str(Path(__file__).parent.parent)
|
||||||
if str(MONKEY_ISLAND_DIR_BASE_PATH) not in sys.path:
|
if str(MONKEY_ISLAND_DIR_BASE_PATH) not in sys.path:
|
||||||
sys.path.insert(0, MONKEY_ISLAND_DIR_BASE_PATH)
|
sys.path.insert(0, MONKEY_ISLAND_DIR_BASE_PATH)
|
||||||
|
|
||||||
import monkey_island.cc.environment.environment_singleton as env_singleton # noqa: E402
|
|
||||||
import monkey_island.cc.setup.config_setup as config_setup # noqa: E402
|
import monkey_island.cc.setup.config_setup as config_setup # noqa: E402
|
||||||
from common.version import get_version # noqa: E402
|
from common.version import get_version # noqa: E402
|
||||||
from monkey_island.cc.app import init_app # noqa: E402
|
from monkey_island.cc.app import init_app # noqa: E402
|
||||||
|
@ -89,8 +90,6 @@ def _configure_logging(config_options):
|
||||||
|
|
||||||
|
|
||||||
def _initialize_globals(config_options: IslandConfigOptions, server_config_path: str):
|
def _initialize_globals(config_options: IslandConfigOptions, server_config_path: str):
|
||||||
env_singleton.initialize_from_file(server_config_path)
|
|
||||||
|
|
||||||
initialize_services(config_options.data_dir)
|
initialize_services(config_options.data_dir)
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,23 +143,16 @@ def _start_island_server(should_setup_only, config_options: IslandConfigOptions)
|
||||||
f"{config_options.key_path}."
|
f"{config_options.key_path}."
|
||||||
)
|
)
|
||||||
|
|
||||||
if env_singleton.env.is_debug():
|
http_server = WSGIServer(
|
||||||
app.run(
|
("0.0.0.0", ISLAND_PORT),
|
||||||
host="0.0.0.0",
|
app,
|
||||||
debug=True,
|
certfile=config_options.crt_path,
|
||||||
ssl_context=(config_options.crt_path, config_options.key_path),
|
keyfile=config_options.key_path,
|
||||||
)
|
log=logger,
|
||||||
else:
|
error_log=logger,
|
||||||
http_server = WSGIServer(
|
)
|
||||||
("0.0.0.0", env_singleton.env.get_island_port()),
|
_log_init_info()
|
||||||
app,
|
http_server.serve_forever()
|
||||||
certfile=config_options.crt_path,
|
|
||||||
keyfile=config_options.key_path,
|
|
||||||
log=logger,
|
|
||||||
error_log=logger,
|
|
||||||
)
|
|
||||||
_log_init_info()
|
|
||||||
http_server.serve_forever()
|
|
||||||
|
|
||||||
bootloader_server_thread.join()
|
bootloader_server_thread.join()
|
||||||
|
|
||||||
|
@ -178,12 +170,7 @@ def _log_init_info():
|
||||||
logger.info(f"version: {get_version()}")
|
logger.info(f"version: {get_version()}")
|
||||||
logger.info(
|
logger.info(
|
||||||
"Listening on the following URLs: {}".format(
|
"Listening on the following URLs: {}".format(
|
||||||
", ".join(
|
", ".join(["https://{}:{}".format(x, ISLAND_PORT) for x in local_ip_addresses()])
|
||||||
[
|
|
||||||
"https://{}:{}".format(x, env_singleton.env.get_island_port())
|
|
||||||
for x in local_ip_addresses()
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
MonkeyDownload.log_executable_hashes()
|
MonkeyDownload.log_executable_hashes()
|
||||||
|
|
|
@ -7,7 +7,7 @@ import requests
|
||||||
import urllib3
|
import urllib3
|
||||||
|
|
||||||
from common.common_consts.timeouts import SHORT_REQUEST_TIMEOUT
|
from common.common_consts.timeouts import SHORT_REQUEST_TIMEOUT
|
||||||
from monkey_island.cc.environment import Environment
|
from monkey_island.cc.server_utils.consts import ISLAND_PORT
|
||||||
|
|
||||||
# Disable "unverified certificate" warnings when sending requests to island
|
# Disable "unverified certificate" warnings when sending requests to island
|
||||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # noqa: DUO131
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # noqa: DUO131
|
||||||
|
@ -49,4 +49,4 @@ class BootloaderHTTPRequestHandler(BaseHTTPRequestHandler):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_bootloader_resource_url(server_ip):
|
def get_bootloader_resource_url(server_ip):
|
||||||
return "https://" + server_ip + ":" + str(Environment._ISLAND_PORT) + "/api/bootloader/"
|
return "https://" + server_ip + ":" + str(ISLAND_PORT) + "/api/bootloader/"
|
||||||
|
|
|
@ -51,3 +51,5 @@ DEFAULT_CERTIFICATE_PATHS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
GEVENT_EXCEPTION_LOG = "gevent_exceptions.log"
|
GEVENT_EXCEPTION_LOG = "gevent_exceptions.log"
|
||||||
|
|
||||||
|
ISLAND_PORT = 5000
|
||||||
|
|
|
@ -5,7 +5,6 @@ import logging
|
||||||
|
|
||||||
from jsonschema import Draft4Validator, validators
|
from jsonschema import Draft4Validator, validators
|
||||||
|
|
||||||
import monkey_island.cc.environment.environment_singleton as env_singleton
|
|
||||||
from common.config_value_paths import (
|
from common.config_value_paths import (
|
||||||
AWS_KEYS_PATH,
|
AWS_KEYS_PATH,
|
||||||
EXPORT_MONKEY_TELEMS_PATH,
|
EXPORT_MONKEY_TELEMS_PATH,
|
||||||
|
@ -19,6 +18,7 @@ from common.config_value_paths import (
|
||||||
USER_LIST_PATH,
|
USER_LIST_PATH,
|
||||||
)
|
)
|
||||||
from monkey_island.cc.database import mongo
|
from monkey_island.cc.database import mongo
|
||||||
|
from monkey_island.cc.server_utils.consts import ISLAND_PORT
|
||||||
from monkey_island.cc.server_utils.encryption import get_datastore_encryptor
|
from monkey_island.cc.server_utils.encryption import get_datastore_encryptor
|
||||||
from monkey_island.cc.services.config_manipulator import update_config_per_mode
|
from monkey_island.cc.services.config_manipulator import update_config_per_mode
|
||||||
from monkey_island.cc.services.config_schema.config_schema import SCHEMA
|
from monkey_island.cc.services.config_schema.config_schema import SCHEMA
|
||||||
|
@ -264,11 +264,11 @@ class ConfigService:
|
||||||
def set_server_ips_in_config(config):
|
def set_server_ips_in_config(config):
|
||||||
ips = local_ip_addresses()
|
ips = local_ip_addresses()
|
||||||
config["internal"]["island_server"]["command_servers"] = [
|
config["internal"]["island_server"]["command_servers"] = [
|
||||||
"%s:%d" % (ip, env_singleton.env.get_island_port()) for ip in ips
|
"%s:%d" % (ip, ISLAND_PORT) for ip in ips
|
||||||
]
|
]
|
||||||
config["internal"]["island_server"]["current_server"] = "%s:%d" % (
|
config["internal"]["island_server"]["current_server"] = "%s:%d" % (
|
||||||
ips[0],
|
ips[0],
|
||||||
env_singleton.env.get_island_port(),
|
ISLAND_PORT,
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -5,9 +5,8 @@ import stat
|
||||||
import subprocess
|
import subprocess
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
|
|
||||||
import monkey_island.cc.environment.environment_singleton as env_singleton
|
|
||||||
from monkey_island.cc.resources.monkey_download import get_monkey_executable
|
from monkey_island.cc.resources.monkey_download import get_monkey_executable
|
||||||
from monkey_island.cc.server_utils.consts import MONKEY_ISLAND_ABS_PATH
|
from monkey_island.cc.server_utils.consts import ISLAND_PORT, MONKEY_ISLAND_ABS_PATH
|
||||||
from monkey_island.cc.services.utils.network_utils import local_ip_addresses
|
from monkey_island.cc.services.utils.network_utils import local_ip_addresses
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -45,7 +44,7 @@ class LocalMonkeyRunService:
|
||||||
# run the monkey
|
# run the monkey
|
||||||
try:
|
try:
|
||||||
ip = local_ip_addresses()[0]
|
ip = local_ip_addresses()[0]
|
||||||
port = env_singleton.env.get_island_port()
|
port = ISLAND_PORT
|
||||||
|
|
||||||
args = [dest_path, "m0nk3y", "-s", f"{ip}:{port}"]
|
args = [dest_path, "m0nk3y", "-s", f"{ip}:{port}"]
|
||||||
subprocess.Popen(args, cwd=LocalMonkeyRunService.DATA_DIR)
|
subprocess.Popen(args, cwd=LocalMonkeyRunService.DATA_DIR)
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
import os
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
|
||||||
def no_credentials(server_configs_dir):
|
|
||||||
return os.path.join(server_configs_dir, "server_config_no_credentials.json")
|
|
|
@ -1,16 +0,0 @@
|
||||||
from typing import Dict
|
|
||||||
from unittest import TestCase
|
|
||||||
|
|
||||||
from monkey_island.cc.environment import Environment, EnvironmentConfig
|
|
||||||
|
|
||||||
|
|
||||||
class TestEnvironment(TestCase):
|
|
||||||
def _test_bool_env_method(
|
|
||||||
self, method_name: str, env: Environment, config: Dict, expected_result: bool
|
|
||||||
):
|
|
||||||
env._config = EnvironmentConfig(config)
|
|
||||||
method = getattr(env, method_name)
|
|
||||||
if expected_result:
|
|
||||||
self.assertTrue(method())
|
|
||||||
else:
|
|
||||||
self.assertFalse(method())
|
|
|
@ -1,32 +0,0 @@
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from monkey_island.cc.environment.environment_config import EnvironmentConfig
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def config_file(tmpdir):
|
|
||||||
return os.path.join(tmpdir, "test_config.json")
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_with_no_credentials(no_credentials):
|
|
||||||
config_dict = EnvironmentConfig(no_credentials).to_dict()
|
|
||||||
|
|
||||||
assert len(config_dict.keys()) == 1
|
|
||||||
assert config_dict["server_config"] == "password"
|
|
||||||
|
|
||||||
|
|
||||||
def test_save_to_file(config_file, no_credentials):
|
|
||||||
shutil.copyfile(no_credentials, config_file)
|
|
||||||
|
|
||||||
environment_config = EnvironmentConfig(config_file)
|
|
||||||
environment_config.aws = "test_aws"
|
|
||||||
environment_config.save_to_file()
|
|
||||||
|
|
||||||
with open(config_file, "r") as f:
|
|
||||||
from_file = json.load(f)
|
|
||||||
|
|
||||||
assert environment_config.to_dict() == from_file["environment"]
|
|
|
@ -1,6 +1,5 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from monkey_island.cc.environment import Environment
|
|
||||||
from monkey_island.cc.services.config import ConfigService
|
from monkey_island.cc.services.config import ConfigService
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +16,6 @@ def PORT():
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def config(monkeypatch, IPS, PORT):
|
def config(monkeypatch, IPS, PORT):
|
||||||
monkeypatch.setattr("monkey_island.cc.services.config.local_ip_addresses", lambda: IPS)
|
monkeypatch.setattr("monkey_island.cc.services.config.local_ip_addresses", lambda: IPS)
|
||||||
monkeypatch.setattr(Environment, "_ISLAND_PORT", PORT)
|
|
||||||
config = ConfigService.get_default_config(True)
|
config = ConfigService.get_default_config(True)
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,8 @@ class MockClass:
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="function", autouse=True)
|
@pytest.fixture(scope="function", autouse=True)
|
||||||
def mock_port_in_env_singleton(monkeypatch, PORT):
|
def mock_port(monkeypatch, PORT):
|
||||||
mock_singleton = MockClass()
|
monkeypatch.setattr("monkey_island.cc.services.config.ISLAND_PORT", PORT)
|
||||||
mock_singleton.env = MockClass()
|
|
||||||
mock_singleton.env.get_island_port = lambda: PORT
|
|
||||||
monkeypatch.setattr("monkey_island.cc.services.config.env_singleton", mock_singleton)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("uses_encryptor")
|
@pytest.mark.usefixtures("uses_encryptor")
|
||||||
|
|
Loading…
Reference in New Issue