Stabilize credential-change test suite (RAILIANCE-WP-0014)
Five failures in full credential test discovery, none of them broker regressions: - CCR-2026-0009 referenced a policy file that was never added, and used a schema-invalid access_frontdoor.readiness value. Add the least-privilege workload-kv-read-qonto-assistant.hcl (read-only on tenants/binky/qonto-api) and set readiness to pending-review. The lane stays proposed and non-resolvable. - Three refusal tests used the live CCR-2026-0002 file as their "unapproved CCR" fixture. That lane is now approved, applied and active, so the gates correctly permitted it and the tests failed; applier-apply then walked into its interactive confirmation prompt and raised EOFError under a non-interactive runner. Add an unapproved_ccr() helper that materializes a normalized temp copy so approval state is no longer read off a mutable production artifact. - The approve/unconfirmed-claim test demoted an active CCR to approved while leaving resolvable=true, tripping a correct validation rule. Build it from the same helper. No gate, blocker, validation rule, or grant semantic was changed. Verified: credential discovery 52/52 and full discovery 61/61 pass non-interactively, make credential-change-validate passes all nine CCRs, the grant catalog validates, and both audit-core openbao-database-credential grants retain exec-env-only delivery and revoke-on-exec-exit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
9f6bdffec4
commit
b7aef386d5
4 changed files with 195 additions and 32 deletions
|
|
@ -29,6 +29,26 @@ class CredentialChangeTests(unittest.TestCase):
|
|||
/ "credential-change-requests/CCR-2026-0002-issue-core-ingestion-api-key.yaml"
|
||||
)
|
||||
|
||||
def unapproved_ccr(self, source: Path | None = None) -> Path:
|
||||
"""Return a temp CCR copy that is genuinely pre-approval.
|
||||
|
||||
Refusal tests must not read approval state off a live repo CCR: once a
|
||||
lane is applied and activated, the file stops being an unapproved
|
||||
fixture and the expected refusal silently turns into a success.
|
||||
"""
|
||||
source = source or self.issue_core
|
||||
tmp = Path(tempfile.mkdtemp())
|
||||
self.addCleanup(shutil.rmtree, tmp, True)
|
||||
copied = tmp / source.name
|
||||
shutil.copy2(source, copied)
|
||||
data = credential_change.load_yaml(copied)
|
||||
data["status"] = "proposed"
|
||||
data["review"]["comments"] = []
|
||||
data["access_frontdoor"]["readiness"] = "pending-review"
|
||||
data["access_frontdoor"]["resolvable"] = False
|
||||
credential_change.dump_yaml(copied, data)
|
||||
return copied
|
||||
|
||||
def test_sample_ccr_validates_without_bound_claim_warning(self) -> None:
|
||||
ccr, errors, warnings = credential_change.validate_ccr(self.sample)
|
||||
self.assertEqual(errors, [])
|
||||
|
|
@ -249,38 +269,34 @@ class CredentialChangeTests(unittest.TestCase):
|
|||
def test_operator_commands_refuse_unapproved_ccr(self) -> None:
|
||||
with self.assertRaises(SystemExit):
|
||||
credential_change.command_operator_commands(
|
||||
type("Args", (), {"ref": str(self.issue_core)})()
|
||||
type("Args", (), {"ref": str(self.unapproved_ccr())})()
|
||||
)
|
||||
|
||||
def test_approve_records_comment_but_unconfirmed_claim_still_blocks_apply(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
tmp_path = Path(tmp)
|
||||
ccr_dir = tmp_path / "ccrs"
|
||||
ccr_dir.mkdir()
|
||||
copied = ccr_dir / self.issue_core.name
|
||||
shutil.copy2(self.issue_core, copied)
|
||||
old_ccr_dir = os.environ.get("CCR_DIR")
|
||||
os.environ["CCR_DIR"] = str(ccr_dir)
|
||||
try:
|
||||
credential_change.append_decision(
|
||||
copied, "approved", "unit-test", "looks right"
|
||||
copied = self.unapproved_ccr()
|
||||
ccr_dir = copied.parent
|
||||
old_ccr_dir = os.environ.get("CCR_DIR")
|
||||
os.environ["CCR_DIR"] = str(ccr_dir)
|
||||
try:
|
||||
credential_change.append_decision(
|
||||
copied, "approved", "unit-test", "looks right"
|
||||
)
|
||||
copied_data = credential_change.load_yaml(copied)
|
||||
copied_data["openbao"]["auth"]["bound_claims_confirmed"] = False
|
||||
credential_change.dump_yaml(copied, copied_data)
|
||||
ccr, errors, _warnings = credential_change.validate_ccr(copied)
|
||||
self.assertEqual(errors, [])
|
||||
self.assertEqual(ccr["status"], "approved")
|
||||
self.assertEqual(ccr["review"]["comments"][-1]["comment"], "looks right")
|
||||
with self.assertRaises(SystemExit):
|
||||
credential_change.command_apply_plan(
|
||||
type("Args", (), {"ref": "CCR-2026-0002"})()
|
||||
)
|
||||
copied_data = credential_change.load_yaml(copied)
|
||||
copied_data["openbao"]["auth"]["bound_claims_confirmed"] = False
|
||||
credential_change.dump_yaml(copied, copied_data)
|
||||
ccr, errors, _warnings = credential_change.validate_ccr(copied)
|
||||
self.assertEqual(errors, [])
|
||||
self.assertEqual(ccr["status"], "approved")
|
||||
self.assertEqual(ccr["review"]["comments"][-1]["comment"], "looks right")
|
||||
with self.assertRaises(SystemExit):
|
||||
credential_change.command_apply_plan(
|
||||
type("Args", (), {"ref": "CCR-2026-0002"})()
|
||||
)
|
||||
finally:
|
||||
if old_ccr_dir is None:
|
||||
os.environ.pop("CCR_DIR", None)
|
||||
else:
|
||||
os.environ["CCR_DIR"] = old_ccr_dir
|
||||
finally:
|
||||
if old_ccr_dir is None:
|
||||
os.environ.pop("CCR_DIR", None)
|
||||
else:
|
||||
os.environ["CCR_DIR"] = old_ccr_dir
|
||||
|
||||
def test_confirm_binding_records_comment_and_clears_warning(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
|
|
@ -324,7 +340,7 @@ class CredentialChangeTests(unittest.TestCase):
|
|||
|
||||
def test_applier_dry_run_refuses_unapproved_ccr(self) -> None:
|
||||
exit_code = credential_change.command_applier_dry_run(
|
||||
type("Args", (), {"ref": str(self.issue_core), "json": False})()
|
||||
type("Args", (), {"ref": str(self.unapproved_ccr()), "json": False})()
|
||||
)
|
||||
self.assertEqual(exit_code, 1)
|
||||
|
||||
|
|
@ -406,7 +422,7 @@ class CredentialChangeTests(unittest.TestCase):
|
|||
"Args",
|
||||
(),
|
||||
{
|
||||
"ref": str(self.issue_core),
|
||||
"ref": str(self.unapproved_ccr()),
|
||||
"actor": "unit-test",
|
||||
"confirm": None,
|
||||
"bao_bin": "bao",
|
||||
|
|
@ -509,7 +525,7 @@ class CredentialChangeTests(unittest.TestCase):
|
|||
"Args",
|
||||
(),
|
||||
{
|
||||
"ref": str(self.issue_core),
|
||||
"ref": str(self.unapproved_ccr()),
|
||||
"json": False,
|
||||
"execute_metadata": False,
|
||||
"actor": "unit-test",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue