Require the organization the token speaks for

What does this MR do and why?

Authn::TokenExchange::TokenIssuer derived two claims from the user's home organization, origin_id and organization_role. IAM keys a principal identity on (origin, origin_id, local_id), so the organization decides which principal a token resolves to. Deriving it from the user hid that choice from the caller, so organization: is now a required argument.

No behaviour change. Both callers pass the value they were already getting.

  • The Artifact Registry services pass the request organization. callers_own_organization? still forces that to equal the home organization, so the token is identical to before.
  • POST /api/v4/token_exchange passes the caller's own organization explicitly. Deliberately not Current.organization, because Gitlab::Current::Organization#from_headers resolves X-GitLab-Organization-ID with no membership check, so wiring that in would let a caller mint a signed token naming an organization they have no relationship with. A new spec holds that the header cannot steer the token.

Why now

At launch every user stays homed in the default organization and picks up an organization_users row for organizations their groups transfer into (confirmation from the Organizations team). Artifact Registry role grants compare the home organization, so they cannot work in any other organization, which is currently blocking staging verification of the grant path in artifact-registry#473.

Fixing that needs two things. The service checks have to read organization_users, and the token has to carry the request organization. This MR is only the second half's plumbing, with no behaviour change, so the behavioural change can land as a small reviewable follow-up.

How to set up and validate locally

bundle exec rspec \
  ee/spec/lib/authn/token_exchange/token_issuer_spec.rb \
  ee/spec/requests/api/authn/token_exchange_spec.rb \
  ee/spec/services/authz/artifact_registry/

Two specs gained coverage that did not exist before. The issuer now has cases for the claims following the organization argument rather than the home organization, and the endpoint has one for the header being ignored.

The seven other spec files that reference TokenIssuer stub .new without argument constraints, so they are unaffected.

Merge request reports

Loading
Loading