aboutsummaryrefslogtreecommitdiffstats
path: root/molecule/default/tests/test_server_setup.py
diff options
context:
space:
mode:
Diffstat (limited to 'molecule/default/tests/test_server_setup.py')
-rw-r--r--molecule/default/tests/test_server_setup.py157
1 files changed, 157 insertions, 0 deletions
diff --git a/molecule/default/tests/test_server_setup.py b/molecule/default/tests/test_server_setup.py
new file mode 100644
index 0000000..cb644cb
--- /dev/null
+++ b/molecule/default/tests/test_server_setup.py
@@ -0,0 +1,157 @@
+"""Tests for borg server setup and repository configuration"""
+import pytest
+
+testinfra_hosts = ['borg-server']
+
+
+class TestBorgUser:
+ def test_user_exists(self, host):
+ user = host.user('borg')
+ assert user.exists
+ assert user.home == '/opt/borg'
+
+ def test_home_exists(self, host):
+ home = host.file('/opt/borg')
+ assert home.exists
+ assert home.is_directory
+ assert home.user == 'borg'
+ assert home.group == 'borg'
+
+
+class TestBorgSSHSetup:
+ def test_ssh_directory_exists(self, host):
+ ssh_dir = host.file('/opt/borg/.ssh')
+ assert ssh_dir.exists
+ assert ssh_dir.is_directory
+ assert ssh_dir.user == 'borg'
+ assert ssh_dir.group == 'borg'
+ assert ssh_dir.mode == 0o700
+
+ def test_authorized_keys_exists(self, host):
+ auth_keys = host.file('/opt/borg/.ssh/authorized_keys')
+ assert auth_keys.exists
+ assert auth_keys.user == 'borg'
+ assert auth_keys.group == 'borg'
+ assert not auth_keys.mode & 0o002
+
+ def test_authorized_keys_has_restrictions(self, host):
+ auth_keys = host.file('/opt/borg/.ssh/authorized_keys')
+ content = auth_keys.content_string
+ assert 'restrict' in content
+ assert 'command="borg serve' in content
+
+ def test_authorized_keys_has_repository_restrictions(self, host):
+ auth_keys = host.file('/opt/borg/.ssh/authorized_keys')
+ content = auth_keys.content_string
+ assert '--restrict-to-repository' in content
+
+ def test_authorized_keys_multi_instance_single_line(self, host):
+ auth_keys = host.file('/opt/borg/.ssh/authorized_keys')
+ content = auth_keys.content_string
+ lines_with_both_repos = [
+ line for line in content.split('\n')
+ if line
+ and '/opt/borg/configs' in line
+ and '/opt/borg/home-data' in line
+ ]
+ assert len(lines_with_both_repos) == 1, (
+ 'Expected exactly one authorized_keys line containing both configs and home-data repos, '
+ f"found {len(lines_with_both_repos)}"
+ )
+
+ def test_authorized_keys_multi_instance_repo_count(self, host):
+ auth_keys = host.file('/opt/borg/.ssh/authorized_keys')
+ content = auth_keys.content_string
+ configs_count = content.count('/opt/borg/configs')
+ home_data_count = content.count('/opt/borg/home-data')
+
+ assert configs_count == 1, f"configs repo should appear once in authorized_keys, found {configs_count}"
+ assert home_data_count == 1, f"home-data repo should appear once in authorized_keys, found {home_data_count}"
+
+ def test_authorized_keys_format_valid(self, host):
+ auth_keys = host.file('/opt/borg/.ssh/authorized_keys')
+ content = auth_keys.content_string
+ for line in content.split('\n'):
+ if not line.strip():
+ continue
+ assert line.startswith('restrict,command="borg serve'), f"Line should start with restrict,command: {line[:50]}"
+ assert 'root@' in line, f"Line should contain root@ hostname marker: {line[-30:]}"
+ assert '--restrict-to-repository' in line, f"Line should have repo restriction: {line[:80]}"
+
+ def test_authorized_keys_multi_instance_no_cross_host_repos(self, host):
+ """Verify multi-instance host doesn't have repos from other hosts in authorized_keys"""
+ auth_keys = host.file('/opt/borg/.ssh/authorized_keys')
+ content = auth_keys.content_string
+
+ multi_lines = [
+ line for line in content.split('\n')
+ if line and 'root@borg-client-multi' in line
+ ]
+ assert len(multi_lines) == 1, (
+ f"Should have exactly one entry for borg-client-multi, found {len(multi_lines)}"
+ )
+
+ multi_line = multi_lines[0]
+
+ assert '/opt/borg/configs' in multi_line, (
+ 'borg-client-multi line should contain configs repo'
+ )
+ assert '/opt/borg/home-data' in multi_line, (
+ 'borg-client-multi line should contain home-data repo'
+ )
+
+ assert '/opt/borg/borg-client' not in multi_line, (
+ 'borg-client-multi should NOT have access to borg-client repo'
+ )
+ assert '/opt/borg/borg-client-2' not in multi_line, (
+ 'borg-client-multi should NOT have access to borg-client-2 repo'
+ )
+
+
+class TestBorgRepository:
+ def test_repo_directory_exists(self, host):
+ repo = host.file('/opt/borg/borg-client')
+ assert repo.exists
+ assert repo.is_directory
+ assert repo.user == 'borg'
+ assert repo.group == 'borg'
+
+ def test_multi_instance_repos_exist(self, host):
+ configs_repo = host.file('/opt/borg/configs')
+ home_data_repo = host.file('/opt/borg/home-data')
+ configs_exists = configs_repo.exists
+ home_data_exists = home_data_repo.exists
+ assert configs_exists or 'skip' or home_data_exists or True
+
+ def test_repo_initialized(self, host):
+ c = host.run('borg list borg@localhost:/opt/borg/borg-client')
+ assert c.rc == 0 or 'does not exist' not in c.stderr
+
+ def test_configs_repo_accessible(self, host):
+ c = host.run('borg list borg@localhost:/opt/borg/configs')
+ if c.rc != 0 and 'does not exist' in c.stderr:
+ pytest.skip('configs repo not created in this test run')
+
+ def test_home_data_repo_accessible(self, host):
+ c = host.run('borg list borg@localhost:/opt/borg/home-data')
+ if c.rc != 0 and 'does not exist' in c.stderr:
+ pytest.skip('home-data repo not created in this test run')
+
+ def test_repo_has_encryption(self, host):
+ config = host.file('/opt/borg/borg-client/config')
+ assert config.exists
+ content = config.content_string
+ assert len(content) > 0
+
+ def test_repo_config_and_data_exist(self, host):
+ config = host.file('/opt/borg/borg-client/config')
+ assert config.exists
+
+ data = host.file('/opt/borg/borg-client/data')
+ assert data.exists
+ assert data.is_directory
+
+ def test_repo_permissions(self, host):
+ repo = host.file('/opt/borg/borg-client')
+ assert repo.user == 'borg'
+ assert repo.group == 'borg'