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
115
116
117
118
119
120
121
122
|
"""Tests for borg server setup and repository configuration"""
import pytest
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"]
|