Sandor Molnar created KNOX-3449:
-----------------------------------
Summary: k8s delegation E2E: CI harness + same-subject exchange,
TrustedOIDCIssuers admin API, and negative-path coverage
Key: KNOX-3449
URL: https://issues.apache.org/jira/browse/KNOX-3449
Project: Apache Knox
Issue Type: Task
Components: CI
Affects Versions: 3.1.0
Reporter: Sandor Molnar
Assignee: Sandor Molnar
Fix For: 3.1.0
*Description*
Stand up the CI harness that lets our Docker E2E suite treat the throwaway k3s
cluster as a trusted OIDC issuer, and add all delegation/token-exchange tests
that pass against the currently-merged backend. This is the "ready now" half of
KNOX-3238; the policy-enforced delegation and headless-exchange tests are split
into a separate, blocked sub-task (see Dependencies).
The base compose stack already runs k3s + a bootstrap job for the SPIFFE-header
ServiceAccountValidator path, but that trust is fabric8/kubeconfig-based and
unrelated to JWT/JWKS verification. Nothing today lets Knox fetch and trust the
k3s OIDC JWKS, and no topology exposes the KNOXIDF_ADMIN API. This ticket
builds that wiring and proves the token-exchange path end-to-end on real
projected ServiceAccount tokens.
*Scope*
+In scope+
* New compose overlay
.github/workflows/compose/docker-compose.k8s-delegation.yml + a label-gated CI
job in tests.yml (pattern: the existing knoxidf-federation / hashicorp-vault
overlays).
* Extend the k8s bootstrap so k3s issues SA tokens with a reachable issuer
(service-account-issuer=[https://k3s:6443),] grant anonymous access to the OIDC
discovery/JWKS endpoints (system:service-account-issuer-discovery →
system:unauthenticated), and export the cluster CA cert + issuer URL + a
freshly-minted projected SA token to the shared k3s-output volume.
* Custom Knox entrypoint (mounted via the overlay, mirroring
gateway-single-eku.sh) that imports the k3s CA into the JVM cacerts before
starting the gateway — required because JWKS verification (Nimbus) and OIDC
discovery both use the JVM default trust store, not
gateway.httpclient.truststore.*.
* New topology knoxidf-admin.xml declaring <role>KNOXIDF_ADMIN</role> behind
ShiroProvider (basic auth) + AclsAuthz (admin-only). Reuse the existing
knoxidf-token.xml (JWTProvider → KNOXIDF) for the exchange call.
* New test file .github/workflows/tests/test_k8s_delegation.py covering the
acceptance criteria below.
+Out of scope+
* Actor-token delegation with policy enforcement (AC4) and headless
requested_subject exchange (AC5) — blocked on backend work, tracked separately.
* Any backend/Java changes — this ticket is harness + tests only.
*Acceptance criteria*
* (AC1) test_k8s_delegation.py runs in CI under the new k8s delegation compose
overlay.
* (AC8) The bootstrap exports the k3s CA cert and issuer URL to the shared
volume; Knox trusts the JWKS endpoint and tests can register the issuer.
* (AC2) A setup-validation step decodes the minted SA token and asserts the
typ JOSE header is absent (documents why the permissive verifier / KNOX-3434 is
needed).
* (AC9) TrustedOIDCIssuers admin API works over the wire: register (POST
.../knoxidf/admin/v1/trusted-oidc-issuers), list (GET), refresh JWKS (POST
.../refresh-jwks?issuerUrl=), remove (DELETE ?issuerUrl=) — with list
assertions before/after.
* (AC3) A same-subject exchange
(grant_type=urn:ietf:params:oauth:grant-type:token-exchange, subject_token =
k3s projected SA token, no actor_token) succeeds with HTTP 200 after the issuer
is registered.
* (AC6) An exchange whose subject_token carries an unregistered issuer is
rejected with HTTP 401 invalid_request (and no outbound JWKS fetch).
* (AC7) An exchange whose subject_token has a past exp is rejected with HTTP
401 "Token has expired".
*Technical notes*
* Exchange endpoint: POST
[https://knox:8443/gateway/knoxidf-token/knoxidf/api/v1/token.] The
KNOXIDF_ADMIN/KNOXIDF roles auto-select the H2-backed TrustedOidcIssuerService
(self-provisions under securityDir/h2db) — no DB stand-up or extra config
needed.
* Register body:
{"issuerUrl":"[https://k3s:6443|https://k3s:6443/]","dynamicJwks":true,"clusterName":"k3s"}.
issuerUrl must be HTTPS or registration 400s. Leave
knox.token.exchange.dynamic.jwks.allow.http unset (k3s JWKS is HTTPS).
* The SA token's iss must equal the registered issuerUrl and be reachable for
discovery; hence setting
service-account-issuer=[https://k3s:6443|https://k3s:6443/] (the --tls-san=k3s
cert already covers that host).
* AC6/AC7 can use hand-crafted JWTs — expiry and issuer-trust are checked
before signature verification, so no k3s signing key is required. Add PyJWT to
requirements.txt or build the token manually.
* The tests service must mount k3s-output (read-only) to read the exported SA
token + CA; it currently does not.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)