Drift, ablaufende und abgelaufene Schluessel, unerreichbare Hosts und
geaenderte Host-Keys sollen auffallen, ohne dass jemand taeglich in die
Oberflaeche schaut. Versand per SMTP (Microsoft 365, STARTTLS) und per
Webhook mit HMAC-Signatur, eingestellt unter /einstellungen.
Die Anlaesse liest der Worker aus der Datenbank, statt sie im Abgleich
auszuloesen: der Abgleich-Ablauf bleibt unberuehrt, und ein verpasster
Lauf holt sich der naechste. Ein Versandprotokoll (Zustellung) mit
Anlass-Fingerabdruck verhindert Doppelmeldungen und haelt Fehlschlaege
fuer begrenzte Wiederholungen fest. Taeglich eine Zusammenfassung,
geaenderte Host-Keys im Fuenf-Minuten-Takt sofort.
Versand und Testnachricht laufen im Worker, damit der Webprozess keinen
Weg zu Mailserver oder Webhook-Ziel braucht. Passwort und Geheimnis
liegen nur verschluesselt in der Datenbank; die Seite zeigt "gesetzt".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ein Schlüssel soll nach Projektende mit einem Klick von allen Hosts
verschwinden – aber nie als „widerrufen“ gelten, solange er irgendwo noch
liegt. Deshalb ein Zwischenzustand (widerrufEingeleitetAm): Verwendungen
werden zum Entfernen vorgemerkt, der bestehende Dry-Run mit Hash-Sperre
zeigt und schreibt die Änderungen, und erst wenn keine Verwendung mehr
offen ist, setzt der Abschluss WIDERRUFEN (bzw. ROTIERT für #023).
Scheitert ein Host, bleibt der Schlüssel im Zwischenzustand und die Seite
nennt die offenen Ziele.
Zielkonten lassen sich optional mit entfernen, aber erst nach den
Schlüsseln und nie, wenn ein anderer aktiver Schlüssel sie noch nutzt.
Massenwiderruf (Admin, frische Bestätigung) nutzt einen gemeinsamen
Dry-Run und protokolliert je Schlüssel. Abgelaufene Schlüssel erscheinen
im Filter „abgelaufen“ und bieten den Widerruf an – entfernt wird nie
automatisch.
Migration 20261012130000_widerruf_eingeleitet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ein Abgleich liest je Host alle authorized_keys in einem SSH-Aufruf,
als jeweiliger Benutzer, und vergleicht sie mit dem Soll: fehlende,
von Hand geaenderte und unbekannte Keys, falsche Rechte, beschaedigte
Bloecke und veraenderte Private Keys. Befunde werden geoeffnet und
wieder geschlossen, Zustaende von Verwendungen und Host nachgezogen.
Auf dem Host aendert der Abgleich nichts.
Der Zeitplan liegt in pg-boss und feuert auch bei mehreren Workern
nur einmal. Auf der Hostseite stehen Abweichungen und der Ist-Zustand
je Benutzer; unbekannte Keys lassen sich uebernehmen - nur bekannt
machen oder mit Dry-Run in den verwalteten Block holen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ein Durchgang fuer den Kern-Anwendungsfall: Vorlage und Zweck, Host A,
Host B mit Zielbenutzer, Zusammenfassung, dann Schluessel erzeugen,
Benutzer anlegen, zuweisen, Dry-Run, ausrollen und Verbindung testen.
Die Vorlage Deployment-Zugang fuellt deploy, Ablaufdatum, from= und
Alias vor; bei root als Ziel warnt der Assistent ausdruecklich.
Die Ausfuehrung ist wiederaufnehmbar: wird mittendrin eine frische
Bestaetigung fuer das Zielkonto noetig, geschieht sie in einem neuen
Tab, und nichts wird doppelt angelegt. Zielkonten laufen als eigene
Vorgaenge (neue Migration) und merken sich, ob sshkv den Benutzer
angelegt hat - nur dann loescht ein Widerruf ihn spaeter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Personen lassen sich anlegen, bearbeiten und archivieren; ihr Detail
zeigt ihre Schluessel. Unter "Meine Schluessel" hinterlegt jede Rolle
eigene Public Keys (Freigabe Frage 4), wirksam erst nach Zuweisung
durch einen Operator oder Admin.
Warum so:
- Die eigene Person entsteht beim ersten Aufruf oder wird verknuepft:
per benutzerId, sonst per E-Mail - aber nur, wenn der OIDC-Anbieter
die Adresse bestaetigt hat. Dafuer merkt sich Benutzer jetzt
emailBestaetigt (Migration); sonst koennte jemand mit selbst
gewaehlter Adresse die Keys einer fremden Person sehen.
- Die Self-Service-Services nehmen nur den angemeldeten Benutzer und
leiten die Person selbst ab; fremde Schluessel-IDs gelten als nicht
vorhanden.
- Entfernen nur fuer eigene, selbst hinterlegte Keys ohne Verwendung,
bedingt geloescht, damit eine gleichzeitige Zuweisung nicht per
Cascade verschwindet.
- Archivieren statt Loeschen: wer bis wann welchen Key hatte, bleibt
nachvollziehbar.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Schluessel werden jetzt verwaltet statt nur im Prototyp gezeigt: Liste
mit Filter, Anlegen (erzeugen oder importieren), Detail nach dem
Prototyp aus #002, Bearbeiten der Metadaten und Download <slug>.pub.
Warum so:
- Erzeugen und Import eines Paars laufen als Vorgang im Worker, weil
nur er den Master-Key hat. Passphrase und importierter Private Key
reisen wie das Bootstrap-Passwort mit SSHKV_APP_SECRET verschluesselt
im Job, nie in Vorgang.eingabe; der Worker loescht den Job danach.
- Ein reiner Public Key ist kein Geheimnis und wird direkt im Web
angelegt, mit verstaendlicher Meldung bei einem Duplikat.
- Das Web liest nie das Chiffrat: ob ein Private Key gespeichert ist,
verraet masterKeyVersion (per CHECK an das Chiffrat gekoppelt). Ein
struktureller Test verlangt fuer jede zeilenliefernde Abfrage auf
Schluessel ausserhalb des Workers ein festes select.
- Migration: Vorgangsarten fuer Erzeugen, Import und (fuer #014) das
Loeschen des Private Keys; CHECKs fuer den Slug (landet in
Dateinamen) und "geloescht nur ohne Chiffrat".
- Platzhalter PublicAusrollenAktion/PrivateAusrollenAktion fuer #016/#017.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SSHKV_SEED_DEMO=1 legt sechs Demo-Hosts, drei Gruppen und einen Kunden an,
damit Entwicklung, Screenshots und Handbuch ohne echte Server auskommen.
Nur mit der Variable, damit eine echte Instanz nie Phantom-Hosts bekommt;
Upsert nach Name haelt den Seed idempotent.
Das Screenshot-Skript kennt jetzt Seiten mit wechselnder ID (folgen: erster
passender Link) und nimmt Hostliste und Hostdetail auf.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Alle Modelle fuer die fuenf Phasen in einer Migration, damit spaetere
Phasen keine Umbauten an Kerntabellen brauchen. Was auch an der
Service-Schicht vorbei gelten muss, steht als CHECK, partieller Index
oder Trigger in der Datenbank: Personen-Keys ohne Private Key, genau
ein Instanz-Deployment-Key, ein vertrauter Host-Key je Algorithmus,
shell-sichere Zielbenutzer und Pfade.
Das Protokoll ist append-only und per Hash-Kette verbunden; den Hash
berechnet ein Trigger, damit keine Zeile ohne Verkettung entstehen
kann (#005 baut darauf auf).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Konfiguration aus Laufzettel uebernommen, damit alle Projekte gleich
gebaut und geprueft werden. Entwicklungsdatenbank auf 5436, weil 5433
und 5434 von ProxLedger und Laufzettel belegt sind.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>