Skip to content

Conversation

@puertomontt
Copy link
Contributor

@puertomontt puertomontt commented Nov 4, 2025

Description

Add envoy JWT policy using GatewayExtension. Based on Nina's work in #11445.

  • Adds new JWT Authentication API on TrafficPolicy
  • Adds new JWT Provider type to GatewayExtension

Co-authored by: npolshakova [email protected]

Change Type

/kind feature

Changelog

Added JWT Authentication configuration to the TrafficPolicy and support for JWT Providers to the GatewayExtension.

Additional Notes

Signed-off-by: omar <[email protected]>
Signed-off-by: omar <[email protected]>
Signed-off-by: omar <[email protected]>
Signed-off-by: omar <[email protected]>
Signed-off-by: omar <[email protected]>
Copilot AI review requested due to automatic review settings November 4, 2025 15:51
@github-actions github-actions bot added do-not-merge/description-invalid do-not-merge/release-note-invalid Indicates that a PR should not merge because it's missing one of the release note labels. kind/feature Categorizes issue or PR as related to a new feature. labels Nov 4, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds comprehensive JWT authentication functionality to the kgateway project, enabling JWT validation for HTTP routes and gateways.

  • Adds JWT provider configuration through GatewayExtension CRD
  • Implements JWT validation policies attachable to gateways and routes
  • Supports JWKS from inline keys, files, or Kubernetes secrets

Reviewed Changes

Copilot reviewed 27 out of 28 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
api/v1alpha1/jwt.go New API types for JWT validation configuration including providers, token sources, and JWKS
api/v1alpha1/gateway_extensions_types.go Adds JWTProviders extension type to GatewayExtension spec
api/v1alpha1/traffic_policy_types.go Adds JWT field to TrafficPolicySpec
internal/kgateway/extensions2/plugins/trafficpolicy/jwt.go Core JWT translation logic converting CRD specs to Envoy JWT auth filters
internal/kgateway/extensions2/plugins/trafficpolicy/jtw_test.go Unit tests for JWT translation functions
internal/kgateway/extensions2/plugins/trafficpolicy/gateway_extension.go Resolves JWT providers into Envoy configuration
internal/kgateway/extensions2/plugins/trafficpolicy/traffic_policy_plugin.go Integrates JWT handling into traffic policy plugin
test/e2e/features/jwt/suite.go E2E test suite for JWT authentication
install/helm/kgateway-crds/templates/*.yaml CRD definitions for JWT configuration
go.mod / go.sum Adds go-jose/v3 dependency for JWT/JWKS handling

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 120 to 124
err = s.testInstallation.Actions.Kubectl().ApplyFile(s.ctx, testdefaults.HttpbinManifest)
s.Require().NoError(err)

// Apply curl pod for testing
err = s.testInstallation.Actions.Kubectl().ApplyFile(s.ctx, testdefaults.CurlPodManifest)
Copy link

Copilot AI Nov 4, 2025

Choose a reason for hiding this comment

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

Comment on line 119 says 'Apply curl pod for testing' but it's actually applying the httpbin manifest. Comment on line 122 is correct. Update line 119 comment to 'Apply httpbin for testing' or similar.

Copilot uses AI. Check for mistakes.
@puertomontt puertomontt linked an issue Nov 4, 2025 that may be closed by this pull request
@github-actions github-actions bot added release-note and removed do-not-merge/description-invalid do-not-merge/release-note-invalid Indicates that a PR should not merge because it's missing one of the release note labels. labels Nov 4, 2025
Signed-off-by: omar <[email protected]>
Copy link
Contributor

@howardjohn howardjohn left a comment

Choose a reason for hiding this comment

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

None of my comments are blocking.

// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=100
// +optional
HeaderSource []HeaderSource `json:"headers,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need a list for this and query params? seems like you only want to fetch from one place generally?

// Name is the JWT claim name, for example, "sub".
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=2048
Name string `json:"name"`
Copy link
Contributor

Choose a reason for hiding this comment

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

claims can be nested (they are JSON). do we support that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it technically would work using dot-separated paths

// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=2048
// +optional
InlineKey *string `json:"key,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: key is probably an inaccurate name. Its a keyset, not a key


// SecretRef configures storing the JWK in a Kubernetes secret in the same namespace as the JWTValidationPolicy.
// +optional
SecretRef *corev1.LocalObjectReference `json:"secretRef,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Secret may be a bit odd given its not really secret.. configMap may be appropriate?

Copy link
Contributor

@dmitri-d dmitri-d Nov 4, 2025

Choose a reason for hiding this comment

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

technically a jwks can contain a private key, but I can't think where we'd need it? ConfigMap should be ok, but maybe with a note in the doc re: private keys (should someone copy-paste jwks from an IdP)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

changed to ConfigMap

@@ -0,0 +1,77 @@
---
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's add an e2e test to check jwt is working with rbac like this example: https://github.com/npolshakova/kgateway/blob/d7da5dfb9b2e626c6ce2ff764d85d768b1f042c2/test/kubernetes/e2e/features/jwt/testdata/jwt-rbac.yaml#L50
from the additional notes section: #11923

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added

// +required
ExtensionRef *NamespacedObjectReference `json:"extensionRef"`

// TODO: add support for ValidationMode here (REQUIRE_VALID,ALLOW_MISSING,ALLOW_MISSING_OR_FAILED)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should add the allow_missing.required/allow_missing_or_failed option here as well.


// TODO: add support for ValidationMode here (REQUIRE_VALID,ALLOW_MISSING,ALLOW_MISSING_OR_FAILED)

// TODO(npolshak): Add option to disable all jwt filters.
Copy link
Contributor

Choose a reason for hiding this comment

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

We probably want this as well now that there is a pattern for it: https://github.com/kgateway-dev/kgateway/blob/main/api/v1alpha1/ext_auth_types.go#L27

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this isn't straightforward for jwt. would require composite filter similar to extproc.

the alternative is to disable using RBAC

// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=2048
// +optional
InlineKey *string `json:"key,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

do we support PEM format here? or only JWKS format?
(asking as gloo edge supported PEM)

// JWTProviders configures a map of unique JWTProvider name to JWTProviders
// +optional
// +kubebuilder:validation:MaxProperties=32
JWTProviders map[string]JWTProvider `json:"jwtProviders,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

what is the name used for here?
can we use a list of map type instead of map? i think it renders more consistently?
is there a way to configure if this is pre or post ext auth?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the provider name needs to be unique, but that can be enforced at the plugin level. We might want to add a way to configure pre/post ext auth using the kgateway.dev/policy-weight?

Copy link
Contributor

Choose a reason for hiding this comment

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

you can validate uniqueness of a list in CEL as well FWIW

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.

JWT validation policy

6 participants