Repository navigation
atecontroller publishes actor JWT verification keys for ate-idp-server to serve - #2134
Closed
Max Thompson (thompsonmax) wants to merge 6 commits into
Closed
Max Thompson (thompsonmax) wants to merge 6 commits into
Max Thompson (thompsonmax) wants to merge 6 commits into
Conversation
Max Thompson (thompsonmax)
requested review from
Eitan Yarmush (EItanya),
Shruti Nair (SHRUTI6991) and
Taahir Ahmed (ahmedtd)
October 2, 2026 20:07
Max Thompson (thompsonmax)
marked this pull request as ready for review
October 2, 2026 20:07
Max Thompson (thompsonmax)
force-pushed
the
actor-jwks-configmap
branch
2 times, most recently
from
October 5, 2026 17:20
dcf01d8 to
d759c5c
Compare
Add oidcdiscovery.Thumbprint, the RFC 7638 SHA-256 thumbprint of an RSA or P-256 public key, and replace GenerateECDSAP256Authority with GenerateAuthority, which generates an RS256 or ES256 key and defaults its ID to the thumbprint. A thumbprint ID cannot collide across operators or be reused for a different key. kubectl ate admin make-jwt-pool gains --alg, defaulting to RS256, and --key-id now defaults to the thumbprint. ate-setup creates the same kind of pool. RS256 works with relying parties that do not support ES256. Existing pools are untouched, so keys named "1" keep working.
New actor JWT pools default to ES256 again, matching every existing pool. make-jwt-pool --alg defaults to ES256, and ate-setup reads the algorithm from ACTOR_JWT_ALGORITHM (ES256 or RS256, default ES256), so an install whose relying parties do not support ES256 can choose RS256 without creating the pool by hand. Key IDs still default to the thumbprint.
Use go-jose's JSONWebKey.Thumbprint instead of building the RFC 7638 canonical form by hand. Thumbprint still accepts only RSA and P-256 keys, the types the pool generates. go-jose moves from an indirect to a direct dependency; it was already vendored.
kubectl-ate's make-jwt-pool and ate-setup each generated an authority, made it active, and marshaled the pool. GeneratePool does that and returns the serialized pool and the authority's ID, so both callers only build their Secret.
Add JWKS, which serializes verification keys into the JWK set relying parties fetch from the issuer, sorted by key ID. It encodes with go-jose's JSONWebKey, as the Kubernetes service account issuer does, and adds the checks go-jose leaves to the caller: the set is not empty, key IDs are present and unique, and each algorithm fits its key (ES256 for P-256 EC, RS256, RS384, or RS512 for RSA), so a malformed pool cannot publish a set that verifiers would reject. localjwtauthority.VerificationKey gains Algorithm so callers can publish it.
ate-idp-server serves the actor JWT key set but must never see the signing keys, so something with access to the actor-id-jwt-pool Secret has to copy the public half out. ActorJWKSReconciler watches that Secret and server-side-applies the JWK set of every authority in the pool, active or not, into the actor-id-jwks ConfigMap under jwks.json. The ConfigMap is owned by the Secret, so garbage collection removes the published keys along with the pool. An unreadable or empty pool fails the reconcile and leaves the last good key set in place, since relying parties cache whatever ate-idp-server serves. Deleting or editing the ConfigMap by hand is reverted. atecontroller gains ConfigMap write access through a Role scoped to the system namespace. Its Secret cache now covers the whole system namespace: a cache takes one field selector per namespace, and two controllers each need a different Secret.
Max Thompson (thompsonmax)
force-pushed
the
actor-jwks-configmap
branch
from
October 5, 2026 17:42
d759c5c to
b933fd9
Compare
2 tasks
Collaborator
Author
|
Closing in favor of having ate-idp-server read the pool Secret directly with RefreshingPool (#2099), which removes the need for this controller and the ConfigMap. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #1756. Stacked on #2132, which is stacked on #1961; only the last commit is new.
ActorJWKSReconcilerto atecontroller. It watches theactor-id-jwt-poolSecret and server-side-applies the public key of every authority, active or not, into theactor-id-jwksConfigMap asjwks.json, the file ate-idp-server (Add ate-idp-server to serve the discovery document and key set for actor JWTs #2099) reads. ate-idp-server never sees the signing keys.ate-system.For reviewers: atecontroller's Secret cache now covers all of
ate-systemrather than onlyegress-mitm-ca-pool, because a cache takes one field selector per namespace. Its ClusterRole already reads Secrets cluster-wide.Testing: fake-client tests for publishing, rotation, reverting edits, a missing pool, and bad pools. Not run against a cluster; the e2e PR covers that once the manifests land.