Verify reader scope before accepting absence of enrolled factors
All checks were successful
Authentication acceptance / acceptance (push) Successful in 1m6s
Build and Publish Container Image / build-and-push (push) Successful in 53s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a092fe-13b1-7f12-ac74-7d258af4d79c
This commit is contained in:
tegwick 2026-09-13 16:59:09 +02:00
parent 122a0d1369
commit 113f3a6296
6 changed files with 221 additions and 7 deletions

View file

@ -91,3 +91,26 @@ an OpenBao path. Deploying an approved file requires a separate protected mount,
read permission for KeyCape's runtime identity, renewal/expiry ownership, and
positive factor/no-factor plus failed-credential/recovery evidence. Existing live
configuration and policy have not been changed by implementing this feature.
## Distinguish missing factors from revoked reader access
The installed provider returns HTTP 200 with zero tokens after tokenlist policy
withdrawal. Before accepting a no-factor result, KeyCape therefore requires a
second exact-serial lookup for `privacyidea.readProbeSerial`. This must identify
a disabled, unassigned token in exactly the configured realm. Missing probe,
missing visibility, assignment, activation, realm mismatch or provider failure
denies the decision. Existing confirmed factors still require MFA.
The production probe is `KCFACTORSCOPE01`, created idempotently by NetKingdom's
`sso-mfa/k8s/privacyidea/keycape-scope-probe.py`. Its key is generated by the
provider and never delivered to KeyCape. Keep it disabled and unassigned; it
exists solely to prove realm visibility. Removing it intentionally makes
no-factor decisions unavailable until scope proof is restored.
`provider-onboarding-contract.py` uses a temporary in-memory database and no
production configuration or credentials. Against the installed provider it
proved password-only pass-through, pending-active enrollment, cancellation,
TOTP possession confirmation (explicit `type=totp` on confirmation), confirmed
state, empty-success on permission withdrawal, permission recovery and rejection
of a genuinely provider-issued expired JWT. Production expiry/revocation drills
remain separately recorded under RPF-WP-0040-T04.