import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { randomBytes } from "node:crypto"; import { tmpdir } from "node:os"; import path from "node:path"; import { prisma } from "@/lib/db"; import { verschluesseln } from "@/lib/geheimnisse"; import { vorgangAusfuehren } from "@/worker/ausfuehren"; import { masterKeyVergessen } from "@/worker/geheimnisse"; import { HANDLER } from "@/worker/handler"; import { rootPasswort, type Ziel } from "./ziele"; /** Gemeinsame Vorbereitung fuer Integrationstests: Master-Key, Host mit Bootstrap (#016). */ export function masterKeyAnlegen(): () => void { const verzeichnis = mkdtempSync(path.join(tmpdir(), "sshkv-master-")); const datei = path.join(verzeichnis, "master.key"); writeFileSync(datei, randomBytes(32), { mode: 0o600 }); process.env["SSHKV_MASTER_KEY_FILE"] = datei; masterKeyVergessen(); return () => rmSync(verzeichnis, { recursive: true, force: true }); } export async function vorgangLaufen( art: | "HOSTKEY_ABRUFEN" | "BOOTSTRAP" | "TROCKENLAUF" | "AUSROLLEN" | "VERBINDUNGSTEST" | "ZIELKONTO_ANLEGEN" | "ZIELKONTO_ENTFERNEN" | "ABGLEICH" | "ROTATION", daten: { hostId?: string; eingabe?: object; geheim?: string; angefordertVonId?: string; }, ) { const vorgang = await prisma.vorgang.create({ data: { art, hostId: daten.hostId ?? null, eingabe: daten.eingabe ?? {}, angefordertVonId: daten.angefordertVonId ?? null, }, }); await vorgangAusfuehren(vorgang.id, HANDLER, daten.geheim); return prisma.vorgang.findUniqueOrThrow({ where: { id: vorgang.id } }); } /** Host anlegen, Host-Key vertrauen, Bootstrap per root-Passwort. */ export async function eingerichteterHost( ziel: Ziel, name: string, anmeldeart: "DIENSTBENUTZER" | "ROOT" = "DIENSTBENUTZER", ) { const host = await prisma.host.create({ data: { name, adresse: ziel.host, port: ziel.port, anmeldeart } }); await vorgangLaufen("HOSTKEY_ABRUFEN", { hostId: host.id }); await prisma.hostSchluessel.updateMany({ where: { hostId: host.id }, data: { status: "VERTRAUT" } }); const bootstrap = await vorgangLaufen("BOOTSTRAP", { hostId: host.id, eingabe: { modus: "passwort", benutzer: "root" }, geheim: verschluesseln(rootPasswort()), }); if (bootstrap.status !== "ERLEDIGT") throw new Error(`Bootstrap fehlgeschlagen: ${bootstrap.fehler}`); return prisma.host.findUniqueOrThrow({ where: { id: host.id } }); }