The founder's applier-dry-run of CCR-2026-0064 crashed (KeyError 'source') in render_applier_dry_run. New test renders the dry run and the apply plan through the CLI. The --record-state-hub summary of approve no longer assumes openbao.fields, which lane CCRs without a KV path do not have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 943911@bnt-lap001 Assistant-Session: fc322940-1c8e-4bed-ab39-86cec99f23a0
156 lines
7.1 KiB
Python
156 lines
7.1 KiB
Python
"""auth-role-presence-watch lane (CCR-2026-0064, net-kingdom NK-WP-0058-T06)."""
|
|
from __future__ import annotations
|
|
|
|
import copy
|
|
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-0064-nk-bounded-executor-window-watch.yaml"
|
|
WATCHED = "auth/kubernetes/role/net-kingdom-bind-executor-svc-authelia-write"
|
|
|
|
|
|
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("auth_role_watch_lane", "scripts/auth_role_watch_lane.py")
|
|
cc = load("credential_change_cli_watch", "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", "write"]:
|
|
state["policies"][args[2]] = open(args[3]).read()
|
|
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":
|
|
role = json.load(open(args[2][1:]))
|
|
state["roles"][args[1]] = {k: (900 if v == "15m" else v) for k, v in role.items()}
|
|
elif args[0] == "read":
|
|
print(json.dumps({"data": state["roles"][args[1]]}))
|
|
json.dump(state, open(path, "w"))
|
|
'''
|
|
|
|
|
|
class AuthRoleWatchLaneTests(unittest.TestCase):
|
|
def test_ccr_validates_and_blocks_until_approved_and_bound(self):
|
|
_ccr, errors, _w = cc.validate_ccr(CCR_PATH)
|
|
self.assertEqual(errors, [])
|
|
draft = copy.deepcopy(_ccr) # independent of the file's live review state
|
|
draft.update(status="proposed")
|
|
draft["openbao"]["auth"]["bound_claims_confirmed"] = False
|
|
blockers = cc.applier_readiness_blockers(draft)
|
|
self.assertIn("applier requires confirmed OpenBao auth binding", blockers)
|
|
ready = copy.deepcopy(_ccr)
|
|
ready["status"] = "approved"
|
|
ready["openbao"]["auth"]["bound_claims_confirmed"] = True
|
|
self.assertEqual(cc.applier_readiness_blockers(ready), [])
|
|
|
|
def test_dry_run_and_apply_plan_render_through_the_cli(self):
|
|
"""2026-11-06: the founder's dry run crashed on a policy_write without source and body."""
|
|
ready = copy.deepcopy(ccr())
|
|
ready.update(status="approved")
|
|
ready["openbao"]["auth"]["bound_claims_confirmed"] = True
|
|
dry = cc.render_applier_dry_run(cc.applier_dry_run_payload(ready, []))
|
|
self.assertIn("policy_write: sys/policies/acl/net-kingdom-bounded-executor-window-watch", dry)
|
|
self.assertIn('path "%s" {' % WATCHED, dry)
|
|
self.assertIn("auth_role_write: auth/kubernetes/role/net-kingdom-bounded-executor-window-watch", dry)
|
|
self.assertIn("CCR-2026-0064", cc.render_applier_apply_plan(ready, []))
|
|
|
|
def test_flag_policy_is_one_read_and_self_lifecycle(self):
|
|
text = (ROOT / ccr()["openbao"]["policy_file"]).read_text()
|
|
paths = [line.split('"')[1] for line in text.splitlines() if line.startswith("path ")]
|
|
self.assertEqual(paths, [WATCHED, "auth/token/lookup-self", "auth/token/revoke-self"])
|
|
self.assertIn('path "%s" {\n capabilities = ["read"]\n}' % WATCHED, text)
|
|
self.assertNotIn("delete", text)
|
|
|
|
def test_close_mode_adds_only_delete_on_the_same_path(self):
|
|
c = ccr()
|
|
c["openbao"]["watch"]["mode"] = "close"
|
|
self.assertIn('path "%s" {\n capabilities = ["read", "delete"]\n}' % WATCHED, lane.generated_policy_hcl(c))
|
|
self.assertIn("openbao.policy_file differs from the policy generated from the CCR", lane.validate(c, ROOT))
|
|
|
|
def test_validator_rejects_widening(self):
|
|
cases = [
|
|
("unknown mode", lambda c: c["openbao"]["watch"].update(mode="admin")),
|
|
("other mount", lambda c: c["openbao"]["watch"].update(mount="netkingdom")),
|
|
("watch itself", lambda c: c["openbao"]["auth"].update(role=c["openbao"]["watch"]["role"])),
|
|
("long ttl", lambda c: c["openbao"]["auth"].update(ttl="1h")),
|
|
("default policy", lambda c: c["openbao"]["auth"].update(token_no_default_policy=False)),
|
|
("extra policy", lambda c: c["openbao"]["auth"]["policies"].append("platform-admin")),
|
|
("two accounts", lambda c: c["openbao"]["auth"]["bound_claims"]["service_account_names"].append("x")),
|
|
("extra claim", lambda c: c["openbao"]["auth"]["bound_claims"].update(other=["x"])),
|
|
("other audience", lambda c: c["openbao"]["auth"].update(audience="kubernetes")),
|
|
("staging", lambda c: c["target"].update(environment="staging")),
|
|
]
|
|
for label, mutate in cases:
|
|
with self.subTest(label):
|
|
c = ccr()
|
|
mutate(c)
|
|
self.assertNotEqual(lane.validate(c, ROOT), [], label)
|
|
|
|
def test_edited_policy_file_is_refused(self):
|
|
c = ccr()
|
|
with tempfile.TemporaryDirectory(dir=ROOT / "openbao/policies") as tmp:
|
|
edited = Path(tmp) / "p.hcl"
|
|
edited.write_text(lane.generated_policy_hcl(c) + 'path "platform/*" {\n capabilities = ["read"]\n}\n')
|
|
c["openbao"]["policy_name"] = "p"
|
|
c["openbao"]["policy_file"] = str(edited.relative_to(ROOT))
|
|
self.assertNotEqual(lane.validate(c, ROOT), [])
|
|
|
|
def _apply(self, mounts):
|
|
tmp = Path(tempfile.mkdtemp())
|
|
(tmp / "state.json").write_text(json.dumps({"mounts": mounts, "policies": {}, "roles": {}}))
|
|
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 test_apply_writes_policy_and_role_and_reads_back(self):
|
|
error, state = self._apply({"kubernetes/": "kubernetes"})
|
|
self.assertIsNone(error)
|
|
role = state["roles"]["auth/kubernetes/role/net-kingdom-bounded-executor-window-watch"]
|
|
self.assertEqual(role["bound_service_account_names"], ["nk-window-watch"])
|
|
self.assertEqual(role["token_policies"], ["net-kingdom-bounded-executor-window-watch"])
|
|
self.assertEqual(set(state["policies"]), {"net-kingdom-bounded-executor-window-watch"})
|
|
self.assertNotIn(WATCHED, state["roles"]) # the watched role is never written here
|
|
|
|
def test_apply_refuses_without_the_kubernetes_mount(self):
|
|
error, state = self._apply({})
|
|
self.assertIsNotNone(error)
|
|
self.assertEqual(state["policies"], {})
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|