feat(deploy): reset-password kann das Passwort aus der .env nehmen

--from-env liest WERKBAUM_MASTER_PASSWORT aus der .env, --stdin die erste
Zeile von stdin. Beides ausdruecklich zu verlangen und nie stillschweigend:
Sonst setzte ein versehentlicher Aufruf ein Passwort, das in einer Datei
steht, die man gerade nicht im Kopf hat.

--stdin war noetig, um den Fernteil ueberhaupt ohne Terminal pruefen zu
koennen; --from-env macht die Datei nuetzlich, wenn man sie ohnehin behaelt.
Beides in .env.example dokumentiert, samt dem Preis: Ein Klartext-Passwort auf
der Platte ist so sicher wie die Platte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mhoennig
2026-08-26 19:26:51 +02:00
co-authored by Claude Opus 5
parent 0e63165838
commit 22f942c6a5
+27 -4
View File
@@ -14,6 +14,14 @@
# #
# ssh-ziel ohne Angabe BACKEND_SSH aus .env (Vorlage: .env.example) # ssh-ziel ohne Angabe BACKEND_SSH aus .env (Vorlage: .env.example)
# --no-restart Hash schreiben, Dienst nicht neu starten # --no-restart Hash schreiben, Dienst nicht neu starten
# --stdin Passwort aus der ersten Zeile von stdin lesen, statt zu
# fragen. Für Automatisierung — und dafür, dass ein Passwort
# aus einer Datei kommen kann, ohne über ein Terminal (und
# dessen Echo) zu laufen. Ohne Terminal ist das der einzige Weg.
# --from-env Passwort aus WERKBAUM_MASTER_PASSWORT in der .env nehmen.
# Ausdrücklich zu verlangen und nie stillschweigend: Sonst
# setzte ein versehentlicher Aufruf ein Passwort, das in einer
# Datei steht, die man gerade nicht im Kopf hat.
# #
# Das Passwort verlässt diesen Rechner nur über die SSH-Verbindung und wird # Das Passwort verlässt diesen Rechner nur über die SSH-Verbindung und wird
# **nur als Hash** gespeichert (`<BACKEND_DIR>/env`, Modus 600). Danach prüft # **nur als Hash** gespeichert (`<BACKEND_DIR>/env`, Modus 600). Danach prüft
@@ -26,9 +34,13 @@ set -euo pipefail
SSH_TARGET="" SSH_TARGET=""
RESTART=1 RESTART=1
VON_STDIN=0
AUS_ENV=0
for arg in "$@"; do for arg in "$@"; do
case "$arg" in case "$arg" in
--no-restart) RESTART=0 ;; --no-restart) RESTART=0 ;;
--stdin) VON_STDIN=1 ;;
--from-env) AUS_ENV=1 ;;
-h|--help) -h|--help)
awk 'NR>2 { if ($0 ~ /^#/) { sub(/^# ?/, ""); print } else exit }' "$0" awk 'NR>2 { if ($0 ~ /^#/) { sub(/^# ?/, ""); print } else exit }' "$0"
exit 0 ;; exit 0 ;;
@@ -54,10 +66,21 @@ case "$DIR" in /*) DIR_SH="$DIR" ;; *) DIR_SH="\$HOME/$DIR" ;; esac
echo "==> Master-Passwort für ${SSH_TARGET}" echo "==> Master-Passwort für ${SSH_TARGET}"
echo " (die Dokumentenliste; alles andere ist über die Dokument-UUID erreichbar)" echo " (die Dokumentenliste; alles andere ist über die Dokument-UUID erreichbar)"
# Verdeckt einlesen, zweimal. `read -s` gibt es in bash überall; auf ein if [ "$AUS_ENV" -eq 1 ]; then
# Terminal angewiesen ist es nicht, deshalb der Hinweis bei Rohr-Eingabe. PASSWORT="$(env_value WERKBAUM_MASTER_PASSWORT)"
if [ -z "$PASSWORT" ]; then
echo "WERKBAUM_MASTER_PASSWORT steht nicht in ${ENV_FILE}." >&2
exit 2
fi
echo " Passwort aus ${ENV_FILE} (${#PASSWORT} Zeichen)"
elif [ "$VON_STDIN" -eq 1 ]; then
# Erste Zeile von stdin. Keine Wiederholung: Wer es aus einer Datei liefert,
# vertippt sich nicht — er hat ein anderes Problem, wenn der Wert falsch ist.
IFS= read -r PASSWORT || true
else
# Verdeckt einlesen, zweimal.
if [ ! -t 0 ]; then if [ ! -t 0 ]; then
echo "Kein Terminal — dieses Skript fragt nach und braucht eines." >&2 echo "Kein Terminal — mit --stdin geht es auch ohne." >&2
exit 2 exit 2
fi fi
printf ' Neues Passwort: ' printf ' Neues Passwort: '
@@ -65,11 +88,11 @@ read -rs PASSWORT
printf '\n Wiederholen: ' printf '\n Wiederholen: '
read -rs PASSWORT2 read -rs PASSWORT2
printf '\n' printf '\n'
if [ "$PASSWORT" != "$PASSWORT2" ]; then if [ "$PASSWORT" != "$PASSWORT2" ]; then
echo "Die beiden Eingaben sind verschieden — nichts geändert." >&2 echo "Die beiden Eingaben sind verschieden — nichts geändert." >&2
exit 1 exit 1
fi fi
fi
if [ -z "$PASSWORT" ]; then if [ -z "$PASSWORT" ]; then
echo "Leeres Passwort — nichts geändert." >&2 echo "Leeres Passwort — nichts geändert." >&2
exit 1 exit 1