When a location uses SSH key auth, show a key card: paste an existing private key, or 'Generate keypair', then the card displays the public key to copy into the remote server's authorized_keys (with Copy/Delete). Wires to the ssh-key-set/generate/delete CLI; key mutations refresh locations.json so the card reflects state immediately. applySshAuthVisibility toggles the card vs the password field by auth mode. Private key only ever flows in (base64); only the public key is ever shown. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
114 lines
3.2 KiB
Bash
114 lines
3.2 KiB
Bash
#!/bin/bash
|
|
|
|
# LibrePortal-managed SSH key store for backup locations. Each location's
|
|
# private key lives at configs/backup/locations/<idx>/ssh.key. Public key
|
|
# is derived on the fly via ssh-keygen -y, so we never persist it
|
|
# separately. The CFG_BACKUP_LOC_<idx>_SSH_AUTH selector (key|password)
|
|
# is the only ssh-related value in the location.config file.
|
|
|
|
# Refresh locations.json so the editor reflects new key state (public key /
|
|
# "key set" status) right after a mutation. No-op if the generator isn't loaded.
|
|
backupSshKeyRefreshUi()
|
|
{
|
|
declare -f webuiGenerateBackupLocations >/dev/null 2>&1 && webuiGenerateBackupLocations >/dev/null 2>&1
|
|
return 0
|
|
}
|
|
|
|
backupSshKeyFile()
|
|
{
|
|
local idx="$1"
|
|
backupLocationSshKey "$idx"
|
|
}
|
|
|
|
backupSshKeyExists()
|
|
{
|
|
local idx="$1"
|
|
[[ -f "$(backupSshKeyFile "$idx")" ]]
|
|
}
|
|
|
|
# Decode a base64-encoded private key and write it to the location's key
|
|
# file. The frontend base64-encodes pasted multi-line keys so we can ship
|
|
# them through the existing single-line task command pipeline.
|
|
backupSshKeySet()
|
|
{
|
|
local idx="$1"
|
|
local key_b64="$2"
|
|
|
|
if [[ -z "$idx" || -z "$key_b64" ]]; then
|
|
isError "backupSshKeySet requires <idx> <base64-key>"
|
|
return 1
|
|
fi
|
|
|
|
backupLocationEnsureDir "$idx"
|
|
local owner
|
|
owner=$(backupLocationOwner)
|
|
local key_file
|
|
key_file=$(backupSshKeyFile "$idx")
|
|
|
|
local decoded
|
|
decoded=$(echo "$key_b64" | base64 -d 2>/dev/null)
|
|
if [[ -z "$decoded" ]]; then
|
|
isError "Failed to base64-decode the supplied key"
|
|
return 1
|
|
fi
|
|
|
|
echo "$decoded" | sudo tee "$key_file" >/dev/null
|
|
sudo chown "$owner":"$owner" "$key_file"
|
|
sudo chmod 0600 "$key_file"
|
|
|
|
if ! sudo -u "$owner" ssh-keygen -y -f "$key_file" >/dev/null 2>&1; then
|
|
isError "Key written but ssh-keygen can't read it — check the format (OpenSSH PEM: ed25519, rsa, ecdsa)"
|
|
return 1
|
|
fi
|
|
|
|
isSuccessful "SSH key saved for location $idx"
|
|
backupSshKeyRefreshUi
|
|
}
|
|
|
|
backupSshKeyGenerate()
|
|
{
|
|
local idx="$1"
|
|
if [[ -z "$idx" ]]; then
|
|
isError "backupSshKeyGenerate requires <idx>"
|
|
return 1
|
|
fi
|
|
|
|
backupLocationEnsureDir "$idx"
|
|
local owner
|
|
owner=$(backupLocationOwner)
|
|
local key_file
|
|
key_file=$(backupSshKeyFile "$idx")
|
|
|
|
if [[ -f "$key_file" ]]; then
|
|
sudo rm -f "$key_file" "${key_file}.pub"
|
|
fi
|
|
|
|
sudo -u "$owner" ssh-keygen -t ed25519 -f "$key_file" -N "" -C "libreportal-loc-${idx}" -q
|
|
sudo chmod 0600 "$key_file"
|
|
[[ -f "${key_file}.pub" ]] && sudo rm -f "${key_file}.pub" # we re-derive when needed
|
|
|
|
isSuccessful "Generated ed25519 keypair for location $idx"
|
|
isNotice "Public key (paste into the remote host's ~/.ssh/authorized_keys):"
|
|
backupSshKeyPublic "$idx"
|
|
backupSshKeyRefreshUi
|
|
}
|
|
|
|
backupSshKeyPublic()
|
|
{
|
|
local idx="$1"
|
|
local key_file
|
|
key_file=$(backupSshKeyFile "$idx")
|
|
[[ -f "$key_file" ]] || return 1
|
|
sudo -u "$(backupLocationOwner)" ssh-keygen -y -f "$key_file" 2>/dev/null
|
|
}
|
|
|
|
backupSshKeyDelete()
|
|
{
|
|
local idx="$1"
|
|
local key_file
|
|
key_file=$(backupSshKeyFile "$idx")
|
|
[[ -f "$key_file" ]] && sudo rm -f "$key_file" "${key_file}.pub"
|
|
isSuccessful "SSH key removed for location $idx"
|
|
backupSshKeyRefreshUi
|
|
}
|