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']
|