aboutsummaryrefslogtreecommitdiffstats
path: root/molecule/default/tests/test_server_setup.py
blob: 590a33c8625ddcebe7fa63489674ce631ca23a88 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
"""Tests for borg server setup and repository configuration"""
import pytest
import re

testinfra_hosts = ['borg-server', 'borg-server-2']

SERVER_CONFIGS = {
    'borg-server': {
        'user': 'borg',
        'home': '/opt/borg',
        'client_repo': 'borg-client',
    },
    'borg-server-2': {
        'user': 'backupserver',
        'home': '/var/backups',
        'client_repo': 'borg-client-2',
    },
}


@pytest.fixture
def config(host):
    return SERVER_CONFIGS[host.backend.hostname]


class TestBorgUser:
    def test_user_exists(self, host, config):
        user = host.user(config['user'])
        assert user.exists
        assert user.home == config['home']

    def test_home_exists(self, host, config):
        home = host.file(config['home'])
        assert home.exists
        assert home.is_directory
        assert home.user == config['user']
        assert home.group == config['user']


class TestBorgSSHSetup:
    def test_ssh_directory_exists(self, host, config):
        ssh_dir = host.file(f"{config['home']}/.ssh")
        assert ssh_dir.exists
        assert ssh_dir.is_directory
        assert ssh_dir.user == config['user']
        assert ssh_dir.group == config['user']
        assert ssh_dir.mode == 0o700

    def test_authorized_keys_exists(self, host, config):
        auth_keys = host.file(f"{config['home']}/.ssh/authorized_keys")
        assert auth_keys.exists
        assert auth_keys.user == config['user']
        assert auth_keys.group == config['user']
        assert not auth_keys.mode & 0o002

    def test_authorized_keys_has_restrictions(self, host, config):
        auth_keys = host.file(f"{config['home']}/.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, config):
        auth_keys = host.file(f"{config['home']}/.ssh/authorized_keys")
        content = auth_keys.content_string
        assert '--restrict-to-repository' in content

    def test_authorized_keys_format_valid(self, host, config):
        auth_keys = host.file(f"{config['home']}/.ssh/authorized_keys")
        content = auth_keys.content_string
        valid_hosts = (
            'borg-client',
            'borg-client-2',
            'borg-client-multi',
            'borg-client-nonroot',
            'borg-client-multi-keys',
        )
        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 '@' in line and line.rstrip().endswith(valid_hosts), f"Line should contain user@hostname marker: {line[-40:]}"
            assert '--restrict-to-repository' in line, f"Line should have repo restriction: {line[:80]}"


class TestBorgRepository:
    def test_repo_directory_exists(self, host, config):
        repo = host.file(f"{config['home']}/{config['client_repo']}")
        assert repo.exists
        assert repo.is_directory
        assert repo.user == config['user']
        assert repo.group == config['user']

    def test_repo_initialized(self, host, config):
        c = host.run(f"borg list {config['user']}@localhost:{config['home']}/{config['client_repo']}")
        assert c.rc == 0 or 'does not exist' not in c.stderr

    def test_repo_has_encryption(self, host, config):
        repo_config = host.file(f"{config['home']}/{config['client_repo']}/config")
        assert repo_config.exists
        content = repo_config.content_string
        assert len(content) > 0

    def test_repo_config_and_data_exist(self, host, config):
        repo_config = host.file(f"{config['home']}/{config['client_repo']}/config")
        assert repo_config.exists

        data = host.file(f"{config['home']}/{config['client_repo']}/data")
        assert data.exists
        assert data.is_directory

    def test_repo_permissions(self, host, config):
        repo = host.file(f"{config['home']}/{config['client_repo']}")
        assert repo.user == config['user']
        assert repo.group == config['user']