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/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/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 }