feat(server): Proxmox-Server verwalten mit Fingerprint-Pinning
Server lassen sich anlegen, prüfen, bearbeiten und löschen. Proxmox liefert ab Werk ein selbst signiertes Zertifikat; der Admin sieht es vor dem Speichern und bestätigt den SHA-256-Fingerprint. Der Pin wird in einem eigenen undici-Connector geprüft, sodass eine fremde Gegenstelle das Token nie zu sehen bekommt. Weder Prüfung noch Pin ist im Schema, im Client und per CHECK ausgeschlossen. Fehler von Proxmox werden zu Ursache und Hinweis; bei 403 nennt der Hinweis das fehlende Recht samt Pfad. Getestet gegen einen HTTPS-Mock und im gebauten Stand auf Desktop und 390 px. Closes #002 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { MOCK_TOKEN_GEHEIMNIS, MOCK_TOKEN_ID } from "../proxmox-mock/mock";
|
||||
import { MOCK_PORT } from "./global-setup";
|
||||
import { anmelden, E2E_PRAEFIX, keinQuerscrollen } from "./helfer";
|
||||
|
||||
test("Server anlegen: Zertifikat pinnen, Verbindung prüfen, SSH-Schlüssel, löschen", async ({ page }) => {
|
||||
const name = `${E2E_PRAEFIX}-${test.info().project.name}`;
|
||||
await anmelden(page, "/server/neu");
|
||||
await expect(page.getByRole("heading", { name: "Server anlegen" })).toBeVisible();
|
||||
await keinQuerscrollen(page);
|
||||
|
||||
await page.getByLabel("Kurzname").fill(name);
|
||||
await page.getByLabel("Anzeigename").fill("E2E-Testserver");
|
||||
await page.getByLabel("Adresse").fill(`127.0.0.1:${MOCK_PORT}`);
|
||||
await page.getByRole("button", { name: "Zertifikat holen" }).click();
|
||||
await expect(page.getByText("Selbst signiertes Zertifikat")).toBeVisible();
|
||||
await page.getByLabel("Fingerprint stimmt – Zertifikat pinnen").check();
|
||||
|
||||
await page.getByLabel("Token-ID").fill(MOCK_TOKEN_ID);
|
||||
await page.getByLabel("Secret").fill(MOCK_TOKEN_GEHEIMNIS);
|
||||
await page.getByRole("button", { name: "Verbindung prüfen" }).click();
|
||||
await expect(page.getByText("Verbunden · Proxmox VE")).toBeVisible();
|
||||
await expect(page.getByText("9.2.1")).toBeVisible();
|
||||
await page.screenshot({ path: `test-results/server-neu-${test.info().project.name}.png`, fullPage: true });
|
||||
|
||||
await page.getByLabel("SSH zu den Nodes nutzen").check();
|
||||
await page.getByRole("button", { name: "Server anlegen" }).click();
|
||||
await expect(page).toHaveURL(new RegExp(`/server/${name}$`));
|
||||
await expect(page.getByRole("heading", { name: "E2E-Testserver" })).toBeVisible();
|
||||
|
||||
await page.getByRole("button", { name: "Schlüssel erzeugen" }).click();
|
||||
await expect(page.getByText(/ssh-ed25519 AAAA/)).toBeVisible();
|
||||
await keinQuerscrollen(page);
|
||||
await page.screenshot({
|
||||
path: `test-results/server-detail-${test.info().project.name}.png`,
|
||||
fullPage: true,
|
||||
});
|
||||
|
||||
await page.getByRole("button", { name: "Server löschen" }).click();
|
||||
await page.getByRole("button", { name: "Wirklich löschen" }).click();
|
||||
await expect(page).toHaveURL(/\/server$/);
|
||||
await expect(page.getByText(name)).toHaveCount(0);
|
||||
});
|
||||
Reference in New Issue
Block a user