Add filesystem-backed SSH credentials for the native systemd deployment path. Generated keys are stored below POBSYNC_HOME with 0600 permissions, while Django keeps the public key, fingerprint, path, and selection metadata. Add a Django SSH key generation view, delete action for unused generated keys, and a management command used by the installer to ensure a default backup key exists. Update runtime config to use generated key paths directly as IdentityFile, extend host checks to verify key readability, and keep legacy uploaded keys available for compatibility.
48 lines
1.9 KiB
Python
48 lines
1.9 KiB
Python
from __future__ import annotations
|
|
|
|
from django.core.management.base import BaseCommand, CommandError
|
|
|
|
from pobsync_backend.models import GlobalConfig, SshCredential
|
|
from pobsync_backend.ssh_keys import SshKeyError, generate_ssh_key
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = "Ensure a filesystem-backed SSH key exists for pobsync backups."
|
|
|
|
def add_arguments(self, parser):
|
|
parser.add_argument("--name", default="default", help="Credential name to create or reuse.")
|
|
parser.add_argument("--key-type", default="ed25519", choices=("ed25519", "rsa"))
|
|
parser.add_argument(
|
|
"--set-global-default",
|
|
action="store_true",
|
|
help="Set this key as default on the default global config when it exists.",
|
|
)
|
|
|
|
def handle(self, *args, **options):
|
|
name = options["name"]
|
|
credential, created = SshCredential.objects.get_or_create(
|
|
name=name,
|
|
defaults={
|
|
"key_type": options["key_type"],
|
|
"notes": "Generated by pobsync installer.",
|
|
},
|
|
)
|
|
|
|
if not credential.key_path and not credential.private_key:
|
|
try:
|
|
generate_ssh_key(credential, key_type=options["key_type"])
|
|
except SshKeyError as exc:
|
|
raise CommandError(str(exc)) from exc
|
|
created = True
|
|
|
|
if options["set_global_default"]:
|
|
global_config = GlobalConfig.objects.filter(name="default").first()
|
|
if global_config is not None and global_config.default_ssh_credential_id is None:
|
|
global_config.default_ssh_credential = credential
|
|
global_config.save(update_fields=["default_ssh_credential", "updated_at"])
|
|
|
|
action = "created" if created else "exists"
|
|
self.stdout.write(self.style.SUCCESS(f"SSH credential {action}: {credential.name}"))
|
|
if credential.public_key:
|
|
self.stdout.write(credential.public_key)
|