// Bulk revocation through the certificate list. const { test, expect } = require("@playwright/test"); function unique(prefix) { return `${prefix}-${Date.now()}-${Math.floor(Math.random() * 1000)}`; } 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.getByRole("heading", { name: "Vaults" })).toBeVisible(); } async function api(page, method, url, body) { return page.evaluate( async ({ method, url, body }) => { const response = await fetch(url, { method, headers: { "content-type": "application/json" }, body: body === undefined ? undefined : JSON.stringify(body), }); const text = await response.text(); return { status: response.status, json: text ? JSON.parse(text) : null }; }, { method, url, body } ); } test("bulk revocation from the certificate list", async ({ page }) => { const user = unique("bulk"); const vaultName = unique("Bulk Vault"); await login(page, user); const vault = await api(page, "POST", "/api/vaults", { name: vaultName }); expect(vault.status).toBe(201); const vaultId = vault.json.id; const caKey = await api(page, "POST", `/api/vaults/${vaultId}/keys`, { name: "Bulk CA key", key_type: "rsa", size: 2048, }); expect(caKey.status).toBe(201); const now = new Date(); const later = new Date(now.getTime() + 365 * 24 * 3600 * 1000); const ca = await api(page, "POST", `/api/vaults/${vaultId}/certificates`, { name: "Bulk CA", key_id: caKey.json.id, subject: [ { name: "C", value: "DE" }, { name: "O", value: "KCA E2E" }, { name: "CN", value: "Bulk CA" }, ], not_before: now.toISOString(), not_after: later.toISOString(), extensions: { basic_constraints: { critical: true, ca: true, path_length: null }, key_usage: { critical: true, usages: ["key_cert_sign", "crl_sign"] }, subject_key_identifier: { critical: false }, authority_key_identifier: { critical: false }, }, }); expect(ca.status).toBe(201); const caId = ca.json.id; async function leaf(name) { const key = await api(page, "POST", `/api/vaults/${vaultId}/keys`, { name: `${name} key`, key_type: "rsa", size: 2048, }); expect(key.status).toBe(201); const cert = await api(page, "POST", `/api/vaults/${vaultId}/certificates`, { name, key_id: key.json.id, signer_id: caId, subject: [ { name: "C", value: "DE" }, { name: "O", value: "KCA E2E" }, { name: "CN", value: name }, ], not_before: now.toISOString(), not_after: later.toISOString(), extensions: { basic_constraints: { critical: true, ca: false, path_length: null }, key_usage: { critical: true, usages: ["digital_signature"] }, subject_alt_name: { critical: false, entries: [{ type: "dns", value: name }] }, subject_key_identifier: { critical: false }, authority_key_identifier: { critical: false }, }, }); expect(cert.status).toBe(201); return cert.json; } await leaf("bulk-one.example"); await leaf("bulk-two.example"); await page.goto(`/vaults/${vaultId}/certificates`); await expect(page.getByRole("heading", { name: "Certificates" })).toBeVisible(); await page.evaluate(() => { window.confirm = () => true; }); await page.getByRole("button", { name: "Select all revocable" }).click(); await expect(page.getByText("2 selected")).toBeVisible(); await page.locator("select").first().selectOption("keyCompromise"); await page.getByRole("button", { name: "Revoke selected" }).click(); await expect(page.getByText(/Revoked 2 certificate\(s\); 0 already revoked; 0 error\(s\)/)).toBeVisible(); const revocations = await api(page, "GET", `/api/vaults/${vaultId}/certificates`); const revoked = revocations.json.results.filter((cert) => cert.revoked); expect(revoked).toHaveLength(2); });