96 lines
4.1 KiB
Python
96 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()
|