railiance-platform/tests/test_openbao_ui_role_select.py
codex 0f0282a436
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
RPF-WP-0057: capabilities-self grant for the hub-writer caller and UI workload role choice (NK-WP-0051-T06)
credential-change.py generates sys/capabilities-self (update) when
openbao.token_capabilities_self is true. Proposed CCR-2026-0045 sets it
for workload-kv-read-reuse-surface-runtime so the ops-mason proof stops
calling sys/capabilities with a root token. The OpenBao login page keeps
its platform-admin button and adds an allow-listed workload role choice.
Repo only; nothing applied to OpenBao or the cluster.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1041694@bnt-lap001
Assistant-Session: 7af0bb68-ac4a-4ce3-8639-24ddd84c0b52
2026-10-14 23:45:00 +02:00

95 lines
4.1 KiB
Python

"""NK-WP-0051-T06: the OpenBao login page can choose the workload role.
The main button stays role platform-admin. Workload roles come only from the
presets allow-list. The script runs in node against a minimal DOM stub.
"""
from __future__ import annotations
import json
import shutil
import subprocess
import unittest
from pathlib import Path
REPO_DIR = Path(__file__).resolve().parents[1]
OVERLAY = REPO_DIR / "helm/openbao-ui-overlay"
WORKLOAD_ROLE = "reuse-surface-hub-writer-workload-kv-read"
HARNESS = r"""
const fs = require("fs");
const [script, presetsPath, clickId, selectValue] = process.argv.slice(1);
const presets = JSON.parse(fs.readFileSync(presetsPath, "utf8"));
presets.workloadRoles = (presets.workloadRoles || []).concat([{ role: "Bad Role!" }]);
const els = {};
function el(id) {
const node = { id, hidden: false, disabled: false, textContent: "", value: "",
children: [], listeners: {}, classList: { add() {} },
appendChild(c) { this.children.push(c); if (!this.value) this.value = c.value; },
addEventListener(t, f) { this.listeners[t] = f; } };
els[id] = node; return node;
}
["login-title","login-banner","login-submit","login-error","login-workload",
"login-workload-summary","login-workload-hint","login-workload-role","login-workload-submit"].forEach(el);
els["login-workload"].hidden = true;
const posted = [];
global.document = { getElementById: (id) => els[id] || null,
createElement: () => ({ value: "", textContent: "" }) };
global.window = { location: { origin: "http://127.0.0.1:18200", assign() {} } };
global.fetch = async (url, opts) => {
if (url.endsWith("presets.json")) return { ok: true, json: async () => presets };
posted.push({ url, body: JSON.parse(opts.body) });
return { ok: true, json: async () => ({ data: { auth_url: "https://kc.example/authorize" } }) };
};
eval(fs.readFileSync(script, "utf8"));
setTimeout(async () => {
if (selectValue) els["login-workload-role"].value = selectValue;
await els[clickId].listeners.click();
console.log(JSON.stringify({ posted,
options: els["login-workload-role"].children.map((c) => c.value),
workloadHidden: els["login-workload"].hidden,
error: els["login-error"].textContent }));
}, 20);
"""
@unittest.skipUnless(shutil.which("node"), "node is not installed")
class OpenBaoUiRoleSelectTests(unittest.TestCase):
def run_page(self, click_id: str, select_value: str = "") -> dict:
proc = subprocess.run(
["node", "-e", HARNESS, str(OVERLAY / "login.js"), str(OVERLAY / "presets.json"),
click_id, select_value],
capture_output=True, text=True, check=True, timeout=30,
)
return json.loads(proc.stdout.strip().splitlines()[-1])
def test_presets_keep_platform_admin_and_list_workload_role(self) -> None:
presets = json.loads((OVERLAY / "presets.json").read_text(encoding="utf-8"))
self.assertEqual(presets["role"], "platform-admin")
self.assertEqual(presets["mount"], "netkingdom")
self.assertIn(WORKLOAD_ROLE, [entry["role"] for entry in presets["workloadRoles"]])
def test_main_button_stays_platform_admin(self) -> None:
result = self.run_page("login-submit")
self.assertEqual(len(result["posted"]), 1)
self.assertEqual(result["posted"][0]["url"], "/v1/auth/netkingdom/oidc/auth_url")
self.assertEqual(result["posted"][0]["body"]["role"], "platform-admin")
self.assertEqual(
result["posted"][0]["body"]["redirect_uri"],
"http://127.0.0.1:18200/ui/vault/auth/netkingdom/oidc/callback",
)
def test_workload_button_uses_selected_listed_role(self) -> None:
result = self.run_page("login-workload-submit", WORKLOAD_ROLE)
self.assertFalse(result["workloadHidden"])
self.assertEqual(result["options"], [WORKLOAD_ROLE])
self.assertEqual(result["posted"][0]["body"]["role"], WORKLOAD_ROLE)
def test_unlisted_role_is_refused(self) -> None:
result = self.run_page("login-workload-submit", "platform-admin")
self.assertEqual(result["posted"], [])
self.assertIn("listed workload role", result["error"])
if __name__ == "__main__":
unittest.main()