railiance-platform/tests/test_ccr_intake.py
codex 7e7ca8be51
All checks were successful
CCR intake gate / gate (push) Successful in 3m12s
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
RPF-WP-0061: render-policy and plan_ref for ops-mason submissions; approvals only via sync-decision
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 306568@bnt-lap001
Assistant-Session: 8bdf8150-ea56-41e7-9132-13f04f6b0b91
2026-10-18 12:53:19 +02:00

296 lines
14 KiB
Python

from __future__ import annotations
import argparse
import importlib.util
import os
import shutil
import sys
import tempfile
import unittest
from pathlib import Path
from unittest import mock
REPO_DIR = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_DIR / "scripts"))
SPEC = importlib.util.spec_from_file_location(
"credential_change", REPO_DIR / "scripts/credential-change.py"
)
credential_change = importlib.util.module_from_spec(SPEC)
assert SPEC.loader is not None
sys.modules[SPEC.name] = credential_change
SPEC.loader.exec_module(credential_change)
import ccr_intake # noqa: E402
cc = credential_change
STANDARD = "CCR-2026-0051-mas-tem-relay-smtp.yaml"
POLICY = "openbao/policies/workload-kv-read-mas-tem-relay.hcl"
class CcrIntakeTests(unittest.TestCase):
"""Run against a scratch repo root so nothing is written into the real tree."""
def setUp(self) -> None:
self.root = Path(tempfile.mkdtemp())
self.addCleanup(shutil.rmtree, self.root, True)
self.ccrs = self.root / "credential-change-requests"
self.ccrs.mkdir()
(self.root / "openbao/policies").mkdir(parents=True)
shutil.copy2(REPO_DIR / "credential-change-requests" / STANDARD, self.ccrs / STANDARD)
shutil.copy2(REPO_DIR / POLICY, self.root / POLICY)
for target in (cc, ccr_intake):
patcher = mock.patch.object(target, "REPO_DIR", self.root)
patcher.start()
self.addCleanup(patcher.stop)
env = mock.patch.dict(os.environ, {"CCR_DIR": str(self.ccrs)})
env.start()
self.addCleanup(env.stop)
self.profile, _digest = ccr_intake.load_profile()
self.path = self.ccrs / STANDARD
# The live CCR moves through approval; the fixture must stay pre-approval.
self.edit(lambda d: (d.update(status="proposed"), d["review"].update(comments=[]),
d.pop("state_hub", None)))
def edit(self, change) -> None:
data = cc.load_yaml(self.path)
change(data)
cc.dump_yaml(self.path, data)
def violations(self) -> list[str]:
return ccr_intake.standard_violations(cc.load_yaml(self.path), self.profile, self.ccrs, cc)
def assert_violation(self, change, fragment: str) -> None:
self.edit(change)
found = self.violations()
self.assertTrue(any(fragment in item for item in found), found)
def test_standard_lane_passes_and_records_review_without_approval(self) -> None:
self.assertEqual(ccr_intake.review_standard(self.path, cc), [])
data = cc.load_yaml(self.path)
self.assertEqual(data["status"], "proposed")
comment = data["review"]["comments"][-1]
self.assertEqual(comment["decision"], "approved")
self.assertIn("ccr-standard-lane v1 sha256:", comment["comment"])
self.assertTrue(comment["reviewer"].startswith("railiance-platform-owner"))
self.assertIn("apply requires status approved, got proposed", cc.apply_blockers(data))
def test_check_mode_does_not_write(self) -> None:
before = self.path.read_text()
ccr_intake.review_standard(self.path, cc, write=False)
self.assertEqual(self.path.read_text(), before)
def test_out_of_profile_records_needs_platform_review(self) -> None:
self.edit(lambda d: d["risk"].update(classification="high"))
self.assertTrue(ccr_intake.review_standard(self.path, cc))
comment = cc.load_yaml(self.path)["review"]["comments"][-1]
self.assertEqual(comment["decision"], "needs_platform_review")
self.assertEqual(cc.load_yaml(self.path)["status"], "proposed")
def test_requires_proposed_status(self) -> None:
self.edit(lambda d: d.update(status="approved"))
with self.assertRaises(SystemExit):
ccr_intake.review_standard(self.path, cc)
def test_metadata_read_rejected(self) -> None:
self.assert_violation(lambda d: d["openbao"].update(metadata_read=True), "metadata_read")
def test_kv_path_outside_prefixes_rejected(self) -> None:
self.assert_violation(
lambda d: d["openbao"].update(kv_path="platform/operators/founder/x"), "outside the standard"
)
def test_supplier_path_needs_exactly_two_segments(self) -> None:
self.assert_violation(
lambda d: d["openbao"].update(kv_path="platform/suppliers/scaleway/a/b"), "outside the standard"
)
def test_policy_file_drift_rejected(self) -> None:
(self.root / POLICY).write_text('path "platform/data/suppliers/*" {\n capabilities = ["read"]\n}\n')
self.assertTrue(any("differs" in v for v in self.violations()))
def test_long_ttl_rejected(self) -> None:
self.assert_violation(lambda d: d["openbao"]["auth"].update(token_max_ttl="1h"), "token_max_ttl")
def test_default_policy_rejected(self) -> None:
self.assert_violation(
lambda d: d["openbao"]["auth"].update(token_no_default_policy=False), "token_no_default_policy"
)
def test_role_prefix_and_audience_enforced(self) -> None:
self.assert_violation(lambda d: d["openbao"]["auth"].update(role="mas-eso"), "role must start")
self.assert_violation(lambda d: d["openbao"]["auth"].update(audience="vault"), "audience")
def test_two_service_accounts_rejected(self) -> None:
self.assert_violation(
lambda d: d["openbao"]["auth"]["bound_claims"]["service_account_names"].append("other"),
"service account",
)
def test_reserved_namespace_rejected(self) -> None:
self.assert_violation(
lambda d: d["openbao"]["auth"]["bound_claims"].update(service_account_namespaces=["external-secrets"]),
"reserved",
)
def test_second_reader_of_path_rejected(self) -> None:
other = cc.load_yaml(self.path)
other.update(id="CCR-2026-0052", status="active")
cc.dump_yaml(self.ccrs / "CCR-2026-0052-other.yaml", other)
self.assertTrue(any("already has a reader: CCR-2026-0052" in v for v in self.violations()))
def test_cancelled_reader_is_not_a_conflict(self) -> None:
other = cc.load_yaml(self.path)
other.update(id="CCR-2026-0052", status="cancelled")
cc.dump_yaml(self.ccrs / "CCR-2026-0052-other.yaml", other)
self.assertEqual(self.violations(), [])
def test_next_id_and_duplicate_detection(self) -> None:
self.assertEqual(ccr_intake.next_ccr_id(self.ccrs, 2026), "CCR-2026-0052")
self.assertEqual(ccr_intake.next_ccr_id(self.ccrs, 2027), "CCR-2027-0001")
self.assertEqual(ccr_intake.duplicate_ids(self.ccrs, cc), {})
shutil.copy2(self.path, self.ccrs / "CCR-2026-0051-race.yaml")
self.assertIn("CCR-2026-0051", ccr_intake.duplicate_ids(self.ccrs, cc))
def submit_args(self, **overrides) -> argparse.Namespace:
draft_dir = Path(tempfile.mkdtemp())
self.addCleanup(shutil.rmtree, draft_dir, True)
draft = cc.load_yaml(self.path)
draft.update(id="CCR-DRAFT-MAS", status="draft")
draft["openbao"].update(
kv_path="platform/suppliers/scaleway/other-relay",
policy_name="workload-kv-read-other-relay",
policy_file="openbao/policies/workload-kv-read-other-relay.hcl",
)
draft["openbao"]["auth"]["policies"] = ["workload-kv-read-other-relay"]
draft["review"]["comments"] = [{"reviewer": "someone", "decision": "approved", "comment": "x"}]
cc.dump_yaml(draft_dir / "draft.yaml", draft)
(draft_dir / "policy.hcl").write_text(
(self.root / POLICY).read_text().replace("mas-tem-relay", "other-relay")
)
values = dict(ccr=str(draft_dir / "draft.yaml"), policy=str(draft_dir / "policy.hcl"),
slug="other-relay", requester="ops-mason", profile=str(ccr_intake.DEFAULT_PROFILE))
values.update(overrides)
return argparse.Namespace(**values)
def test_submit_allocates_id_copies_policy_and_reviews(self) -> None:
destination, violations = ccr_intake.submit(self.submit_args(), cc)
self.assertEqual(violations, [])
self.assertEqual(destination.name, "CCR-2026-0052-other-relay.yaml")
data = cc.load_yaml(destination)
self.assertEqual((data["id"], data["status"]), ("CCR-2026-0052", "proposed"))
self.assertEqual(len(data["review"]["comments"]), 1)
self.assertTrue(data["review"]["comments"][0]["reviewer"].startswith("railiance-platform-owner"))
self.assertTrue((self.root / "openbao/policies/workload-kv-read-other-relay.hcl").exists())
def test_submit_refuses_unlisted_requester(self) -> None:
with self.assertRaises(SystemExit):
ccr_intake.submit(self.submit_args(requester="random-agent"), cc)
def test_submit_refuses_policy_overwrite(self) -> None:
(self.root / "openbao/policies/workload-kv-read-other-relay.hcl").write_text("different\n")
with self.assertRaises(SystemExit):
ccr_intake.submit(self.submit_args(), cc)
def test_submit_refuses_secret_markers(self) -> None:
args = self.submit_args()
Path(args.ccr).write_text(Path(args.ccr).read_text() + "# hvs.notarealtoken\n")
with self.assertRaises(SystemExit):
ccr_intake.submit(args, cc)
def submitted_branch(self) -> tuple[Path, str]:
main_root = Path(tempfile.mkdtemp())
self.addCleanup(shutil.rmtree, main_root, True)
shutil.copytree(self.root, main_root, dirs_exist_ok=True)
destination, _violations = ccr_intake.submit(self.submit_args(), cc)
return main_root, destination.stem
def test_branch_gate_accepts_clean_submission(self) -> None:
main_root, stem = self.submitted_branch()
self.assertEqual(ccr_intake.branch_gate(main_root, stem, cc), [])
def test_branch_gate_refuses_extra_changes(self) -> None:
main_root, stem = self.submitted_branch()
(self.root / "registry").mkdir()
(self.root / "registry/ccr-standard-profile.yaml").write_text("submitters: [anyone]\n")
errors = ccr_intake.branch_gate(main_root, stem, cc)
self.assertIn("ccr branch may not change registry/ccr-standard-profile.yaml", errors)
def test_branch_gate_refuses_modified_existing_policy(self) -> None:
main_root, stem = self.submitted_branch()
path = self.ccrs / f"{stem}.yaml"
data = cc.load_yaml(path)
data["openbao"]["policy_file"] = POLICY
cc.dump_yaml(path, data)
(self.root / POLICY).write_text((self.root / POLICY).read_text() + "# widened\n")
errors = ccr_intake.branch_gate(main_root, stem, cc)
self.assertTrue(any("may not modify" in e for e in errors), errors)
def test_branch_gate_refuses_hand_edited_review(self) -> None:
main_root, stem = self.submitted_branch()
path = self.ccrs / f"{stem}.yaml"
data = cc.load_yaml(path)
data["review"]["comments"].append({"reviewer": "founder", "decision": "approved", "comment": "ok"})
cc.dump_yaml(path, data)
errors = ccr_intake.branch_gate(main_root, stem, cc)
self.assertTrue(any("policy-as-code approval" in e for e in errors), errors)
def test_branch_gate_refuses_unlisted_requester(self) -> None:
main_root, stem = self.submitted_branch()
path = self.ccrs / f"{stem}.yaml"
data = cc.load_yaml(path)
data["requester"]["agent"] = "someone-else"
cc.dump_yaml(path, data)
errors = ccr_intake.branch_gate(main_root, stem, cc)
self.assertTrue(any("listed submitter" in e for e in errors), errors)
def test_branch_gate_refuses_existing_ccr(self) -> None:
main_root = Path(tempfile.mkdtemp())
self.addCleanup(shutil.rmtree, main_root, True)
shutil.copytree(self.root, main_root, dirs_exist_ok=True)
errors = ccr_intake.branch_gate(main_root, Path(STANDARD).stem, cc)
self.assertTrue(any("already exists on main" in e for e in errors), errors)
def test_request_decision_records_id_after_platform_review(self) -> None:
ccr_intake.review_standard(self.path, cc)
with mock.patch.object(cc, "state_hub_post_json", return_value={"id": "dec-1", "status": "open"}) as post:
ccr_intake.request_decision(self.path, cc, "http://hub")
payload = post.call_args.args[2]
self.assertIn("APPROVE: CCR-2026-0051", payload["description"])
self.assertNotIn("status", payload)
self.assertNotIn("Decision link", payload["description"])
state_hub = cc.load_yaml(self.path)["state_hub"]
self.assertEqual(state_hub["decision_id"], "dec-1")
self.assertEqual(cc.load_yaml(self.path)["status"], "proposed")
with self.assertRaises(SystemExit):
ccr_intake.request_decision(self.path, cc, "http://hub")
def test_request_decision_requires_platform_approval(self) -> None:
self.edit(lambda d: d["risk"].update(classification="high"))
ccr_intake.review_standard(self.path, cc)
with mock.patch.object(cc, "state_hub_post_json") as post, self.assertRaises(SystemExit):
ccr_intake.request_decision(self.path, cc, "http://hub")
post.assert_not_called()
def test_request_decision_refuses_pre_resolved_decision(self) -> None:
ccr_intake.review_standard(self.path, cc)
resolved = {"id": "dec-2", "status": "resolved"}
with mock.patch.object(cc, "state_hub_post_json", return_value=resolved), self.assertRaises(SystemExit):
ccr_intake.request_decision(self.path, cc, "http://hub")
def test_render_policy_matches_reviewed_policy_file(self) -> None:
rendered = ccr_intake.standard_policy_hcl("platform/suppliers/scaleway/mas-tem-relay", cc)
self.assertEqual(rendered, (REPO_DIR / POLICY).read_text())
def test_plan_ref_passes_through_submit_and_is_shape_checked(self) -> None:
args = self.submit_args()
draft = cc.load_yaml(Path(args.ccr))
draft["plan_ref"] = {"repo": "ops-mason", "path": "plans/x.md", "commit": "d19e6b1"}
cc.dump_yaml(Path(args.ccr), draft)
destination, violations = ccr_intake.submit(args, cc)
self.assertEqual(violations, [])
self.assertEqual(cc.load_yaml(destination)["plan_ref"]["commit"], "d19e6b1")
self.assert_violation(lambda d: d.update(plan_ref={"repo": "ops-mason"}), "plan_ref")
if __name__ == "__main__":
unittest.main()