NK-WP-0056-T19: executor approval exercise; parse approval-engine's stored assurance object
The exercise runs the real request phase, KeyCape client credentials, preflight and consume against KeyCape's pinned image and approval-engine's source with synthetic keys. It found that approval-engine stores an entry's assurance as the verified token's JSON object (KeyCape assuranceClaim), so the executor's comparison with a bare "aal2" refused every real founder approval. entry_is_aal2 now requires level aal2/aal3 with mfa true and fails closed otherwise. Fakes use the real shape. The request-phase tests freeze the clock inside the example admission's window (they had expired on 2026-11-03T11:00Z). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 523928@bnt-lap001 Assistant-Session: 6c737afb-9c14-4152-9f02-477214b9c350
This commit is contained in:
parent
338483f621
commit
625ad652b9
6 changed files with 458 additions and 6 deletions
|
|
@ -21,6 +21,11 @@ bea = X.bea
|
|||
|
||||
PILOT = bea.load(X.REPO / "examples/bounded-execution-admission/bind-rotation-svc-authelia.yaml")
|
||||
ADMIN_SUB = "kc-sub-0f3a" # opaque KeyCape subject of the human approver `admin`
|
||||
# approval-engine stores the verified assurance claim as JSON (api.py); KeyCape mints this shape (token.go).
|
||||
AAL2 = json.dumps({"at": 1793000000, "level": "aal2", "methods": ["pwd", "otp"], "mfa": True, "source": "key-cape"},
|
||||
sort_keys=True)
|
||||
AAL1 = json.dumps({"at": 1793000000, "level": "aal1", "methods": ["pwd"], "mfa": False, "source": "key-cape"},
|
||||
sort_keys=True)
|
||||
NOW = dt.datetime(2026, 11, 3, 9, 30, tzinfo=dt.UTC)
|
||||
SECRET = "synthetic-bind-value-never-emitted"
|
||||
|
||||
|
|
@ -51,7 +56,7 @@ class FakeCarrier:
|
|||
"human_control": True, "pdp_path": False},
|
||||
"validity": {"not_before": admission["spec"]["window"]["not_before"],
|
||||
"expires_at": admission["spec"]["window"]["not_after"]},
|
||||
"entries": [{"subject_id": ADMIN_SUB, "assurance": "aal2", "principal_type": "human",
|
||||
"entries": [{"subject_id": ADMIN_SUB, "assurance": AAL2, "principal_type": "human",
|
||||
"approved_at": "2026-11-03T08:55:00Z"}],
|
||||
}
|
||||
for k, v in over.items():
|
||||
|
|
@ -223,7 +228,7 @@ class RefusalTests(Base):
|
|||
"trust_not_satisfied:runtime_secret_trust": lambda: setattr(self.w, "trust_ok", False),
|
||||
"approval_binding": lambda: self.w.carrier.approval["binding"]["target"].update(admission_digest="sha256:" + "0" * 64),
|
||||
"approval_status": lambda: self.w.carrier.approval.update(status="requested"),
|
||||
"approval_entry": lambda: self.w.carrier.approval["entries"][0].update(assurance="aal1"),
|
||||
"approval_entry": lambda: self.w.carrier.approval["entries"][0].update(assurance=AAL1),
|
||||
"approval_expires_before_window_end": lambda: self.w.carrier.approval["validity"].update(expires_at="2026-11-03T10:00:00Z"),
|
||||
}
|
||||
for reason, mutate in cases.items():
|
||||
|
|
@ -233,13 +238,24 @@ class RefusalTests(Base):
|
|||
self.assert_no_effect(self.run_it(), reason)
|
||||
|
||||
def test_approval_by_someone_not_listed_or_not_human(self):
|
||||
for entry in ({"subject_id": "kc-sub-other", "assurance": "aal2", "principal_type": "human"},
|
||||
{"subject_id": ADMIN_SUB, "assurance": "aal2", "principal_type": "service"}):
|
||||
for entry in ({"subject_id": "kc-sub-other", "assurance": AAL2, "principal_type": "human"},
|
||||
{"subject_id": ADMIN_SUB, "assurance": AAL2, "principal_type": "service"}):
|
||||
with self.subTest(entry=entry):
|
||||
self.setUp()
|
||||
self.w.carrier.approval["entries"] = [entry]
|
||||
self.assert_no_effect(self.run_it(), "approval_entry")
|
||||
|
||||
def test_assurance_must_be_keycapes_verified_aal2(self):
|
||||
"""T19 finding: approval-engine stores the token's assurance object as JSON, never a bare level."""
|
||||
for assurance in ("aal2", AAL1, json.dumps({"level": "aal2", "mfa": False}), "not json", None,
|
||||
json.dumps(["aal2"])):
|
||||
with self.subTest(assurance=assurance):
|
||||
self.setUp()
|
||||
self.w.carrier.approval["entries"][0]["assurance"] = assurance
|
||||
self.assert_no_effect(self.run_it(), "approval_entry")
|
||||
for assurance in (AAL2, json.loads(AAL2), json.dumps({"level": "aal3", "mfa": True})):
|
||||
self.assertTrue(X.entry_is_aal2(assurance))
|
||||
|
||||
def test_actor_must_be_this_executor(self):
|
||||
self.w.carrier.approval["binding"]["actor"] = "service:someone-else"
|
||||
self.assert_no_effect(self.run_it(), "approval_binding")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue