Skip to content
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

Adding GEP-3567: Gateway TLS Updates for HTTP/2 Connection Coalescing #3572

Merged
merged 1 commit into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions geps/gep-3567/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# GEP-3567: Gateway TLS Updates for HTTP/2 Connection Coalescing

* Issue: [#3567](https://github.com/kubernetes-sigs/gateway-api/issues/3567)
* Status: Implementable

## TLDR

As described in the [previous
doc](https://docs.google.com/document/d/1g_TNN8eOaVDC3xesO9JFdvQbPFdSTHp1vb70TD3-Vrs/edit?tab=t.0#heading=h.qiz1tfw67tbp),
the current state of TLS configuration on Gateways can lead to confusing
behavior when combined with HTTP/2 connection coalescing. This GEP proposes a
series of changes to the API to address these problems.

## Goals

* Take steps that will make it less likely for users to encounter these problems
* Warn when users have configuration that is prone to these issues
* Provide central source of documentation explaining both the problem and
potential solutions

## Non-Goals

* Breaking or significantly disruptive changes to the existing API surface

## Introduction

Gateway API creates situations where clients might be able to send requests
through a Listener that, according to the Gateway’s configuration, is not
supposed to receive these requests. This can cause requests to be apparently
mis-routed.

The problem here is an inherent conflict between the API and the mechanics of
HTTPS. Gateway API uses the “hostname” field in the Listener to constrain both
the TLS certificate selection and the host header of requests. But when a server
presents a TLS certificate that is valid for multiple domains, a client is free
to reuse its TLS connection for requests sent to any of those domains (for
HTTP2, see RFC). The SNI hostname, which the client presents only with the
initial TLS handshake, doesn’t constrain the host header of the requests that
the client sends.

Gateway API deals with this situation imprecisely, stating:

The Listener Hostname SHOULD match at both the TLS and HTTP protocol layers as described above. If an implementation does not ensure that both the SNI and Host header match the Listener hostname, it MUST clearly document that.

In practice we can end up with an implementation that misroutes requests when a
Gateway is configured using certificates that use multiple or wildcard SANs.

### Example

The following configuration ([from the Gateway API
documentation](https://gateway-api.sigs.k8s.io/guides/tls/#wildcard-tls-listeners))
illustrates the problem:


```
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: wildcard-tls-gateway
spec:
gatewayClassName: example
listeners:
- name: foo-https
protocol: HTTPS
port: 443
hostname: foo.example.com
tls:
certificateRefs:
- kind: Secret
group: ""
name: foo-example-com-cert # SAN: foo.example.com
- name: wildcard-https
protocol: HTTPS
port: 443
hostname: "*.example.com"
tls:
certificateRefs:
- kind: Secret
group: ""
name: wildcard-example-com-cert # SAN: *.example.com
```


The Gateway API definition requires requests to `foo.example.com` to be
associated with the `foo-https` listener, on connections negotiated with
`foo-example-com-cert`.

Suppose a client sends a request to `bar.example.com`, specifying that as the
SNI hostname, and establishes a TLS connection attached to the `wildcard-https`
Listener. And then it sends a subsequent request to `foo.example.com`. The
client can correctly reuse its existing TLS connection for the second request,
because the `wildcard-example-com-cert` is valid also for `foo.example.com`. But
now the Gateway has a problem: Routing the request via the `wildcard-https`
Listener violates the intent of the configuration, and routing via the
`foo-https` Listener is inconsistent with the connection’s having been
negotiated with the other Listener’s certificate.

Mapping a request to a Listener matters if the Gateway configuration has
different
[HTTPRoutes](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRoute)
bound to the different Listeners. It also matters if the Listeners have
different
[GatewayTlsConfigs](https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.GatewayTLSConfig)
attached, for example if one Listener uses mutual TLS and the other does not.


### Interaction with Client Cert Validation

[GEP-91](https://gateway-api.sigs.k8s.io/geps/gep-91/) introduced Client
Certificate Validation to Gateway Listeners as a new experimental concept. If an
implementation is unable to properly isolate HTTPS listeners, this could result
in this Client Cert Validation being bypassed. Before this feature can graduate
beyond experimental, we’ll need to resolve this underlying issue.

## Proposal

### A) Add Warning in Gateway Status
A new condition will be added to Gateways: `OverlappingTLSConfig`.
Implementations MUST add this condition to status when a Gateway is configured
with TLS configuration across multiple Listeners. Implementations MAY add this
condition to status when a Gateway is configured with overlapping TLS
certifications. Note that since this is a negative polarity condition, it would
only be populated when it is true.

### B) Modify API Spec to recommend sending 421s
The Gateway spec for `listener.hostname` will be updated to recommend returning
a 421 when this problem occurs.

### C) Top Level Gateway TLS Config for Client Cert Validation

A follow up discussion for GEP-91 will consider if Client Cert Validation should
be moved or copied to a new top level Gateway TLS config instead of
per-listener.

robscott marked this conversation as resolved.
Show resolved Hide resolved
## Conformance Details

#### Feature Names

A) None, this will be required for any implementations that support HTTP +
Gateways.

B) `GatewayReturn421`

C) Will be covered in GEP-91

### Conformance tests

A) A new conformance test will be added to ensure that the new status condition
is populated when a Gateway is configured with overlapping TLS configuration.

B) A new conformance test will be added to ensure that implementations return a
421 when a connection is reused for a different listener with an overlapping
SNI.

C) Will be covered in GEP-91

## Alternatives

Discussed in more detail the [original
doc](https://docs.google.com/document/d/1g_TNN8eOaVDC3xesO9JFdvQbPFdSTHp1vb70TD3-Vrs/edit?tab=t.0#heading=h.qiz1tfw67tbp)
33 changes: 33 additions & 0 deletions geps/gep-3567/metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: internal.gateway.networking.k8s.io/v1alpha1
kind: GEPDetails
number: 3567
name: Gateway TLS Updates for HTTP/2 Connection Coalescing
status: Implementable
# Any authors who contribute to the GEP in any way should be listed here using
# their Github handle.
authors:
- robscott
relationships:
# obsoletes indicates that a GEP makes the linked GEP obsolete, and completely
# replaces that GEP. The obsoleted GEP MUST have its obsoletedBy field
# set back to this GEP, and MUST be moved to Declined.
obsoletes: {}
obsoletedBy: {}
# extends indicates that a GEP extends the linkned GEP, adding more detail
# or additional implementation. The extended GEP MUST have its extendedBy
# field set back to this GEP.
extends: {}
extendedBy: {}
# seeAlso indicates other GEPs that are relevant in some way without being
# covered by an existing relationship.
seeAlso: {}
# references is a list of hyperlinks to relevant external references.
# It's intended to be used for storing Github discussions, Google docs, etc.
references: {}
# featureNames is a list of the feature names introduced by the GEP, if there
# are any. This will allow us to track which feature was introduced by which GEP.
featureNames:
- GatewayReturn421
# changelog is a list of hyperlinks to PRs that make changes to the GEP, in
# ascending date order.
changelog: {}