"""RPF-WP-0054-T05: broker-issuer-binding lane (CCR-2026-0043).""" from __future__ import annotations import importlib.util import json import os import stat import sys import tempfile import unittest from pathlib import Path import yaml ROOT = Path(__file__).resolve().parents[1] CCR_PATH = ROOT / "credential-change-requests/CCR-2026-0043-keycape-client-secret-generate-issuer-binding.yaml" ISSUER = "credential-broker-keycape-client-secret-generate-issuer" def load(name: str, rel: str): spec = importlib.util.spec_from_file_location(name, ROOT / rel) module = importlib.util.module_from_spec(spec) sys.modules[name] = module spec.loader.exec_module(module) return module lane = load("issuer_binding_lane", "scripts/issuer_binding_lane.py") cc = load("credential_change_cli_issuer", "scripts/credential-change.py") def ccr() -> dict: return yaml.safe_load(CCR_PATH.read_text()) FAKE_BAO = r'''#!/usr/bin/env python3 import json, os, sys path = os.environ["FAKE_BAO_STATE"] state = json.load(open(path)) args = [a for a in sys.argv[1:] if a != "-format=json"] state.setdefault("calls", []).append(args) if args[:2] == ["auth", "list"]: print(json.dumps({k: {"type": v} for k, v in state["mounts"].items()})) elif args[:2] == ["policy", "read"]: if args[2] not in state["policies"]: json.dump(state, open(path, "w")); sys.exit(2) print(state["policies"][args[2]]) elif args[0] == "write": state["roles"][args[1]] = json.load(open(args[2][1:])) elif args[0] == "read": print(json.dumps({"data": state["roles"][args[1]]})) json.dump(state, open(path, "w")) ''' class IssuerBindingLaneTests(unittest.TestCase): def test_ccr_validates_and_is_ready_to_reapply(self): _ccr, errors, _w = cc.validate_ccr(CCR_PATH) self.assertEqual(errors, []) self.assertEqual(cc.applier_readiness_blockers(_ccr), []) def test_unconfirmed_binding_blocks_the_applier(self): c = ccr() c["openbao"]["auth"]["bound_claims_confirmed"] = False self.assertIn("applier requires confirmed OpenBao auth binding", cc.applier_readiness_blockers(c)) def test_role_carries_only_the_issuer_policy(self): role = json.loads((ROOT / ccr()["openbao"]["auth"]["role_file"]).read_text()) self.assertEqual(role["token_policies"], [ISSUER]) self.assertEqual(role["bound_claims"], {"groups": ["net-kingdom-admins"], "/assurance/level": "aal2"}) self.assertTrue(role["token_no_default_policy"]) def test_validator_rejects_widening(self): good = json.loads((ROOT / ccr()["openbao"]["auth"]["role_file"]).read_text()) cases = [ ("other policy", {"token_policies": [ISSUER, "platform-admin"]}), ("no aal2", {"bound_claims": {"groups": ["net-kingdom-admins"]}}), ("public callback", {"allowed_redirect_uris": ["https://bao.coulomb.social/ui/vault/auth/netkingdom/oidc/callback"]}), ("long ttl", {"token_ttl": "1h"}), # Probe 2026-10-10: a limited-use token cannot create the grant token. ("limited uses", {"token_num_uses": 8}), ] for label, change in cases: with self.subTest(label): with tempfile.TemporaryDirectory(dir=ROOT / "openbao/auth") as tmp: role_file = Path(tmp) / "role.json" role_file.write_text(json.dumps({**good, **change})) c = ccr() c["openbao"]["auth"]["role_file"] = str(role_file.relative_to(ROOT)) self.assertNotEqual(lane.validate(c, ROOT), [], label) c = ccr() c["openbao"]["issuer_policy"] = "platform-admin" self.assertNotEqual(lane.validate(c, ROOT), []) def _apply(self, policies, mounts=None): tmp = Path(tempfile.mkdtemp()) state = {"mounts": mounts if mounts is not None else {"netkingdom/": "oidc"}, "policies": policies, "roles": {}} (tmp / "state.json").write_text(json.dumps(state)) bao = tmp / "bao" bao.write_text(FAKE_BAO) bao.chmod(bao.stat().st_mode | stat.S_IEXEC) os.environ["FAKE_BAO_STATE"] = str(tmp / "state.json") error = None try: lane.run_apply(ccr(), ROOT, str(bao), quiet=True) except lane.BaoError as exc: error = exc return error, json.loads((tmp / "state.json").read_text()) def live_issuer(self): return {ISSUER: (ROOT / f"openbao/policies/{ISSUER}.hcl").read_text()} def test_apply_writes_role_and_reads_back(self): error, state = self._apply(self.live_issuer()) self.assertIsNone(error) self.assertIn("auth/netkingdom/role/credential-broker-keycape-client-secret-generate", state["roles"]) def test_apply_refuses_missing_or_drifted_issuer_policy_before_writing(self): for policies in ({}, {ISSUER: 'path "platform/*" { capabilities = ["read"] }'}): with self.subTest(policies=list(policies)): error, state = self._apply(policies) self.assertIsNotNone(error) self.assertEqual(state["roles"], {}) def test_apply_refuses_non_oidc_mount(self): error, state = self._apply(self.live_issuer(), {"netkingdom/": "jwt"}) self.assertIsNotNone(error) self.assertEqual(state["roles"], {}) if __name__ == "__main__": unittest.main()