Auf der Hostseite: Host-Key abrufen, Fingerprint vergleichen und vertrauen oder ablehnen. Weicht ein Key vom vertrauten ab, erscheint eine deutliche Warnung, und Annehmen geht nur mit Haekchen und frischer Bestaetigung. Danach Bootstrap per Einmal-Passwort oder per Befehl und Verbindungspruefung, jeweils mit Fortschrittsanzeige. Der sshd-Befund empfiehlt prohibit-password, wenn root sich per Passwort anmelden darf - nur als Hinweis, geaendert wird nichts. E2E im gebauten Stand mit Worker gegen ein echtes sshd. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
73 lines
3.3 KiB
TypeScript
73 lines
3.3 KiB
TypeScript
import { execFileSync } from "node:child_process";
|
||
import { expect, test } from "@playwright/test";
|
||
import "dotenv/config";
|
||
|
||
/**
|
||
* Einen neuen Host in Betrieb nehmen (#008–#010), im gebauten Stand mit laufendem Worker
|
||
* gegen das Testziel B aus docker-compose.test.yml:
|
||
* Host anlegen → Host-Key abrufen → vertrauen → Bootstrap per Passwort → Verbindung pruefen.
|
||
* Laeuft gegen die Entwicklungsdatenbank; der Host heisst zz-e2e-… und wird am Ende archiviert.
|
||
*/
|
||
const ZIEL_PORT = (process.env["SSHKV_TEST_ZIEL_B"] ?? "127.0.0.1:2222").split(":")[1] ?? "2222";
|
||
const ROOT_PASSWORT = process.env["SSHKV_TEST_ROOT_PASSWORT"] || "sshkv-test";
|
||
|
||
test.setTimeout(120_000);
|
||
|
||
test.beforeAll(() => {
|
||
// Testziel ohne Dienstbenutzer, damit der Bootstrap wirklich etwas zu tun hat.
|
||
execFileSync("docker", [
|
||
"compose",
|
||
"-f",
|
||
"docker-compose.test.yml",
|
||
"exec",
|
||
"-T",
|
||
"ziel-b",
|
||
"sh",
|
||
"-c",
|
||
"userdel -r sshkv 2>/dev/null; rm -f /etc/sudoers.d/sshkv; true",
|
||
]);
|
||
});
|
||
|
||
test("neuen Host einrichten", async ({ page }) => {
|
||
const name = `zz-e2e-${Date.now().toString(36)}`;
|
||
|
||
await page.goto("/anmelden");
|
||
await page.getByRole("link", { name: /Mit Mock-OIDC anmelden/ }).click();
|
||
await page.locator('button[data-rolle="admin"]').click();
|
||
await page.getByRole("button", { name: "Anmelden", exact: true }).click();
|
||
await expect(page.getByRole("heading", { name: "Übersicht" })).toBeVisible();
|
||
|
||
await page.goto("/hosts/neu");
|
||
await page.getByLabel("Name").fill(name);
|
||
await page.getByLabel("Adresse").fill("127.0.0.1");
|
||
await page.getByLabel("Port").fill(ZIEL_PORT);
|
||
await page.getByRole("button", { name: "Host anlegen" }).click();
|
||
await expect(page.getByRole("heading", { name })).toBeVisible();
|
||
|
||
await page.getByRole("button", { name: "Host-Key abrufen" }).click();
|
||
await expect(page.getByRole("button", { name: "Fingerprint stimmt – vertrauen" })).toBeVisible({
|
||
timeout: 30_000,
|
||
});
|
||
await page.getByRole("button", { name: "Fingerprint stimmt – vertrauen" }).click();
|
||
await expect(page.getByText("Einmalig per Passwort")).toBeVisible({ timeout: 15_000 });
|
||
await expect(page.getByLabel("Bootstrap-Befehl", { exact: true })).toContainText("SSHKV_BOOTSTRAP");
|
||
|
||
await page.getByLabel("Passwort", { exact: true }).fill(ROOT_PASSWORT);
|
||
await page.getByRole("button", { name: "Zugang einrichten" }).click();
|
||
await expect(page.getByRole("button", { name: "Verbindung prüfen" })).toBeVisible({ timeout: 60_000 });
|
||
await expect(page.getByText("noch nicht eingerichtet")).toHaveCount(0);
|
||
|
||
await expect(page.getByText(/Empfohlen: PermitRootLogin prohibit-password/)).toBeVisible();
|
||
const pruefen = page.getByRole("button", { name: "Verbindung prüfen" });
|
||
await pruefen.click();
|
||
// Gezielt im Block dieses Knopfs – der Host-Key-Knopf zeigt sein eigenes „Erledigt.“.
|
||
await expect(pruefen.locator("..").getByText("Erledigt.")).toBeVisible({ timeout: 30_000 });
|
||
|
||
await page.screenshot({ path: "docs/anleitung/bilder/host-eingerichtet-desktop.png", fullPage: true });
|
||
|
||
// Aufraeumen: archivieren, damit die Liste nicht waechst.
|
||
await page.getByRole("button", { name: "Host archivieren" }).click();
|
||
await page.getByRole("dialog").getByRole("button", { name: "Archivieren", exact: true }).click();
|
||
await expect(page).toHaveURL(/\/hosts$/);
|
||
});
|