Skip to content

docs(spec): CITrust reconciler on Keycloak 26.x token-exchange v2 (PLAT-DATA-25) - #820

Open
markturansky wants to merge 1 commit into
mainfrom
implementer/spec-PLAT-DATA-25-citrust-keycloak-token-exchange
Open

markturansky wants to merge 1 commit into
mainfrom
implementer/spec-PLAT-DATA-25-citrust-keycloak-token-exchange

Conversation

@markturansky

Copy link
Copy Markdown
Collaborator

Purpose

This change codifies the intent of issue #819 (PLAT-DATA-25) in the CI Trust
Extension API specification. It specifies the CITrust reconciler against the
Keycloak 26.x external-to-internal token-exchange v2 mechanism. The fine-grained
admin authorization v1 path, which the earlier draft assumed, is disabled on the
production fleet Keycloak and returns HTTP 501. This is a specification change
only; it adds no code.

What changes

In specs/platform/ci-trust-ext-api.spec.md (prefix PLAT-CITR):

  • The architecture prose no longer points to the v1 helper
    (EnsureE2ETokenExchange / enableTokenExchangePermissions) as the path to
    extend. The v2 requirement is scoped to the production fleet Keycloak. The v1
    helper stays valid only for the separate end-to-end impersonation subsystem.
  • PLAT-CITR-01: the control plane adopts a platform-provisioned (gitops)
    identity provider. It does not create a parallel one and does not delete the
    provisioned one (scenario 01.02). This resolves the idp_alias difference.
  • PLAT-CITR-02: the exchange is realized through the v2 admin-REST path with the
    public federation client. A delete reverts the authorization.
  • PLAT-CITR-04: the per-repository subject predicate is the trust boundary.
    Audience pinning is necessary but not sufficient, because any repository can
    mint a token that carries the pinned audience (scenario 04.02).
  • PLAT-CITR-05: deleting a CITrust revokes the exchange (scenario 05.02).
  • PLAT-CITR-08 (new): Keycloak 26.x external-to-internal token-exchange v2. The
    v1 token-exchange and fine-grained-authz-v1 paths are prohibited.
  • PLAT-CITR-09 (new): the reconcile is idempotent and re-entrant. Its artifacts
    survive the realm-reconcile job. It fails closed on unknown Keycloak state.
  • The security analysis and the PLAT-CITR count in specs/ids.md are updated.

Whole-tree coherence audit

All of specs/ was searched for the key terms: token-exchange,
EnsureE2ETokenExchange, enableTokenExchangePermissions, fine-grained,
management/permissions, external-internal, subject_issuer, and Keycloak
26.x.

  • The end-to-end and pull-request impersonation specs
    (ephemeral-pr-environments, ephemeral-test-credentials, e2e-testing)
    describe a separate subsystem on its own Keycloak. They stay coherent because
    the CITrust spec now scopes the v2 requirement to the production fleet Keycloak.
  • Remaining hits (oidc-integration BFF refresh, openshell-gateway-console,
    openshell-gateway-service-accounts, hsctl-release) are unrelated uses of the
    phrase.
  • data-model.spec.md (PLAT-DATA-24/25) kinds are unchanged.

Verification

  • make check-spec-ids passes.
  • make check-forbidden-terms passes.
  • The pre-commit policy hook passes.

Closes #819

🤖 Generated with Claude Code

…e v2

Codify the intent of issue #819 (PLAT-DATA-25) in the CI Trust
Extension API specification. The reconciler realization moves from the
Keycloak fine-grained-authz v1 path, which the production fleet Keycloak
26.x has disabled (501), to the external-to-internal token-exchange v2
mechanism with a public, keyless requester.

Changes to specs/platform/ci-trust-ext-api.spec.md (prefix PLAT-CITR):
- Rewrite the architecture prose that cited the v1 helper
  EnsureE2ETokenExchange / enableTokenExchangePermissions as the path to
  extend; scope the v2 requirement to the production fleet Keycloak and
  note the v1 helper stays valid only for the separate e2e impersonation
  subsystem.
- PLAT-CITR-01: adopt a platform-provisioned (gitops) IdP instead of
  creating a parallel one; do not delete it on CIProvider delete
  (scenario 01.02). Resolves the idp_alias discrepancy.
- PLAT-CITR-02: realize the exchange through the v2 admin-REST path with
  the public federation client; delete reverts the authorization.
- PLAT-CITR-04: make the per-repository subject predicate the real trust
  boundary; audience pinning is necessary but not sufficient
  (scenario 04.02).
- PLAT-CITR-05: deleting a CITrust revokes the exchange (scenario 05.02).
- PLAT-CITR-08 (new): Keycloak 26.x external-to-internal token-exchange
  v2; prohibit the v1 token-exchange and fine-grained-authz-v1 paths.
- PLAT-CITR-09 (new): idempotent, re-entrant reconcile whose artifacts
  survive the realm-reconcile job; fail-closed on unknown Keycloak state.
- Update the security analysis and the PLAT-CITR count in specs/ids.md.

Whole-tree coherence audit: grepped all of specs/ for token-exchange,
EnsureE2ETokenExchange, enableTokenExchangePermissions, fine-grained,
management/permissions, external-internal, and Keycloak 26.x. The e2e /
PR-environment impersonation specs (ephemeral-pr-environments,
ephemeral-test-credentials, e2e-testing) describe a distinct subsystem
on its own Keycloak and stay coherent now that the CITrust spec scopes
v2 to the production fleet. Other hits (oidc-integration BFF refresh,
gateway-console, gateway-service-accounts, hsctl-release) are unrelated
uses of the phrase. data-model.spec.md (PLAT-DATA-24/25) kinds are
unchanged.

Closes #819

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 28, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@markturansky

Copy link
Copy Markdown
Collaborator Author

Spec review: agent/review-spec-approved

Verdict: APPROVED.

This specification change meets the intent of issue #819 (PLAT-DATA-25). The review found no blocking contradiction in the specs/ tree.

Strengths

  • The intent is codified correctly. The spec replaces the v1 token-exchange path with the Keycloak 26.x external-to-internal token-exchange v2 mechanism (TOKEN_EXCHANGE_EXTERNAL_INTERNAL_V2), driven through the admin REST API, with a public keyless requester client. This matches the issue and the live Keycloak 26.6 facts the issue records.
  • The security boundary is stated correctly. PLAT-CITR-04 makes the per-subject repository / repository_owner claim predicate the real trust boundary and states that audience pinning is necessary but not sufficient, because any repository can mint a token with the pinned audience. This is the central security point of the issue.
  • The spec stays a behavior contract, not an implementation plan. It leaves the exact v2 admin-REST shape and the choice between an IdP mapper and an exchange authorization policy to the implementer, as the issue open questions ask, while it still fixes the observable behavior.
  • New requirements are complete and well formed. PLAT-CITR-08 (v2 mechanism; v1 and the v1 permission API prohibited, 501) and PLAT-CITR-09 (idempotent, re-entrant, survives the realm-reconcile job, fails closed on unknown state) cover the acceptance criteria. PLAT-CITR-09 cites STD-RCON-02 and STD-RCON-08 correctly.
  • IdP adoption is resolved. PLAT-CITR-01 and scenario 01.02 state that the control plane adopts the gitops-provisioned github-actions IdP and does not create or delete a parallel one. This agrees with the gitops plumbing the issue references.
  • IDs are correct. The file holds 9 PLAT-CITR requirements and specs/ids.md records 9. Scenario IDs follow the canonical form.
  • Whole-tree coherence holds. The v1 helper EnsureE2ETokenExchange / enableTokenExchangePermissions and FGAP v1 are still used only by the e2e and ephemeral pull-request impersonation subsystem (ephemeral-pr-environments, ephemeral-test-credentials, e2e-testing), which runs on a separate, throwaway Keycloak where v1 is enabled. The CITrust spec scopes the v2 requirement to the production fleet Keycloak, so no sibling spec contradicts it.

Non-blocking observations

These are terminology-consistency points, not blockers. Neither line asserts the prohibited v1 mechanism; both use "permission" as a generic noun and defer the realization contract to this spec.

  1. specs/platform/data-model.spec.md:1619 still describes the CITrust realization as "a token-exchange permission from the shared federation client onto the gateway audience." This is the pre-change wording. For coherence with PLAT-CITR-02, consider "token-exchange authorization."
  2. specs/platform/ci-trust-ext-api.spec.md:196 (PLAT-CITR-05 requirement prose) still says "token-exchange permission," while the rest of the file now standardizes on "authorization" (PLAT-CITR-02 and the new scenario 05.02). Align the wording in a later pass.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(control-plane): implement CITrust reconciler — Keycloak v2 external→internal token-exchange (PLAT-DATA-25)

1 participant