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
+13 -2
View File
@@ -1,6 +1,7 @@
import type { Prisma } from "@/generated/prisma/client";
import type { ProtokollErgebnis } from "@/generated/prisma/enums";
import { prisma } from "@/lib/db";
import { schwaerzen } from "@/lib/protokoll-schwaerzen";
/**
* Schreibt einen Eintrag ins revisionssichere Protokoll (#005).
@@ -34,8 +35,18 @@ export async function protokollieren(
hostName: eintrag.hostName ?? null,
zielbenutzer: eintrag.zielbenutzer ?? null,
fingerprint: eintrag.fingerprint ?? null,
diff: eintrag.diff ?? null,
details: (eintrag.details as Prisma.InputJsonValue | undefined) ?? undefined,
// Auch der Diff: er stammt aus Dateien auf den Hosts, und eine authorized_keys-Datei
// kann versehentlich einen eingefuegten Private Key enthalten.
diff: eintrag.diff ? (schwaerzen(eintrag.diff) as string) : null,
details: eintrag.details ? (schwaerzen(eintrag.details) as Prisma.InputJsonValue) : undefined,
},
});
}
/** Prueft die Hash-Kette in der Datenbank; liefert die erste fehlerhafte ID oder null. */
export async function protokollKettePruefen(): Promise<bigint | null> {
const [zeile] = await prisma.$queryRaw<
{ ergebnis: bigint | null }[]
>`SELECT protokoll_kette_pruefen() AS ergebnis`;
return zeile?.ergebnis ?? null;
}