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)