backups: Generate SSH client key if needed

Tests:

- Click on Add Remote Backup Location. Logs show that SSH client key is
  generated. The private key is readable only by plinth user.

- Go back, and click on Add Remote Backup Location again. Logs show that SSH
  client key already exists.

Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
James Valleroy 2025-12-06 12:06:21 -05:00 committed by Sunil Mohan Adapa
parent 33d05ef5be
commit 156d0b761f
No known key found for this signature in database
GPG Key ID: 43EA1CFF0AA7C5F2
2 changed files with 24 additions and 1 deletions

View File

@ -137,6 +137,20 @@ def get_known_hosts_path():
return pathlib.Path(cfg.data_dir) / '.ssh' / 'known_hosts'
def generate_ssh_client_auth_key():
"""Generate SSH client authentication keypair, if needed."""
key_path = pathlib.Path(cfg.data_dir) / '.ssh' / 'id_ed25519'
if not key_path.exists():
logger.info('Generating SSH client key %s for FreedomBox service',
key_path)
subprocess.run(
['ssh-keygen', '-t', 'ed25519', '-N', '', '-f',
str(key_path)], stdout=subprocess.DEVNULL, check=True)
else:
logger.info('SSH client key %s for FreedomBox service already exists',
key_file)
def is_ssh_hostkey_verified(hostname):
"""Check whether SSH Hostkey has already been verified.

View File

@ -24,7 +24,8 @@ from plinth.errors import PlinthError
from plinth.modules import backups, storage
from plinth.views import AppView
from . import (SESSION_PATH_VARIABLE, api, errors, forms, get_known_hosts_path,
from . import (SESSION_PATH_VARIABLE, api, errors, forms,
generate_ssh_client_auth_key, get_known_hosts_path,
is_ssh_hostkey_verified, privileged)
from .decorators import delete_tmp_backup_file
from .repository import (BorgRepository, SshBorgRepository, get_instance,
@ -358,6 +359,14 @@ class AddRemoteRepositoryView(FormView):
form_class = forms.AddRemoteRepositoryForm
template_name = 'backups_add_remote_repository.html'
def get(self, *args, **kwargs):
"""Handle GET requests.
Generate SSH client authentication key if necessary.
"""
generate_ssh_client_auth_key()
return super().get(*args, kwargs)
def get_context_data(self, **kwargs):
"""Return additional context for rendering the template."""
context = super().get_context_data(**kwargs)