Repository navigation
kubectl ate admin can rotate the actor JWT signing key - #2140
Open
Max Thompson (thompsonmax) wants to merge 3 commits into
Open
Max Thompson (thompsonmax) wants to merge 3 commits into
Max Thompson (thompsonmax) wants to merge 3 commits into
Conversation
Max Thompson (thompsonmax)
requested review from
Eitan Yarmush (EItanya),
Shruti Nair (SHRUTI6991) and
Taahir Ahmed (ahmedtd)
October 2, 2026 22:13
Max Thompson (thompsonmax)
marked this pull request as ready for review
October 2, 2026 22:20
Max Thompson (thompsonmax)
force-pushed
the
actor-jwt-key-rotation
branch
3 times, most recently
from
October 5, 2026 17:42
d968111 to
af94766
Compare
| "encoding/base64" | ||
| "fmt" | ||
|
|
||
| jose "github.com/go-jose/go-jose/v4" |
Collaborator
There was a problem hiding this comment.
Don't use go-jose, we've reimplemented everything else in-tree. Serialize the key using X509.MarshalPKIXPublicKey, then take the SHA256 of that.
Collaborator
Author
Rotating the actor JWT signing key meant editing the pool Secret by hand. ConcretePool gains AddAuthority, Activate, and RemoveAuthority, and kubectl ate admin gains add-jwt-key, activate-jwt-key, and remove-jwt-key on top of them, so a rotation is: add a key, which is published but signs nothing; activate it once relying parties have refetched the key set; remove the old key once its tokens expire. The pool refuses a duplicate or empty key ID, activating a key it does not hold, and removing the key that signs. Each command reads the Secret, changes the pool, and writes it back conditional on the resourceVersion it read, rerunning the change against the current pool on a conflict so a concurrent edit is not lost. The pool commands now share one helper to build the Kubernetes client, and make-jwt-pool's algorithm and key ID flag variables are renamed so the new commands can share them.
A rotation ends by removing the old key by ID, and nothing showed the pool's key IDs short of decoding the Secret, which prints the private keys. list-jwt-keys prints each key's ID and algorithm and marks the one that signs. ConcretePool.ActiveID names the signing key, falling back to the first authority when none is designated as SignJWT does, and RemoveAuthority now uses it too so the listing and the removal check agree.
Max Thompson (thompsonmax)
force-pushed
the
actor-jwt-key-rotation
branch
from
October 6, 2026 16:14
af94766 to
a408363
Compare
RS256 does not fix an RSA key size, and the 2048-bit keys GenerateAuthority made are too weak for the actor JWT signing key. RS256 is kept only for relying parties that require it, such as Azure workload identity federation; ES256 stays the default. GenerateAuthority now makes 4096-bit RSA keys, and a pool refuses an RSA key of any other size, both when one is added and when the pool Secret is loaded. A pool holding a 2048-bit key fails to load until the key is rotated out.
Wiz Scan Summary
To detect these findings earlier in the dev lifecycle, try the Wiz Code extension for VS Code, JetBrains, or Visual Studio. |
2 tasks
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.
kubectl ate admin add-jwt-key,activate-jwt-key, andremove-jwt-key, so rotating the actor JWT signing key no longer means editing the pool Secret by hand. A new key is published but signs nothing until activated, which gives relying parties time to fetch it.list-jwt-keys, which prints each key's ID and algorithm and marks the active one, so finding the key to remove doesn't mean decoding a Secret full of private keys.ConcretePoolgainsAddAuthority,Activate,RemoveAuthority, andActiveID. They refuse a duplicate or empty key ID, activating a key the pool doesn't hold, and removing the key that signs.The commands don't wait for relying parties; the operator decides when to activate and remove. A pool that already holds a 2048-bit RSA key fails to load until that key is rotated out.
Testing: unit tests for the pool methods, and fake-clientset tests for a full rotation, a conflict retry, refused changes, and the listing, plus tests that 2048-bit RSA keys are refused. Not run against a cluster.