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

Adds API to GEP-91: Client Certificate Validation #2273

Merged
merged 21 commits into from
Apr 8, 2024
Merged
Changes from 19 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
152 changes: 147 additions & 5 deletions geps/gep-91/index.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,164 @@
# GEP-91: Client Certificate Validation for TLS terminating at the Gateway Listener

* Issue: [#91](https://github.com/kubernetes-sigs/gateway-api/issues/91)
* Status: Provisional
* Status: Implementable
Copy link
Member

Choose a reason for hiding this comment

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

Before this formally moves to experimental, I think we need a corresponding metadata file for this GEP. Not going to block on this specific PR since it can easily be handled in a following.


(See definitions in [GEP Status][/contributing/gep#status].)

## TLDR

This GEP proposes a way to validate the TLS certificate presented by the downstream client to the server
(Gateway Listener in this case) during a [TLS Handshake Protocol][], also commonly referred to as mutual TLS (mTLS).
This GEP proposes a way to validate the TLS certificate presented by the frontend client to the server
(Gateway Listener in this case) during a [TLS Handshake Protocol][].

## Goals
- Define an API field to specify the CA Certificate within the Gateway Listener configuration that can be used as a trusted anchor to validate the certificates presented by the client.

* Define an API field to specify the CA Certificate within the Gateway Listener configuration that can be used as a trust anchor to validate the certificates presented by the client. This use case has been highlighted in the [TLS Configuration GEP][] under segment 1 and in the [Gateway API TLS Use Cases][] document under point 7.

## Non-Goals
- Define other fields that can be used to verify the client certificate such as the Certificate Hash or Subject Alt Name.
* Define other fields that can be used to verify the client certificate such as the Certificate Hash.

## Existing support in Implementations

This feature is widely supported in implementations that support Gateway API.
This table highlights the support. Please feel free to add any missing implementations not mentioned below.

| Implementation | Support |
|----------------|------------|
| Apache APISIX | [ApisixTls.Client.CASecret](https://apisix.apache.org/docs/ingress-controller/tutorials/mtls/#mutual-authentication) |
| Contour | [HTTPProxy.Spec.VirtualHost.Tls.ClientValidation.CASecret](https://projectcontour.io/docs/v1.17.1/config/tls-termination/) |
| Emissary Ingress| [TlSContext.Spec.Secret](https://www.getambassador.io/docs/emissary/latest/topics/running/tls/mtls) |
| Gloo Edge | [VirtualService.Spec.SSLConfig.SecretRef](https://docs.solo.io/gloo-edge/latest/guides/security/tls/server_tls/#configuring-downstream-mtls-in-a-virtual-service) |
| Istio | [Gateway.Spec.Servers.TLS.Mode](https://istio.io/latest/docs/tasks/traffic-management/ingress/secure-ingress/#configure-a-mutual-tls-ingress-gateway) |
| Kong | [mTLS Plugin](https://docs.konghq.com/hub/kong-inc/mtls-auth/) |
| Traefik | [TLSOption.Spec.ClientAuth](https://doc.traefik.io/traefik/https/tls/#client-authentication-mtls) |
| NGINX Ingress Controller | [ingressMTLS](https://docs.nginx.com/nginx-ingress-controller/configuration/policy-resource/#ingressmtls) |

### API

* Introduce a `FrontendValidation` field of type `FrontendTLSValidation` within [GatewayTLSConfig][] that can be used to validate the peer (frontend) with which the TLS connection is being made.
* Introduce a `caCertificateRefs` field within `FrontendTLSValidation` that can be used to specify a list of CA Certificates that can be used as a trust anchor to validate the certificates presented by the client.
* This new field is mutually exclusive with the [BackendTLSPolicy][] configuation which is used to validate the TLS certificate presented by the backend peer on the connection between the Gateway and the backend, and this GEP is adding support for validating the TLS certificate presented by the frontend client on the connection between the Gateway and the frontend. Both these configurations can coexist at the same time without affecting one another.
* Also introduce a `ObjectReference` structure that can be used to specify `caCertificateRefs` references.

#### GO

```go
// ObjectReference identifies an API object including its namespace.
//
// The API object must be valid in the cluster; the Group and Kind must
// be registered in the cluster for this reference to be valid.
//
// References to objects with invalid Group and Kind are not valid, and must
// be rejected by the implementation, with appropriate Conditions set
// on the containing object.
type ObjectReference struct {
// Group is the group of the referent. For example, "gateway.networking.k8s.io".
// When unspecified or empty string, core API group is inferred.
Group Group `json:"group"`

// Kind is kind of the referent. For example "ConfigMap" or "Service".
Kind Kind `json:"kind"`

// Name is the name of the referent.
Name ObjectName `json:"name"`

// Namespace is the namespace of the referenced object. When unspecified, the local
// namespace is inferred.
//
// Note that when a namespace different than the local namespace is specified,
// a ReferenceGrant object is required in the referent namespace to allow that
// namespace's owner to accept the reference. See the ReferenceGrant
// documentation for details.
//
// Support: Core
//
// +optional
Namespace *Namespace `json:"namespace,omitempty"`
}

type GatewayTLSConfig struct {
......
// FrontendValidation holds configuration information for validating the frontend (client).
// Setting this field will require clients to send a client certificate
// required for validation during the TLS handshake. In browsers this may result in a dialog appearing
// that requests a user to specify the client certificate.
// The maximum depth of a certificate chain accepted in verification is Implementation specific.
FrontendValidation *FrontendTLSValidation `json:"frontendValidation,omitempty"`
}

// FrontendTLSValidation holds configuration information that can be used to validate
// the frontend initiating the TLS connection
type FrontendTLSValidationContext struct {
// CACertificateRefs contains one or more references to
// Kubernetes objects that contain TLS certificates of
// the Certificate Authorities that can be used
// as a trust anchor to validate the certificates presented by the client.
//
// A single CA certificate reference to a Kubernetes ConfigMap
// has "Core" support.
// Implementations MAY choose to support attaching multiple CA certificates to
// a Listener, but this behavior is implementation-specific.
//
// Support: Core - An optional single reference to a single Kubernetes Secret
// and to a single Kubernetes ConfigMap with the CA certificate in a key named `ca.crt`.
arkodg marked this conversation as resolved.
Show resolved Hide resolved
//
// Support: Implementation-specific (More than one reference, or other kinds
// of resources).
//
// References to a resource in a different namespace are invalid UNLESS there
// is a ReferenceGrant in the target namespace that allows the certificate
// to be attached. If a ReferenceGrant does not allow this reference, the
// "ResolvedRefs" condition MUST be set to False for this listener with the
// "RefNotPermitted" reason.
//
// +kubebuilder:validation:MaxItems=8
// +kubebuilder:validation:MinItems=1
CACertificateRefs []ObjectReference `json:"caCertificateRefs,omitempty"`
}
arkodg marked this conversation as resolved.
Show resolved Hide resolved

```

#### YAML

```yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: client-validation-basic
spec:
gatewayClassName: acme-lb
listeners:
- name: foo-https
protocol: HTTPS
port: 443
hostname: foo.example.com
tls:
certificateRefs:
- kind: Secret
group: ""
name: foo-example-com-cert
frontendValidation:
caCertificateRefs:
- kind: ConfigMap
group: ""
name: foo-example-com-ca-cert
```

## Deferred

This section highlights use cases that may be covered in a future iteration of this GEP

* Using system CA certificates as the trust anchor to validate the certificates presented by the frontend client.
* Supporting a mode where validating client certficates is optional, useful for debugging and migrating to strict TLS.
* Supporting an optional `subjectAltNames` field within `FrontendTLSValidation` that can be used to specify one or more alternate names to verify the subject identity in the certificate presented by the client. This field falls under Authorization, the initial focus here is on Client Authentication and will be revisited when Authorization is tackled as a whole in the project.
* Specifying the verification depth in the client certificate chain. This is being deferred because the default verification depth differs across implementations.


## References

[TLS Handshake Protocol]: https://www.rfc-editor.org/rfc/rfc5246#section-7.4
[Certificate Path Validation]: https://www.rfc-editor.org/rfc/rfc5280#section-6
[GatewayTLSConfig]: https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.GatewayTLSConfig
[BackendTLSPolicy]: https://gateway-api.sigs.k8s.io/api-types/backendtlspolicy/
[TLS Configuration GEP]: https://gateway-api.sigs.k8s.io/geps/gep-2907/
[Gateway API TLS Use Cases]: https://docs.google.com/document/d/17sctu2uMJtHmJTGtBi_awGB0YzoCLodtR6rUNmKMCs8/edit?pli=1#heading=h.cxuq8vo8pcxm