Files
sshkeyvault/docs/betrieb/sicherheit.md
T
florian.wildeandClaude Opus 5.5 3b28f73c95 docs(betrieb): Handbuch, Bedrohungsanalyse, geprobte Sicherung (#029)
Handbuch mit Bildern fuer alle Ablaeufe, darunter der Kern-
Anwendungsfall und der Deployment-Zugang fuer Claude Code.
Betriebsdoku zu Installation, authentik und Reverse Proxy sowie eine
Bedrohungsanalyse mit Notfallplan fuer den Fall, dass sshkv selbst
kompromittiert wird.

Sicherung und Wiederherstellung als Skripte, auf einem Wegwerf-Stapel
geprobt. Dabei fielen zwei Fehler auf: das Schema der Warteschlange
liess sich nicht zurueckspielen, und ein Abbruch ohne Transaktion
loeschte es halb. Jetzt nur Schema public, in einer Transaktion, mit
Pruefwert des Master-Keys. Der Worker startet nicht, wenn der
Master-Key nicht zur Datenbank passt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:46:38 +02:00

6.1 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 nur mit Passwort und TOTP; Rate-Limit gegen Raten.
  • 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.

Eine eingebaute Rotation des Deployment-Keys gibt es noch nicht (siehe docs/issues). Bis dahin ist Schritt 2 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.