(bugfix) Use service-level known_hosts for generated SSH keys

When a selected SSH credential has no pinned known_hosts entries, create
and use a pobsync service-level known_hosts file under POBSYNC_HOME/state.

Pass UserKnownHostsFile and StrictHostKeyChecking=accept-new to SSH so
unattended backups no longer depend on root's known_hosts or an
interactive shell session.

Keep pinned credential known_hosts behavior unchanged when entries are
configured explicitly.
This commit is contained in:
2026-05-19 20:01:39 +02:00
parent d3ffca1843
commit 8bd2a8ff1a
3 changed files with 36 additions and 2 deletions

View File

@@ -90,6 +90,7 @@ class DjangoConfigSourceTests(TestCase):
self.assertIn("-oBatchMode=yes", cfg["ssh"]["options"])
self.assertIn(f"-oIdentityFile={identity_file}", cfg["ssh"]["options"])
self.assertIn(f"-oUserKnownHostsFile={known_hosts}", cfg["ssh"]["options"])
self.assertNotIn("-oStrictHostKeyChecking=accept-new", cfg["ssh"]["options"])
self.assertEqual(cfg["ssh_credential"]["storage"], "database")
def test_host_ssh_credential_overrides_global_credential(self) -> None:
@@ -135,3 +136,25 @@ class DjangoConfigSourceTests(TestCase):
self.assertIn(f"-oIdentityFile={identity_file}", cfg["ssh"]["options"])
self.assertEqual(cfg["ssh_credential"]["storage"], "filesystem")
def test_missing_known_hosts_uses_service_accept_new_file(self) -> None:
with TemporaryDirectory() as tmp:
identity_file = Path(tmp) / "identity"
identity_file.write_text("PRIVATE KEY\n", encoding="utf-8")
identity_file.chmod(0o600)
credential = SshCredential.objects.create(name="backup-key", key_path=str(identity_file), public_key="PUBLIC")
GlobalConfig.objects.create(
name="default",
backup_root="/backups",
pobsync_home="/opt/pobsync",
default_ssh_credential=credential,
)
HostConfig.objects.create(host="web-01", address="web-01.example.test")
with override_settings(POBSYNC_HOME=str(Path(tmp) / "home")):
cfg = DjangoConfigSource().effective_config_for_host("web-01")
service_known_hosts = Path(tmp) / "home" / "state" / "known_hosts"
self.assertTrue(service_known_hosts.exists())
self.assertIn(f"-oUserKnownHostsFile={service_known_hosts}", cfg["ssh"]["options"])
self.assertIn("-oStrictHostKeyChecking=accept-new", cfg["ssh"]["options"])