pve-cluster: Phase 4 als Rolle – Admin-Gruppe/-Konten, Healer-Token, Benachrichtigungen, Firewall mit IPSET management (Tasks 4.1–4.4)
ci / test (push) Failing after 21s
ci / test (push) Failing after 21s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
5c790cc8d4
commit
81602373fc
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
# Persönliches Admin-Konto fertigstellen: Passwort, TOTP (Authenticator-App) und Recovery-Keys.
|
||||
# Läuft auf dem Admin-Laptop (Git-Bash). Das Konto selbst legt playbooks/cluster.yml an.
|
||||
#
|
||||
# platform/proxmox/scripts/pve-admin-user.sh r.rapp [pve44]
|
||||
#
|
||||
# Ergebnis (nie ins Repo):
|
||||
# <ENV> PVE_ADMIN_<NAME>_PASS wird ergänzt, falls noch nicht vorhanden
|
||||
# (Standard: C:/Users/r.rapp/it/proxmox/.env)
|
||||
# <ENVDIR>/tfa-<name>.txt otpauth-URI zum Eintippen/Scannen und die Recovery-Keys (0600)
|
||||
# Idempotent: Passwort nur beim ersten Lauf, TOTP/Recovery nur, wenn noch keine 2FA existiert.
|
||||
set -euo pipefail
|
||||
user=${1:?Benutzername ohne @pve}
|
||||
node=${2:-pve44}
|
||||
env_file=${PVE_ENV:-C:/Users/r.rapp/it/proxmox/.env}
|
||||
out_dir=$(dirname "$env_file")
|
||||
userid="${user}@pve"
|
||||
var="PVE_ADMIN_$(echo "$user" | tr 'a-z.-' 'A-Z__')_PASS"
|
||||
tfa_file="$out_dir/tfa-${user}.txt"
|
||||
|
||||
run() { ssh -T -o BatchMode=yes -o ConnectTimeout=10 "$node" "$@"; }
|
||||
|
||||
run "pveum user list --output-format json" | grep -q "\"userid\":\"$userid\"" \
|
||||
|| { echo "FEHLER: $userid gibt es nicht – erst playbooks/cluster.yml laufen lassen" >&2; exit 1; }
|
||||
|
||||
# 1. Passwort (einmalig erzeugen, in .env ablegen, nie ausgeben)
|
||||
if ! grep -qE "^${var}=" "$env_file"; then
|
||||
pw=$(openssl rand -base64 24 | tr -d '/+=' | cut -c1-24)
|
||||
printf '%s=%s\n' "$var" "$pw" >> "$env_file"
|
||||
printf '%s' "$pw" | run "p=\$(cat); pvesh set /access/password --userid $userid --password \"\$p\""
|
||||
echo "Passwort gesetzt und als $var in $env_file abgelegt"
|
||||
else
|
||||
echo "Passwort: $var ist schon in $env_file, unverändert"
|
||||
fi
|
||||
|
||||
# 2. TOTP und Recovery-Keys, nur wenn für das Konto noch keine 2FA existiert
|
||||
if run "pvesh get /access/tfa/$userid --output-format json" | grep -q '"type"'; then
|
||||
echo "2FA: für $userid existiert schon ein Eintrag, nichts geändert (siehe $tfa_file)"
|
||||
exit 0
|
||||
fi
|
||||
secret=$(openssl rand 20 | base32 | tr -d '=')
|
||||
uri="otpauth://totp/knaster:${userid}?secret=${secret}&issuer=knaster&digits=6&period=30&algorithm=SHA1"
|
||||
# aktuellen Code auf dem Knoten berechnen (Zeit des Knotens, kein Zusatzpaket)
|
||||
code=$(run "python3 -c \"
|
||||
import base64,hmac,struct,time,hashlib
|
||||
s='$secret'
|
||||
k=base64.b32decode(s+'='*(-len(s)%8))
|
||||
h=hmac.new(k,struct.pack('>Q',int(time.time())//30),hashlib.sha1).digest()
|
||||
o=h[-1]&15
|
||||
print('%06d'%((struct.unpack('>I',h[o:o+4])[0]&0x7fffffff)%1000000))\"")
|
||||
run "pvesh create /access/tfa/$userid --type totp --description 'Authenticator-App' --totp '$uri' --value $code" >/dev/null
|
||||
keys=$(run "pvesh create /access/tfa/$userid --type recovery --description 'Recovery-Keys (offline)' --output-format json" \
|
||||
| python3 -c 'import json,sys; print("\n".join(json.load(sys.stdin)["recovery"]))')
|
||||
umask 077
|
||||
{
|
||||
echo "Proxmox 2FA für $userid (angelegt $(date +%F))"
|
||||
echo
|
||||
echo "TOTP in die Authenticator-App eintragen (QR aus der URI erzeugen oder Secret manuell eingeben):"
|
||||
echo "$uri"
|
||||
echo "Secret: $secret"
|
||||
echo
|
||||
echo "Recovery-Keys (je einmal gültig, offline aufbewahren):"
|
||||
echo "$keys"
|
||||
} > "$tfa_file"
|
||||
echo "TOTP und Recovery-Keys angelegt: $tfa_file (0600). Anmeldung: Weboberfläche, Realm 'Proxmox VE authentication server'."
|
||||
Reference in New Issue
Block a user