Add server template apply modes, bulk revocation, explicit DN order and detail tabs

This commit is contained in:
2026-10-23 05:33:43 +00:00
parent 5eb7866f5b
commit 763268bd40
13 changed files with 1477 additions and 633 deletions
+115
View File
@@ -0,0 +1,115 @@
// 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);
});