test: authenticate the caproni e2e suite with a token-exchange JWT

Summary

The test/caproni e2e rig and its suite (scripts/e2e/run-e2e-tests.sh) ran on the bootstrap-token stub. This switches them to token_exchange so the suite exercises the JWT authentication path instead.

  • test/caproni/values/artifact-registry.yaml — replace the auth.bootstrap_token block with auth.token_exchange, verifying against the self-signed iam-data-access rig's committed JWKS (scripts/iam-rig-mint-jwt/testdata/jwks.json). No monolith or IAM service in the cluster is required; the pod only needs egress to fetch the JWKS. keys_url is pinned to main (a stable committed fixture), mirroring the raw-JWKS URL the test:integration:iam-rig job already uses.
  • scripts/e2e/run-e2e-tests.sh — mint a short-lived rig JWT per run with iam-rig-mint-jwt (issuer and audience matching the config, origin_id set to the provisioned namespace's entity, and the non-empty local_id claim that userauth requires) instead of sending the dev bootstrap token. AR_TOKEN still overrides, for a rig on a different issuer.
  • docs/dev/caproni-e2e.md — describe the new auth path.

Behavior-preserving for the suite's assertions; only the credential and the AR auth mode change. ~58 lines across 3 files.

Governing ADRs

ADR-020 (Authentication flow) — token-exchange local JWT validation. This change conforms: it moves the e2e rig onto the token-exchange validator using the interim self-signed issuer ADR-020 describes, rather than the bootstrap stub. No deviation; no product code changes.

Testing

Deployed the test/caproni rig locally (published v1.373.0 chart + these values) and ran the suite end to end:

  • The deployed AR logged token-exchange: JWKS fetched; verifier ready from the committed keys_url, and gated readiness on it.
  • run-e2e-tests.sh minted a rig JWT and passed all 8 scenarios (provision 201, idempotent replay 200, resolve 200, create repo 201, read 200, list 200, recreate conflict 409). The JWT authenticated on both the /api/gitlab/v1 platform surface (validator fallback) and the /api/v1 management surface.

Supporting local checks:

  • The minted token verifies through AR's real tokenexchange.Validator against the committed JWKS with the config's issuer/audience.
  • The pod's appConfig.data loads through config.Load with token_exchange selected and bootstrap_token absent.
  • go test ./internal/auth/... ./internal/config/... ./scripts/iam-rig-mint-jwt/... and the composed-app token-exchange test pass; shellcheck clean.

The CI test:e2e:caproni job (k3d in dind) and the -tags=integration suite (testcontainers) run in CI.

Merge request reports

Loading
Loading