feat(protokoll): Eintraege vor dem Schreiben schwaerzen (#005)

Details und Diff laufen durch schwaerzen(), damit kein Private Key und
kein Passwort ins unveraenderliche Protokoll geraet - was dort einmal
steht, laesst sich per Trigger nicht mehr entfernen.

Der Wortstamm privat ist dafuer zu breit: er schwaerzte auch Pfade und
Verwendungszaehler, die das Protokoll gerade zeigen soll. Jetzt greifen
nur Felder, die den Schluessel selbst tragen, und jeder PEM-Block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 09:30:51 +02:00
co-authored by Claude Opus 5.5
parent b194054d30
commit 364c514b04
5 changed files with 99 additions and 11 deletions
+16
View File
@@ -96,3 +96,19 @@ describe("schwaerzen", () => {
expect(schwaerzen({ x: geteilt, y: geteilt })).toEqual({ x: { a: 1 }, y: { a: 1 } });
});
});
describe("harmlose Felder mit privat im Namen (#005)", () => {
it("bleiben lesbar", () => {
expect(
schwaerzen({
privateVerwendungen: 2,
privatePfad: "~/.ssh/id_ed25519_x",
privatGeloeschtAm: "2026-10-12",
}),
).toEqual({
privateVerwendungen: 2,
privatePfad: "~/.ssh/id_ed25519_x",
privatGeloeschtAm: "2026-10-12",
});
});
});
+49
View File
@@ -0,0 +1,49 @@
import { beforeEach, describe, expect, it } from "vitest";
import { prisma } from "@/lib/db";
import { protokollieren, protokollKettePruefen } from "@/server/services/protokoll";
import { datenbankLeeren } from "./hilfen/db";
/** Protokoll-Service (#005): schwaerzt vor dem Schreiben und laesst die Kette pruefen. */
const KEY =
"-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAA\n-----END OPENSSH PRIVATE KEY-----";
beforeEach(async () => {
await datenbankLeeren();
});
describe("protokollieren", () => {
it("schreibt Akteur, Aktion und Ergebnis", async () => {
await protokollieren({
akteur: { id: "b1", name: "Florian" },
aktion: "schluessel.erzeugt",
ergebnis: "ERFOLG",
hostName: "srv-pve01",
fingerprint: "SHA256:abc",
});
const [eintrag] = await prisma.protokoll.findMany();
expect(eintrag).toMatchObject({
akteurName: "Florian",
aktion: "schluessel.erzeugt",
hostName: "srv-pve01",
});
expect(await protokollKettePruefen()).toBeNull();
});
it("laesst keinen Private Key und kein Passwort hinein", async () => {
await protokollieren({
akteur: "System",
aktion: "test",
ergebnis: "FEHLER",
diff: `+ ${KEY}`,
details: { passwort: "geheim123", fehler: `Parser scheiterte an ${KEY}`, privatePfad: "~/.ssh/id_x" },
});
const [eintrag] = await prisma.protokoll.findMany();
const text = JSON.stringify(eintrag, (_, wert: unknown) =>
typeof wert === "bigint" ? String(wert) : wert,
);
expect(text).not.toContain("PRIVATE KEY");
expect(text).not.toContain("geheim123");
expect(text).toContain("~/.ssh/id_x");
});
});