Files
sshkeyvault/docs/betrieb/sicherheit.md
T
florian.wildeandClaude Opus 5.5 4219701b29 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>
2026-10-12 22:36:25 +02:00

6.8 KiB
Raw Blame History

Sicherheit und Bedrohungsanalyse

SSHKeyVault (sshkv) verwaltet die SSH-Zugänge zu Servern – und hat dafür selbst root-gleichen Zugriff auf alle verwalteten Hosts. Wer sshkv übernimmt, übernimmt die Infrastruktur. Diese Seite beschreibt, wie sshkv aufgebaut ist, um das zu erschweren, was trotzdem passieren kann und was im Ernstfall zu tun ist.

Was sshkv besitzt

Wert Wo Schutz
Deployment-Key (Private Key) Datenbank, verschlüsselt Envelope Encryption mit Master-Key; nur der Worker entschlüsselt
Private Keys von Service-Schlüsseln Datenbank, verschlüsselt wie oben; Anzeige nur für Admins mit frischer Bestätigung, protokolliert
Master-Key Datei auf dem Docker-Host, nur im Worker eingebunden Dateirechte 0400, nicht in der Datenbank, nicht im Image, nicht im Repo
SSHKV_APP_SECRET .env signiert Sitzungen, verschlüsselt TOTP-Geheimnis, SMTP-Passwort, Webhook-Geheimnis und Job-Transporte
Host-Keys der Hosts Datenbank öffentlich; schützen vor Man-in-the-Middle (strikte Prüfung)
Protokoll Datenbank append-only per Trigger, Hash-Kette, optional Syslog

Personen-Keys speichert sshkv nur als Public Key – ein Datenbankregel verhindert, dass dort je ein Private Key steht. Bootstrap-Passwörter werden nie gespeichert.

Aufbau, der Angriffe erschwert

  • Web und Worker getrennt. Der Webprozess kennt den Master-Key nicht und spricht kein SSH. Eine Lücke in der Weboberfläche allein entschlüsselt keine Private Keys; ein Test hält strukturell fest, dass der Webprozess nichts aus src/worker importiert und nur eine einzige Datei die verschlüsselten Felder liest.
  • Envelope Encryption (AES-256-GCM): je Private Key ein eigener Datenschlüssel, gebunden an ID und Fingerprint des Schlüssels. Ein Datenbank-Dump allein gibt keinen Schlüssel preis (Test).
  • Strikte Host-Key-Prüfung bei jeder Verbindung. Ein geänderter Host-Key bricht die Verbindung vor dem Senden von Zugangsdaten ab; Ersetzen nur mit Häkchen und frischer Bestätigung.
  • Dateien auf den Hosts schreibt sshkv als jeweiliger Zielbenutzer (runuser): Ein Symlink im Home eines Benutzers kann root nicht dazu bringen, /etc/shadow zu lesen oder zu überschreiben (Integrationstest).
  • Dry-Run mit optimistischer Sperre: Ausgerollt wird nur, was ein Mensch gesehen hat. Hat sich die Datei oder die Zuweisung seitdem geändert, bricht der Vorgang ab.
  • 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 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.

Was passiert, wenn sshkv kompromittiert wird?

Angreifer hat … Folge Gegenmaßnahme
nur ein Datenbank-Backup Hosts, Zuweisungen, Public Keys, Protokoll sichtbar; keine Private Keys Backup trotzdem vertraulich behandeln (verrät die Struktur der Infrastruktur)
Datenbank + Master-Key alle Private Keys inkl. Deployment-Key → root auf allen Hosts Master-Key getrennt aufbewahren; Notfallplan unten
die Weboberfläche als Admin (gestohlene Sitzung) kann Schlüssel zuweisen und ausrollen; Private Keys nur nach erneuter Anmeldung kurze Sitzungen (8 h), Re-Auth, Protokoll + Syslog zeigen jede Aktion
den Webprozess (Codeausführung) Datenbankzugriff, aber kein Master-Key Worker getrennt; Master-Key nur im Worker-Container
den Worker oder Docker-Host alles Host härten, nur internes Netz, Updates, Zugriff auf den Docker-Host streng begrenzen
einen verwalteten Host kann sshkv nicht angreifen; sieht nur den Public Key des Deployment-Keys —

Notfallplan „sshkv kompromittiert“

  1. Sofort: Netzwerkzugang zu sshkv sperren (Firewall/VPN), Container anhalten (docker compose stop). Die Hosts bleiben erreichbar – sshkv ist kein Teil des Logins.
  2. Deployment-Key auf allen Hosts entfernen: Auf jedem Host in ~sshkv/.ssh/authorized_keys (bzw. /root/.ssh/authorized_keys bei Anmeldeart root) die Zeile mit sshkv-deployment@… löschen und /etc/sudoers.d/sshkv entfernen. Mit einem Konfigurationsmanagement oder einer Schleife über die Hostliste (CSV-Export der Zuweisungen bzw. Hostliste).
  3. Ausgerollte Service-Keys tauschen: Jeder Private Key, den sshkv kannte, gilt als bekannt. Nach dem Wiederaufbau alle Service-Schlüssel rotieren (geführte Rotation) und alte widerrufen.
  4. Neu aufsetzen: neuer Master-Key, neues SSHKV_APP_SECRET, frische Datenbank oder geprüftes Backup; der Worker erzeugt einen neuen Deployment-Key; Hosts per Bootstrap neu aufnehmen.
  5. Protokoll auswerten: Syslog-Kopie (unveränderlich außerhalb von sshkv) mit dem Protokoll vergleichen; protokoll_kette_pruefen() zeigt manipulierte Zeilen.

Rotation des Deployment-Keys (Einstellungen → Instanz → „Deployment-Key rotieren“, nur Admin mit frischer Bestätigung): regelmäßig, oder wenn nur der Key abgeflossen sein kann – etwa ein verlorenes Backup samt Master-Key. Der neue Key kommt erst neben den alten, wird auf jedem Host geprüft und löst den alten dann ab; zuletzt wird der alte aus allen Blöcken entfernt und sein Private Key verworfen. Ist sshkv selbst kompromittiert, hilft das nicht – der Instanz ist dann nicht mehr zu trauen, Schritt 2 bleibt Handarbeit.

Betriebsregeln

  • Nur intern betreiben. Die Weboberfläche gehört ins interne Netz oder hinter ein VPN, nie ins Internet. Compose bindet standardmäßig nur an 127.0.0.1; ein Reverse Proxy mit TLS steht davor (siehe installation.md).
  • Docker-Host wie einen Bastion-Host behandeln: wenige Admins, SSH nur mit Schlüssel, Updates, keine anderen Dienste.
  • Master-Key getrennt sichern, Rechte 0400, nur für den Worker-Benutzer lesbar.
  • Syslog einschalten (SSHKV_SYSLOG_*), damit eine Kopie des Protokolls außerhalb von sshkv liegt.
  • Hosts: PermitRootLogin prohibit-password (sshkv zeigt das als Hinweis an), Anmeldeart „Dienstbenutzer“ bevorzugen – dann kann root-Login ganz aus bleiben.
  • Benachrichtigungen für Drift und geänderte Host-Keys aktivieren, damit Abweichungen auffallen.