// End-to-end smoke test for the KCA PKI workflow. const { test, expect } = require("@playwright/test"); function unique(prefix) { return `${prefix}-${Date.now()}-${Math.floor(Math.random() * 1000)}`; } async function field(page, label) { return page.locator("label").filter({ hasText: label }).first().locator("..").locator("input, select, textarea").first(); } async function login(page, username) { await page.goto("/login"); await page.getByRole("link", { name: "Sign in with default" }).click(); await page.getByPlaceholder("Enter any user/subject").fill(username); await page.getByRole("button", { name: "Sign-in" }).click(); await expect(page).toHaveURL(/\/$/); await expect(page.getByRole("heading", { name: "Vaults" })).toBeVisible(); } test("core PKI workflow", async ({ page }) => { const user = unique("e2e"); const vaultName = unique("Vault"); const caName = unique("E2E CA"); const leafName = unique("www.e2e.example"); await login(page, user); // Vault await page.getByRole("button", { name: "New vault" }).click(); await page.getByPlaceholder("Production PKI").fill(vaultName); await page.getByRole("button", { name: "Create vault" }).click(); await page.getByRole("link", { name: vaultName }).click(); await expect(page.getByRole("heading", { name: vaultName })).toBeVisible(); const vaultUrl = page.url(); // Key await page.getByRole("link", { name: "New key" }).click(); await page.getByPlaceholder("webserver-key").fill(`${caName} key`); await page.getByRole("button", { name: "Generate key" }).click(); await expect(page.getByRole("heading", { name: `${caName} key` })).toBeVisible(); // CA certificate await page.goto(`${vaultUrl}/certificates/new`); await expect(page.getByRole("heading", { name: "New certificate" })).toBeVisible(); await (await field(page, "Internal name")).fill(caName); await (await field(page, "Common name (CN)")).fill(caName); await (await field(page, "Organization (O)")).fill("KCA E2E"); await (await field(page, "Country (C)")).fill("DE"); await page.locator("#new-key").check(); await (await field(page, "Basic constraints")).selectOption("ca"); await page.locator("label").filter({ hasText: "Certificate sign" }).locator("..").locator("input[type=checkbox]").check(); await page.locator("label").filter({ hasText: "CRL sign" }).locator("..").locator("input[type=checkbox]").check(); await page.getByRole("button", { name: "Create certificate" }).click(); await expect(page.getByText("CA certificate", { exact: false })).toBeVisible(); const caUrl = page.url(); await page.locator(".nav-tabs").getByRole("tab", { name: "CA", exact: true }).click(); await (await field(page, "CA · default signing template")).selectOption("builtin:tls-server"); await page.getByRole("button", { name: "Save CA" }).click(); await expect(page.getByText("CA properties saved.")).toBeVisible(); // Leaf signed by the CA await page.goto(`${vaultUrl}/certificates/new`); await (await field(page, "Internal name")).fill(leafName); await (await field(page, "Issuer")).selectOption({ label: caName }); await (await field(page, "Common name (CN)")).fill(leafName); await (await field(page, "Organization (O)")).fill("KCA E2E"); await (await field(page, "Country (C)")).fill("DE"); await page.locator("#new-key").check(); await expect(page.getByText("CA default template: TLS server")).toBeVisible(); await page.getByRole("button", { name: "Apply CA default" }).click(); await expect(page.locator("label").filter({ hasText: "TLS server" }).locator("..").locator("input[type=checkbox]")).toBeChecked(); await page.locator("input[placeholder*='DNS:example.com']").fill(`DNS:${leafName}`); await page.getByRole("button", { name: "Create certificate" }).click(); await expect(page.getByRole("heading", { name: leafName })).toBeVisible(); await page.locator(".nav-tabs").getByRole("tab", { name: "Extensions", exact: true }).click(); await expect(page.getByText("serverAuth", { exact: false })).toBeVisible(); // Certificate list links to the detail route in both views. const certDetailUrl = /\/vaults\/[^/]+\/certificates\/[^/]+$/; await page.goto(`${vaultUrl}/certificates`); await expect(page.getByRole("button", { name: "Select all revocable" })).toHaveCount(0); await expect(page.getByRole("button", { name: "Revoke selected" })).toHaveCount(0); await expect(page.locator("input[data-cert-id]")).toHaveCount(0); await page.getByRole("link", { name: leafName, exact: true }).click(); await expect(page).toHaveURL(certDetailUrl); await expect(page.getByRole("heading", { name: leafName })).toBeVisible(); await page.goto(`${vaultUrl}/certificates`); await page.getByRole("button", { name: "Plain view" }).click(); await expect(page.getByRole("button", { name: "Select all revocable" })).toHaveCount(0); await expect(page.getByRole("button", { name: "Revoke selected" })).toHaveCount(0); await expect(page.locator("input[data-cert-id]")).toHaveCount(0); await page.getByRole("link", { name: leafName, exact: true }).click(); await expect(page).toHaveURL(certDetailUrl); await expect(page.getByRole("heading", { name: leafName })).toBeVisible(); // Search await page.goto(`${vaultUrl}/search`); await page.locator("input[placeholder='Search…']").fill(leafName); await page.getByRole("button", { name: "Search" }).click(); await expect(page.getByRole("link", { name: leafName, exact: true })).toBeVisible(); // Certificate header controls replace the Export, Revoke and Transform tabs. await page.getByRole("link", { name: leafName, exact: true }).click(); const leafUrl = page.url(); const certificateTabs = page.locator(".nav-tabs"); await expect(certificateTabs.getByRole("tab", { name: "Export", exact: true })).toHaveCount(0); await expect(certificateTabs.getByRole("tab", { name: "Revoke", exact: true })).toHaveCount(0); await expect(certificateTabs.getByRole("tab", { name: "Transform", exact: true })).toHaveCount(0); const downloadPromise = page.waitForEvent("download"); await page.getByRole("button", { name: "Export", exact: true }).click(); const exportDialog = page.getByRole("dialog", { name: "Export certificate", exact: true }); await expect(exportDialog).toBeVisible(); await exportDialog.getByLabel("Format", { exact: true }).selectOption("pem"); await exportDialog.getByRole("button", { name: "Download", exact: true }).click(); const download = await downloadPromise; expect(download.suggestedFilename()).toBe(`${leafName}.crt`); await expect(exportDialog).toHaveCount(0); const transformButton = page.getByRole("button", { name: "Transform", exact: true }); await transformButton.click(); for (const name of ["Extract public key", "Create request", "Create template", "Similar certificate"]) { await expect(page.getByRole("menuitem", { name, exact: true })).toBeVisible(); } await page.getByRole("menuitem", { name: "Extract public key", exact: true }).click(); await expect(page).toHaveURL(/\/keys\/[^/]+$/); await page.goto(leafUrl); await transformButton.click(); await page.getByRole("menuitem", { name: "Create request", exact: true }).click(); await expect(page).toHaveURL(/\/requests\/[^/]+$/); await page.goto(leafUrl); await transformButton.click(); await page.getByRole("menuitem", { name: "Create template", exact: true }).click(); await expect(page).toHaveURL(/\/templates\/[^/]+$/); await page.goto(leafUrl); await transformButton.click(); await page.getByRole("menuitem", { name: "Similar certificate", exact: true }).click(); await expect(page).toHaveURL(`${leafUrl}/similar`); await expect(page.getByRole("heading", { name: "New certificate" })).toBeVisible(); await page.goto(leafUrl); await page.getByRole("button", { name: "Actions", exact: true }).click(); await expect(page.getByRole("menuitem", { name: "Renew", exact: true })).toBeVisible(); await expect(page.getByRole("menuitem", { name: "Delete", exact: true })).toBeVisible(); const revokeAction = page.getByRole("menuitem", { name: "Revoke", exact: true }); await expect(revokeAction).toBeEnabled(); await revokeAction.click(); const revokeDialog = page.getByRole("dialog", { name: "Revoke certificate", exact: true }); await expect(revokeDialog).toBeVisible(); await revokeDialog.getByLabel("Reason", { exact: true }).selectOption("keyCompromise"); await revokeDialog.getByRole("button", { name: "Revoke certificate", exact: true }).click(); await expect(revokeDialog).toHaveCount(0); await expect(page.getByText("revoked", { exact: true })).toBeVisible(); await page.getByRole("button", { name: "Actions", exact: true }).click(); await expect(page.getByRole("menuitem", { name: "Revoke", exact: true })).toBeDisabled(); // CRL from the CA await page.goto(caUrl); await expect(page.getByRole("heading", { name: caName })).toBeVisible(); await page.getByRole("button", { name: "Actions", exact: true }).click(); await expect(page.getByRole("menuitem", { name: "Revoke", exact: true })).toBeDisabled(); await page.getByRole("button", { name: "Actions", exact: true }).click(); await page.locator(".nav-tabs").getByRole("tab", { name: "CA", exact: true }).click(); await page.getByRole("button", { name: "Generate CRL" }).click(); await expect(page).toHaveURL(/\/crls\//); await expect(page.getByText(/CRL number \d+ · 1 revoked/)).toBeVisible(); // API token await page.goto("/tokens"); await page.getByPlaceholder("CI uploader").fill(unique("token")); await page.getByRole("button", { name: "Create" }).click(); await expect(page.getByText("Token created", { exact: false })).toBeVisible(); });