feat(schluessel): erzeugen, importieren, exportieren (#012)
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>
This commit is contained in:
@@ -20,6 +20,8 @@ const REGELN = [
|
||||
"privateverwendung_pfad_gueltig",
|
||||
"publicverwendung_host_oder_gruppe",
|
||||
"benutzer_notfall_vollstaendig",
|
||||
"schluessel_slug_gueltig",
|
||||
"schluessel_geloescht_ohne_private_key",
|
||||
].sort();
|
||||
|
||||
const INDIZES = [
|
||||
@@ -90,6 +92,25 @@ describe("Datenbankregeln", () => {
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("laesst nur Slugs zu, die in Dateinamen passen (#012)", async () => {
|
||||
for (const slug of ["Gross", "mit leer", "../x", "a_b", "", "x".repeat(65)]) {
|
||||
await expect(schluesselAnlegen({ slug })).rejects.toThrow();
|
||||
}
|
||||
await expect(schluesselAnlegen({ slug: "backup-srv-pve01" })).resolves.toBeDefined();
|
||||
});
|
||||
|
||||
it("kennt „Private Key geloescht“ nur ohne Chiffrat (#014)", async () => {
|
||||
await expect(
|
||||
schluesselAnlegen({
|
||||
privatGeloeschtAm: new Date(),
|
||||
privatVerschluesselt: Buffer.from("x"),
|
||||
dekVerschluesselt: Buffer.from("y"),
|
||||
masterKeyVersion: 1,
|
||||
}),
|
||||
).rejects.toThrow();
|
||||
await expect(schluesselAnlegen({ privatGeloeschtAm: new Date() })).resolves.toBeDefined();
|
||||
});
|
||||
|
||||
it("laesst nur einen aktiven Instanz-Deployment-Key zu", async () => {
|
||||
await expect(schluesselAnlegen({ kategorie: "DIENST", instanzStandard: true })).rejects.toThrow();
|
||||
await schluesselAnlegen({ kategorie: "DEPLOYMENT", instanzStandard: true });
|
||||
|
||||
Reference in New Issue
Block a user