[
https://issues.apache.org/jira/browse/KNOX-3449?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Sandor Molnar updated KNOX-3449:
--------------------------------
Description:
*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.
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.
was:
*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.
> 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
> Priority: Major
> 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.
> 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)