Merge pull request #1620 from guardicore/1506-remove-environments

Remove environments
This commit is contained in:
Mike Salvatore 2021-11-22 06:40:40 -05:00 committed by GitHub
commit f457635507
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 27 additions and 246 deletions

View File

@ -1,5 +0,0 @@
from enum import Enum
class Environment(Enum):
AWS = "AWS"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,15 +143,8 @@ 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():
app.run(
host="0.0.0.0",
debug=True,
ssl_context=(config_options.crt_path, config_options.key_path),
)
else:
http_server = WSGIServer( http_server = WSGIServer(
("0.0.0.0", env_singleton.env.get_island_port()), ("0.0.0.0", ISLAND_PORT),
app, app,
certfile=config_options.crt_path, certfile=config_options.crt_path,
keyfile=config_options.key_path, keyfile=config_options.key_path,
@ -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()

View File

@ -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/"

View File

@ -51,3 +51,5 @@ DEFAULT_CERTIFICATE_PATHS = {
} }
GEVENT_EXCEPTION_LOG = "gevent_exceptions.log" GEVENT_EXCEPTION_LOG = "gevent_exceptions.log"
ISLAND_PORT = 5000

View File

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

View File

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

View File

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

View File

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

View File

@ -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"]

View File

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

View File

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