From 8d872069976c5445c4396804ef3a0196f10eb14b Mon Sep 17 00:00:00 2001 From: Colin Wilk Date: Sat, 27 Jun 2026 23:01:10 +0200 Subject: feat: add per-repo SSH key support Add borg_ssh_key_per_repo option to generate unique SSH keypairs per (server, repo) combination. When enabled, each repository gets its own authorized_keys entry, enabling: - Independent --append-only settings per repository - Per-repo storage quotas --- molecule/default/tests/test_server_setup.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'molecule/default/tests/test_server_setup.py') diff --git a/molecule/default/tests/test_server_setup.py b/molecule/default/tests/test_server_setup.py index 3c494f7..5ec1520 100644 --- a/molecule/default/tests/test_server_setup.py +++ b/molecule/default/tests/test_server_setup.py @@ -1,5 +1,6 @@ """Tests for borg server setup and repository configuration""" import pytest +import re testinfra_hosts = ['borg-server'] @@ -62,8 +63,13 @@ class TestBorgSSHSetup: 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') + + restricted_repos = re.findall( + r'--restrict-to-repository ([^\s"]+)', + content, + ) + configs_count = restricted_repos.count('/opt/borg/configs') + home_data_count = restricted_repos.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}" @@ -71,11 +77,18 @@ class TestBorgSSHSetup: def test_authorized_keys_format_valid(self, host): auth_keys = host.file('/opt/borg/.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(('borg-client', 'borg-client-2', 'borg-client-multi', 'borg-client-nonroot')), f"Line should contain user@hostname marker: {line[-40:]}" + 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]}" def test_authorized_keys_multi_instance_no_cross_host_repos(self, host): @@ -85,7 +98,7 @@ class TestBorgSSHSetup: multi_lines = [ line for line in content.split('\n') - if line and 'root@borg-client-multi' in line + if line.rstrip().endswith('root@borg-client-multi') ] assert len(multi_lines) == 1, ( f"Should have exactly one entry for borg-client-multi, found {len(multi_lines)}" -- cgit v1.2.3