Unveränderter Stand von certvia/dev (a48c5fb) plus Craftvia-Spezifikation und Brandbook unter docs/craftvia/. ISMS-Module werden im Folgecommit entfernt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
36 lines
1.6 KiB
TypeScript
36 lines
1.6 KiB
TypeScript
// SEC3-d Backfill: bestehende Klartext-TOTP-Secrets (Identity + PlatformAdmin) verschlüsseln.
|
|
// Idempotent — bereits verschlüsselte (enc:v1:) werden übersprungen. Optional: der Code
|
|
// akzeptiert Alt-Klartext ohnehin weiter; dieses Skript verschlüsselt ihn aktiv.
|
|
// Lauf (mit gesetztem DATABASE_URL + AUTH_SECRET): npx tsx scripts/encrypt-mfa-secrets.ts
|
|
import { PrismaClient } from "@prisma/client";
|
|
import { PrismaPg } from "@prisma/adapter-pg";
|
|
import { encryptSecret, isEncrypted } from "../src/server/secret-crypto";
|
|
|
|
const prisma = new PrismaClient({ adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL }) });
|
|
|
|
async function main() {
|
|
let users = 0;
|
|
// Option C: MFA-Secrets leben an der globalen Identity.
|
|
for (const u of await prisma.identity.findMany({ where: { mfaSecret: { not: null } }, select: { id: true, mfaSecret: true } })) {
|
|
if (u.mfaSecret && !isEncrypted(u.mfaSecret)) {
|
|
await prisma.identity.update({ where: { id: u.id }, data: { mfaSecret: encryptSecret(u.mfaSecret) } });
|
|
users++;
|
|
}
|
|
}
|
|
let admins = 0;
|
|
for (const a of await prisma.platformAdmin.findMany({ where: { mfaSecret: { not: null } }, select: { id: true, mfaSecret: true } })) {
|
|
if (a.mfaSecret && !isEncrypted(a.mfaSecret)) {
|
|
await prisma.platformAdmin.update({ where: { id: a.id }, data: { mfaSecret: encryptSecret(a.mfaSecret) } });
|
|
admins++;
|
|
}
|
|
}
|
|
console.log(`Verschlüsselt: ${users} Nutzer-Secret(s), ${admins} Plattform-Admin-Secret(s).`);
|
|
}
|
|
|
|
main()
|
|
.catch((e) => {
|
|
console.error("Backfill fehlgeschlagen:", e.message);
|
|
process.exit(1);
|
|
})
|
|
.finally(() => prisma.$disconnect());
|