Skip to content

GEP-91: Address connection coalescing security issue - API updates #3960

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

kl52752
Copy link
Contributor

@kl52752 kl52752 commented Jul 28, 2025

What type of PR is this?
/kind gep

What this PR does / why we need it:
Implements API changes for GEP-91

Which issue(s) this PR fixes:

Fixes 3567
Relates to: #3760 (comment)

Does this PR introduce a user-facing change?:

NONE

@k8s-ci-robot k8s-ci-robot added release-note-none Denotes a PR that doesn't merit a release note. kind/gep PRs related to Gateway Enhancement Proposal(GEP) do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. labels Jul 28, 2025
@k8s-ci-robot k8s-ci-robot requested review from candita and robscott July 28, 2025 10:03
@k8s-ci-robot k8s-ci-robot added needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Jul 28, 2025
@k8s-ci-robot
Copy link
Contributor

Hi @kl52752. Thanks for your PR.

I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Jul 28, 2025
@kl52752
Copy link
Contributor Author

kl52752 commented Jul 28, 2025

/assign @robscott @arkodg @youngnick @shaneutt

Copy link
Contributor

@youngnick youngnick left a comment

Choose a reason for hiding this comment

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

Small clarification about pointer-to-string, but aside from that, LGTM.

@kl52752 kl52752 force-pushed the gep-91-api branch 2 times, most recently from 4c15adf to 1cde002 Compare July 30, 2025 07:26
@youngnick
Copy link
Contributor

/ok-to-test
/approve

@k8s-ci-robot k8s-ci-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Aug 6, 2025
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: kl52752, youngnick

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 6, 2025
@kl52752 kl52752 force-pushed the gep-91-api branch 2 times, most recently from 52f2fd5 to 6a5f47f Compare August 6, 2025 06:41
@k8s-ci-robot k8s-ci-robot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Aug 6, 2025
@kl52752
Copy link
Contributor Author

kl52752 commented Aug 6, 2025

/retest

@kl52752
Copy link
Contributor Author

kl52752 commented Aug 6, 2025

/retest

Copy link
Member

@robscott robscott left a comment

Choose a reason for hiding this comment

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

Thanks @kl52752!

// +optional
//
// <gateway:experimental>
TLSConfigs []TLSConfig `json:"tlsConfigs,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

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

🤔 This field name feels a little funny to me. Something about configs as a plural word doesn't seem quite right. Some alternatives that may not be better:

  1. tlsByPort
  2. tlsPerPort
  3. tls
  4. frontendTLS

Since even from the outset port is optional, 1 or 2 probably aren't great. Since there's at least a theoretical world where we add something TLS related here that isn't tied to frontend TLS, we could regret 4 in the future. So maybe 3 is the least bad, although even that adds some confusion as that tls field would have no overlap with listener.tls. Open to other ideas here.

/cc @arkodg @youngnick

Copy link
Contributor

Choose a reason for hiding this comment

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

if there is no strict rule for pluralizing / s slice fields, then +1 for tls

Copy link
Contributor

Choose a reason for hiding this comment

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

I do like the idea of tlsByPort or tlsPerPort, but I think that might also be confusing with the defaulting behavior?

I think that tls is an acceptable alternative though.

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 find the tls name for an array a bit confusing (specially the case when you iterate over tls). If we want "default" configuration to be explicit (see comment) we could consider creating a struct with default configuration (no port at all) and array with per ports override. This way it will be explicit, readable and not at all confusing :)

type GatewayTLSConfig struct {
defaultTLS *FrontendTLSValidation
tlsPerPort []TLSConfig
}

and in GatewaySpec we can name this field as tls

Copy link
Contributor

Choose a reason for hiding this comment

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

I added a different proposal above, but this could also work.

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 personally prefer mine solution than Nicks. I like it that default configuration is extracted from per ports override and now when default configuration is required it makes much sense.
I need to add more validations for per port overrides like uniquest etc but port = 0 will be forbidden.

@shaneutt @robscott which version do you prefer?

Copy link
Contributor

Choose a reason for hiding this comment

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

After some reflection, I think that @kl52752's option here is better, agreed. Separating the default config into its own section lets us say "the default config applies to all listeners with matching ports that terminate TLS, unless there is a matching config in the tlsPerPort section. In that case only the config in the tlsPerPort section applies."

Copy link
Member

Choose a reason for hiding this comment

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

I'm fine with that approach as well, thanks @kl52752!

Copy link
Member

Choose a reason for hiding this comment

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

👍

@kl52752
Copy link
Contributor Author

kl52752 commented Aug 7, 2025

/retest

@PT-GD
Copy link

PT-GD commented Aug 11, 2025

@kl52752 I am looking for a solution where the same certificate is on two distinct listeners on a gateway. This is necessary because the Gateway API allows a single listener per gateway and the hostname for a listener can be either an FQDN or a wildcard FQDN. The behavior of wildcard certificates in TLS is that they match the apex (FQDN) or one label deep of wildcarded names.

Will this GEP address coalescing connections to prevent HTTP/2 connection reuse issues when mutual TLS (client certificates) are not involved and two listeners attached to a gateway share the same server certificate? [Perhaps there should be a test for this, if there isn't one]?

See also https://istio.io/latest/docs/ops/common-problems/network-issues/#404-errors-occur-when-multiple-gateways-configured-with-same-tls-certificate for how this impact users of the Istio controller for the Gateway API.

@shaneutt shaneutt self-requested a review August 12, 2025 11:34
@shaneutt shaneutt dismissed their stale review August 12, 2025 11:35

I think we have consensus now on the approach, so removing my block.

@kl52752
Copy link
Contributor Author

kl52752 commented Aug 12, 2025

@kl52752 I am looking for a solution where the same certificate is on two distinct listeners on a gateway. This is necessary because the Gateway API allows a single listener per gateway and the hostname for a listener can be either an FQDN or a wildcard FQDN. The behavior of wildcard certificates in TLS is that they match the apex (FQDN) or one label deep of wildcarded names.

Will this GEP address coalescing connections to prevent HTTP/2 connection reuse issues when mutual TLS (client certificates) are not involved and two listeners attached to a gateway share the same server certificate? [Perhaps there should be a test for this, if there isn't one]?

See also https://istio.io/latest/docs/ops/common-problems/network-issues/#404-errors-occur-when-multiple-gateways-configured-with-same-tls-certificate for how this impact users of the Istio controller for the Gateway API.

hi @PT-GD in this GEP it is possible to attach the same FrontendValidation config (referencing the same ConfigMap) to 2 distinct Listeners in tlsPerPort field. The restriction here is that every port needs unique configuration but not the other way.
If they are listening on different port, you can do this by creating TLSConfig struct with the same FrontendTLSValidation but different port. If they are Listening on the same port only one FrontendTLSValidation is needed:
see the snippet:

apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: client-validation-basic
spec:
  gatewayClassName: acme-lb
  tls:
    defaultTLS: 
      caCertificateRefs:
        - kind: ConfigMap
          group: ""
          name: default-cert
        mode: AllowInsecureFallback
    tlsPerPort:
        - port: 443 // this configuration will apply to all Listeners matching this port
          frontendValidation:
            caCertificateRefs:
            - kind: ConfigMap
            group: ""
            name: foo-example-com-ca-cert
        - port: 8443 // If needed you can create second entry referencing the same ConfigMap for another port
          frontendValidation:
            caCertificateRefs:
            - kind: ConfigMap
            group: ""
            name: foo-example-com-ca-cert
            

@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Aug 12, 2025
Copy link
Member

@robscott robscott left a comment

Choose a reason for hiding this comment

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

Thanks @kl52752!

//
// +required
// <gateway:experimental>
DefaultTLS FrontendTLSValidation `json:"defaultTLS"`
Copy link
Member

Choose a reason for hiding this comment

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

Want to avoid names that stutter (tls.defaultTLS -> tls.default)

Suggested change
DefaultTLS FrontendTLSValidation `json:"defaultTLS"`
Default FrontendTLSValidation `json:"default"`

Copy link
Member

Choose a reason for hiding this comment

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

Also recommend an intermediate struct here so we leave room for other forms of TLS config at this default level. So tls.default.frontendValidation.mode instead of tls.default.mode.

//
// +optional
// <gateway:experimental>
TLSPerPort []TLSConfig `json:"tlsPerPort,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

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

Similar comment to above.

Suggested change
TLSPerPort []TLSConfig `json:"tlsPerPort,omitempty"`
PerPort []TLSConfig `json:"perPort,omitempty"`

@@ -624,6 +644,31 @@ const (
TLSModePassthrough TLSModeType = "Passthrough"
)

// TLSConfig describes a TLS configuration defined per port.
type TLSConfig struct {
Copy link
Member

Choose a reason for hiding this comment

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

Recommend something like this to make it clear that this is per-port.

Suggested change
type TLSConfig struct {
type TLSPortConfig struct {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. kind/gep PRs related to Gateway Enhancement Proposal(GEP) ok-to-test Indicates a non-member PR verified by an org member that is safe to test. release-note-none Denotes a PR that doesn't merit a release note. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
Status: Review
Development

Successfully merging this pull request may close these issues.

GEP-3567: Gateway TLS Updates for HTTP Connection Coalescing
7 participants