feat(anmeldung): lokale Benutzerkonten mit Pflicht-TOTP (#035)

Ohne authentik gab es nur den Notfall-Admin – ein geteiltes Konto ohne
Rollen und ohne erkennbare Akteure im Audit-Log. Admins legen jetzt
lokale Konten an; sshkv erzeugt ein Einmal-Passwort, das bei der ersten
Anmeldung ersetzt wird, danach ist TOTP Pflicht.

Rollen, Sperren (beendet Sitzungen sofort) und Zurücksetzen unter
Einstellungen → Benutzer, nur für Admins mit frischer Bestätigung.
SSHKV_LOKALE_KONTEN=0 schaltet lokale Konten ab; der Notfall-Admin
bleibt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 22:36:25 +02:00
co-authored by Claude Opus 5.5
parent d9eec3d991
commit 4219701b29
41 changed files with 1295 additions and 109 deletions
+17 -3
View File
@@ -40,9 +40,13 @@ in die Verwaltung.
- **Mit authentik anmelden** – der Normalfall. Ihre Rolle (Leser, Operator, Admin) kommt aus den
authentik-Gruppen und wird bei jeder Anmeldung neu bestimmt.
- **Notfallzugang** – nur, wenn authentik ausfällt. Anmeldename, Passwort und ein Code aus einer
Authenticator-App. Bei der ersten Anmeldung richtet der Notfall-Admin den zweiten Faktor ein
(QR-Code scannen, Code bestätigen).
- **Lokales Konto** – ohne authentik oder zusätzlich dazu. Ein Admin legt das Konto an und gibt
Ihnen ein **Einmal-Passwort**. Bei der ersten Anmeldung (Abschnitt „Lokales Konto oder
Notfallzugang“) setzen Sie ein eigenes Passwort (mindestens 12 Zeichen) und richten den zweiten
Faktor ein: QR-Code mit einer Authenticator-App scannen, Code bestätigen. Danach immer
Anmeldename, Passwort und Code.
- **Notfallzugang** – nur, wenn authentik ausfällt. Gleiches Formular; der Notfall-Admin richtet
bei der ersten Anmeldung ebenfalls den zweiten Faktor ein.
Kritische Aktionen (Private Key anzeigen, Benutzer mit sudo anlegen, Massenwiderruf, Host-Key
ersetzen) verlangen eine **erneute Bestätigung**; sie gilt fünf Minuten.
@@ -225,6 +229,16 @@ weder ändern noch löschen; jeder Eintrag ist per Hash mit seinem Vorgänger ve
## 12. Einstellungen und Benachrichtigungen
**Benutzer** (Einstellungen → Instanz → „Konten verwalten“, nur Admin): lokale Konten anlegen –
sshkv erzeugt das Einmal-Passwort und zeigt es **genau einmal** –, Rollen ändern, Konten sperren
(beendet laufende Sitzungen sofort) und zurücksetzen (neues Einmal-Passwort, TOTP neu einrichten,
etwa nach verlorenem Telefon). Konten aus authentik erscheinen nach ihrer ersten Anmeldung; ihre
Rolle kommt aus den Gruppen, sie lassen sich hier nur sperren. Der Notfall-Admin ist
unveränderlich.
![Benutzer](bilder/benutzer-desktop.png)
Unter **Einstellungen** (ändern nur Admins) richten Sie Benachrichtigungen ein:
- **E-Mail** über SMTP – für Microsoft 365 vorbelegt (`smtp.office365.com:587`, STARTTLS).
Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

+13
View File
@@ -40,6 +40,19 @@ zeigt `db`, `web` und `worker` als *healthy*.
„auth_time fehlt oder ist zu alt“ – dann die Flow-Einstellung in authentik prüfen.
- [ ] Abmelden beendet die Sitzung (Zurück-Knopf zeigt keine Daten mehr).
## B2 · Lokale Konten (wenn ohne oder neben authentik)
- [ ] Einstellungen → „Konten verwalten“ → Konto anlegen (frische Bestätigung nötig) → das
Einmal-Passwort erscheint genau einmal; nach Neuladen ist es weg.
- [ ] Erste Anmeldung im privaten Browserfenster: eigenes Passwort setzen (unter 12 Zeichen wird
abgelehnt), TOTP einrichten, Rolle stimmt (unten links „über lokales Konto“).
- [ ] Sperren → die Sitzung im anderen Fenster endet beim nächsten Klick; Entsperren → wieder
anmeldbar.
- [ ] Zurücksetzen → neues Einmal-Passwort, TOTP wird neu eingerichtet.
- [ ] Audit-Log enthält Anlegen, Passwort gesetzt, Sperren – **kein** Passwort im Klartext.
- [ ] Mit `SSHKV_LOKALE_KONTEN=0` und `docker compose up -d`: lokales Konto kommt nicht mehr
hinein, der Notfall-Admin schon.
## C · Notfall-Admin
- [ ] `/anmelden` → „Notfallzugang“: Benutzer `notfall` + Passwort aus `.env` → TOTP-Einrichtung
+14
View File
@@ -71,6 +71,20 @@ Erneute Bestätigung vor kritischen Aktionen schickt `prompt=login` und `max_age
| Operator | zusätzlich Hosts verwalten, Host-Keys bestätigen, Schlüssel erzeugen, Public Keys ausrollen, abgleichen |
| Admin | zusätzlich Private Keys ausrollen/anzeigen/löschen, Zielkonten mit sudo, Massenwiderruf, Einstellungen, Vorlagen |
## Ohne authentik starten: lokale Konten
authentik ist nicht Pflicht. Ohne `SSHKV_OIDC_*` zeigt die Anmeldeseite nur das Formular für
lokale Konten und den Notfallzugang:
1. Als **Notfall-Admin** anmelden (TOTP einrichten).
2. Einstellungen → „Konten verwalten“ → für jede Person ein Konto mit passender Rolle anlegen und
das Einmal-Passwort auf sicherem Weg weitergeben.
3. Für den Alltag die eigenen Konten nutzen, den Notfall-Admin nur im Notfall – so bleibt im
Audit-Log erkennbar, wer was getan hat.
Später lässt sich authentik dazuschalten; lokale Konten und OIDC laufen nebeneinander.
`SSHKV_LOKALE_KONTEN=0` schaltet die lokalen Konten danach ab.
## Reverse Proxy (Beispiel Caddy)
```caddyfile
+5 -1
View File
@@ -37,7 +37,11 @@ Private Key steht. Bootstrap-Passwörter werden nie gespeichert.
- **Rollen:** Private Keys anzeigen, ausrollen und löschen, Deployment-Key, Zielkonten mit sudo und
Massenwiderruf nur für Admins; kritische Aktionen zusätzlich mit erneuter Anmeldung (5 Minuten).
Ohne passende authentik-Gruppe gibt es keinen Zugang, auch keinen lesenden.
- **Notfall-Admin** nur mit Passwort **und** TOTP; Rate-Limit gegen Raten.
- **Notfall-Admin und lokale Konten** nur mit Passwort **und** TOTP; Rate-Limit gegen Raten
(5 Fehlversuche je Anmeldename in 15 Minuten). Lokale Konten bekommen ein vom System erzeugtes
Einmal-Passwort, das bei der ersten Anmeldung ersetzt werden muss – Admins kennen die Passwörter
anderer nie. Sperren beendet Sitzungen sofort; `SSHKV_LOKALE_KONTEN=0` schaltet lokale Konten
ganz ab.
- **Weboberfläche:** Content-Security-Policy mit Nonce, `X-Frame-Options: DENY`, `Referrer-Policy:
no-referrer`, HttpOnly-/SameSite-Cookies, Secure hinter HTTPS; Server Actions mit Origin-Prüfung.
+32
View File
@@ -0,0 +1,32 @@
# #035 Lokale Benutzerkonten
**Status:** erledigt
**Meilenstein:** v1.0.0
**Labels:** sicherheit, backend, ui
**Geschätzt:** 2 h **Tatsächlich:** 0 h 55 min
## Ziel
sshkv ohne authentik in Betrieb nehmen können – mit eigenen Konten je Person statt eines geteilten Notfall-Admins, damit Rollen und Audit-Log stimmen. Später laufen lokale Konten und OIDC nebeneinander, oder die lokalen werden abgeschaltet.
## Aufgaben
- [x] Anmeldung mit Anmeldename, Passwort und Pflicht-TOTP für lokale Konten (gleicher Ablauf wie der Notfall-Admin)
- [x] Einmal-Passwort vom System, Pflichtwechsel bei der ersten Anmeldung (`passwortWechselNoetig`, Seite `/anmelden/passwort`)
- [x] Benutzerverwaltung `/einstellungen/benutzer`: anlegen, Rolle ändern, sperren/entsperren, zurücksetzen – Recht `benutzerVerwalten` (Admin + frische Bestätigung)
- [x] OIDC-Konten nur sperrbar; Notfall-Admin und eigenes Konto unveränderlich
- [x] Schalter `SSHKV_LOKALE_KONTEN` (Standard an), auch in `docker-compose.yml`
- [x] Protokoll für alle Schritte, nie mit Passwort
- [x] Doku: Handbuch, Installation („Ohne authentik starten“), Sicherheit, Abnahme-Liste
## Akzeptanzkriterien
- [x] DB-Tests: erste Anmeldung (Einmal-Passwort → eigenes → TOTP → angemeldet), schwache/unveränderte Passwörter, doppelte Namen, Rollen- und Sperrregeln, Zurücksetzen, abgeschaltet
- [x] E2E: Admin legt an, Person meldet sich zum ersten Mal an, Operator kommt nicht in die Benutzerverwaltung, Sperren beendet die Sitzung sofort
## Abhängigkeiten
#004
## Notizen / Entscheidungen
- **TOTP ist Pflicht** auch für lokale Konten (Entscheidung Florian, 12.10.2026).
- **Dauerhaft, aber abschaltbar** per `SSHKV_LOKALE_KONTEN=0` (Entscheidung Florian, 12.10.2026).
- **Admins wählen keine Passwörter für andere:** sshkv erzeugt ein Einmal-Passwort (4 × 5 Zeichen ohne verwechselbare Zeichen, gut 115 Bit), das genau einmal angezeigt wird.
- **12 Zeichen Mindestlänge** für eigene Passwörter – mit Pflicht-TOTP ausreichend; der Notfall-Admin behält 16.
- **Sperren beendet Sitzungen sofort** (`sitzungenGueltigAb`); eine Rollenänderung verwirft die gespeicherte Bestätigung.
- Lokale Konten bekommen keine E-Mail-Adresse, damit die OIDC-Verknüpfung per E-Mail nie ein lokales Konto übernehmen kann.