import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest"; import { POST as hostSchluesselPost } from "@/app/api/v1/server/[name]/ssh/hostschluessel/route"; import { POST as testPost } from "@/app/api/v1/server/[name]/test/route"; import { verschluesseln } from "@/lib/geheimnisse"; import { MOCK_TOKEN_GEHEIMNIS, MOCK_TOKEN_ID, ProxmoxMock } from "./proxmox-mock/mock"; import { szenarioEinrichten } from "./proxmox-mock/szenario"; import { SshMock, testPaar } from "./ssh-mock"; import { datenbankLeeren, datenbankVerfuegbar, testPrisma } from "./helpers/db"; import { angemeldet, anfrage, kontext } from "./helpers/anfragen"; const mock = new ProxmoxMock(); const paar = testPaar(); let ssh: SshMock; describe.runIf(datenbankVerfuegbar)("Verbindungstest über die API", () => { beforeAll(async () => { await mock.starten(); szenarioEinrichten(mock, { version: "8.3.5", importStorage: true }); ssh = await new SshMock(paar.public).starten(); }); afterAll(async () => { await mock.stoppen(); await ssh.stoppen(); }); let admin: string; let operator: string; beforeEach(async () => { await datenbankLeeren(); admin = (await angemeldet("ADMIN")).cookie; operator = (await angemeldet("OPERATOR")).cookie; await testPrisma.server.create({ data: { name: "rz1", titel: "RZ 1", url: mock.url, tokenId: MOCK_TOKEN_ID, tokenGeheimnis: verschluesseln(MOCK_TOKEN_GEHEIMNIS), fingerabdruck: mock.fingerabdruck, sshAktiv: true, sshPort: ssh.port, sshPrivat: verschluesseln(paar.private), sshOeffentlich: paar.public, }, }); }); const testen = async (cookie: string) => await testPost(anfrage("POST", "/api/v1/server/rz1/test", cookie), kontext({ name: "rz1" })); it("speichert Bericht, Version und Erreichbarkeit; Operator darf testen", async () => { const antwort = await testen(operator); expect(antwort.status).toBe(200); const ergebnis = await antwort.json(); expect(ergebnis.ok).toBe(true); expect(ergebnis.bericht.ssh).toBe("nicht_bestaetigt"); const server = await testPrisma.server.findUniqueOrThrow({ where: { name: "rz1" } }); expect(server).toMatchObject({ erreichbar: true, pveVersion: "8.3.5" }); expect(await testPrisma.protokoll.count({ where: { aktion: "Verbindung getestet" } })).toBe(1); }); it("Host-Key bestätigen: nur der gesehene, nur durch Admins – danach geht SSH", async () => { const erst = await (await testen(admin)).json(); const gesehen = erst.bericht.knoten[0].ssh.hostSchluessel as string; const pfad = "/api/v1/server/rz1/ssh/hostschluessel"; expect( ( await hostSchluesselPost( anfrage("POST", pfad, operator, { knoten: "pve01", hostSchluessel: gesehen }), kontext({ name: "rz1" }), ) ).status, ).toBe(403); const untergeschoben = "SHA256:" + "A".repeat(43); const abgelehnt = await hostSchluesselPost( anfrage("POST", pfad, admin, { knoten: "pve01", hostSchluessel: untergeschoben }), kontext({ name: "rz1" }), ); expect(abgelehnt.status).toBe(409); const ok = await hostSchluesselPost( anfrage("POST", pfad, admin, { knoten: "pve01", hostSchluessel: gesehen }), kontext({ name: "rz1" }), ); expect(ok.status).toBe(200); expect((await ok.json()).sshHostSchluessel).toEqual({ pve01: gesehen }); const dann = await (await testen(admin)).json(); expect(dann.bericht.ssh).toBe("ok"); expect(dann.bericht.faehigkeiten.templateBau.weg).toBe("ssh"); }); it("ein nicht erreichbarer Server ist ein Ergebnis, kein Fehler", async () => { await testPrisma.server.update({ where: { name: "rz1" }, data: { url: "https://127.0.0.1:9" } }); const antwort = await testen(admin); expect(antwort.status).toBe(200); const ergebnis = await antwort.json(); expect(ergebnis).toMatchObject({ ok: false }); expect((await testPrisma.server.findUniqueOrThrow({ where: { name: "rz1" } })).erreichbar).toBe(false); }); });