Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
25 changes: 25 additions & 0 deletions geps/gep-4078/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# GEP-4078: Certificate Pinning for Client Certificate Validation

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

(See [status definitions](../overview.md#gep-states).)

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in BCP 14 ([RFC8174]) when, and
only when, they appear in all capitals, as shown here.

[RFC8174]: https://www.rfc-editor.org/rfc/rfc8174

## What
Enhance the existing Client Certificate Validation defined in [GEP-91](../gep-91/index.md) by introducing support for certificate pinning. This allows specifying one or more certificate or public key hashes (SPKI) that are considered valid for client connections. During TLS client authentication, the Gateway will validate not only against the configured CAs, but also against the pinned certificates or keys. This provides a mechanism to restrict allowed clients to a narrowly defined set of certificates, even if the CA trust domain is broad.
Copy link
Member

@rikatz rikatz Sep 10, 2025

Choose a reason for hiding this comment

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

not really important at this moment, but do we/should we care also about validating the certificate CN or some other field? see as a reference: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#client-certificate-authentication

Copy link
Member Author

@snorwin snorwin Sep 10, 2025

Choose a reason for hiding this comment

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

IMO CN and SAN validation for client certificates should be part of the Gateway API too, but I would prefer a dedicated GEP for it.

Copy link
Member

Choose a reason for hiding this comment

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

lgtm

Copy link
Contributor

Choose a reason for hiding this comment

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

During TLS client authentication, the Gateway will validate not only against the configured CAs, but also against the pinned certificates or keys.

I think that we should allow configuring validation either with CAs or by certificate pinning. Combining two of them with AND does not make sense to me.

Copy link
Member Author

Choose a reason for hiding this comment

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

I updated the GEP to make it clearer that certificate pinning is intended as an alternative to the existing CA-based validation of client certificates.


## Why
While [GEP-91](../gep-91/index.md) enables client certificate validation against a CA, in practice many operators rely on large organizational CAs or even on public CAs. These often cover many certificates and, as a result, unintentionally expand the trust boundary. This limitation becomes particularly significant when client certificates are used not only for encryption but also for authentication. In these cases, operators may want to restrict access to an explicit set of identities, rather than the entire population served by a CA.
In addition, certificate pinning strengthens security by reducing exposure to rogue certificates and mitigating the risk of man-in-the-middle (MITM) attacks.

## Who: Beneficiaries
* **Application Developers**: Can use certificate pinning as a lightweight alternative to JWTs or other token systems, authenticating users or devices directly through TLS without additional infrastructure.
* **Platform Operators/Administrators**: Gain a standardized way to enforce fine-grained client restrictions, even when using broad or public CAs, which improves security.
* **Security and Compliance Teams**: Benefit from a certificate-bound authentication mechanism that limits access to explicitly approved identities, aligning with regulatory and organizational policies.
35 changes: 35 additions & 0 deletions geps/gep-4078/metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
apiVersion: internal.gateway.networking.k8s.io/v1alpha1
kind: GEPDetails
number: 4078
name: Certificate Pinning for Client Certificate Validation
status: Provisional
# Any authors who contribute to the GEP in any way should be listed here using
# their GitHub handle.
authors:
- snorwin
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 linked GEP, adding more detail
# or additional implementation. The extended GEP MUST have its extendedBy
# field set back to this GEP.
extends:
- number: 91
name: Client Certificate Validation for TLS terminating at the Gateway Listener
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.
# This is the value added to supportedFeatures and the conformance tests, in string form.
featureNames: {}
# changelog is a list of hyperlinks to PRs that make changes to the GEP, in
# ascending date order.
changelog: {}
26 changes: 26 additions & 0 deletions geps/gep-91/metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,29 @@ name: Client Certificate Validation for TLS terminating at the Gateway Listener
status: Provisional
authors:
- arkodg
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: {}
Copy link
Member

Choose a reason for hiding this comment

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

fun fact, this is an array per GEP API definition, and setting it as "{}" will break people trying to programatically unmarshal/decode this (see me fighting and failing against it at #4075

So the right thing here is to set these fields as [] (empty array) and not as {} (empty object).

Take a look into my PR above, you will see me changing this on a lot of places :)

obsoletedBy: {}
# extends indicates that a GEP extends the linked GEP, adding more detail
# or additional implementation. The extended GEP MUST have its extendedBy
# field set back to this GEP.
extends: {}
extendedBy:
- number: 4078
name: Certificate Pinning for Client Certificate Validation
# 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.
# This is the value added to supportedFeatures and the conformance tests, in string form.
featureNames: {}
# changelog is a list of hyperlinks to PRs that make changes to the GEP, in
# ascending date order.
changelog: {}