diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index b154a88..1729bfa 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -64,6 +64,7 @@ | task | RPF-WP-ADHOC-2026-11-03-T02 | done | — | workplans/ADHOC-2026-11-03.md | | task | RPF-WP-ADHOC-2026-11-03-T03 | done | — | workplans/ADHOC-2026-11-03.md | | task | RPF-WP-ADHOC-2026-11-03-T04 | done | — | workplans/ADHOC-2026-11-03.md | +| task | RPF-WP-ADHOC-2026-11-03-T05 | done | — | workplans/ADHOC-2026-11-03.md | | task | RPF-WP-0015-T01 | done | — | workplans/RPF-WP-0015-audit-core-custody-and-recovery-coordination.md | | task | RPF-WP-0015-T02 | done | — | workplans/RPF-WP-0015-audit-core-custody-and-recovery-coordination.md | | task | RPF-WP-0015-T03 | done | — | workplans/RPF-WP-0015-audit-core-custody-and-recovery-coordination.md | diff --git a/tests/test_eso_auth_recovery.py b/tests/test_eso_auth_recovery.py index 6a08271..fac8e58 100644 --- a/tests/test_eso_auth_recovery.py +++ b/tests/test_eso_auth_recovery.py @@ -6,11 +6,31 @@ from types import SimpleNamespace import unittest from unittest.mock import patch +import yaml + ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT / 'scripts')) import repair_eso_kubernetes_auth as repair +APPROVED_CCR_STATUSES = {'approved', 'applied', 'verified', 'active'} + + +def approved_extension_paths(policy_file, lane_kv_path): + """Exact data paths that approved CCRs add to a recovery lane's policy file.""" + paths = [] + for ccr_path in sorted((ROOT / 'credential-change-requests').glob('CCR-*.yaml')): + ccr = yaml.safe_load(ccr_path.read_text()) + openbao = ccr.get('openbao') or {} + if ccr.get('status') not in APPROVED_CCR_STATUSES or openbao.get('policy_file') != policy_file: + continue + mount = openbao['mount'] + data_path = mount + '/data/' + openbao['kv_path'][len(mount) + 1:] + if data_path != lane_kv_path: + paths.append(data_path) + return paths + + class EsoRecoveryTests(unittest.TestCase): def setUp(self): self.lane = json.loads((ROOT / 'openbao/eso-auth-recovery/lanes.json').read_text())[0] @@ -32,12 +52,17 @@ class EsoRecoveryTests(unittest.TestCase): def test_no_credential_values_or_parent_access_in_generated_policies(self): for lane in json.loads((ROOT / 'openbao/eso-auth-recovery/lanes.json').read_text()): - policy=(ROOT / 'openbao/policies' / (lane['policy']+'.hcl')).read_text() + policy_file='openbao/policies/'+lane['policy']+'.hcl' + policy=(ROOT / policy_file).read_text() self.assertNotIn('*',policy) self.assertNotIn('/metadata/',policy) self.assertNotIn('"list"',policy) - self.assertEqual(policy.count('path "'),3) - self.assertIn('path "'+lane['kv_path']+'"',policy) + # Lane path plus token lookup-self/revoke-self, plus one exact data path + # per approved CCR that extends this policy file (e.g. CCR-2026-0046). + extra=approved_extension_paths(policy_file, lane['kv_path']) + self.assertEqual(policy.count('path "'),3+len(extra)) + for path in [lane['kv_path'], 'auth/token/lookup-self', 'auth/token/revoke-self', *extra]: + self.assertIn('path "'+path+'"',policy) def test_expired_token_response_is_distinct_from_authority_failure(self): for code in [400,403]: diff --git a/workplans/ADHOC-2026-11-03.md b/workplans/ADHOC-2026-11-03.md index f518875..fb22c85 100644 --- a/workplans/ADHOC-2026-11-03.md +++ b/workplans/ADHOC-2026-11-03.md @@ -163,3 +163,29 @@ Result: `test_credential_change.py` passes in full. Across the 25 test files that touch policies or CCRs, 337 pass and 1 fails. That failure is `test_eso_auth_recovery` (a lane policy has 4 paths and the test expects 3). It was on the T02 list and fails the same way without this change. + +## Repair the drifted ESO recovery policy test + +```task +id: RPF-WP-ADHOC-2026-11-03-T05 +status: done +priority: medium +``` + +`test_eso_auth_recovery` expected exactly three paths in each recovery lane's +policy. `workload-kv-read-reuse-surface-runtime-eso.hcl` has a fourth: the exact +data path `platform/workloads/reuse/reuse-surface/forgejo-source-read`. It was +added by CCR-2026-0046, which is `approved` and was recorded as verified in +`2951b69` (RPF-WP-0058). The test, written 2026-09-05, predates it. The source +was right; the test was stale. + +The test now allows one extra exact data path for each CCR that is approved, +applied, verified or active and names the same `policy_file`. The bans on +wildcards, metadata and `list` are unchanged, and the lane path and both token +self paths are now asserted explicitly. A mutation check passes: with +CCR-2026-0046 set back to `proposed`, the test fails. + +The policy comment still says "CCR-2026-0046 proposed" and was deliberately +left alone. `repair_eso_kubernetes_auth.py` requires the live policy to equal +this file byte for byte (`policy_drift`), so editing the comment would make the +next attended recovery refuse.