Skip to content

Conversation

@dmitri-d
Copy link
Contributor

@dmitri-d dmitri-d commented Dec 1, 2025

Description

This PR depends on changes in #13011. The PR introduces support for setting of tls options for connections to remote jwks sources in jwks store. This is accomplished by setting a backendRef on a AgentgatewayPolicy, finding a matching BackendTLSPolicy, and using it to configure tls options.

If no BackendTLSPolicy is present, an http client with default tls options is used (including setting InsecureSkipVerify to false).

Implemenation Notes

  • Only k8s service and static agent backends can be pointed to in backendRefs. We should probably validate that jwksUri and the service/backend are consistent.
  • Limited set of tls options can be configured:
  • system or custom CA certs to use
  • enabling/disabling InsecureSkipVerify. I don't think we support this anywhere else, could be confusing.

Change Type

/kind feature

Changelog

Support setting of tls options in connections to remote jwks sources.

Additional Notes

Example of a policy using remote jwks, configured via static backend:

apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayPolicy
metadata:
  name: route-policy
spec:
  targetRefs:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: route-secure
  traffic:
    jwtAuthentication:
      mode: Strict
      providers:
      - issuer: https://kgateway.dev
        jwks:
          remote:
            jwksPath: org-one/keys
            backendRef:
              group: agentgateway.dev
              kind: AgentgatewayBackend
              name: dummy-idp-1
              port: 8443
      - issuer: https://kgateway.dev
        jwks:
          remote:
            jwksPath: org-two/keys
            backendRef:
              group: agentgateway.dev
              kind: AgentgatewayBackend
              name: dummy-idp
              port: 8443
---
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayBackend
metadata:
  name: dummy-idp
spec:
  policies:
    tls:
      insecureSkipVerify: All
  static:
    host: dummy-idp.default
    port: 8443

Example of a policy using remote jwks, configured via k8s service:

apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayPolicy
metadata:
  name: route-policy
spec:
  targetRefs:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    name: route-secure
  traffic:
    jwtAuthentication:
      mode: Strict
      providers:
      - issuer: https://kgateway.dev
        jwks:
          remote:
            jwksPath: org-one/keys
            backendRef:
              group: ""
              kind: Service
              name: dummy-idp
              port: 8443
---
apiVersion: agentgateway.dev/v1alpha1
kind: AgentgatewayPolicy
metadata:
  name: idp-policy
spec:
  targetRefs:
  - group: ""
    kind: Service
    name: dummy-idp
  backend:
    tls:
      caCertificateRefs:
      - name: ca
---
apiVersion: v1
kind: Service
metadata:
  name: dummy-idp
  namespace: default
  labels:
    app: dummy-idp
spec:
  ports:
    - name: http
      port: 8443
      targetPort: 8443
  selector:
    app.kubernetes.io/name: dummy-idp

Copilot AI review requested due to automatic review settings December 1, 2025 18:35
@dmitri-d dmitri-d self-assigned this Dec 1, 2025
@gateway-bot gateway-bot added kind/feature Categorizes issue or PR as related to a new feature. release-note labels Dec 1, 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 introduces support for configurable TLS options when connecting to remote JWKS sources in the JWKS store. It allows users to specify custom TLS configurations via BackendTLSPolicy by setting a backendRef on an AgentgatewayPolicy.

Key changes include:

  • Refactored JWKS store architecture to use event-driven updates via channels instead of queue-based polling
  • Added support for custom TLS configurations per JWKS source through BackendTLSPolicy integration
  • Separated concerns into dedicated controllers: policy controller for JWKS source changes and ConfigMap controller for persistence
  • Improved security by removing default InsecureSkipVerify: true from HTTP clients

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
internal/kgateway/jwks/jwks_store.go Refactored to use channel-based updates; added mapping between ConfigMap names and JWKS URIs
internal/kgateway/jwks/jwks_fetcher.go Added TLS configuration support per keyset; simplified keyset management API; removed default insecure TLS
internal/kgateway/jwks/jwks_cache.go Added thread-safe methods with mutex locks; removed comparison logic from add operation
internal/kgateway/jwks/config_map_syncer.go Simplified by removing write logic and KRT collection; now only handles loading ConfigMaps
internal/kgateway/agentjwksstore/policy_controller.go New controller that watches policies and creates JWKS sources with TLS configs from BackendTLSPolicy
internal/kgateway/agentjwksstore/cm_controller.go New controller that persists JWKS to ConfigMaps using event queue pattern
internal/kgateway/controller/start.go Updated to initialize new controllers in correct order
internal/kgateway/jwks/jwks_fetcher_test.go Updated tests to use new defaultJwksClient field name
api/v1alpha1/agentgateway_policy_types.go Made BackendRef a pointer and JwksUri required; removed mutual exclusivity validation
install/helm/kgateway-crds/templates/gateway.kgateway.dev_agentgatewaypolicies.yaml Updated CRD to reflect API changes
api/v1alpha1/zz_generated.deepcopy.go Generated code for pointer-based BackendRef deep copy

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

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

@dmitri-d dmitri-d mentioned this pull request Dec 1, 2025
Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Dmitri Dolguikh <[email protected]>
@lgadban lgadban self-requested a review December 5, 2025 17:36
Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Dmitri Dolguikh <[email protected]>
Signed-off-by: Dmitri Dolguikh <[email protected]>
@npolshakova npolshakova added this pull request to the merge queue Dec 16, 2025
// +kubebuilder:validation:Pattern=`^(https|http):\/\/[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*(:\d+)?\/.*$`
// +optional
JwksUri string `json:"uri,omitempty"`
// Path to IdP jwks endpoint. Default tls settings are used to connect to this url.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: would be nice to have a trivial example here on the format, e.g. /path/here.

we could also throw validation to e.g. enforce : is not included, etc.

Comment on lines 555 to +556
// Supported types: Service and Backend.
// +optional
BackendRef gwv1.BackendObjectReference `json:"backendRef,omitempty"`
// +required
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: we can add some color here explaining that the backendRef determines where and how to establish a connection and allows policy to be attached etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will do

backends krt.Collection[*agentgateway.AgentgatewayBackend],
agentgatewayPolicies krt.Collection[*agentgateway.AgentgatewayPolicy]) JwksUrlBuilder {

policiesByTargetRefIndex := krtpkg.UnnamedIndex(agentgatewayPolicies, func(in *agentgateway.AgentgatewayPolicy) []TargetRefIndexKey {
Copy link
Contributor

Choose a reason for hiding this comment

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

just curious, do we not have an index like this elsewhere in the agw codebase?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not that I could find.

return "", nil, fmt.Errorf("only static backends are supported; backend: %s, policy: %s", backendRef, types.NamespacedName{Namespace: defaultNS, Name: policyName})
}

// TODO (dmitri-d) only inline tls config is supported atm, do we want to support attching AgentgatewayPolicy too?
Copy link
Contributor

Choose a reason for hiding this comment

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

this TODO is a bit confusing, is this saying we may want to support AgwPolicy being attached to the Backend being referenced?

If so I think we would want to do that in the future to have a consistent approach.

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'll remove the TODO, that's been implemented.

Kind: string(*ref.Kind),
Group: string(ptr.OrEmpty(ref.Group)),
Namespace: refNamespace,
// no port, as policy targetRef may not have it
Copy link
Contributor

Choose a reason for hiding this comment

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

// no port, as policy targetRef may not have it

is there an implication here?
i.e. can AgwPolicy not sectionName specific ports?

Copy link
Contributor Author

@dmitri-d dmitri-d Dec 16, 2025

Choose a reason for hiding this comment

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

an issue here is that sectionName is optional and we don't know apriori if it's present in the policy's targetRef; so we either ignore it completely (an issue if there are multiple policies targeting the same service but different ports), or do multiple searches (with the port set first, then without the port).

backendRef, types.NamespacedName{Namespace: refNamespace, Name: policyName}, err)
}
tlsConfig = tlsc
} else { // check if a
Copy link
Contributor

Choose a reason for hiding this comment

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

// check if a

is this just leftover cruft?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

indeed it is.

Merged via the queue into kgateway-dev:main with commit e344ba6 Dec 16, 2025
29 checks passed
@apexlnc
Copy link
Contributor

apexlnc commented Dec 16, 2025

Feedback on required backendRef for remote JWKS

Following up on the discussion about keeping backendRef required - wanted to share our experience with this change.

Use case: JWT authentication with public IdP JWKS endpoints (GitHub Actions, GitLab CI)

Before:

jwks:
  remote:
    uri: https://token.actions.githubusercontent.com/.well-known/jwks
    cacheDuration: 30m

After:

# Need to create a Backend for a public HTTPS endpoint
backends:
  github-jwks:
    static:
      host: token.actions.githubusercontent.com
      port: 443
    policies:
      tls:
        sni: token.actions.githubusercontent.com

# Then reference it
jwks:
  remote:
    jwksPath: .well-known/jwks
    backendRef:
      name: github-jwks
      group: agentgateway.dev
      kind: AgentgatewayBackend
    cacheDuration: 30m

For public HTTPS endpoints with standard TLS (common for IdPs like GitHub, GitLab, Auth0, Okta, etc.), the Backend object adds a bit of extra configuration when custom TLS settings aren't needed.

Thought: Would it be possible to make backendRef optional and fall back to the previous uri behavior when not specified? That would keep things simple for common cases while still enabling custom TLS configuration when needed.

Thanks for considering!

@lgadban
Copy link
Contributor

lgadban commented Dec 19, 2025

@apexlnc per your comment above @dmitri-d opened #13186

As described in the issue there may be larger work necessary to get this working in a consistent manner across the various agentgateway policies.

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.

5 participants