(feature) Add Django-managed SSH credentials
Add SSH credentials as first-class Django data so backup keys can be uploaded through the control panel instead of mounted into containers. Credentials can be selected globally or overridden per host. At runtime the selected key is materialized inside the container with restrictive file permissions and injected into the rsync SSH command via IdentityFile. Known hosts entries are handled the same way when configured. Add control panel views for creating and listing SSH keys, expose the fields in config forms and admin, document the workflow, and cover global and host credential selection with tests.
This commit is contained in:
@@ -20,8 +20,9 @@ from .forms import (
|
||||
ManualBackupForm,
|
||||
RetentionApplyForm,
|
||||
ScheduleConfigForm,
|
||||
SshCredentialForm,
|
||||
)
|
||||
from .models import BackupRun, GlobalConfig, HostConfig, ScheduleConfig, SnapshotRecord
|
||||
from .models import BackupRun, GlobalConfig, HostConfig, ScheduleConfig, SnapshotRecord, SshCredential
|
||||
from .retention import run_sql_retention_apply, run_sql_retention_plan
|
||||
from .snapshot_discovery import discover_snapshots, inspect_snapshot_discovery
|
||||
|
||||
@@ -57,6 +58,34 @@ def dashboard(request):
|
||||
return render(request, "pobsync_backend/dashboard.html", context)
|
||||
|
||||
|
||||
@staff_member_required
|
||||
def ssh_credentials(request):
|
||||
context = {
|
||||
"credentials": SshCredential.objects.order_by("name"),
|
||||
}
|
||||
return render(request, "pobsync_backend/ssh_credentials.html", context)
|
||||
|
||||
|
||||
@staff_member_required
|
||||
def create_ssh_credential(request):
|
||||
if request.method == "POST":
|
||||
form = SshCredentialForm(request.POST)
|
||||
if form.is_valid():
|
||||
credential = form.save()
|
||||
messages.success(request, f"SSH credential saved for {credential.name}.")
|
||||
return redirect("ssh_credentials")
|
||||
else:
|
||||
form = SshCredentialForm()
|
||||
|
||||
return render(
|
||||
request,
|
||||
"pobsync_backend/ssh_credential_form.html",
|
||||
{
|
||||
"form": form,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@staff_member_required
|
||||
def edit_global_config(request):
|
||||
global_config = GlobalConfig.objects.filter(name="default").first()
|
||||
|
||||
Reference in New Issue
Block a user