railiance-platform/tests/test_service_jwt_lane.py
codex 1b36e147e3 RPF-WP-0035-T02: record founder approval and delegated apply of CCR-2026-0038
Service-JWT login lane (mount keycape-services, role secrets-engine-openbao,
policy secrets-engine-login-self) applied 2026-10-08T22:42Z with matching
readback. T02 now waits only on the live login proof (SECRETS-WP-0012-T03).

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 469992@bnt-lap001
Assistant-Session: e4b8e420-df0a-441d-83ae-7f19130594d9
2026-10-09 11:47:09 +02:00

171 lines
7.6 KiB
Python

"""CCR-2026-0038 service-jwt-login lane: validator, invariant (ii), fake-bao applier."""
from __future__ import annotations
import copy
import importlib.util
import json
import os
import re
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-0038-secrets-engine-service-jwt-login.yaml"
GUARDED = "platform/data/workloads/keycape/secrets-engine-openbao"
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("service_jwt_lane", "scripts/service_jwt_lane.py")
cc = load("credential_change_cli", "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
state = json.load(open(os.environ["FAKE_BAO_STATE"]))
open(os.environ["FAKE_BAO_LOG"], "a").write(json.dumps(sys.argv[1:]) + "\n")
args = [a for a in sys.argv[1:] if a != "-format=json"]
if args[:2] == ["auth", "list"]:
print(json.dumps({k: {"type": v} for k, v in state["mounts"].items()}))
elif args[:2] == ["policy", "read"]:
print(state["policy"])
elif args[0] == "read" and args[1].endswith("/config"):
print(json.dumps({"data": state["config"]}))
elif args[0] == "read":
print(json.dumps({"data": state["role"]}))
'''
class ServiceJwtLaneTests(unittest.TestCase):
def test_ccr_validates_and_records_the_delegated_apply(self):
_ccr, errors, _w = cc.validate_ccr(CCR_PATH)
self.assertEqual(errors, [])
self.assertEqual(_ccr["status"], "applied")
self.assertTrue(_ccr["openbao"]["auth"]["bound_claims_confirmed"])
evidence = _ccr["verification"]["evidence"]
self.assertTrue(
any(e["kind"] == "delegated_metadata_apply" and e["result"] == "passed"
for e in evidence),
evidence,
)
def test_invariant_ii_policy_has_no_capability_on_the_client_secret_path(self):
policy = (ROOT / "openbao/policies/secrets-engine-login-self.hcl").read_text()
stanzas = re.findall(r'path "([^"]+)"\s*{\s*capabilities = \[([^\]]*)\]', policy)
for path, caps in stanzas:
if path.startswith("platform/"):
self.assertEqual(caps.strip(), '"deny"', path)
self.assertIn((GUARDED, '"deny"'), stanzas)
granted = {p for p, c in stanzas if c.strip() != '"deny"'}
self.assertEqual(granted, {p for p, _ in lane.SELF_GRANTS})
self.assertNotIn("*", policy)
def test_validator_rejects_widening(self):
cases = []
c = ccr(); c["openbao"]["guarded_paths"] = ["platform/data/workloads/*"]; cases.append(c)
c = ccr(); c["openbao"]["auth"]["mount"] = "netkingdom"; cases.append(c)
c = ccr(); c["openbao"]["policy_name"] = "platform-admin"; cases.append(c)
c = ccr(); c["target"]["environment"] = "staging"; cases.append(c)
for case in cases:
self.assertTrue(lane.validate(case, ROOT), case["openbao"])
def test_validator_rejects_bad_role_file(self):
with tempfile.TemporaryDirectory() as tmp:
repo = Path(tmp)
(repo / "openbao/auth").mkdir(parents=True)
(repo / "openbao/policies").mkdir(parents=True)
c = ccr()
(repo / c["openbao"]["policy_file"]).write_text(lane.generated_policy_hcl(c))
(repo / c["openbao"]["auth"]["config_file"]).write_text(
(ROOT / c["openbao"]["auth"]["config_file"]).read_text())
base = json.loads((ROOT / c["openbao"]["auth"]["role_file"]).read_text())
self.assertEqual(self._role_errors(repo, c, base), [])
for mutate in (
lambda r: r.update(token_ttl="1h"),
lambda r: r.update(token_no_default_policy=False),
lambda r: r.update(token_policies=["secrets-engine-login-self", "default"]),
lambda r: r.update(token_period="5m"),
lambda r: r["bound_claims"].update(roles="*"),
lambda r: r.update(bound_audiences=["other"]),
lambda r: r.update(token_num_uses=0),
):
role = copy.deepcopy(base); mutate(role)
self.assertTrue(self._role_errors(repo, c, role), role)
def _role_errors(self, repo, c, role):
(repo / c["openbao"]["auth"]["role_file"]).write_text(json.dumps(role))
return lane.validate(c, repo)
def _fake(self, tmp: Path, mounts: dict, policy: str | None = None, role_ttl=300):
c = ccr()
role = lane.role_payload(c, ROOT); role["token_ttl"] = role_ttl
role["token_max_ttl"] = role["token_explicit_max_ttl"] = 300
state = {"mounts": mounts, "policy": policy if policy is not None else lane.generated_policy_hcl(c),
"config": lane.config_payload(c, ROOT), "role": role}
(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")
os.environ["FAKE_BAO_LOG"] = str(tmp / "log")
return c, str(bao)
def _log(self, tmp: Path):
return [json.loads(l) for l in (tmp / "log").read_text().splitlines()]
def test_apply_enables_absent_mount_writes_in_order_and_reads_back(self):
with tempfile.TemporaryDirectory() as t:
tmp = Path(t)
c, bao = self._fake(tmp, {"keycape-services/": "jwt"})
# first auth list sees no mount; later readback sees jwt
state = json.loads((tmp / "state.json").read_text())
state["mounts"] = {}
(tmp / "state.json").write_text(json.dumps(state))
with self.assertRaises(lane.BaoError): # readback: mount absent in fake
lane.run_apply(c, ROOT, bao, quiet=True)
verbs = [a[:2] for a in self._log(tmp)]
self.assertEqual(verbs[:5], [["auth", "list"], ["policy", "write"], ["auth", "enable"],
["write", "auth/keycape-services/config"],
["write", "auth/keycape-services/role/secrets-engine-openbao"]])
self.assertIn("jwt", self._log(tmp)[2])
def test_apply_on_existing_jwt_mount_skips_enable_and_passes_readback(self):
with tempfile.TemporaryDirectory() as t:
tmp = Path(t)
c, bao = self._fake(tmp, {"keycape-services/": "jwt"})
lane.run_apply(c, ROOT, bao, quiet=True)
verbs = [a[:2] for a in self._log(tmp)]
self.assertNotIn(["auth", "enable"], verbs)
for argv in self._log(tmp):
self.assertFalse(any("token" in a.lower() and "=" in a for a in argv), argv)
def test_apply_refuses_foreign_mount_type_before_any_write(self):
with tempfile.TemporaryDirectory() as t:
tmp = Path(t)
c, bao = self._fake(tmp, {"keycape-services/": "oidc"})
with self.assertRaises(lane.BaoError):
lane.run_apply(c, ROOT, bao, quiet=True)
self.assertEqual([a[:2] for a in self._log(tmp)], [["auth", "list"]])
def test_readback_detects_policy_drift(self):
with tempfile.TemporaryDirectory() as t:
tmp = Path(t)
c, bao = self._fake(tmp, {"keycape-services/": "jwt"}, policy='path "platform/data/*" {}')
self.assertIn("policy text differs from source", lane.readback_mismatches(c, ROOT, bao))
if __name__ == "__main__":
unittest.main()