#012 Schlüssel erzeugen, importieren, exportieren #12

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

Ziel

Schlüsselliste und -formular: erzeugen (ed25519, rsa-4096), importieren (Public oder Paar), exportieren; Kategorien, Tags, Ablaufdatum.

Aufgaben

  • Liste mit Filter
  • Erzeugen-Dialog
  • Import mit Prüfung
  • Export Public Key
  • Schlüsseldetail-Gerüst mit Verwendungen

Akzeptanzkriterien

  • Private Keys erscheinen nie in Listen-Antworten

Abhängigkeiten

#006

Notizen / Entscheidungen

  • Migration 20261012100000_schluessel_vorgaenge: Vorgangsarten SCHLUESSEL_ERZEUGEN,
    SCHLUESSEL_IMPORTIEREN, PRIVATE_KEY_LOESCHEN (für #014 gleich mit), CHECK
    schluessel_slug_gueltig (^[a-z0-9-]{1,64}$, der Slug landet in Dateinamen) und
    schluessel_geloescht_ohne_private_key.
  • Erzeugen und Paar-Import laufen im Worker (src/worker/ablaeufe/schluessel.ts). Das Web
    prüft nur Metadaten (Slug frei, Person/Vorlage vorhanden, Ablauf nicht in der Vergangenheit)
    und reiht den Vorgang ein. Passphrase und importierter Private Key reisen wie das
    Bootstrap-Passwort mit SSHKV_APP_SECRET verschlüsselt im Job (geheim), nie in
    Vorgang.eingabe; der Worker löscht den Job danach. Der Worker prüft die Metadaten erneut.
  • Kategorie: Erzeugen und Paar-Import legen immer DIENST an. Personen-Keys speichert sshkv
    nie mit Private Key (DB-CHECK), Deployment-Keys verwaltet der Worker selbst. Der
    Public-Key-Import kennt PERSON und DIENST.
  • Passphrase: beim Erzeugen optional; gespeichert wird dann der passphrasengeschützte
    OpenSSH-Key (passphraseGeschuetzt = true). Beim Import dient sie nur zum Lesen von Public Key
    und Fingerprint und wird verworfen; gespeichert wird der Key so, wie er kam. Hinweis in der
    Oberfläche: „Für automatische Anmeldungen (Host-zu-Host) ungeeignet.“
  • Typ: RSA4096 nur bei genau 4096 Bit, sonst ANDERER (z. B. RSA-3072, ecdsa). Die RSA-
    Mindestlänge 2048 gilt beim Import.
  • Slug: aus dem Zweck abgeleitet (Umlaute gefaltet), bei Kollision -2, -3 …; ein
    ausdrücklich gewünschter Kurzname muss frei sein. Slug, Typ und Kommentar sind danach nicht
    mehr änderbar – sie stehen schon in Dateinamen und authorized_keys-Zeilen.
  • Status von Hand nur AKTIV ↔ ABGELAUFEN; ROTIERT/WIDERRUFEN setzen #023/#024,
    Deployment-Keys sind ausgenommen (sonst erzeugte der Worker beim Start einen neuen).
  • Ablaufdatum ohne Angabe aus Vorlage.standardLaufzeitTage.
  • „Private Key gespeichert?“ liest das Web aus masterKeyVersion (der CHECK
    schluessel_umschlag_vollstaendig koppelt sie an das Chiffrat) – das Chiffrat wird im Web
    nie selektiert.
  • Grenze abgesichert: tests/schluessel-grenze.test.ts verlangt für jeden zeilenliefernden
    prisma.schluessel.*-Aufruf außerhalb von src/worker ein select und verbietet
    schluessel: true als Relation; tests/schluessel.test.ts prüft, dass weder Vorgang,
    Protokoll noch pg-boss-Job nach Erzeugen/Import den Key oder die Passphrase enthalten.
  • Platzhalter für #016/#017: src/app/(app)/schluessel/[id]/PublicAusrollenAktion.tsx und
    PrivateAusrollenAktion.tsx, Props { schluesselId: string; darf: boolean }, rendern null.
  • Personen-Keys zeigen im Detail nur die Karte „Public Key ausgerollt auf“ (eine Private-Karte
    wäre immer leer).
  • Prototyp /schluessel/beispiel samt src/beispiel/schluessel.ts entfernt; die Übersicht
    (noch Prototyp, #026) verlinkt auf /schluessel.

Quelle: docs/issues/012-schluessel-verwalten.md – dort wird dieses Issue gepflegt.

## Ziel Schlüsselliste und -formular: erzeugen (ed25519, rsa-4096), importieren (Public oder Paar), exportieren; Kategorien, Tags, Ablaufdatum. ## Aufgaben - [x] Liste mit Filter - [x] Erzeugen-Dialog - [x] Import mit Prüfung - [x] Export Public Key - [x] Schlüsseldetail-Gerüst mit Verwendungen ## Akzeptanzkriterien - [x] Private Keys erscheinen nie in Listen-Antworten ## Abhängigkeiten #006 ## Notizen / Entscheidungen - **Migration `20261012100000_schluessel_vorgaenge`:** Vorgangsarten `SCHLUESSEL_ERZEUGEN`, `SCHLUESSEL_IMPORTIEREN`, `PRIVATE_KEY_LOESCHEN` (für #014 gleich mit), CHECK `schluessel_slug_gueltig` (`^[a-z0-9-]{1,64}$`, der Slug landet in Dateinamen) und `schluessel_geloescht_ohne_private_key`. - **Erzeugen und Paar-Import laufen im Worker** (`src/worker/ablaeufe/schluessel.ts`). Das Web prüft nur Metadaten (Slug frei, Person/Vorlage vorhanden, Ablauf nicht in der Vergangenheit) und reiht den Vorgang ein. Passphrase und importierter Private Key reisen wie das Bootstrap-Passwort mit `SSHKV_APP_SECRET` verschlüsselt im Job (`geheim`), nie in `Vorgang.eingabe`; der Worker löscht den Job danach. Der Worker prüft die Metadaten erneut. - **Kategorie:** Erzeugen und Paar-Import legen immer `DIENST` an. Personen-Keys speichert sshkv nie mit Private Key (DB-CHECK), Deployment-Keys verwaltet der Worker selbst. Der Public-Key-Import kennt `PERSON` und `DIENST`. - **Passphrase:** beim Erzeugen optional; gespeichert wird dann der passphrasengeschützte OpenSSH-Key (`passphraseGeschuetzt = true`). Beim Import dient sie nur zum Lesen von Public Key und Fingerprint und wird verworfen; gespeichert wird der Key so, wie er kam. Hinweis in der Oberfläche: „Für automatische Anmeldungen (Host-zu-Host) ungeeignet.“ - **Typ:** `RSA4096` nur bei genau 4096 Bit, sonst `ANDERER` (z. B. RSA-3072, ecdsa). Die RSA- Mindestlänge 2048 gilt beim Import. - **Slug:** aus dem Zweck abgeleitet (Umlaute gefaltet), bei Kollision `-2`, `-3` …; ein ausdrücklich gewünschter Kurzname muss frei sein. Slug, Typ und Kommentar sind danach nicht mehr änderbar – sie stehen schon in Dateinamen und authorized_keys-Zeilen. - **Status von Hand** nur `AKTIV` ↔ `ABGELAUFEN`; `ROTIERT`/`WIDERRUFEN` setzen #023/#024, Deployment-Keys sind ausgenommen (sonst erzeugte der Worker beim Start einen neuen). - **Ablaufdatum** ohne Angabe aus `Vorlage.standardLaufzeitTage`. - **„Private Key gespeichert?“** liest das Web aus `masterKeyVersion` (der CHECK `schluessel_umschlag_vollstaendig` koppelt sie an das Chiffrat) – das Chiffrat wird im Web nie selektiert. - **Grenze abgesichert:** `tests/schluessel-grenze.test.ts` verlangt für jeden zeilenliefernden `prisma.schluessel.*`-Aufruf außerhalb von `src/worker` ein `select` und verbietet `schluessel: true` als Relation; `tests/schluessel.test.ts` prüft, dass weder Vorgang, Protokoll noch pg-boss-Job nach Erzeugen/Import den Key oder die Passphrase enthalten. - **Platzhalter** für #016/#017: `src/app/(app)/schluessel/[id]/PublicAusrollenAktion.tsx` und `PrivateAusrollenAktion.tsx`, Props `{ schluesselId: string; darf: boolean }`, rendern `null`. - Personen-Keys zeigen im Detail nur die Karte „Public Key ausgerollt auf“ (eine Private-Karte wäre immer leer). - Prototyp `/schluessel/beispiel` samt `src/beispiel/schluessel.ts` entfernt; die Übersicht (noch Prototyp, #026) verlinkt auf `/schluessel`. --- Quelle: `docs/issues/012-schluessel-verwalten.md` – dort wird dieses Issue gepflegt.
florian.wilde added this to the v0.2.0 milestone 2026-10-12 15:12:39 +00:00
florian.wilde added the uibackend labels 2026-10-12 15:12:39 +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#12