(bugfix) Add SSH private key file upload
Allow SSH credentials to be created from an uploaded private key file as an alternative to pasting the key into a textarea. Use multipart form handling in the credential views so server-side keys can be imported without copy/paste wrapping or formatting damage. Cover the upload path with a view test while keeping existing pasted key validation behavior intact.
This commit is contained in:
@@ -147,11 +147,16 @@ class ManualBackupForm(forms.Form):
|
||||
|
||||
|
||||
class SshCredentialForm(forms.ModelForm):
|
||||
private_key_file = forms.FileField(
|
||||
required=False,
|
||||
help_text="Optional. Upload the private key file directly to avoid copy/paste formatting problems.",
|
||||
)
|
||||
private_key = forms.CharField(
|
||||
widget=forms.Textarea(attrs={"spellcheck": "false", "autocomplete": "off"}),
|
||||
required=False,
|
||||
help_text=(
|
||||
"Paste the complete unencrypted OpenSSH private key, including BEGIN/END lines. "
|
||||
"Use the matching public key in the field below only as a cross-check."
|
||||
"Leave empty when uploading a private key file."
|
||||
),
|
||||
)
|
||||
public_key = forms.CharField(
|
||||
@@ -171,7 +176,19 @@ class SshCredentialForm(forms.ModelForm):
|
||||
fields = ("name", "private_key", "public_key", "known_hosts", "notes")
|
||||
|
||||
def clean_private_key(self) -> str:
|
||||
private_key = normalize_private_key(self.cleaned_data["private_key"])
|
||||
uploaded_file = self.files.get("private_key_file")
|
||||
if uploaded_file:
|
||||
try:
|
||||
raw_private_key = uploaded_file.read().decode("utf-8")
|
||||
except UnicodeDecodeError as exc:
|
||||
raise forms.ValidationError("SSH private key files must be UTF-8 text files.") from exc
|
||||
else:
|
||||
raw_private_key = self.cleaned_data.get("private_key", "")
|
||||
|
||||
if not raw_private_key.strip():
|
||||
raise forms.ValidationError("Paste a private key or upload a private key file.")
|
||||
|
||||
private_key = normalize_private_key(raw_private_key)
|
||||
public_key = validate_ssh_private_key(private_key)
|
||||
self.derived_public_key = public_key
|
||||
return f"{private_key}\n"
|
||||
|
||||
Reference in New Issue
Block a user