From 5b567140c790c75a0a289d25f79ecdc37eee3477 Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Fri, 5 Jul 2019 22:50:33 +0200 Subject: [PATCH 01/12] design: Added tls-client-verification.md Updates: #1090 Signed-off-by: Lars Ekman --- design/tls-client-verification.md | 124 ++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 design/tls-client-verification.md diff --git a/design/tls-client-verification.md b/design/tls-client-verification.md new file mode 100644 index 00000000000..5a705028184 --- /dev/null +++ b/design/tls-client-verification.md @@ -0,0 +1,124 @@ +# Client certificate validation (mTLS) + +Status: Draft + +See issue #1090 + +## Goals + +- Allow client certificate validation (mTLS) performed by Envoy +- Allow various ways for client certificate validation; Spki, Hash and CA +- Forward client certificate details to the backend (in the fcc- header) +- Document mTLS configuration and client certificate detail forwarding. + +## Non Goals + +- Configure what (if any) client certificate details to forward to the backend +- Repeat configuration details described in Envoy documentation (make references) + + +## Background + +Client certificate validation (mTLS) is supported by Envoy. It should +be possible for `contour` users to utilize this feature. + + +## High-Level Design + +At a high level I propose the following: + +1. A new record "clientValidation" is added in spec.virtualhost.tls + in the IngressRoute. + +2. The `clientValidation` contains configuration for client + certificate validation Many ways of client certificate validation + may be specified (all ways supported by Envoy). + + +### Sample YAML + +``` +apiVersion: contour.heptio.com/v1beta1 +kind: IngressRoute +metadata: + name: kahttp + namespace: default +spec: + virtualhost: + fqdn: kahttp.com + tls: + secretName: contour-secret + clientValidation: + secretName: clientsecret + spkis: + - 2IEpPESU/mmC30tPsnOfbGKdwKdQfN/wZw1QWpjGlmk= + routes: + - match: / + services: + - name: kahttp + port: 80 +``` + +## Detailed Design + + +### CAs in Secrets + +Same as for [TLS backend verification](tls-backend-verification.md) + + +### Changes to the DAG + +A new typed will be added to the `dag` package, `ClientValidation` +to capture the validation parameters. It will be added to `SecureVirtualHost`. + +```go +package dag + +type ClientValidation struct { + // The CA for client validation. + *Secret + // SPKIs used to validate the client certificate + Spkis []string + // Hashes used to validate the client certificate + Hashes []string +} +``` + +### Changes to internal/envoy + +`DownstreamTLSContext()` is extended to take a `clientValidation` this +is a pointer to a structure and may be `nil`. A structure was prefered +before adding a whole bunch of parameters. + +### Changes to internal/contour + +No changes will be required to the code in `cluster.go`. Test cases +will need to be updated. + +### Changes to internal/e2e + +Test cases will need to be updated. + +### Changes to internal/contour + +The `listener.go` will pass ClientValidation data to envoy and +ForwardClientCertDetails is set to SANITIZE_SET. + + +## Alternatives Considered + +To use annotation in the `Ingress` object was considered to clumsy. + +The ForwardClientCertDetails should really be configurable but it was +hard to find a good way. + +## Security Considerations + +This proposal assumes that the API server is secure. If secret or CA +data stored in the API server is modified, verification will be +ineffective. + +This proposal also assumes that RBAC is in place and only the owners +of the Service, Secret, IngressRoute documents in a namespace can +modify them. From 81d7571c6aeefe2a6576b5eb67393bee7ef6d803 Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Fri, 5 Jul 2019 22:53:47 +0200 Subject: [PATCH 02/12] apis/contour; Add clientValidation configuration Updates #1090 Signed-off-by: Lars Ekman Add a "clientValidation" in the IngressRoute for validation of client certificated (mTLS). This commit does not include CRD validation. --- apis/contour/v1beta1/ingressroute.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/apis/contour/v1beta1/ingressroute.go b/apis/contour/v1beta1/ingressroute.go index f766ca07433..f1038c51ab5 100644 --- a/apis/contour/v1beta1/ingressroute.go +++ b/apis/contour/v1beta1/ingressroute.go @@ -52,6 +52,17 @@ type TLS struct { // and the encrypted handshake will be passed through to the // backing cluster. Passthrough bool `json:"passthrough,omitempty"` + // If specified client-certificate is required and validated (mTLS). + ClientValidation *ClientValidation `json:"clientValidation,omitempty"` +} + +type ClientValidation struct { + // The name of a secret in the current namespace used to validate the client certificate + SecretName string `json:"secretName,omitempty"` + // SPKIs used to validate the client certificate + Spkis []string `json:"spkis,omitempty"` + // Hashes used to validate the client certificate + Hashes []string `json:"hashes,omitempty"` } // Route contains the set of routes for a virtual host From 17d3d279e3d8bfc12e115d4239c4a6c4bb0cc08a Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Fri, 5 Jul 2019 22:55:48 +0200 Subject: [PATCH 03/12] internal/dag: Handle the clientValidation configuration Updates #1090 Signed-off-by: Lars Ekman The clientValidation is used for client certificate validation (mTLS) --- internal/dag/builder.go | 6 ++++++ internal/dag/dag.go | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/internal/dag/builder.go b/internal/dag/builder.go index cc03f45cee4..ea204a82808 100644 --- a/internal/dag/builder.go +++ b/internal/dag/builder.go @@ -495,6 +495,12 @@ func (b *builder) computeIngressRoutes() { svhost.Secret = sec svhost.MinProtoVersion = minProtoVersion(ir.Spec.VirtualHost.TLS.MinimumProtocolVersion) enforceTLS = true + if tls.ClientValidation != nil { + svhost.ClientValidation = &ClientValidation{ + Spkis: tls.ClientValidation.Spkis, + Hashes: tls.ClientValidation.Hashes, + } + } } // passthrough is true if tls.secretName is not present, and // tls.passthrough is set to true. diff --git a/internal/dag/dag.go b/internal/dag/dag.go index a23a0231e5c..2d81cb4e628 100644 --- a/internal/dag/dag.go +++ b/internal/dag/dag.go @@ -146,6 +146,20 @@ type SecureVirtualHost struct { // The cert and key for this host. *Secret + + // The client certificate validation for this host (mTLS) + *ClientValidation +} + +type ClientValidation struct { + // The CA for client validation. + *Secret + // SPKIs used to validate the client certificate + Spkis []string + // Hashes used to validate the client certificate + Hashes []string + // How certificate details shall be forwarded to the backend + ForwardClientCertDetails string } func (s *SecureVirtualHost) Visit(f func(Vertex)) { From 566dd23d693d56a87ba1eac991d37498fed67b64 Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Fri, 5 Jul 2019 22:57:22 +0200 Subject: [PATCH 04/12] internal/envoy: Handle clientValidation (mTLS) Update #1090 Signed-off-by: Lars Ekman If ClientValidation is configured for a virtual host Envoy is configured to validate the client certificate (mTLS) --- internal/envoy/auth.go | 21 +++++++++++++++++++-- internal/envoy/listener.go | 9 +++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/internal/envoy/auth.go b/internal/envoy/auth.go index c056bb9b405..317cd9ee739 100644 --- a/internal/envoy/auth.go +++ b/internal/envoy/auth.go @@ -16,6 +16,7 @@ package envoy import ( "github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" "github.com/envoyproxy/go-control-plane/envoy/api/v2/core" + "github.com/gogo/protobuf/types" ) var ( @@ -91,9 +92,16 @@ func validationContext(ca []byte, subjectName string) *auth.CommonTlsContext_Val } } +type ClientValidation struct { + Ca []byte + Spkis []string + Hashes []string + ForwardClientCertDetails string +} + // DownstreamTLSContext creates a new DownstreamTlsContext. -func DownstreamTLSContext(secretName string, tlsMinProtoVersion auth.TlsParameters_TlsProtocol, alpnProtos ...string) *auth.DownstreamTlsContext { - return &auth.DownstreamTlsContext{ +func DownstreamTLSContext(secretName string, clientValidation *ClientValidation, tlsMinProtoVersion auth.TlsParameters_TlsProtocol, alpnProtos ...string) *auth.DownstreamTlsContext { + context := auth.DownstreamTlsContext{ CommonTlsContext: &auth.CommonTlsContext{ TlsParams: &auth.TlsParameters{ TlsMinimumProtocolVersion: tlsMinProtoVersion, @@ -107,4 +115,13 @@ func DownstreamTLSContext(secretName string, tlsMinProtoVersion auth.TlsParamete AlpnProtocols: alpnProtos, }, } + if clientValidation != nil { + context.RequireClientCertificate = &types.BoolValue{Value: true} + context.CommonTlsContext.ValidationContextType = &auth.CommonTlsContext_ValidationContext{ + ValidationContext: &auth.CertificateValidationContext{ + VerifyCertificateSpki: clientValidation.Spkis, + }, + } + } + return &context } diff --git a/internal/envoy/listener.go b/internal/envoy/listener.go index 75cecda7991..9d8b342dd99 100644 --- a/internal/envoy/listener.go +++ b/internal/envoy/listener.go @@ -118,10 +118,11 @@ func HTTPConnectionManager(routename, accessLogPath string) listener.Filter { // a Host: header. See #537. AcceptHttp_10: true, }, - AccessLog: FileAccessLog(accessLogPath), - UseRemoteAddress: &types.BoolValue{Value: true}, // TODO(jbeda) should this ever be false? - NormalizePath: &types.BoolValue{Value: true}, - IdleTimeout: idleTimeout(HTTPDefaultIdleTimeout), + AccessLog: FileAccessLog(accessLogPath), + UseRemoteAddress: &types.BoolValue{Value: true}, // TODO(jbeda) should this ever be false? + NormalizePath: &types.BoolValue{Value: true}, + IdleTimeout: idleTimeout(HTTPDefaultIdleTimeout), + ForwardClientCertDetails: http.SANITIZE_SET, }), }, } From d587de76ecea46d6d657bd0ab55395861e093a73 Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Fri, 5 Jul 2019 23:00:16 +0200 Subject: [PATCH 05/12] internal/contour; Use ClientValidation if configured Updates #1090 Signed-off-by: Lars Ekman If ClientValidation is configured validation data is sent to Envoy for client validation (mTLS) --- internal/contour/listener.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/internal/contour/listener.go b/internal/contour/listener.go index 6e2b7149967..2aa3e7e3186 100644 --- a/internal/contour/listener.go +++ b/internal/contour/listener.go @@ -318,7 +318,15 @@ func (v *listenerVisitor) visit(vertex dag.Vertex) { // attach certificate data to this listener if provided. if vh.Secret != nil { - fc.TlsContext = envoy.DownstreamTLSContext(envoy.Secretname(vh.Secret), vh.MinProtoVersion, alpnProtos...) + if vh.ClientValidation != nil { + clientValidation := &envoy.ClientValidation{ + Spkis: vh.ClientValidation.Spkis, + ForwardClientCertDetails: vh.ClientValidation.ForwardClientCertDetails, + } + fc.TlsContext = envoy.DownstreamTLSContext(envoy.Secretname(vh.Secret), clientValidation, vh.MinProtoVersion, alpnProtos...) + } else { + fc.TlsContext = envoy.DownstreamTLSContext(envoy.Secretname(vh.Secret), nil, vh.MinProtoVersion, alpnProtos...) + } } v.listeners[ENVOY_HTTPS_LISTENER].FilterChains = append(v.listeners[ENVOY_HTTPS_LISTENER].FilterChains, fc) From 35c65a35906ea199e042bcffd7e02695368aee0d Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Sat, 6 Jul 2019 13:21:02 +0200 Subject: [PATCH 06/12] Unit-tests; Corrected regression tests No unit-tests for mTLS added in this commit Signed-off-by: Lars Ekman --- internal/contour/listener_test.go | 2 +- internal/e2e/lds_test.go | 2 +- internal/envoy/listener_test.go | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/contour/listener_test.go b/internal/contour/listener_test.go index 03e95215b96..c7afa6b2acb 100644 --- a/internal/contour/listener_test.go +++ b/internal/contour/listener_test.go @@ -646,7 +646,7 @@ func filterchain(filters ...listener.Filter) []listener.FilterChain { } func tlscontext(tlsMinProtoVersion auth.TlsParameters_TlsProtocol, alpnprotos ...string) *auth.DownstreamTlsContext { - return envoy.DownstreamTLSContext("default/secret/735ad571c1", tlsMinProtoVersion, alpnprotos...) + return envoy.DownstreamTLSContext("default/secret/735ad571c1", nil, tlsMinProtoVersion, alpnprotos...) } func secretdata(cert, key string) map[string][]byte { diff --git a/internal/e2e/lds_test.go b/internal/e2e/lds_test.go index 5a3c185b560..500ed474e55 100644 --- a/internal/e2e/lds_test.go +++ b/internal/e2e/lds_test.go @@ -1435,7 +1435,7 @@ func filterchaintls(domain string, secret *v1.Secret, filter listener.Filter, al ServerNames: []string{domain}, } secretName := envoy.Secretname(&dag.Secret{Object: secret}) - fc.TlsContext = envoy.DownstreamTLSContext(secretName, auth.TlsParameters_TLSv1_1, alpn...) + fc.TlsContext = envoy.DownstreamTLSContext(secretName, nil, auth.TlsParameters_TLSv1_1, alpn...) return []listener.FilterChain{fc} } diff --git a/internal/envoy/listener_test.go b/internal/envoy/listener_test.go index 08f3a8571f5..840bb524529 100644 --- a/internal/envoy/listener_test.go +++ b/internal/envoy/listener_test.go @@ -164,7 +164,7 @@ func TestSocketAddress(t *testing.T) { func TestDownstreamTLSContext(t *testing.T) { const secretName = "default/tls-cert" - got := DownstreamTLSContext(secretName, auth.TlsParameters_TLSv1_1, "h2", "http/1.1") + got := DownstreamTLSContext(secretName, nil, auth.TlsParameters_TLSv1_1, "h2", "http/1.1") want := &auth.DownstreamTlsContext{ CommonTlsContext: &auth.CommonTlsContext{ TlsParams: &auth.TlsParameters{ @@ -258,6 +258,7 @@ func TestHTTPConnectionManager(t *testing.T) { UseRemoteAddress: &types.BoolValue{Value: true}, NormalizePath: &types.BoolValue{Value: true}, IdleTimeout: duration(HTTPDefaultIdleTimeout), + ForwardClientCertDetails: http.SANITIZE_SET, }), }, }, From 7a0c928ffd7961e294679f68865466140b7e486d Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Sat, 6 Jul 2019 13:31:12 +0200 Subject: [PATCH 07/12] internal/envoy; gofmt on _test Signed-off-by: Lars Ekman --- internal/envoy/listener_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/envoy/listener_test.go b/internal/envoy/listener_test.go index 840bb524529..91a8fb223b6 100644 --- a/internal/envoy/listener_test.go +++ b/internal/envoy/listener_test.go @@ -254,10 +254,10 @@ func TestHTTPConnectionManager(t *testing.T) { // a Host: header. See #537. AcceptHttp_10: true, }, - AccessLog: FileAccessLog("/dev/stdout"), - UseRemoteAddress: &types.BoolValue{Value: true}, - NormalizePath: &types.BoolValue{Value: true}, - IdleTimeout: duration(HTTPDefaultIdleTimeout), + AccessLog: FileAccessLog("/dev/stdout"), + UseRemoteAddress: &types.BoolValue{Value: true}, + NormalizePath: &types.BoolValue{Value: true}, + IdleTimeout: duration(HTTPDefaultIdleTimeout), ForwardClientCertDetails: http.SANITIZE_SET, }), }, From 623a0057da15acd53a41af85fdb5274a5aec8287 Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Sat, 6 Jul 2019 13:52:52 +0200 Subject: [PATCH 08/12] design: Corrected spelling Signed-off-by: Lars Ekman --- design/tls-client-verification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/tls-client-verification.md b/design/tls-client-verification.md index 5a705028184..5d5cc6c84ad 100644 --- a/design/tls-client-verification.md +++ b/design/tls-client-verification.md @@ -88,7 +88,7 @@ type ClientValidation struct { ### Changes to internal/envoy `DownstreamTLSContext()` is extended to take a `clientValidation` this -is a pointer to a structure and may be `nil`. A structure was prefered +is a pointer to a structure and may be `nil`. A structure was preferred before adding a whole bunch of parameters. ### Changes to internal/contour From b0bc0e5edd35787d531328cf43081101ad4a02f4 Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Sat, 6 Jul 2019 14:32:11 +0200 Subject: [PATCH 09/12] docs; User documentation for mTLS Updates #1090 Signed-off-by: Lars Ekman --- docs/ingressroute.md | 75 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/docs/ingressroute.md b/docs/ingressroute.md index 2d01d7765fc..f42e77e9a39 100644 --- a/docs/ingressroute.md +++ b/docs/ingressroute.md @@ -350,6 +350,81 @@ spec: In this example, the permission for Contour to reference the Secret `example-com-wildcard` in the `admin` namespace has been delegated to IngressRoute objects in the `example-com` namespace. +#### Mutual TLS (client validation) + +Mutual TLS (mTLS) means that not only the server but also the client must present a certificate for validation. + +```yaml +apiVersion: contour.heptio.com/v1beta1 +kind: IngressRoute +metadata: + name: www + namespace: default +spec: + virtualhost: + fqdn: foo.com + tls: + secretName: server-secret + clientValidation: + secretName: client-secret + routes: + - match: / + services: + - name: s1 + port: 80 +``` + +With this configuration clients accessing `foo.com` must provide a certificate that can be validated by the CA stored in the `client-secret`. If the client validation fails the access will be rejected. + + +##### Other ways of client certificate validation + +Envoy allows two other ways for client certificate validation; + +* Subject Public Key Information (SPKI) +* Certificate hash + +These can also be specified in `clientValidation`; + +```yaml +apiVersion: contour.heptio.com/v1beta1 +kind: IngressRoute +metadata: + name: www + namespace: default +spec: + virtualhost: + fqdn: foo.com + tls: + secretName: server-secret + clientValidation: + spkis: + - 2IEpPESU/mmC30tPsnOfbGKdwKdQfN/wZw1QWpjGlmk= + hashes: + - c49c6930b9fbfb72a0d9d07504133d26c87588aa2d32b2919475f647a62f6fec + routes: + - match: / + services: + - name: s1 + port: 80 +``` + +Please read the [Envoy documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/auth/cert.proto.html#auth-certificatevalidationcontext) for details. + + +##### Forward client certificate details + +The backend application may need information of the certificate used (by envoy) to validate the client. Contour forwards client certificate details in the `X-Forwarded-Client-Cert` http header; + +``` +X-Forwarded-Client-Cert: [Hash=c49c6930b9fbfb72a0d9d07504133d26c87588aa2d32b2919475f647a62f6fec] +``` + +The hash uniquely identifies the used client certificate. + +Contour uses the [SANITIZE_SET](https://www.envoyproxy.io/docs/envoy/latest/api-v2/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#envoy-api-enum-config-filter-network-http-connection-manager-v2-httpconnectionmanager-forwardclientcertdetails) option in `envoy`. + + ### Routing Each route entry in an IngressRoute must start with a prefix match. From 9f052d9b6edc17403bbcc16de0ab7c26aa7d971c Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Sat, 6 Jul 2019 16:42:05 +0200 Subject: [PATCH 10/12] internal: Make client validation with Hashes work Updates #1090 Signed-off-by: Lars Ekman Also remove misplaced ForwardCertificateDetails items. --- internal/contour/listener.go | 4 ++-- internal/dag/dag.go | 2 -- internal/envoy/auth.go | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/contour/listener.go b/internal/contour/listener.go index 2aa3e7e3186..4811093b04b 100644 --- a/internal/contour/listener.go +++ b/internal/contour/listener.go @@ -320,8 +320,8 @@ func (v *listenerVisitor) visit(vertex dag.Vertex) { if vh.Secret != nil { if vh.ClientValidation != nil { clientValidation := &envoy.ClientValidation{ - Spkis: vh.ClientValidation.Spkis, - ForwardClientCertDetails: vh.ClientValidation.ForwardClientCertDetails, + Spkis: vh.ClientValidation.Spkis, + Hashes: vh.ClientValidation.Hashes, } fc.TlsContext = envoy.DownstreamTLSContext(envoy.Secretname(vh.Secret), clientValidation, vh.MinProtoVersion, alpnProtos...) } else { diff --git a/internal/dag/dag.go b/internal/dag/dag.go index 2d81cb4e628..bfe0e1c650f 100644 --- a/internal/dag/dag.go +++ b/internal/dag/dag.go @@ -158,8 +158,6 @@ type ClientValidation struct { Spkis []string // Hashes used to validate the client certificate Hashes []string - // How certificate details shall be forwarded to the backend - ForwardClientCertDetails string } func (s *SecureVirtualHost) Visit(f func(Vertex)) { diff --git a/internal/envoy/auth.go b/internal/envoy/auth.go index 317cd9ee739..939cf84ca95 100644 --- a/internal/envoy/auth.go +++ b/internal/envoy/auth.go @@ -120,6 +120,7 @@ func DownstreamTLSContext(secretName string, clientValidation *ClientValidation, context.CommonTlsContext.ValidationContextType = &auth.CommonTlsContext_ValidationContext{ ValidationContext: &auth.CertificateValidationContext{ VerifyCertificateSpki: clientValidation.Spkis, + VerifyCertificateHash: clientValidation.Hashes, }, } } From df61698f6738e9593086d4a49a395c1e9e5b96e8 Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Mon, 8 Jul 2019 12:10:42 +0200 Subject: [PATCH 11/12] Start CA validation design Signed-off-by: Lars Ekman --- internal/dag/builder.go | 7 +++++++ internal/envoy/auth.go | 7 +++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/internal/dag/builder.go b/internal/dag/builder.go index ea204a82808..14bbd3eb69d 100644 --- a/internal/dag/builder.go +++ b/internal/dag/builder.go @@ -500,6 +500,13 @@ func (b *builder) computeIngressRoutes() { Spkis: tls.ClientValidation.Spkis, Hashes: tls.ClientValidation.Hashes, } + if tls.ClientValidation.SecretName != "" { + m := splitSecret(tls.ClientValidation.SecretName, ir.Namespace) + sec := b.lookupSecret(m, validSecret) + if sec != nil { + svhost.ClientValidation.Secret = sec + } + } } } // passthrough is true if tls.secretName is not present, and diff --git a/internal/envoy/auth.go b/internal/envoy/auth.go index 939cf84ca95..809d1873c44 100644 --- a/internal/envoy/auth.go +++ b/internal/envoy/auth.go @@ -93,10 +93,9 @@ func validationContext(ca []byte, subjectName string) *auth.CommonTlsContext_Val } type ClientValidation struct { - Ca []byte - Spkis []string - Hashes []string - ForwardClientCertDetails string + Secret *auth.Secret + Spkis []string + Hashes []string } // DownstreamTLSContext creates a new DownstreamTlsContext. From 6095bed1c611a01b5b0c4f9d7e3cd66a1690ea7f Mon Sep 17 00:00:00 2001 From: Lars Ekman Date: Mon, 8 Jul 2019 13:51:34 +0200 Subject: [PATCH 12/12] design; Removed the design document Signed-off-by: Lars Ekman Moved to a separate PR --- design/tls-client-verification.md | 124 ------------------------------ 1 file changed, 124 deletions(-) delete mode 100644 design/tls-client-verification.md diff --git a/design/tls-client-verification.md b/design/tls-client-verification.md deleted file mode 100644 index 5d5cc6c84ad..00000000000 --- a/design/tls-client-verification.md +++ /dev/null @@ -1,124 +0,0 @@ -# Client certificate validation (mTLS) - -Status: Draft - -See issue #1090 - -## Goals - -- Allow client certificate validation (mTLS) performed by Envoy -- Allow various ways for client certificate validation; Spki, Hash and CA -- Forward client certificate details to the backend (in the fcc- header) -- Document mTLS configuration and client certificate detail forwarding. - -## Non Goals - -- Configure what (if any) client certificate details to forward to the backend -- Repeat configuration details described in Envoy documentation (make references) - - -## Background - -Client certificate validation (mTLS) is supported by Envoy. It should -be possible for `contour` users to utilize this feature. - - -## High-Level Design - -At a high level I propose the following: - -1. A new record "clientValidation" is added in spec.virtualhost.tls - in the IngressRoute. - -2. The `clientValidation` contains configuration for client - certificate validation Many ways of client certificate validation - may be specified (all ways supported by Envoy). - - -### Sample YAML - -``` -apiVersion: contour.heptio.com/v1beta1 -kind: IngressRoute -metadata: - name: kahttp - namespace: default -spec: - virtualhost: - fqdn: kahttp.com - tls: - secretName: contour-secret - clientValidation: - secretName: clientsecret - spkis: - - 2IEpPESU/mmC30tPsnOfbGKdwKdQfN/wZw1QWpjGlmk= - routes: - - match: / - services: - - name: kahttp - port: 80 -``` - -## Detailed Design - - -### CAs in Secrets - -Same as for [TLS backend verification](tls-backend-verification.md) - - -### Changes to the DAG - -A new typed will be added to the `dag` package, `ClientValidation` -to capture the validation parameters. It will be added to `SecureVirtualHost`. - -```go -package dag - -type ClientValidation struct { - // The CA for client validation. - *Secret - // SPKIs used to validate the client certificate - Spkis []string - // Hashes used to validate the client certificate - Hashes []string -} -``` - -### Changes to internal/envoy - -`DownstreamTLSContext()` is extended to take a `clientValidation` this -is a pointer to a structure and may be `nil`. A structure was preferred -before adding a whole bunch of parameters. - -### Changes to internal/contour - -No changes will be required to the code in `cluster.go`. Test cases -will need to be updated. - -### Changes to internal/e2e - -Test cases will need to be updated. - -### Changes to internal/contour - -The `listener.go` will pass ClientValidation data to envoy and -ForwardClientCertDetails is set to SANITIZE_SET. - - -## Alternatives Considered - -To use annotation in the `Ingress` object was considered to clumsy. - -The ForwardClientCertDetails should really be configurable but it was -hard to find a good way. - -## Security Considerations - -This proposal assumes that the API server is secure. If secret or CA -data stored in the API server is modified, verification will be -ineffective. - -This proposal also assumes that RBAC is in place and only the owners -of the Service, Secret, IngressRoute documents in a namespace can -modify them.