feat: verify JWTs against authn's JWKS instead of a shared signing key - #146
Merged
Conversation
Pinned to the krateo-platformops/plumbing@feat/rs256-jwks-keysource commit pending release; re-pin to the tagged version once krateo-platformops/plumbing#21 is merged and tagged.
snowplow no longer holds a copy of authn's signing key. It resolves RS256
verification keys by "kid" from authn's JWKS endpoint
(GET /.well-known/jwks.json) via a cached jwtutil.JWKSKeySource, defaulting to
<url-authn>/.well-known/jwks.json unless --jwks-url/JWT_JWKS_URL overrides it.
Fetches are lazy (first validation, not at boot) and cached, so snowplow
starts and serves unauthenticated routes even if authn isn't up yet, and a
key rotation on authn's side needs no snowplow redeploy.
middleware.UserConfig and middleware.RefreshAuth take a jwtutil.KeySource in
place of the raw signing-key string; the snowplow-local UserConfig mirror of
plumbing's use.UserConfig (AC-D3.14 provenance guard) is re-audited
line-by-line against upstream's new KeySource-based flow and re-pinned.
Chart: helm/snowplow's jwtSignKeySecretName and its envFrom secretRef are
gone; jwt.{jwksUrl,cacheTTL,minRefreshInterval,requestTimeout} configures the
JWKS client instead. No Secret is mounted.
…cret The RS256 migration made plumbing's e2e.SignUp expect a PEM-encoded RSA private key (JWTSignKey) + a JWTKeyID, but six test setups still passed the old symmetric secret "abbracadabbra", so they failed with e2e.go:50: invalid key: Key must be a PEM encoded PKCS1 or PKCS8 key in TestResolveAPI, TestResolveWidgets(_Extras), TestGet, TestRESTAction, TestCallHandler. Generate an inline PKCS1 PEM RSA key per test (matching the already-fixed internal/rbac/rbac_test.go) and pass JWTSignKey + JWTKeyID: "test-kid". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LJsLqtryCgWwEt8FnPE1se
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.
Summary
kidfrom authn's JWKS endpoint (GET /.well-known/jwks.json) via a cachedjwtutil.JWKSKeySource, defaulting to<URL_AUTHN>/.well-known/jwks.jsonunless--jwks-url/JWT_JWKS_URLoverrides it.middleware.UserConfig/middleware.RefreshAuthtake ajwtutil.KeySourcein place of a raw signing-key string. The snowplow-localUserConfigmirror of plumbing'suse.UserConfig(the AC-D3.14 provenance guard,TestUserConfigMirror_PlumbingVersionPin) is re-audited line-by-line against upstream's newKeySource-based flow and re-pinned.jwtSignKeySecretNameand itsenvFromsecretRefare gone;jwt.{jwksUrl,cacheTTL,minRefreshInterval,requestTimeout}configures the JWKS client instead. No Secret is mounted on snowplow anymore.Cross-repo dependency
Depends on plumbing PR krateo-platformops/plumbing#21 and pairs with authn PR krateo-platformops/authn#20 (which adds the JWKS endpoint this reads from).
go.modis pinned to the plumbing PR's branch-tip commit as a pseudo-version so this branch builds and tests green today;internal/handlers/middleware/userconfig.go'sPinnedPlumbingVersionis pinned to the same pseudo-version. Before merging this PR, once plumbing is tagged, push a follow-up commit here:go get github.com/krateo-platformops/plumbing@<tag> && go mod tidy, then updatePinnedPlumbingVersionto match (no further re-audit needed — content is identical, just the version string).Test plan
go build ./.../go test ./...(go/snowplow), includingTestUserConfigMirror_PlumbingVersionPin, green against the plumbing pseudo-version