diff --git a/docs/optional-mfa.md b/docs/optional-mfa.md index b6e27a8..f95f57a 100644 --- a/docs/optional-mfa.md +++ b/docs/optional-mfa.md @@ -18,56 +18,33 @@ administrative tokenlist permission: a user-role token only lists its own factor regardless of the requested username. Never replace it with a self-service JWT. See the [provider API](https://privacyidea.readthedocs.io/en/stable/modules/api/token.html). -## Deployment gate — optional client policy not yet enabled +## Deployed policy and guarded onboarding -Factor-read custody, automatic renewal and mounted-file delivery were restored -on 2026-09-13 through RPF-WP-0040 / CCR-2026-0023. KeyCape uses adminTokenFile; -per-user provider lookup and mounted renewal passed. Historical resolver incident -lanes remain separate; there is no missing-owner gate for this service lane. +P06 is deployed for `vergabe-demo-company` and `user-engine-portal` only. +The issuer owns persistent runtime overrides in `KEYCAPE_POLICY_PATH` on the +`keycape-authentication-policy` PVC. Use the portal Authentication policy page +with a recent-MFA platform session for preview, acknowledged apply and rollback. +Explicit application AAL2 always wins. Administration requires MFA even when +ordinary portal sign-in is optional until factor activation. -The live provider has `mfa-passthru-phase1`, so a positive validation value alone -can mean directory-password success. KeyCape accepts AAL2 only when a successful -response identifies a TOTP/HOTP token by serial and type. Static-password tokens, -missing factor evidence and unsuccessful status cannot grant AAL2. +privacyIDEA self-service allows TOTP enrollment and deletion only for unfinished +verification-state setup. Possession confirmation activates the factor. An active +factor cannot be deleted, disabled or replaced from a password-only provider +session; use audited platform recovery. Both native issuer and installed-provider +browser acceptance passed against disposable identities and databases. -privacyIDEA's `active` flag does not imply completed enrollment. Its verification -policy sets `rollout_state=verify` while leaving `active` unchanged. KeyCape -therefore recognizes `enrolled` and the provider's legacy empty state as enrolled; -`verify`, `clientwait` and `pending` remain incomplete. Missing/unknown/broken -states and incomplete result pages fail closed. Existing verified factors still -require OTP while an additional token is pending. Mandatory and explicit AAL2 -policies remain mandatory throughout onboarding. +Factor-read custody, automatic renewal and mounted-file delivery use +RPF-WP-0040 / CCR-2026-0023. No-factor decisions require the realm visibility +probe. Provider lookup/credential failures deny login; pending factor state does +not activate MFA. Validation requires actual TOTP/HOTP evidence, so provider +password passthrough cannot establish AAL2. -Current provider self-service policy allows TOTP enrollment/deletion/disabling, -but possession confirmation is not yet required. Review and exercise that -transition plus authenticated recovery before enabling the optional client. - -Remaining live acceptance: - - -1. Verify the deployed provider accepts the raw JWT and returns authoritative - count/tokens results for controlled accounts with and without a factor. - Confirm realm/resolver mapping and administrative tokenlist scope, including - visibility of another user's factor; an empty list alone is not proof. -2. Verify self-service at https://pink-account.coulomb.social: password login, - TOTP enrollment with possession confirmation before activation, cancellation, - and factor removal/recovery. This user-facing flow is not yet verified. -3. Build and pin the reviewed issuer image. Migrate only the exact - vergabe-demo-company registration to mfaOptional using the owner CAS rollout - lane; keep unrelated registrations and Secret bytes intact. The current - vergabe-client-rollout.py intentionally refuses registration differences and - needs an explicit migration before this policy can be applied. -4. Resolve account-portal access for unenrolled users without weakening privileged - access. Review portal policy and self-service permissions before expanding the - optional setting to this shared client. Add the verified enrollment link to - account management once that flow works. -5. Verify fresh password-only admission without a factor, enrollment confirmation, - then OTP enforcement (including reuse of an old AAL1 session). Verify explicit - AAL2 still challenges, lookup failures recover without issuing a code, logout - permits identity switching, and other clients retain their policies. - -Rollback: restore the exact previous client registration and image pin via CAS. -This restores mandatory MFA for the demo client; it is not password-only access. +Release, exact image pins, positive test coverage and rollback order: +`../user-engine/docs/evidence/2026-09-13-p06-authentication-policy.md`. +Actual invited-person and application login remains KEY-WP-0034 and +VERGABE-WP-0019. Keep the policy PVC and provider guard during replacement. +Before reverting pre-P06 portal guards, restore and verify mandatory policy for +both clients in runtime and baseline registration. ## Credential renewal consumer contract @@ -89,8 +66,8 @@ The credential must remain provider-issued, realm-scoped and renewed through owner custody. This consumer feature neither mints credentials nor establishes 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. +positive factor/no-factor plus failed-credential/recovery evidence. The dedicated delivery lane is deployed; historical resolver credential repair +remains separately owned under NK-WP-0033. ## Distinguish missing factors from revoked reader access diff --git a/workplans/KEY-WP-0035-optional-mfa.md b/workplans/KEY-WP-0035-optional-mfa.md index 826eeb8..29eb711 100644 --- a/workplans/KEY-WP-0035-optional-mfa.md +++ b/workplans/KEY-WP-0035-optional-mfa.md @@ -4,11 +4,11 @@ type: workplan title: "Opt-in MFA for demo-company login" domain: infotech repo: key-cape -status: active +status: finished owner: codex topic_slug: infotech created: "2026-09-13" -updated: "2026-09-13" +updated: "2026-09-14" state_hub_workstream_id: "b27601d8-d0a5-5c79-a1ff-c2a4cedafa74" --- @@ -33,7 +33,7 @@ Validation: `go test ./...` and `git diff --check` passed on 2026-09-13. See doc ```task id: KEY-WP-0035-T02 -status: progress +status: done priority: high state_hub_task_id: "b066a273-f91c-50ee-b497-a39eace03b3a" ``` @@ -50,7 +50,7 @@ optional policy. See railiance-platform/docs/evidence/2026-09-13-keycape-factor- ```task id: KEY-WP-0035-T03 -status: wait +status: done priority: high state_hub_task_id: "93ce2e97-6c5a-58a7-8f3c-1c4f0eb6f1b5" ``` @@ -101,3 +101,12 @@ failing closed. Native scope proof passed. Isolated installed-provider tests passed possession confirmation/cancellation, permission withdrawal/recovery and provider-issued JWT expiry; these are now included in CI. T02/T03 remain the actual optional-client and self-service browser activation gates. + +2026-09-14: T02/T03 completed through USER-WP-0033 P06. Installed-provider +native and five browser checks passed, including confirmed activation, +cancellation, old-session MFA and denied active-factor replacement. Portal +guards, provider restrictions and both scoped optional-client policies are live; +PVC readback confirms effective state. Full release evidence and rollback: +`../user-engine/docs/evidence/2026-09-13-p06-authentication-policy.md`. +Residual actual-user and workload sign-in acceptance remains live under +KEY-WP-0034, USER-WP-0028 and VERGABE-WP-0019 before this closure.