Skip to content

feat: add async fetch and retry support for remote JWKS#14211

Merged
puertomontt merged 5 commits into
kgateway-dev:mainfrom
NomadXD:feat/14054
Jun 30, 2026
Merged

feat: add async fetch and retry support for remote JWKS#14211
puertomontt merged 5 commits into
kgateway-dev:mainfrom
NomadXD:feat/14054

Conversation

@NomadXD

@NomadXD NomadXD commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Description

Currently kgateway fetches the remote JWKS synchronously during request time. If the cache expires and the JWKS server is unavailable when a request arrives, that request fails. This adds the option to fetch and cache the JWKS asynchronously, and a retry policy with exponential backoff, making JWT validation resilient to a slow or temporarily unavailable JWKS servers.

fixes #14054

Change Type

/kind feature

Changelog

Added asyncFetch and retryPolicy options to the JWT provider remote JWKS configuration, enabling asynchronous JWKS fetching/caching and retries with exponential backoff.

Additional Notes

The E2E test (TestJwtAuthenticationRemoteAsync) tests the full JWKS flow end to end with asyncFetch and retryPolicy configured. It does not assert the resilience behavior specific to async fetch/retry (e.g. serving from cache while the JWKS server is unavailable, or retrying a failed fetch), since reliably reproducing a JWKS outage and the timing dependent refetch/backoff windows in E2E is inherently flaky. The correctness of the translated Envoy config (asyncFetch, retryPolicy,cacheDuration) is covered by the translator golden test and unit tests.

Copilot AI review requested due to automatic review settings June 9, 2026 06:12
@NomadXD
NomadXD requested a review from a team as a code owner June 9, 2026 06:12
@gateway-bot gateway-bot added kind/feature Categorizes issue or PR as related to a new feature. release-note labels Jun 9, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds support for configuring Envoy JWT remote JWKS async fetch and retry policy through GatewayExtension JWT config, plus translator outputs and end-to-end coverage.

Changes:

  • Extend JWT RemoteJWKS API/CRD with asyncFetch and retryPolicy fields.
  • Update JWT translation to emit Envoy remoteJwks.asyncFetch and remoteJwks.retryPolicy.
  • Add unit/translator tests and new e2e manifest + test case for remote JWKS async behavior.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
test/e2e/features/jwt/testdata/jwt-remote-async.yaml Adds e2e manifests to exercise remote JWKS async fetch + retries.
test/e2e/features/jwt/suite.go Registers and implements a new e2e test that uses the new manifest.
pkg/kgateway/translator/gateway/testutils/inputs/jwt/remote-jwks-async.yaml Adds translator test input for remote JWKS async/retry configuration.
pkg/kgateway/translator/gateway/testutils/outputs/jwt/remote-jwks-async.yaml Adds expected translated output including Envoy asyncFetch/retryPolicy fields.
pkg/kgateway/translator/gateway/gateway_translator_test.go Adds a translator golden test for remote JWKS async/retry.
pkg/kgateway/extensions2/plugins/trafficpolicy/jwt.go Implements translation of asyncFetch and retryPolicy into Envoy JWT config.
pkg/kgateway/extensions2/plugins/trafficpolicy/jwt_test.go Adds unit test coverage for translating async fetch + retry policy.
install/helm/kgateway-crds/templates/gateway.kgateway.dev_gatewayextensions.yaml Exposes new fields in the Helm-rendered CRD schema.
api/v1alpha1/kgateway/jwt_types.go Adds API types for async fetch and retry policy configuration.
Files not reviewed (1)
  • api/v1alpha1/kgateway/zz_generated.deepcopy.go: Language not supported

Comment on lines +215 to +221
s.TestInstallation.AssertionsT(s.T()).EventuallyHTTPRouteCondition(
s.Ctx,
"httpbin-route-get",
"kgateway-base",
gwv1.RouteConditionAccepted,
metav1.ConditionTrue,
)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mirrors the existing TestJwtAuthenticationRemote test, which uses the same single route readiness wait while asserting against both /get and /status/200. Both routes are created from the same manifest in the test setup, so by the time httpbin-route-get is Accepted, httpbin-route-status is effectively ready as well. Also the assertResponse/assertResponseWithoutAuth helpers send with retries, so a brief lag in route programming is absorbed rather than causing an immediate failure.

Comment on lines +212 to +216
// MaxInterval is the maximum interval between retries. If set, it must be greater than
// or equal to BaseInterval. Defaults to 10 times the BaseInterval.
// +optional
// +kubebuilder:validation:XValidation:rule="matches(self, '^([0-9]{1,5}(h|m|s|ms)){1,4}$')",message="invalid duration value"
MaxInterval *metav1.Duration `json:"maxInterval,omitempty"`

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed with d1efb61

Comment on lines +1115 to +1122
maxInterval:
description: |-
MaxInterval is the maximum interval between retries. If set, it must be greater than
or equal to BaseInterval. Defaults to 10 times the BaseInterval.
type: string
x-kubernetes-validations:
- message: invalid duration value
rule: matches(self, '^([0-9]{1,5}(h|m|s|ms)){1,4}$')

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed with d1efb61

Comment on lines +337 to +341
func translateJwksRetryPolicy(in *kgateway.JWKSRetryPolicy) *envoycorev3.RetryPolicy {
retryPolicy := &envoycorev3.RetryPolicy{}
if in.NumRetries != nil {
retryPolicy.NumRetries = wrapperspb.UInt32(uint32(*in.NumRetries)) //nolint:gosec // G115: kubebuilder validation ensures NumRetries is non-negative
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed with d1efb61

@NomadXD
NomadXD requested a review from andy-fong June 10, 2026 04:35
@andy-fong
andy-fong added this pull request to the merge queue Jun 25, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 25, 2026
@andy-fong
andy-fong added this pull request to the merge queue Jun 29, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 29, 2026
@NomadXD

NomadXD commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

@andy-fong Updated the PR on main.

@puertomontt
puertomontt added this pull request to the merge queue Jun 30, 2026
Merged via the queue into kgateway-dev:main with commit 26e9ea7 Jun 30, 2026
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/feature Categorizes issue or PR as related to a new feature. release-note

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Async Fetch support for Remote JWKS

5 participants