LibrePortal/scripts/ssh/host_access.sh
librelad afe0ef1c7e chore: drop duplicate doc files + fix wrong/stale comments
- docs: remove the docs/README.md index and docs/CONTRIBUTING.md pointer
  (duplicate filenames); the canonical contributing guide stays at
  docs/contributing/contributing.md. Clean tree, no name collisions.
- scripts/system/*: 6 helper headers + host_access.sh said the helpers
  install to /usr/local/sbin, but init.sh installs all of them to
  /usr/local/lib/libreportal/ (verified via initRootHelpers + the sudoers
  Cmnd_Alias). Corrected. The only remaining /usr/local/sbin is the legit
  PATH export in the task processor.
- frontend kernel: drop migration-era comments that are now false post-
  modularization (feature-registry 'passive/phase 0/unused', lifecycle
  'ctx.services lands with Phase 2', manifest 'scan generator lands') —
  describe current behaviour instead.

Comment-only edits to scripts/system/* — no footprint_version bump (no
behavioural change; bumping would force needless reinstalls).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-31 01:05:16 +01:00

121 lines
3.7 KiB
Bash

#!/bin/bash
# Admin SSH access to THIS host. Manages the install user's authorized_keys —
# paste a public key to grant access — and, behind a lockout guard, sshd
# password authentication. Everything here is on-demand only: nothing runs
# during install or deploy. LibrePortal is the *server* here, so the admin
# brings their own public key; we never handle their private key.
#
# All the privileged work (editing ~/.ssh and /etc/ssh/sshd_config) lives in the
# root-owned helper /usr/local/lib/libreportal/libreportal-ssh-access (runSshAccess), which
# also enforces the lockout guards in the trust boundary. These functions are the
# manager-side CLI/WebUI front for it: they shape arguments and print the UX.
# The user admins actually log in as (has sudo). Falls back to libreportal.
hostSshUser()
{
echo "${sudo_user_name:-libreportal}"
}
hostSshHome()
{
local u; u=$(hostSshUser)
[[ "$u" == "root" ]] && { echo "/root"; return; }
echo "/home/$u"
}
hostSshAuthKeysFile()
{
echo "$(hostSshHome)/.ssh/authorized_keys"
}
# Refresh the WebUI access snapshot after a change. No-op if generator absent.
hostSshRefreshUi()
{
declare -f webuiGenerateSshAccess >/dev/null 2>&1 && webuiGenerateSshAccess >/dev/null 2>&1
return 0
}
hostSshEnsureDir()
{
runSshAccess ensure-dir
}
# Count valid authorized public keys.
hostSshKeyCount()
{
runSshAccess key-count 2>/dev/null || echo 0
}
# True when sshd currently allows password authentication.
hostSshPasswordAuthEnabled()
{
[[ "$(runSshAccess pw-status 2>/dev/null)" != "off" ]]
}
# Add a base64-encoded PUBLIC key to the install user's authorized_keys.
hostSshKeyAdd()
{
local key_b64="$1"
[[ -z "$key_b64" ]] && { isError "hostSshKeyAdd requires <base64-public-key>"; return 1; }
local out rc
out=$(runSshAccess key-add "$key_b64")
rc=$?
case "$out" in
added) isSuccessful "SSH key authorized for $(hostSshUser)" ;;
already-authorized) isNotice "That key is already authorized." ;;
*)
[[ $rc -ne 0 ]] && { isError "Could not add key (not a valid SSH public key?)"; return 1; }
;;
esac
hostSshRefreshUi
}
# Remove the authorized key whose fingerprint matches $1. The helper guards
# against removing the last key while password auth is off (lockout).
hostSshKeyRemove()
{
local fp="$1"
[[ -z "$fp" ]] && { isError "hostSshKeyRemove requires <fingerprint>"; return 1; }
local out rc
out=$(runSshAccess key-remove "$fp" 2>&1)
rc=$?
if [[ $rc -eq 2 ]]; then
isError "Refusing to remove the last key while password login is disabled — you'd be locked out. Re-enable password login first."
return 1
fi
case "$out" in
removed) isSuccessful "Removed SSH key $fp" ;;
no-match) isNotice "No key matched fingerprint $fp" ;;
*) [[ $rc -ne 0 ]] && { isError "Could not remove key."; return 1; } ;;
esac
hostSshRefreshUi
}
# Enable/disable sshd password authentication. Disabling is guarded (helper-side):
# there must be at least one authorized key, or you'd lock yourself out.
hostSshSetPasswordAuth()
{
local want="$1" # on|off
case "$want" in
on|off) ;;
*) isError "hostSshSetPasswordAuth requires on|off"; return 1 ;;
esac
local out rc
out=$(runSshAccess pw-set "$want" 2>&1)
rc=$?
if [[ $rc -eq 2 ]]; then
isError "Refusing to disable password login with no authorized keys — add a key first or you'll be locked out."
return 1
fi
if [[ $rc -ne 0 ]]; then
isError "sshd config test failed — restored backup, no change made."
return 1
fi
isSuccessful "Password login ${want} (sshd reloaded)."
hostSshRefreshUi
}