#023 Geführte Rotation #23

Closed
opened 2026-10-12 15:12:45 +00:00 by florian.wilde · 0 comments
Owner

Ziel

Neuer Schlüssel an allen Verwendungen, Test, alter entfernt.

Aufgaben

  • „Rotieren“ auf der Schlüsselseite, Schrittfolge /schluessel/[id]/rotieren (wiederaufnehmbar)
  • Neuer Schlüssel gleichen Typs, Name „… (rotiert TT.MM.JJJJ)“, vorgaengerId = alter
  • Zuweisungen übernehmen: Public gleiche Ziele/Optionen, Private gleicher Host/Benutzer/Alias mit neuem Pfad
  • Dry-Run + Ausrollen, Verbindungstests, erst dann den alten widerrufen (#024) → ROTIERT
  • Personen-Key ohne Private Key: nur Hinweis „neuer Public Key nötig“
  • Rotationskette auf der Schlüsselseite (Vorgänger/Nachfolger verlinkt)

Akzeptanzkriterien

  • DB-Tests: Schritte, Reihenfolge, Rechte, Namen/Pfade (tests/rotation.test.ts)
  • Integrationstest: neuer Schlüssel funktioniert, alter von beiden Hosts weg, ssh <alias> geht weiter
  • E2E im Browser (tests/e2e/rotation.spec.ts), Screenshot rotation-desktop.png

Abhängigkeiten

#020, #024

Notizen / Entscheidungen

  • Fünf Schritte: Neuer Schlüssel → Zuweisungen übernehmen → Dry-Run & Ausrollen → Verbindungstests →
    Alten widerrufen. Der aktuelle Schritt wird aus der Datenbank errechnet (rotationsStand), deshalb
    lässt sich die Rotation jederzeit neu laden und fortsetzen; jeder Schritt ist idempotent.
  • Kette sofort: Der Worker setzt vorgaengerId schon beim Erzeugen (neues Feld in der
    Vorgangs-Eingabe) – auch ein abgebrochener Browser hinterlässt keinen verwaisten Schlüssel.
    vorgaengerId ist eindeutig: zwei gleichzeitige Rotationen scheitern verständlich.
  • Gleicher Alias, zwei Zuweisungen: privat.ts schreibt je Alias genau einen config-Eintrag, die
    jüngste Zuweisung gewinnt (an der Position der ersten). So zeigt ssh <alias> nach dem Ausrollen auf
    die neue Datei, während die alte bis zum Widerruf daneben liegt.
  • Neuer Pfad: <alter Pfad ohne -rJJJJMMTT>-rJJJJMMTT, bei Kollision mit laufender Nummer –
    auch entfernte Zuweisungen belegen einen Pfad (eindeutiger Index über alle Zustände).
  • Grün heißt aktuell: Der alte Schlüssel wird nur widerrufen, wenn für jede Private-Zuweisung mit
    Alias ein erfolgreicher VERBINDUNGSTEST nach dem letzten Ausrollen vorliegt (Server prüft das).
    Ohne Private-Zuweisung mit Alias entfällt der Test.
  • Abschluss: Widerruf aus #024 ohne Zielkonten (der Nachfolger nutzt sie weiter); ein aktiver
    Nachfolger macht aus WIDERRUFEN den Status ROTIERT.
  • Ablaufdatum: Der Nachfolger erbt es nur, wenn es in der Zukunft liegt. Eine Passphrase wird nicht
    übernommen (sshkv erzeugt ohne).
  • Rechte: schluesselVerwalten + publicKeyAusrollen, bei Private-Zuweisungen privateKeyAusrollen.
    Deployment-Key: eigene Rotation (später).

Quelle: docs/issues/023-rotation.md – dort wird dieses Issue gepflegt.

## Ziel Neuer Schlüssel an allen Verwendungen, Test, alter entfernt. ## Aufgaben - [x] „Rotieren“ auf der Schlüsselseite, Schrittfolge `/schluessel/[id]/rotieren` (wiederaufnehmbar) - [x] Neuer Schlüssel gleichen Typs, Name „… (rotiert TT.MM.JJJJ)“, `vorgaengerId` = alter - [x] Zuweisungen übernehmen: Public gleiche Ziele/Optionen, Private gleicher Host/Benutzer/Alias mit neuem Pfad - [x] Dry-Run + Ausrollen, Verbindungstests, erst dann den alten widerrufen (#024) → `ROTIERT` - [x] Personen-Key ohne Private Key: nur Hinweis „neuer Public Key nötig“ - [x] Rotationskette auf der Schlüsselseite (Vorgänger/Nachfolger verlinkt) ## Akzeptanzkriterien - [x] DB-Tests: Schritte, Reihenfolge, Rechte, Namen/Pfade (`tests/rotation.test.ts`) - [x] Integrationstest: neuer Schlüssel funktioniert, alter von beiden Hosts weg, `ssh <alias>` geht weiter - [x] E2E im Browser (`tests/e2e/rotation.spec.ts`), Screenshot `rotation-desktop.png` ## Abhängigkeiten #020, #024 ## Notizen / Entscheidungen - **Fünf Schritte:** Neuer Schlüssel → Zuweisungen übernehmen → Dry-Run & Ausrollen → Verbindungstests → Alten widerrufen. Der aktuelle Schritt wird aus der Datenbank errechnet (`rotationsStand`), deshalb lässt sich die Rotation jederzeit neu laden und fortsetzen; jeder Schritt ist idempotent. - **Kette sofort:** Der Worker setzt `vorgaengerId` schon beim Erzeugen (neues Feld in der Vorgangs-Eingabe) – auch ein abgebrochener Browser hinterlässt keinen verwaisten Schlüssel. `vorgaengerId` ist eindeutig: zwei gleichzeitige Rotationen scheitern verständlich. - **Gleicher Alias, zwei Zuweisungen:** `privat.ts` schreibt je Alias genau einen config-Eintrag, die jüngste Zuweisung gewinnt (an der Position der ersten). So zeigt `ssh <alias>` nach dem Ausrollen auf die neue Datei, während die alte bis zum Widerruf daneben liegt. - **Neuer Pfad:** `<alter Pfad ohne -rJJJJMMTT>-rJJJJMMTT`, bei Kollision mit laufender Nummer – auch entfernte Zuweisungen belegen einen Pfad (eindeutiger Index über alle Zustände). - **Grün heißt aktuell:** Der alte Schlüssel wird nur widerrufen, wenn für jede Private-Zuweisung mit Alias ein erfolgreicher `VERBINDUNGSTEST` nach dem letzten Ausrollen vorliegt (Server prüft das). Ohne Private-Zuweisung mit Alias entfällt der Test. - **Abschluss:** Widerruf aus #024 ohne Zielkonten (der Nachfolger nutzt sie weiter); ein aktiver Nachfolger macht aus `WIDERRUFEN` den Status `ROTIERT`. - Ablaufdatum: Der Nachfolger erbt es nur, wenn es in der Zukunft liegt. Eine Passphrase wird nicht übernommen (sshkv erzeugt ohne). - Rechte: `schluesselVerwalten` + `publicKeyAusrollen`, bei Private-Zuweisungen `privateKeyAusrollen`. Deployment-Key: eigene Rotation (später). --- Quelle: `docs/issues/023-rotation.md` – dort wird dieses Issue gepflegt.
florian.wilde added this to the v0.4.0 milestone 2026-10-12 15:12:45 +00:00
florian.wilde added the uibackend labels 2026-10-12 15:12:45 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: florian.wilde/sshkeyvault#23