From ef36ebd64ed9d72b03ab0bb75cdfa6a95e56ceb6 Mon Sep 17 00:00:00 2001 From: Clay Kauzlaric Date: Thu, 12 Oct 2023 18:07:43 -0400 Subject: [PATCH] add config options for min max tls version on upstream connections Signed-off-by: Clay Kauzlaric --- apis/projectcontour/v1alpha1/contourconfig.go | 5 ++ .../v1alpha1/zz_generated.deepcopy.go | 5 ++ cmd/contour/serve.go | 3 + cmd/contour/servecontext.go | 5 ++ examples/contour/01-crds.yaml | 88 +++++++++++++++++++ examples/render/contour-deployment.yaml | 88 +++++++++++++++++++ .../render/contour-gateway-provisioner.yaml | 88 +++++++++++++++++++ examples/render/contour-gateway.yaml | 88 +++++++++++++++++++ examples/render/contour.yaml | 88 +++++++++++++++++++ .../contourconfig/contourconfiguration.go | 5 ++ internal/dag/dag.go | 13 +++ internal/dag/httpproxy_processor.go | 9 ++ internal/envoy/v3/auth.go | 13 ++- internal/envoy/v3/auth_test.go | 19 +++- internal/envoy/v3/cluster.go | 5 +- internal/envoy/v3/cluster_test.go | 50 +++++++++-- internal/envoy/v3/socket_test.go | 4 +- .../v3/backendcavalidation_test.go | 6 +- .../featuretests/v3/backendclientauth_test.go | 5 +- internal/featuretests/v3/envoy.go | 6 +- internal/featuretests/v3/externalname_test.go | 6 +- internal/featuretests/v3/headerpolicy_test.go | 4 +- internal/featuretests/v3/tcpproxy_test.go | 2 +- .../featuretests/v3/upstreamprotocol_test.go | 8 +- pkg/config/parameters.go | 10 +++ .../docs/main/config/api-reference.html | 16 ++++ 26 files changed, 610 insertions(+), 29 deletions(-) diff --git a/apis/projectcontour/v1alpha1/contourconfig.go b/apis/projectcontour/v1alpha1/contourconfig.go index 5699d5e1f30..eb6a226cf1b 100644 --- a/apis/projectcontour/v1alpha1/contourconfig.go +++ b/apis/projectcontour/v1alpha1/contourconfig.go @@ -656,6 +656,11 @@ type ClusterParameters struct { // +kubebuilder:validation:Minimum=1 // +optional PerConnectionBufferLimitBytes *uint32 `json:"per-connection-buffer-limit-bytes,omitempty"` + + // UpstreamTLS contains the TLS policy parameters for upstream connections + // + // +optional + UpstreamTLS *EnvoyTLS `json:"upstream-tls,omitempty"` } // HTTPProxyConfig defines parameters on HTTPProxy. diff --git a/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go b/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go index d889c429aa5..0090426ecea 100644 --- a/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go +++ b/apis/projectcontour/v1alpha1/zz_generated.deepcopy.go @@ -60,6 +60,11 @@ func (in *ClusterParameters) DeepCopyInto(out *ClusterParameters) { *out = new(uint32) **out = **in } + if in.UpstreamTLS != nil { + in, out := &in.UpstreamTLS, &out.UpstreamTLS + *out = new(EnvoyTLS) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterParameters. diff --git a/cmd/contour/serve.go b/cmd/contour/serve.go index d7bd8387a4a..fd55069692c 100644 --- a/cmd/contour/serve.go +++ b/cmd/contour/serve.go @@ -537,6 +537,7 @@ func (s *Server) doServe() error { globalRateLimitService: contourConfiguration.RateLimitService, maxRequestsPerConnection: contourConfiguration.Envoy.Cluster.MaxRequestsPerConnection, perConnectionBufferLimitBytes: contourConfiguration.Envoy.Cluster.PerConnectionBufferLimitBytes, + upstreamTLS: contourConfiguration.Envoy.Cluster.UpstreamTLS, }) // Build the core Kubernetes event handler. @@ -1082,6 +1083,7 @@ type dagBuilderConfig struct { maxRequestsPerConnection *uint32 perConnectionBufferLimitBytes *uint32 globalRateLimitService *contour_api_v1alpha1.RateLimitServiceConfig + upstreamTLS *contour_api_v1alpha1.EnvoyTLS } func (s *Server) getDAGBuilder(dbc dagBuilderConfig) *dag.Builder { @@ -1174,6 +1176,7 @@ func (s *Server) getDAGBuilder(dbc dagBuilderConfig) *dag.Builder { GlobalRateLimitService: dbc.globalRateLimitService, PerConnectionBufferLimitBytes: dbc.perConnectionBufferLimitBytes, SetSourceMetadataOnRoutes: true, + UpstreamTLS: dbc.upstreamTLS, }, } diff --git a/cmd/contour/servecontext.go b/cmd/contour/servecontext.go index 629ef75280f..ea26fe8acdc 100644 --- a/cmd/contour/servecontext.go +++ b/cmd/contour/servecontext.go @@ -570,6 +570,11 @@ func (ctx *serveContext) convertToContourConfigurationSpec() contour_api_v1alpha DNSLookupFamily: dnsLookupFamily, MaxRequestsPerConnection: ctx.Config.Cluster.MaxRequestsPerConnection, PerConnectionBufferLimitBytes: ctx.Config.Cluster.PerConnectionBufferLimitBytes, + UpstreamTLS: &contour_api_v1alpha1.EnvoyTLS{ + MinimumProtocolVersion: ctx.Config.Cluster.UpstreamTLS.MinimumProtocolVersion, + MaximumProtocolVersion: ctx.Config.Cluster.UpstreamTLS.MaximumProtocolVersion, + CipherSuites: ctx.Config.Cluster.UpstreamTLS.CipherSuites, + }, }, Network: &contour_api_v1alpha1.NetworkParameters{ XffNumTrustedHops: &ctx.Config.Network.XffNumTrustedHops, diff --git a/examples/contour/01-crds.yaml b/examples/contour/01-crds.yaml index 98b9fe9cebd..22c197103aa 100644 --- a/examples/contour/01-crds.yaml +++ b/examples/contour/01-crds.yaml @@ -111,6 +111,48 @@ spec: format: int32 minimum: 1 type: integer + upstream-tls: + description: UpstreamTLS contains the TLS policy parameters + for upstream connections + properties: + cipherSuites: + description: "CipherSuites defines the TLS ciphers to + be supported by Envoy TLS listeners when negotiating + TLS 1.2. Ciphers are validated against the set that + Envoy supports by default. This parameter should only + be used by advanced users. Note that these will be ignored + when TLS 1.3 is in use. \n This field is optional; when + it is undefined, a Contour-managed ciphersuite list + will be used, which may be updated to keep it secure. + \n Contour's default list is: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES256-GCM-SHA384\" - \"ECDHE-RSA-AES256-GCM-SHA384\" + \n Ciphers provided are validated against the following + list: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES128-GCM-SHA256\" - \"ECDHE-RSA-AES128-GCM-SHA256\" + - \"ECDHE-ECDSA-AES128-SHA\" - \"ECDHE-RSA-AES128-SHA\" + - \"AES128-GCM-SHA256\" - \"AES128-SHA\" - \"ECDHE-ECDSA-AES256-GCM-SHA384\" + - \"ECDHE-RSA-AES256-GCM-SHA384\" - \"ECDHE-ECDSA-AES256-SHA\" + - \"ECDHE-RSA-AES256-SHA\" - \"AES256-GCM-SHA384\" - + \"AES256-SHA\" \n Contour recommends leaving this undefined + unless you are sure you must. \n See: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters + Note: This list is a superset of what is valid for stock + Envoy builds and those using BoringSSL FIPS." + items: + type: string + type: array + maximumProtocolVersion: + description: "MaximumProtocolVersion is the maximum TLS + version this vhost should negotiate. \n Values: `1.2`, + `1.3`(default). \n Other values will produce an error." + type: string + minimumProtocolVersion: + description: "MinimumProtocolVersion is the minimum TLS + version this vhost should negotiate. \n Values: `1.2` + (default), `1.3`. \n Other values will produce an error." + type: string + type: object type: object defaultHTTPVersions: description: "DefaultHTTPVersions defines the default set of HTTPS @@ -3547,6 +3589,52 @@ spec: format: int32 minimum: 1 type: integer + upstream-tls: + description: UpstreamTLS contains the TLS policy parameters + for upstream connections + properties: + cipherSuites: + description: "CipherSuites defines the TLS ciphers + to be supported by Envoy TLS listeners when negotiating + TLS 1.2. Ciphers are validated against the set that + Envoy supports by default. This parameter should + only be used by advanced users. Note that these + will be ignored when TLS 1.3 is in use. \n This + field is optional; when it is undefined, a Contour-managed + ciphersuite list will be used, which may be updated + to keep it secure. \n Contour's default list is: + - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES256-GCM-SHA384\" - \"ECDHE-RSA-AES256-GCM-SHA384\" + \n Ciphers provided are validated against the following + list: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES128-GCM-SHA256\" - \"ECDHE-RSA-AES128-GCM-SHA256\" + - \"ECDHE-ECDSA-AES128-SHA\" - \"ECDHE-RSA-AES128-SHA\" + - \"AES128-GCM-SHA256\" - \"AES128-SHA\" - \"ECDHE-ECDSA-AES256-GCM-SHA384\" + - \"ECDHE-RSA-AES256-GCM-SHA384\" - \"ECDHE-ECDSA-AES256-SHA\" + - \"ECDHE-RSA-AES256-SHA\" - \"AES256-GCM-SHA384\" + - \"AES256-SHA\" \n Contour recommends leaving this + undefined unless you are sure you must. \n See: + https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters + Note: This list is a superset of what is valid for + stock Envoy builds and those using BoringSSL FIPS." + items: + type: string + type: array + maximumProtocolVersion: + description: "MaximumProtocolVersion is the maximum + TLS version this vhost should negotiate. \n Values: + `1.2`, `1.3`(default). \n Other values will produce + an error." + type: string + minimumProtocolVersion: + description: "MinimumProtocolVersion is the minimum + TLS version this vhost should negotiate. \n Values: + `1.2` (default), `1.3`. \n Other values will produce + an error." + type: string + type: object type: object defaultHTTPVersions: description: "DefaultHTTPVersions defines the default set diff --git a/examples/render/contour-deployment.yaml b/examples/render/contour-deployment.yaml index 5cb52b443b5..cdab2700b73 100644 --- a/examples/render/contour-deployment.yaml +++ b/examples/render/contour-deployment.yaml @@ -330,6 +330,48 @@ spec: format: int32 minimum: 1 type: integer + upstream-tls: + description: UpstreamTLS contains the TLS policy parameters + for upstream connections + properties: + cipherSuites: + description: "CipherSuites defines the TLS ciphers to + be supported by Envoy TLS listeners when negotiating + TLS 1.2. Ciphers are validated against the set that + Envoy supports by default. This parameter should only + be used by advanced users. Note that these will be ignored + when TLS 1.3 is in use. \n This field is optional; when + it is undefined, a Contour-managed ciphersuite list + will be used, which may be updated to keep it secure. + \n Contour's default list is: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES256-GCM-SHA384\" - \"ECDHE-RSA-AES256-GCM-SHA384\" + \n Ciphers provided are validated against the following + list: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES128-GCM-SHA256\" - \"ECDHE-RSA-AES128-GCM-SHA256\" + - \"ECDHE-ECDSA-AES128-SHA\" - \"ECDHE-RSA-AES128-SHA\" + - \"AES128-GCM-SHA256\" - \"AES128-SHA\" - \"ECDHE-ECDSA-AES256-GCM-SHA384\" + - \"ECDHE-RSA-AES256-GCM-SHA384\" - \"ECDHE-ECDSA-AES256-SHA\" + - \"ECDHE-RSA-AES256-SHA\" - \"AES256-GCM-SHA384\" - + \"AES256-SHA\" \n Contour recommends leaving this undefined + unless you are sure you must. \n See: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters + Note: This list is a superset of what is valid for stock + Envoy builds and those using BoringSSL FIPS." + items: + type: string + type: array + maximumProtocolVersion: + description: "MaximumProtocolVersion is the maximum TLS + version this vhost should negotiate. \n Values: `1.2`, + `1.3`(default). \n Other values will produce an error." + type: string + minimumProtocolVersion: + description: "MinimumProtocolVersion is the minimum TLS + version this vhost should negotiate. \n Values: `1.2` + (default), `1.3`. \n Other values will produce an error." + type: string + type: object type: object defaultHTTPVersions: description: "DefaultHTTPVersions defines the default set of HTTPS @@ -3766,6 +3808,52 @@ spec: format: int32 minimum: 1 type: integer + upstream-tls: + description: UpstreamTLS contains the TLS policy parameters + for upstream connections + properties: + cipherSuites: + description: "CipherSuites defines the TLS ciphers + to be supported by Envoy TLS listeners when negotiating + TLS 1.2. Ciphers are validated against the set that + Envoy supports by default. This parameter should + only be used by advanced users. Note that these + will be ignored when TLS 1.3 is in use. \n This + field is optional; when it is undefined, a Contour-managed + ciphersuite list will be used, which may be updated + to keep it secure. \n Contour's default list is: + - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES256-GCM-SHA384\" - \"ECDHE-RSA-AES256-GCM-SHA384\" + \n Ciphers provided are validated against the following + list: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES128-GCM-SHA256\" - \"ECDHE-RSA-AES128-GCM-SHA256\" + - \"ECDHE-ECDSA-AES128-SHA\" - \"ECDHE-RSA-AES128-SHA\" + - \"AES128-GCM-SHA256\" - \"AES128-SHA\" - \"ECDHE-ECDSA-AES256-GCM-SHA384\" + - \"ECDHE-RSA-AES256-GCM-SHA384\" - \"ECDHE-ECDSA-AES256-SHA\" + - \"ECDHE-RSA-AES256-SHA\" - \"AES256-GCM-SHA384\" + - \"AES256-SHA\" \n Contour recommends leaving this + undefined unless you are sure you must. \n See: + https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters + Note: This list is a superset of what is valid for + stock Envoy builds and those using BoringSSL FIPS." + items: + type: string + type: array + maximumProtocolVersion: + description: "MaximumProtocolVersion is the maximum + TLS version this vhost should negotiate. \n Values: + `1.2`, `1.3`(default). \n Other values will produce + an error." + type: string + minimumProtocolVersion: + description: "MinimumProtocolVersion is the minimum + TLS version this vhost should negotiate. \n Values: + `1.2` (default), `1.3`. \n Other values will produce + an error." + type: string + type: object type: object defaultHTTPVersions: description: "DefaultHTTPVersions defines the default set diff --git a/examples/render/contour-gateway-provisioner.yaml b/examples/render/contour-gateway-provisioner.yaml index b0097c823ca..7de50e243a4 100644 --- a/examples/render/contour-gateway-provisioner.yaml +++ b/examples/render/contour-gateway-provisioner.yaml @@ -122,6 +122,48 @@ spec: format: int32 minimum: 1 type: integer + upstream-tls: + description: UpstreamTLS contains the TLS policy parameters + for upstream connections + properties: + cipherSuites: + description: "CipherSuites defines the TLS ciphers to + be supported by Envoy TLS listeners when negotiating + TLS 1.2. Ciphers are validated against the set that + Envoy supports by default. This parameter should only + be used by advanced users. Note that these will be ignored + when TLS 1.3 is in use. \n This field is optional; when + it is undefined, a Contour-managed ciphersuite list + will be used, which may be updated to keep it secure. + \n Contour's default list is: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES256-GCM-SHA384\" - \"ECDHE-RSA-AES256-GCM-SHA384\" + \n Ciphers provided are validated against the following + list: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES128-GCM-SHA256\" - \"ECDHE-RSA-AES128-GCM-SHA256\" + - \"ECDHE-ECDSA-AES128-SHA\" - \"ECDHE-RSA-AES128-SHA\" + - \"AES128-GCM-SHA256\" - \"AES128-SHA\" - \"ECDHE-ECDSA-AES256-GCM-SHA384\" + - \"ECDHE-RSA-AES256-GCM-SHA384\" - \"ECDHE-ECDSA-AES256-SHA\" + - \"ECDHE-RSA-AES256-SHA\" - \"AES256-GCM-SHA384\" - + \"AES256-SHA\" \n Contour recommends leaving this undefined + unless you are sure you must. \n See: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters + Note: This list is a superset of what is valid for stock + Envoy builds and those using BoringSSL FIPS." + items: + type: string + type: array + maximumProtocolVersion: + description: "MaximumProtocolVersion is the maximum TLS + version this vhost should negotiate. \n Values: `1.2`, + `1.3`(default). \n Other values will produce an error." + type: string + minimumProtocolVersion: + description: "MinimumProtocolVersion is the minimum TLS + version this vhost should negotiate. \n Values: `1.2` + (default), `1.3`. \n Other values will produce an error." + type: string + type: object type: object defaultHTTPVersions: description: "DefaultHTTPVersions defines the default set of HTTPS @@ -3558,6 +3600,52 @@ spec: format: int32 minimum: 1 type: integer + upstream-tls: + description: UpstreamTLS contains the TLS policy parameters + for upstream connections + properties: + cipherSuites: + description: "CipherSuites defines the TLS ciphers + to be supported by Envoy TLS listeners when negotiating + TLS 1.2. Ciphers are validated against the set that + Envoy supports by default. This parameter should + only be used by advanced users. Note that these + will be ignored when TLS 1.3 is in use. \n This + field is optional; when it is undefined, a Contour-managed + ciphersuite list will be used, which may be updated + to keep it secure. \n Contour's default list is: + - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES256-GCM-SHA384\" - \"ECDHE-RSA-AES256-GCM-SHA384\" + \n Ciphers provided are validated against the following + list: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES128-GCM-SHA256\" - \"ECDHE-RSA-AES128-GCM-SHA256\" + - \"ECDHE-ECDSA-AES128-SHA\" - \"ECDHE-RSA-AES128-SHA\" + - \"AES128-GCM-SHA256\" - \"AES128-SHA\" - \"ECDHE-ECDSA-AES256-GCM-SHA384\" + - \"ECDHE-RSA-AES256-GCM-SHA384\" - \"ECDHE-ECDSA-AES256-SHA\" + - \"ECDHE-RSA-AES256-SHA\" - \"AES256-GCM-SHA384\" + - \"AES256-SHA\" \n Contour recommends leaving this + undefined unless you are sure you must. \n See: + https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters + Note: This list is a superset of what is valid for + stock Envoy builds and those using BoringSSL FIPS." + items: + type: string + type: array + maximumProtocolVersion: + description: "MaximumProtocolVersion is the maximum + TLS version this vhost should negotiate. \n Values: + `1.2`, `1.3`(default). \n Other values will produce + an error." + type: string + minimumProtocolVersion: + description: "MinimumProtocolVersion is the minimum + TLS version this vhost should negotiate. \n Values: + `1.2` (default), `1.3`. \n Other values will produce + an error." + type: string + type: object type: object defaultHTTPVersions: description: "DefaultHTTPVersions defines the default set diff --git a/examples/render/contour-gateway.yaml b/examples/render/contour-gateway.yaml index e184b93ca01..a29ad1ae03d 100644 --- a/examples/render/contour-gateway.yaml +++ b/examples/render/contour-gateway.yaml @@ -333,6 +333,48 @@ spec: format: int32 minimum: 1 type: integer + upstream-tls: + description: UpstreamTLS contains the TLS policy parameters + for upstream connections + properties: + cipherSuites: + description: "CipherSuites defines the TLS ciphers to + be supported by Envoy TLS listeners when negotiating + TLS 1.2. Ciphers are validated against the set that + Envoy supports by default. This parameter should only + be used by advanced users. Note that these will be ignored + when TLS 1.3 is in use. \n This field is optional; when + it is undefined, a Contour-managed ciphersuite list + will be used, which may be updated to keep it secure. + \n Contour's default list is: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES256-GCM-SHA384\" - \"ECDHE-RSA-AES256-GCM-SHA384\" + \n Ciphers provided are validated against the following + list: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES128-GCM-SHA256\" - \"ECDHE-RSA-AES128-GCM-SHA256\" + - \"ECDHE-ECDSA-AES128-SHA\" - \"ECDHE-RSA-AES128-SHA\" + - \"AES128-GCM-SHA256\" - \"AES128-SHA\" - \"ECDHE-ECDSA-AES256-GCM-SHA384\" + - \"ECDHE-RSA-AES256-GCM-SHA384\" - \"ECDHE-ECDSA-AES256-SHA\" + - \"ECDHE-RSA-AES256-SHA\" - \"AES256-GCM-SHA384\" - + \"AES256-SHA\" \n Contour recommends leaving this undefined + unless you are sure you must. \n See: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters + Note: This list is a superset of what is valid for stock + Envoy builds and those using BoringSSL FIPS." + items: + type: string + type: array + maximumProtocolVersion: + description: "MaximumProtocolVersion is the maximum TLS + version this vhost should negotiate. \n Values: `1.2`, + `1.3`(default). \n Other values will produce an error." + type: string + minimumProtocolVersion: + description: "MinimumProtocolVersion is the minimum TLS + version this vhost should negotiate. \n Values: `1.2` + (default), `1.3`. \n Other values will produce an error." + type: string + type: object type: object defaultHTTPVersions: description: "DefaultHTTPVersions defines the default set of HTTPS @@ -3769,6 +3811,52 @@ spec: format: int32 minimum: 1 type: integer + upstream-tls: + description: UpstreamTLS contains the TLS policy parameters + for upstream connections + properties: + cipherSuites: + description: "CipherSuites defines the TLS ciphers + to be supported by Envoy TLS listeners when negotiating + TLS 1.2. Ciphers are validated against the set that + Envoy supports by default. This parameter should + only be used by advanced users. Note that these + will be ignored when TLS 1.3 is in use. \n This + field is optional; when it is undefined, a Contour-managed + ciphersuite list will be used, which may be updated + to keep it secure. \n Contour's default list is: + - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES256-GCM-SHA384\" - \"ECDHE-RSA-AES256-GCM-SHA384\" + \n Ciphers provided are validated against the following + list: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES128-GCM-SHA256\" - \"ECDHE-RSA-AES128-GCM-SHA256\" + - \"ECDHE-ECDSA-AES128-SHA\" - \"ECDHE-RSA-AES128-SHA\" + - \"AES128-GCM-SHA256\" - \"AES128-SHA\" - \"ECDHE-ECDSA-AES256-GCM-SHA384\" + - \"ECDHE-RSA-AES256-GCM-SHA384\" - \"ECDHE-ECDSA-AES256-SHA\" + - \"ECDHE-RSA-AES256-SHA\" - \"AES256-GCM-SHA384\" + - \"AES256-SHA\" \n Contour recommends leaving this + undefined unless you are sure you must. \n See: + https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters + Note: This list is a superset of what is valid for + stock Envoy builds and those using BoringSSL FIPS." + items: + type: string + type: array + maximumProtocolVersion: + description: "MaximumProtocolVersion is the maximum + TLS version this vhost should negotiate. \n Values: + `1.2`, `1.3`(default). \n Other values will produce + an error." + type: string + minimumProtocolVersion: + description: "MinimumProtocolVersion is the minimum + TLS version this vhost should negotiate. \n Values: + `1.2` (default), `1.3`. \n Other values will produce + an error." + type: string + type: object type: object defaultHTTPVersions: description: "DefaultHTTPVersions defines the default set diff --git a/examples/render/contour.yaml b/examples/render/contour.yaml index 72d6979983d..d9e4f8534a0 100644 --- a/examples/render/contour.yaml +++ b/examples/render/contour.yaml @@ -330,6 +330,48 @@ spec: format: int32 minimum: 1 type: integer + upstream-tls: + description: UpstreamTLS contains the TLS policy parameters + for upstream connections + properties: + cipherSuites: + description: "CipherSuites defines the TLS ciphers to + be supported by Envoy TLS listeners when negotiating + TLS 1.2. Ciphers are validated against the set that + Envoy supports by default. This parameter should only + be used by advanced users. Note that these will be ignored + when TLS 1.3 is in use. \n This field is optional; when + it is undefined, a Contour-managed ciphersuite list + will be used, which may be updated to keep it secure. + \n Contour's default list is: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES256-GCM-SHA384\" - \"ECDHE-RSA-AES256-GCM-SHA384\" + \n Ciphers provided are validated against the following + list: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES128-GCM-SHA256\" - \"ECDHE-RSA-AES128-GCM-SHA256\" + - \"ECDHE-ECDSA-AES128-SHA\" - \"ECDHE-RSA-AES128-SHA\" + - \"AES128-GCM-SHA256\" - \"AES128-SHA\" - \"ECDHE-ECDSA-AES256-GCM-SHA384\" + - \"ECDHE-RSA-AES256-GCM-SHA384\" - \"ECDHE-ECDSA-AES256-SHA\" + - \"ECDHE-RSA-AES256-SHA\" - \"AES256-GCM-SHA384\" - + \"AES256-SHA\" \n Contour recommends leaving this undefined + unless you are sure you must. \n See: https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters + Note: This list is a superset of what is valid for stock + Envoy builds and those using BoringSSL FIPS." + items: + type: string + type: array + maximumProtocolVersion: + description: "MaximumProtocolVersion is the maximum TLS + version this vhost should negotiate. \n Values: `1.2`, + `1.3`(default). \n Other values will produce an error." + type: string + minimumProtocolVersion: + description: "MinimumProtocolVersion is the minimum TLS + version this vhost should negotiate. \n Values: `1.2` + (default), `1.3`. \n Other values will produce an error." + type: string + type: object type: object defaultHTTPVersions: description: "DefaultHTTPVersions defines the default set of HTTPS @@ -3766,6 +3808,52 @@ spec: format: int32 minimum: 1 type: integer + upstream-tls: + description: UpstreamTLS contains the TLS policy parameters + for upstream connections + properties: + cipherSuites: + description: "CipherSuites defines the TLS ciphers + to be supported by Envoy TLS listeners when negotiating + TLS 1.2. Ciphers are validated against the set that + Envoy supports by default. This parameter should + only be used by advanced users. Note that these + will be ignored when TLS 1.3 is in use. \n This + field is optional; when it is undefined, a Contour-managed + ciphersuite list will be used, which may be updated + to keep it secure. \n Contour's default list is: + - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES256-GCM-SHA384\" - \"ECDHE-RSA-AES256-GCM-SHA384\" + \n Ciphers provided are validated against the following + list: - \"[ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-ECDSA-CHACHA20-POLY1305]\" + - \"[ECDHE-RSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305]\" + - \"ECDHE-ECDSA-AES128-GCM-SHA256\" - \"ECDHE-RSA-AES128-GCM-SHA256\" + - \"ECDHE-ECDSA-AES128-SHA\" - \"ECDHE-RSA-AES128-SHA\" + - \"AES128-GCM-SHA256\" - \"AES128-SHA\" - \"ECDHE-ECDSA-AES256-GCM-SHA384\" + - \"ECDHE-RSA-AES256-GCM-SHA384\" - \"ECDHE-ECDSA-AES256-SHA\" + - \"ECDHE-RSA-AES256-SHA\" - \"AES256-GCM-SHA384\" + - \"AES256-SHA\" \n Contour recommends leaving this + undefined unless you are sure you must. \n See: + https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/transport_sockets/tls/v3/common.proto#extensions-transport-sockets-tls-v3-tlsparameters + Note: This list is a superset of what is valid for + stock Envoy builds and those using BoringSSL FIPS." + items: + type: string + type: array + maximumProtocolVersion: + description: "MaximumProtocolVersion is the maximum + TLS version this vhost should negotiate. \n Values: + `1.2`, `1.3`(default). \n Other values will produce + an error." + type: string + minimumProtocolVersion: + description: "MinimumProtocolVersion is the minimum + TLS version this vhost should negotiate. \n Values: + `1.2` (default), `1.3`. \n Other values will produce + an error." + type: string + type: object type: object defaultHTTPVersions: description: "DefaultHTTPVersions defines the default set diff --git a/internal/contourconfig/contourconfiguration.go b/internal/contourconfig/contourconfiguration.go index 52a677a97d3..c2ebe4db4e9 100644 --- a/internal/contourconfig/contourconfiguration.go +++ b/internal/contourconfig/contourconfiguration.go @@ -120,6 +120,11 @@ func Defaults() contour_api_v1alpha1.ContourConfigurationSpec { }, Cluster: &contour_api_v1alpha1.ClusterParameters{ DNSLookupFamily: contour_api_v1alpha1.AutoClusterDNSFamily, + UpstreamTLS: &contour_api_v1alpha1.EnvoyTLS{ + MinimumProtocolVersion: "1.2", + MaximumProtocolVersion: "1.3", + CipherSuites: contour_api_v1alpha1.DefaultTLSCiphers, + }, }, Network: &contour_api_v1alpha1.NetworkParameters{ XffNumTrustedHops: ref.To(uint32(0)), diff --git a/internal/dag/dag.go b/internal/dag/dag.go index aea888e4b16..9a6d7ed28c1 100644 --- a/internal/dag/dag.go +++ b/internal/dag/dag.go @@ -1040,6 +1040,9 @@ type Cluster struct { // PerConnectionBufferLimitBytes defines the soft limit on size of the cluster’s new connection read and write buffers. PerConnectionBufferLimitBytes *uint32 + + // UpstreamTLS contains the TLS version and cipher suite configurations for upstream connections + UpstreamTLS *UpstreamTLS } // WeightedService represents the load balancing weight of a @@ -1229,6 +1232,9 @@ type ExtensionCluster struct { // ClientCertificate is the optional identifier of the TLS secret containing client certificate and // private key to be used when establishing TLS connection to upstream cluster. ClientCertificate *Secret + + // UpstreamTLS contains the TLS version and cipher suite configurations for upstream connections + UpstreamTLS *UpstreamTLS } const singleDNSLabelWildcardRegex = "^[a-z0-9]([-a-z0-9]*[a-z0-9])?" @@ -1260,3 +1266,10 @@ type SlowStartConfig struct { func (s *SlowStartConfig) String() string { return fmt.Sprintf("%s%f%d", s.Window.String(), s.Aggression, s.MinWeightPercent) } + +// UpstreamTLS holds the TLS configuration for upstream connections +type UpstreamTLS struct { + MinimumProtocolVersion string + MaximumProtocolVersion string + CipherSuites []string +} diff --git a/internal/dag/httpproxy_processor.go b/internal/dag/httpproxy_processor.go index 255a1fa0b71..fce428104cb 100644 --- a/internal/dag/httpproxy_processor.go +++ b/internal/dag/httpproxy_processor.go @@ -112,6 +112,10 @@ type HTTPProxyProcessor struct { // configurable and off by default in order to support the feature // without requiring all existing test cases to change. SetSourceMetadataOnRoutes bool + + // UpstreamTLS defines the TLS settings like min/max version + // and cipher suites for upstream connections. + UpstreamTLS *contour_api_v1alpha1.EnvoyTLS } // Run translates HTTPProxies into DAG objects and @@ -1026,6 +1030,11 @@ func (p *HTTPProxyProcessor) computeRoutes( SlowStartConfig: slowStart, MaxRequestsPerConnection: p.MaxRequestsPerConnection, PerConnectionBufferLimitBytes: p.PerConnectionBufferLimitBytes, + UpstreamTLS: &UpstreamTLS{ + MinimumProtocolVersion: p.UpstreamTLS.MinimumProtocolVersion, + MaximumProtocolVersion: p.UpstreamTLS.MaximumProtocolVersion, + CipherSuites: p.UpstreamTLS.CipherSuites, + }, } if service.Mirror && len(r.MirrorPolicies) > 0 { validCond.AddError(contour_api_v1.ConditionTypeServiceError, "OnlyOneMirror", diff --git a/internal/envoy/v3/auth.go b/internal/envoy/v3/auth.go index c2af6d1db20..2d7669500e2 100644 --- a/internal/envoy/v3/auth.go +++ b/internal/envoy/v3/auth.go @@ -25,7 +25,7 @@ import ( // UpstreamTLSContext creates an envoy_v3_tls.UpstreamTlsContext. By default // UpstreamTLSContext returns a HTTP/1.1 TLS enabled context. A list of // additional ALPN protocols can be provided. -func UpstreamTLSContext(peerValidationContext *dag.PeerValidationContext, sni string, clientSecret *dag.Secret, alpnProtocols ...string) *envoy_v3_tls.UpstreamTlsContext { +func UpstreamTLSContext(peerValidationContext *dag.PeerValidationContext, sni string, clientSecret *dag.Secret, upstreamTLS *dag.UpstreamTLS, alpnProtocols ...string) *envoy_v3_tls.UpstreamTlsContext { var clientSecretConfigs []*envoy_v3_tls.SdsSecretConfig if clientSecret != nil { clientSecretConfigs = []*envoy_v3_tls.SdsSecretConfig{{ @@ -34,8 +34,19 @@ func UpstreamTLSContext(peerValidationContext *dag.PeerValidationContext, sni st }} } + tlsParams := &envoy_v3_tls.TlsParameters{} + + if upstreamTLS != nil { + tlsParams = &envoy_v3_tls.TlsParameters{ + TlsMinimumProtocolVersion: ParseTLSVersion(upstreamTLS.MinimumProtocolVersion), + TlsMaximumProtocolVersion: ParseTLSVersion(upstreamTLS.MaximumProtocolVersion), + CipherSuites: tlsParams.CipherSuites, + } + } + context := &envoy_v3_tls.UpstreamTlsContext{ CommonTlsContext: &envoy_v3_tls.CommonTlsContext{ + TlsParams: tlsParams, AlpnProtocols: alpnProtocols, TlsCertificateSdsSecretConfigs: clientSecretConfigs, }, diff --git a/internal/envoy/v3/auth_test.go b/internal/envoy/v3/auth_test.go index 96df9c2a919..43987273b44 100644 --- a/internal/envoy/v3/auth_test.go +++ b/internal/envoy/v3/auth_test.go @@ -41,9 +41,10 @@ func TestUpstreamTLSContext(t *testing.T) { validation *dag.PeerValidationContext alpnProtocols []string externalName string + upstreamTLS *dag.UpstreamTLS want *envoy_v3_tls.UpstreamTlsContext }{ - "no alpn, no validation": { + "no alpn, no validation, no upstreamTLS": { want: &envoy_v3_tls.UpstreamTlsContext{ CommonTlsContext: &envoy_v3_tls.CommonTlsContext{}, }, @@ -108,11 +109,25 @@ func TestUpstreamTLSContext(t *testing.T) { Sni: "projectcontour.local", }, }, + "use TLS 1.3": { + upstreamTLS: &dag.UpstreamTLS{ + MinimumProtocolVersion: "1.3", + MaximumProtocolVersion: "1.3", + }, + want: &envoy_v3_tls.UpstreamTlsContext{ + CommonTlsContext: &envoy_v3_tls.CommonTlsContext{ + TlsParams: &envoy_v3_tls.TlsParameters{ + TlsMinimumProtocolVersion: ParseTLSVersion("1.3"), + TlsMaximumProtocolVersion: ParseTLSVersion("1.3"), + }, + }, + }, + }, } for name, tc := range tests { t.Run(name, func(t *testing.T) { - got := UpstreamTLSContext(tc.validation, tc.externalName, nil, tc.alpnProtocols...) + got := UpstreamTLSContext(tc.validation, tc.externalName, nil, tc.upstreamTLS, tc.alpnProtocols...) protobuf.ExpectEqual(t, tc.want, got) }) } diff --git a/internal/envoy/v3/cluster.go b/internal/envoy/v3/cluster.go index e39beedadee..f47c6bee761 100644 --- a/internal/envoy/v3/cluster.go +++ b/internal/envoy/v3/cluster.go @@ -97,6 +97,7 @@ func Cluster(c *dag.Cluster) *envoy_cluster_v3.Cluster { c.UpstreamValidation, c.SNI, c.ClientCertificate, + c.UpstreamTLS, ), ) case "h2": @@ -106,6 +107,7 @@ func Cluster(c *dag.Cluster) *envoy_cluster_v3.Cluster { c.UpstreamValidation, c.SNI, c.ClientCertificate, + c.UpstreamTLS, "h2", ), ) @@ -177,6 +179,7 @@ func ExtensionCluster(ext *dag.ExtensionCluster) *envoy_cluster_v3.Cluster { ext.UpstreamValidation, ext.SNI, ext.ClientCertificate, + nil, // TODO(KauzClay): should TLS protocol version settings be configurable for extensionservices too? "h2", ), ) @@ -207,7 +210,7 @@ func DNSNameCluster(c *dag.DNSNameCluster) *envoy_cluster_v3.Cluster { var transportSocket *envoy_core_v3.TransportSocket if c.Scheme == "https" { - transportSocket = UpstreamTLSTransportSocket(UpstreamTLSContext(c.UpstreamValidation, c.Address, nil)) + transportSocket = UpstreamTLSTransportSocket(UpstreamTLSContext(c.UpstreamValidation, c.Address, nil, nil)) } cluster.LoadAssignment = ClusterLoadAssignment(envoy.DNSNameClusterName(c), SocketAddress(c.Address, c.Port)) diff --git a/internal/envoy/v3/cluster_test.go b/internal/envoy/v3/cluster_test.go index 42ebd5b108e..92d2593bdc8 100644 --- a/internal/envoy/v3/cluster_test.go +++ b/internal/envoy/v3/cluster_test.go @@ -170,7 +170,7 @@ func TestCluster(t *testing.T) { ServiceName: "default/kuard/http", }, TransportSocket: UpstreamTLSTransportSocket( - UpstreamTLSContext(nil, "", nil, "h2"), + UpstreamTLSContext(nil, "", nil, nil, "h2"), ), TypedExtensionProtocolOptions: map[string]*anypb.Any{ "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": protobuf.MustMarshalAny( @@ -274,7 +274,7 @@ func TestCluster(t *testing.T) { ServiceName: "default/kuard/http", }, TransportSocket: UpstreamTLSTransportSocket( - UpstreamTLSContext(nil, "", nil), + UpstreamTLSContext(nil, "", nil, nil), ), }, }, @@ -290,7 +290,7 @@ func TestCluster(t *testing.T) { ClusterDiscoveryType: ClusterDiscoveryType(envoy_cluster_v3.Cluster_STRICT_DNS), LoadAssignment: ExternalNameClusterLoadAssignment(service(svcExternal, "tls")), TransportSocket: UpstreamTLSTransportSocket( - UpstreamTLSContext(nil, "projectcontour.local", nil), + UpstreamTLSContext(nil, "projectcontour.local", nil, nil), ), }, }, @@ -318,10 +318,48 @@ func TestCluster(t *testing.T) { SubjectName: "foo.bar.io", }, "", + nil, nil), ), }, }, + "UpstreamTLS protocol version set": { + cluster: &dag.Cluster{ + Upstream: service(s1, "tls"), + Protocol: "tls", + UpstreamValidation: &dag.PeerValidationContext{ + CACertificate: secret, + SubjectName: "foo.bar.io", + }, + UpstreamTLS: &dag.UpstreamTLS{ + MinimumProtocolVersion: "1.3", + MaximumProtocolVersion: "1.3", + }, + }, + want: &envoy_cluster_v3.Cluster{ + Name: "default/kuard/443/62d1f9ad02", + AltStatName: "default_kuard_443", + ClusterDiscoveryType: ClusterDiscoveryType(envoy_cluster_v3.Cluster_EDS), + EdsClusterConfig: &envoy_cluster_v3.Cluster_EdsClusterConfig{ + EdsConfig: ConfigSource("contour"), + ServiceName: "default/kuard/http", + }, + TransportSocket: UpstreamTLSTransportSocket( + UpstreamTLSContext( + &dag.PeerValidationContext{ + CACertificate: secret, + SubjectName: "foo.bar.io", + }, + "", + nil, + &dag.UpstreamTLS{ + MinimumProtocolVersion: "1.3", + MaximumProtocolVersion: "1.3", + }, + ), + ), + }, + }, "projectcontour.io/max-connections": { cluster: &dag.Cluster{ Upstream: &dag.Service{ @@ -526,7 +564,7 @@ func TestCluster(t *testing.T) { ServiceName: "default/kuard/http", }, TransportSocket: UpstreamTLSTransportSocket( - UpstreamTLSContext(nil, "", clientSecret), + UpstreamTLSContext(nil, "", clientSecret, nil), ), }, }, @@ -854,7 +892,7 @@ func TestDNSNameCluster(t *testing.T) { }, }, }, - TransportSocket: UpstreamTLSTransportSocket(UpstreamTLSContext(nil, "foo.projectcontour.io", nil)), + TransportSocket: UpstreamTLSTransportSocket(UpstreamTLSContext(nil, "foo.projectcontour.io", nil, nil)), }, }, "HTTPS cluster with upstream validation": { @@ -903,7 +941,7 @@ func TestDNSNameCluster(t *testing.T) { }, }, SubjectName: "foo.projectcontour.io", - }, "foo.projectcontour.io", nil)), + }, "foo.projectcontour.io", nil, nil)), }, }, } diff --git a/internal/envoy/v3/socket_test.go b/internal/envoy/v3/socket_test.go index 8f1802617f6..7949673283d 100644 --- a/internal/envoy/v3/socket_test.go +++ b/internal/envoy/v3/socket_test.go @@ -30,11 +30,11 @@ func TestUpstreamTLSTransportSocket(t *testing.T) { want *envoy_core_v3.TransportSocket }{ "h2": { - ctxt: UpstreamTLSContext(nil, "", nil, "h2"), + ctxt: UpstreamTLSContext(nil, "", nil, nil, "h2"), want: &envoy_core_v3.TransportSocket{ Name: "envoy.transport_sockets.tls", ConfigType: &envoy_core_v3.TransportSocket_TypedConfig{ - TypedConfig: protobuf.MustMarshalAny(UpstreamTLSContext(nil, "", nil, "h2")), + TypedConfig: protobuf.MustMarshalAny(UpstreamTLSContext(nil, "", nil, nil, "h2")), }, }, }, diff --git a/internal/featuretests/v3/backendcavalidation_test.go b/internal/featuretests/v3/backendcavalidation_test.go index ccec1da2e2c..0c779ac577e 100644 --- a/internal/featuretests/v3/backendcavalidation_test.go +++ b/internal/featuretests/v3/backendcavalidation_test.go @@ -76,7 +76,7 @@ func TestClusterServiceTLSBackendCAValidation(t *testing.T) { // assert that there is a regular, non validation enabled cluster in CDS. c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, - tlsCluster(cluster("default/kuard/443/4929fca9d4", "default/kuard/securebackend", "default_kuard_443"), nil, "", "", nil), + tlsCluster(cluster("default/kuard/443/4929fca9d4", "default/kuard/securebackend", "default_kuard_443"), nil, "", "", nil, nil), ), TypeUrl: clusterType, }) @@ -114,7 +114,7 @@ func TestClusterServiceTLSBackendCAValidation(t *testing.T) { // assert that the cluster now has a certificate and subject name. c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, - tlsCluster(cluster("default/kuard/443/c6ccd34de5", "default/kuard/securebackend", "default_kuard_443"), []byte(featuretests.CERTIFICATE), "subjname", "", nil), + tlsCluster(cluster("default/kuard/443/c6ccd34de5", "default/kuard/securebackend", "default_kuard_443"), []byte(featuretests.CERTIFICATE), "subjname", "", nil, nil), ), TypeUrl: clusterType, }) @@ -161,7 +161,7 @@ func TestClusterServiceTLSBackendCAValidation(t *testing.T) { // assert that the cluster now has a certificate and subject name. c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, - tlsCluster(cluster("default/kuard/443/c6ccd34de5", "default/kuard/securebackend", "default_kuard_443"), []byte(featuretests.CERTIFICATE), "subjname", "", nil), + tlsCluster(cluster("default/kuard/443/c6ccd34de5", "default/kuard/securebackend", "default_kuard_443"), []byte(featuretests.CERTIFICATE), "subjname", "", nil, nil), ), TypeUrl: clusterType, }) diff --git a/internal/featuretests/v3/backendclientauth_test.go b/internal/featuretests/v3/backendclientauth_test.go index d3b32cc4382..b686c676de7 100644 --- a/internal/featuretests/v3/backendclientauth_test.go +++ b/internal/featuretests/v3/backendclientauth_test.go @@ -121,7 +121,7 @@ func TestBackendClientAuthenticationWithHTTPProxy(t *testing.T) { c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, - tlsCluster(cluster("default/backend/443/950c17581f", "default/backend/http", "default_backend_443"), []byte(featuretests.CERTIFICATE), "subjname", "", sec1), + tlsCluster(cluster("default/backend/443/950c17581f", "default/backend/http", "default_backend_443"), []byte(featuretests.CERTIFICATE), "subjname", "", sec1, nil), ), TypeUrl: clusterType, }) @@ -159,7 +159,7 @@ func TestBackendClientAuthenticationWithIngress(t *testing.T) { c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, - tlsClusterWithoutValidation(cluster("default/backend/443/4929fca9d4", "default/backend/http", "default_backend_443"), "", sec1), + tlsClusterWithoutValidation(cluster("default/backend/443/4929fca9d4", "default/backend/http", "default_backend_443"), "", sec1, nil), ), TypeUrl: clusterType, }) @@ -214,6 +214,7 @@ func TestBackendClientAuthenticationWithExtensionService(t *testing.T) { SubjectName: "subjname"}, "subjname", &dag.Secret{Object: sec1}, + nil, "h2", ), ) diff --git a/internal/featuretests/v3/envoy.go b/internal/featuretests/v3/envoy.go index 97252185bd2..cf0a0814b71 100644 --- a/internal/featuretests/v3/envoy.go +++ b/internal/featuretests/v3/envoy.go @@ -184,7 +184,7 @@ func cluster(name, servicename, statName string) *envoy_cluster_v3.Cluster { }) } -func tlsCluster(c *envoy_cluster_v3.Cluster, ca []byte, subjectName string, sni string, clientSecret *v1.Secret, alpnProtocols ...string) *envoy_cluster_v3.Cluster { +func tlsCluster(c *envoy_cluster_v3.Cluster, ca []byte, subjectName string, sni string, clientSecret *v1.Secret, upstreamTLS *dag.UpstreamTLS, alpnProtocols ...string) *envoy_cluster_v3.Cluster { var secret *dag.Secret if clientSecret != nil { secret = &dag.Secret{Object: clientSecret} @@ -204,13 +204,14 @@ func tlsCluster(c *envoy_cluster_v3.Cluster, ca []byte, subjectName string, sni SubjectName: subjectName}, sni, secret, + upstreamTLS, alpnProtocols..., ), ) return c } -func tlsClusterWithoutValidation(c *envoy_cluster_v3.Cluster, sni string, clientSecret *v1.Secret, alpnProtocols ...string) *envoy_cluster_v3.Cluster { +func tlsClusterWithoutValidation(c *envoy_cluster_v3.Cluster, sni string, clientSecret *v1.Secret, upstreamTLS *dag.UpstreamTLS, alpnProtocols ...string) *envoy_cluster_v3.Cluster { var secret *dag.Secret if clientSecret != nil { secret = &dag.Secret{Object: clientSecret} @@ -221,6 +222,7 @@ func tlsClusterWithoutValidation(c *envoy_cluster_v3.Cluster, sni string, client nil, sni, secret, + upstreamTLS, alpnProtocols..., ), ) diff --git a/internal/featuretests/v3/externalname_test.go b/internal/featuretests/v3/externalname_test.go index 1d3b1c2b872..917a1753cb1 100644 --- a/internal/featuretests/v3/externalname_test.go +++ b/internal/featuretests/v3/externalname_test.go @@ -219,7 +219,7 @@ func TestExternalNameService(t *testing.T) { }, &envoy_cluster_v3.Cluster{ TransportSocket: envoy_v3.UpstreamTLSTransportSocket( - envoy_v3.UpstreamTLSContext(nil, "external.address", nil, "h2"), + envoy_v3.UpstreamTLSContext(nil, "external.address", nil, nil, "h2"), ), }, ), @@ -271,7 +271,7 @@ func TestExternalNameService(t *testing.T) { externalNameCluster("default/kuard/80/f9439c1de8", "default/kuard", "default_kuard_80", "foo.io", 80), &envoy_cluster_v3.Cluster{ TransportSocket: envoy_v3.UpstreamTLSTransportSocket( - envoy_v3.UpstreamTLSContext(nil, "external.address", nil), + envoy_v3.UpstreamTLSContext(nil, "external.address", nil, nil), ), }, ), @@ -312,7 +312,7 @@ func TestExternalNameService(t *testing.T) { externalNameCluster("default/kuard/80/7d449598f5", "default/kuard", "default_kuard_80", "foo.io", 80), &envoy_cluster_v3.Cluster{ TransportSocket: envoy_v3.UpstreamTLSTransportSocket( - envoy_v3.UpstreamTLSContext(nil, "foo.io", nil), + envoy_v3.UpstreamTLSContext(nil, "foo.io", nil, nil), ), }, ), diff --git a/internal/featuretests/v3/headerpolicy_test.go b/internal/featuretests/v3/headerpolicy_test.go index d22c5a41c6c..824b668d4b3 100644 --- a/internal/featuretests/v3/headerpolicy_test.go +++ b/internal/featuretests/v3/headerpolicy_test.go @@ -214,7 +214,7 @@ func TestHeaderPolicy_ReplaceHeader_HTTProxy(t *testing.T) { c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, - tlsCluster(externalNameCluster("default/externalname/443/9ebffe8f28", "default/externalname/https", "default_externalname_443", "goodbye.planet", 443), nil, "goodbye.planet", "goodbye.planet", nil), + tlsCluster(externalNameCluster("default/externalname/443/9ebffe8f28", "default/externalname/https", "default_externalname_443", "goodbye.planet", 443), nil, "goodbye.planet", "goodbye.planet", nil, nil), ), TypeUrl: clusterType, }) @@ -334,7 +334,7 @@ func TestHeaderPolicy_ReplaceHostHeader_HTTProxy(t *testing.T) { c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, - tlsCluster(externalNameCluster("default/externalname/443/9ebffe8f28", "default/externalname/https", "default_externalname_443", "goodbye.planet", 443), nil, "goodbye.planet", "goodbye.planet", nil), + tlsCluster(externalNameCluster("default/externalname/443/9ebffe8f28", "default/externalname/https", "default_externalname_443", "goodbye.planet", 443), nil, "goodbye.planet", "goodbye.planet", nil, nil), ), TypeUrl: clusterType, }) diff --git a/internal/featuretests/v3/tcpproxy_test.go b/internal/featuretests/v3/tcpproxy_test.go index 29150fe633b..8fae97bc3a2 100644 --- a/internal/featuretests/v3/tcpproxy_test.go +++ b/internal/featuretests/v3/tcpproxy_test.go @@ -374,7 +374,7 @@ func TestTCPProxyTLSBackend(t *testing.T) { svc.Namespace+"/"+svc.Name+"/443/4929fca9d4", svc.Namespace+"/"+svc.Name+"/https", svc.Namespace+"_"+svc.Name+"_443", - ), nil, "", "", nil), + ), nil, "", "", nil, nil), ), TypeUrl: clusterType, }) diff --git a/internal/featuretests/v3/upstreamprotocol_test.go b/internal/featuretests/v3/upstreamprotocol_test.go index b25ba9b90db..878b63b6e01 100644 --- a/internal/featuretests/v3/upstreamprotocol_test.go +++ b/internal/featuretests/v3/upstreamprotocol_test.go @@ -49,7 +49,7 @@ func TestUpstreamProtocolTLS(t *testing.T) { c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, - tlsCluster(cluster("default/kuard/443/4929fca9d4", "default/kuard/securebackend", "default_kuard_443"), nil, "", "", nil), + tlsCluster(cluster("default/kuard/443/4929fca9d4", "default/kuard/securebackend", "default_kuard_443"), nil, "", "", nil, nil), ), TypeUrl: clusterType, }) @@ -61,7 +61,7 @@ func TestUpstreamProtocolTLS(t *testing.T) { c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, - tlsCluster(cluster("default/kuard/443/4929fca9d4", "default/kuard/securebackend", "default_kuard_443"), nil, "", "", nil), + tlsCluster(cluster("default/kuard/443/4929fca9d4", "default/kuard/securebackend", "default_kuard_443"), nil, "", "", nil, nil), ), TypeUrl: clusterType, }) @@ -133,7 +133,7 @@ func TestUpstreamProtocolH2(t *testing.T) { c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, - h2cCluster(tlsCluster(cluster("default/kuard/443/bf1c365741", "default/kuard/securebackend", "default_kuard_443"), nil, "", "", nil, "h2")), + h2cCluster(tlsCluster(cluster("default/kuard/443/bf1c365741", "default/kuard/securebackend", "default_kuard_443"), nil, "", "", nil, nil, "h2")), ), TypeUrl: clusterType, }) @@ -145,7 +145,7 @@ func TestUpstreamProtocolH2(t *testing.T) { c.Request(clusterType).Equals(&envoy_discovery_v3.DiscoveryResponse{ Resources: resources(t, - h2cCluster(tlsCluster(cluster("default/kuard/443/bf1c365741", "default/kuard/securebackend", "default_kuard_443"), nil, "", "", nil, "h2")), + h2cCluster(tlsCluster(cluster("default/kuard/443/bf1c365741", "default/kuard/securebackend", "default_kuard_443"), nil, "", "", nil, nil, "h2")), ), TypeUrl: clusterType, }) diff --git a/pkg/config/parameters.go b/pkg/config/parameters.go index 462361d226c..8ab40d9dda2 100644 --- a/pkg/config/parameters.go +++ b/pkg/config/parameters.go @@ -429,6 +429,11 @@ type ClusterParameters struct { // // +optional PerConnectionBufferLimitBytes *uint32 `yaml:"per-connection-buffer-limit-bytes,omitempty"` + + // UpstreamTLS contains the TLS policy parameters for upstream connections + // + // +optional + UpstreamTLS TLSParameters `yaml:"upstream-tls,omitempty"` } func (p *ClusterParameters) Validate() error { @@ -443,6 +448,11 @@ func (p *ClusterParameters) Validate() error { if p.PerConnectionBufferLimitBytes != nil && *p.PerConnectionBufferLimitBytes < 1 { return fmt.Errorf("invalid per connections buffer limit bytes value %q set on cluster, minimum value is 1", *p.PerConnectionBufferLimitBytes) } + + if err := p.UpstreamTLS.Validate(); err != nil { + return err + } + return nil } diff --git a/site/content/docs/main/config/api-reference.html b/site/content/docs/main/config/api-reference.html index b91773147ef..3c020947da4 100644 --- a/site/content/docs/main/config/api-reference.html +++ b/site/content/docs/main/config/api-reference.html @@ -5653,6 +5653,21 @@

ClusterParameters for more information.

+ + +upstream-tls +
+ + +EnvoyTLS + + + + +(Optional) +

UpstreamTLS contains the TLS policy parameters for upstream connections

+ +

ContourConfigurationSpec @@ -7098,6 +7113,7 @@

EnvoyTLS

(Appears on: +ClusterParameters, EnvoyListenerConfig)