Merge pull request #1549 from guardicore/docker_data_dir_fix

Docker data dir fix
This commit is contained in:
Mike Salvatore 2021-10-25 12:26:14 -04:00 committed by GitHub
commit b91120a677
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 10 deletions

View File

@ -18,6 +18,7 @@ COPY --from=builder /monkey /monkey
WORKDIR /monkey WORKDIR /monkey
EXPOSE 5000 EXPOSE 5000
EXPOSE 5001 EXPOSE 5001
ENV MONKEY_DOCKER_CONTAINER=true
RUN groupadd -r monkey-island && useradd --no-log-init -r -g monkey-island monkey-island RUN groupadd -r monkey-island && useradd --no-log-init -r -g monkey-island monkey-island
RUN chmod 444 /monkey/monkey_island/cc/server.key RUN chmod 444 /monkey/monkey_island/cc/server.key
RUN chmod 444 /monkey/monkey_island/cc/server.csr RUN chmod 444 /monkey/monkey_island/cc/server.csr

View File

@ -70,7 +70,8 @@ def _setup_data_dir(island_args: IslandCmdArgs) -> Tuple[IslandConfigOptions, st
except json.JSONDecodeError as ex: except json.JSONDecodeError as ex:
print(f"Error loading server config: {ex}") print(f"Error loading server config: {ex}")
exit(1) exit(1)
except IncompatibleDataDirectory: except IncompatibleDataDirectory as ex:
print(f"Incompatible data directory: {ex}")
exit(1) exit(1)

View File

@ -5,6 +5,7 @@ from pathlib import Path
from common.version import get_version from common.version import get_version
from monkey_island.cc.server_utils.file_utils import create_secure_directory from monkey_island.cc.server_utils.file_utils import create_secure_directory
from monkey_island.cc.setup.env_utils import is_running_on_docker
from monkey_island.cc.setup.version_file_setup import get_version_from_dir, write_version from monkey_island.cc.setup.version_file_setup import get_version_from_dir, write_version
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -26,24 +27,46 @@ def setup_data_dir(data_dir_path: Path) -> None:
def _is_data_dir_old(data_dir_path: Path) -> bool: def _is_data_dir_old(data_dir_path: Path) -> bool:
dir_exists = data_dir_path.exists() dir_exists = data_dir_path.exists()
if not dir_exists or not os.listdir(data_dir_path):
if is_running_on_docker():
return _is_docker_data_dir_old(data_dir_path)
if not dir_exists or _is_directory_empty(data_dir_path):
return False return False
return _data_dir_version_mismatch_exists(data_dir_path) return _data_dir_version_mismatch_exists(data_dir_path)
def _is_docker_data_dir_old(data_dir_path: Path) -> bool:
if _data_dir_version_mismatch_exists(data_dir_path):
if _is_directory_empty(data_dir_path):
return False
else:
raise IncompatibleDataDirectory(
"Found an old volume. "
"You must create an empty volume for each docker container "
"as specified in setup documentation: "
"https://www.guardicore.com/infectionmonkey/docs/setup/docker/"
)
else:
return False
def _is_directory_empty(path: Path) -> bool:
return not os.listdir(path)
def _handle_old_data_directory(data_dir_path: Path) -> None: def _handle_old_data_directory(data_dir_path: Path) -> None:
should_delete_data_directory = _prompt_user_to_delete_data_directory(data_dir_path) should_delete_data_directory = _prompt_user_to_delete_data_directory(data_dir_path)
if should_delete_data_directory: if should_delete_data_directory:
shutil.rmtree(data_dir_path) shutil.rmtree(data_dir_path)
logger.info(f"{data_dir_path} was deleted.") logger.info(f"{data_dir_path} was deleted.")
else: else:
logger.error( raise IncompatibleDataDirectory(
"Unable to set up data directory. Please backup and delete the existing data directory" "Unable to set up data directory. Please backup and delete the existing data directory"
f" ({data_dir_path}). Then, try again. To learn how to restore and use a backup, please" f" ({data_dir_path}). Then, try again. To learn how to restore and use a backup, please"
" refer to the documentation." " refer to the documentation."
) )
raise IncompatibleDataDirectory()
def _prompt_user_to_delete_data_directory(data_dir_path: Path) -> bool: def _prompt_user_to_delete_data_directory(data_dir_path: Path) -> bool:

View File

@ -0,0 +1,8 @@
import os
# Must match evn var name in build_scripts/docker/Dockerfile:21
DOCKER_ENV_VAR = "MONKEY_DOCKER_CONTAINER"
def is_running_on_docker():
return os.environ.get(DOCKER_ENV_VAR) == "true"

View File

@ -3,6 +3,7 @@ from pathlib import Path
import pytest import pytest
from monkey_island.cc.setup.data_dir import IncompatibleDataDirectory, setup_data_dir from monkey_island.cc.setup.data_dir import IncompatibleDataDirectory, setup_data_dir
from monkey_island.cc.setup.env_utils import DOCKER_ENV_VAR
from monkey_island.cc.setup.version_file_setup import _version_filename from monkey_island.cc.setup.version_file_setup import _version_filename
current_version = "1.1.1" current_version = "1.1.1"
@ -27,6 +28,12 @@ def temp_version_file_path(temp_data_dir_path) -> Path:
return temp_data_dir_path / _version_filename return temp_data_dir_path / _version_filename
def create_bogus_file(dir_path: Path) -> Path:
bogus_file_path = dir_path / "test.txt"
bogus_file_path.touch()
return bogus_file_path
def test_setup_data_dir(temp_data_dir_path, temp_version_file_path): def test_setup_data_dir(temp_data_dir_path, temp_version_file_path):
data_dir_path = temp_data_dir_path data_dir_path = temp_data_dir_path
setup_data_dir(data_dir_path) setup_data_dir(data_dir_path)
@ -41,8 +48,7 @@ def test_old_version_removed(monkeypatch, temp_data_dir_path, temp_version_file_
temp_data_dir_path.mkdir() temp_data_dir_path.mkdir()
temp_version_file_path.write_text(old_version) temp_version_file_path.write_text(old_version)
bogus_file_path = temp_data_dir_path / "test.txt" bogus_file_path = create_bogus_file(temp_data_dir_path)
bogus_file_path.touch()
setup_data_dir(temp_data_dir_path) setup_data_dir(temp_data_dir_path)
@ -58,8 +64,7 @@ def test_old_version_not_removed(
temp_data_dir_path.mkdir() temp_data_dir_path.mkdir()
temp_version_file_path.write_text(old_version) temp_version_file_path.write_text(old_version)
bogus_file_path = temp_data_dir_path / "test.txt" bogus_file_path = create_bogus_file(temp_data_dir_path)
bogus_file_path.touch()
with pytest.raises(IncompatibleDataDirectory): with pytest.raises(IncompatibleDataDirectory):
setup_data_dir(temp_data_dir_path) setup_data_dir(temp_data_dir_path)
@ -71,8 +76,7 @@ def test_old_version_not_removed(
def test_data_dir_setup_not_needed(temp_data_dir_path, temp_version_file_path): def test_data_dir_setup_not_needed(temp_data_dir_path, temp_version_file_path):
temp_data_dir_path.mkdir() temp_data_dir_path.mkdir()
temp_version_file_path.write_text(current_version) temp_version_file_path.write_text(current_version)
bogus_file_path = temp_data_dir_path / "test.txt" bogus_file_path = create_bogus_file(temp_data_dir_path)
bogus_file_path.touch()
setup_data_dir(temp_data_dir_path) setup_data_dir(temp_data_dir_path)
assert temp_version_file_path.read_text() == current_version assert temp_version_file_path.read_text() == current_version
@ -84,3 +88,44 @@ def test_empty_data_dir(temp_data_dir_path, temp_version_file_path):
setup_data_dir(temp_data_dir_path) setup_data_dir(temp_data_dir_path)
assert temp_version_file_path.read_text() == current_version assert temp_version_file_path.read_text() == current_version
def test_new_data_dir_docker(monkeypatch, temp_data_dir_path, temp_version_file_path):
monkeypatch.setenv(DOCKER_ENV_VAR, "true")
temp_data_dir_path.mkdir()
bogus_file_path = create_bogus_file(temp_data_dir_path)
temp_version_file_path.write_text(current_version)
setup_data_dir(temp_data_dir_path)
assert temp_version_file_path.read_text() == current_version
assert bogus_file_path.is_file()
def test_data_dir_docker_old_version(monkeypatch, temp_data_dir_path, temp_version_file_path):
monkeypatch.setenv(DOCKER_ENV_VAR, "true")
temp_data_dir_path.mkdir()
temp_version_file_path.write_text(old_version)
with pytest.raises(IncompatibleDataDirectory):
setup_data_dir(temp_data_dir_path)
def test_empty_data_dir_docker(monkeypatch, temp_data_dir_path, temp_version_file_path):
monkeypatch.setenv(DOCKER_ENV_VAR, "true")
temp_data_dir_path.mkdir()
setup_data_dir(temp_data_dir_path)
assert temp_version_file_path.read_text() == current_version
def test_old_data_dir_docker_no_version(monkeypatch, temp_data_dir_path):
monkeypatch.setenv(DOCKER_ENV_VAR, "true")
temp_data_dir_path.mkdir()
create_bogus_file(temp_data_dir_path)
with pytest.raises(IncompatibleDataDirectory):
setup_data_dir(temp_data_dir_path)