istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/networking/core/cluster_tls_test.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package core
    16  
    17  import (
    18  	"fmt"
    19  	"reflect"
    20  	"testing"
    21  	"time"
    22  
    23  	cluster "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
    24  	core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
    25  	tls "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
    26  	"github.com/google/go-cmp/cmp"
    27  	"google.golang.org/protobuf/testing/protocmp"
    28  	"google.golang.org/protobuf/types/known/durationpb"
    29  
    30  	meshconfig "istio.io/api/mesh/v1alpha1"
    31  	networking "istio.io/api/networking/v1alpha3"
    32  	"istio.io/istio/pilot/pkg/features"
    33  	"istio.io/istio/pilot/pkg/model"
    34  	"istio.io/istio/pilot/pkg/networking/util"
    35  	authn_model "istio.io/istio/pilot/pkg/security/model"
    36  	"istio.io/istio/pilot/pkg/serviceregistry/provider"
    37  	"istio.io/istio/pkg/test"
    38  	"istio.io/istio/pkg/test/util/assert"
    39  )
    40  
    41  func TestApplyUpstreamTLSSettings(t *testing.T) {
    42  	istioMutualTLSSettings := &networking.ClientTLSSettings{
    43  		Mode:            networking.ClientTLSSettings_ISTIO_MUTUAL,
    44  		SubjectAltNames: []string{"custom.foo.com"},
    45  		Sni:             "custom.foo.com",
    46  	}
    47  	mutualTLSSettingsWithCerts := &networking.ClientTLSSettings{
    48  		Mode:              networking.ClientTLSSettings_MUTUAL,
    49  		CaCertificates:    "root-cert.pem",
    50  		ClientCertificate: "cert-chain.pem",
    51  		PrivateKey:        "key.pem",
    52  		SubjectAltNames:   []string{"custom.foo.com"},
    53  		Sni:               "custom.foo.com",
    54  	}
    55  	simpleTLSSettingsWithCerts := &networking.ClientTLSSettings{
    56  		Mode:            networking.ClientTLSSettings_SIMPLE,
    57  		CaCertificates:  "root-cert.pem",
    58  		SubjectAltNames: []string{"custom.foo.com"},
    59  		Sni:             "custom.foo.com",
    60  	}
    61  
    62  	tests := []struct {
    63  		name                       string
    64  		mtlsCtx                    mtlsContextType
    65  		discoveryType              cluster.Cluster_DiscoveryType
    66  		tls                        *networking.ClientTLSSettings
    67  		h2                         bool
    68  		expectTransportSocket      bool
    69  		expectTransportSocketMatch bool
    70  
    71  		validateTLSContext func(t *testing.T, ctx *tls.UpstreamTlsContext)
    72  	}{
    73  		{
    74  			name:                       "user specified without tls",
    75  			mtlsCtx:                    userSupplied,
    76  			discoveryType:              cluster.Cluster_EDS,
    77  			tls:                        nil,
    78  			expectTransportSocket:      false,
    79  			expectTransportSocketMatch: false,
    80  		},
    81  		{
    82  			name:                       "user specified with istio_mutual tls",
    83  			mtlsCtx:                    userSupplied,
    84  			discoveryType:              cluster.Cluster_EDS,
    85  			tls:                        istioMutualTLSSettings,
    86  			expectTransportSocket:      true,
    87  			expectTransportSocketMatch: false,
    88  			validateTLSContext: func(t *testing.T, ctx *tls.UpstreamTlsContext) {
    89  				if got := ctx.CommonTlsContext.GetAlpnProtocols(); !reflect.DeepEqual(got, util.ALPNInMeshWithMxc) {
    90  					t.Fatalf("expected alpn list %v; got %v", util.ALPNInMeshWithMxc, got)
    91  				}
    92  			},
    93  		},
    94  		{
    95  			name:                       "user specified with istio_mutual tls with h2",
    96  			mtlsCtx:                    userSupplied,
    97  			discoveryType:              cluster.Cluster_EDS,
    98  			tls:                        istioMutualTLSSettings,
    99  			expectTransportSocket:      true,
   100  			expectTransportSocketMatch: false,
   101  			h2:                         true,
   102  			validateTLSContext: func(t *testing.T, ctx *tls.UpstreamTlsContext) {
   103  				if got := ctx.CommonTlsContext.GetAlpnProtocols(); !reflect.DeepEqual(got, util.ALPNInMeshH2WithMxc) {
   104  					t.Fatalf("expected alpn list %v; got %v", util.ALPNInMeshH2WithMxc, got)
   105  				}
   106  			},
   107  		},
   108  		{
   109  			name:                       "user specified simple tls",
   110  			mtlsCtx:                    userSupplied,
   111  			discoveryType:              cluster.Cluster_EDS,
   112  			tls:                        simpleTLSSettingsWithCerts,
   113  			expectTransportSocket:      true,
   114  			expectTransportSocketMatch: false,
   115  			validateTLSContext: func(t *testing.T, ctx *tls.UpstreamTlsContext) {
   116  				rootName := "file-root:" + mutualTLSSettingsWithCerts.CaCertificates
   117  				if got := ctx.CommonTlsContext.GetCombinedValidationContext().GetValidationContextSdsSecretConfig().GetName(); rootName != got {
   118  					t.Fatalf("expected root name %v got %v", rootName, got)
   119  				}
   120  				if got := ctx.CommonTlsContext.GetAlpnProtocols(); got != nil {
   121  					t.Fatalf("expected alpn list nil as not h2 or Istio_Mutual TLS Setting; got %v", got)
   122  				}
   123  				if got := ctx.GetSni(); got != simpleTLSSettingsWithCerts.Sni {
   124  					t.Fatalf("expected TLSContext SNI %v; got %v", simpleTLSSettingsWithCerts.Sni, got)
   125  				}
   126  			},
   127  		},
   128  		{
   129  			name:                       "user specified simple tls with h2",
   130  			mtlsCtx:                    userSupplied,
   131  			discoveryType:              cluster.Cluster_EDS,
   132  			tls:                        simpleTLSSettingsWithCerts,
   133  			expectTransportSocket:      true,
   134  			expectTransportSocketMatch: false,
   135  			h2:                         true,
   136  			validateTLSContext: func(t *testing.T, ctx *tls.UpstreamTlsContext) {
   137  				rootName := "file-root:" + mutualTLSSettingsWithCerts.CaCertificates
   138  				if got := ctx.CommonTlsContext.GetCombinedValidationContext().GetValidationContextSdsSecretConfig().GetName(); rootName != got {
   139  					t.Fatalf("expected root name %v got %v", rootName, got)
   140  				}
   141  				if got := ctx.CommonTlsContext.GetAlpnProtocols(); !reflect.DeepEqual(got, util.ALPNH2Only) {
   142  					t.Fatalf("expected alpn list %v; got %v", util.ALPNH2Only, got)
   143  				}
   144  				if got := ctx.GetSni(); got != simpleTLSSettingsWithCerts.Sni {
   145  					t.Fatalf("expected TLSContext SNI %v; got %v", simpleTLSSettingsWithCerts.Sni, got)
   146  				}
   147  			},
   148  		},
   149  		{
   150  			name:                       "user specified mutual tls",
   151  			mtlsCtx:                    userSupplied,
   152  			discoveryType:              cluster.Cluster_EDS,
   153  			tls:                        mutualTLSSettingsWithCerts,
   154  			expectTransportSocket:      true,
   155  			expectTransportSocketMatch: false,
   156  			validateTLSContext: func(t *testing.T, ctx *tls.UpstreamTlsContext) {
   157  				rootName := "file-root:" + mutualTLSSettingsWithCerts.CaCertificates
   158  				certName := fmt.Sprintf("file-cert:%s~%s", mutualTLSSettingsWithCerts.ClientCertificate, mutualTLSSettingsWithCerts.PrivateKey)
   159  				if got := ctx.CommonTlsContext.GetCombinedValidationContext().GetValidationContextSdsSecretConfig().GetName(); rootName != got {
   160  					t.Fatalf("expected root name %v got %v", rootName, got)
   161  				}
   162  				if got := ctx.CommonTlsContext.GetTlsCertificateSdsSecretConfigs()[0].GetName(); certName != got {
   163  					t.Fatalf("expected cert name %v got %v", certName, got)
   164  				}
   165  				if got := ctx.CommonTlsContext.GetAlpnProtocols(); got != nil {
   166  					t.Fatalf("expected alpn list nil as not h2 or Istio_Mutual TLS Setting; got %v", got)
   167  				}
   168  				if got := ctx.GetSni(); got != mutualTLSSettingsWithCerts.Sni {
   169  					t.Fatalf("expected TLSContext SNI %v; got %v", mutualTLSSettingsWithCerts.Sni, got)
   170  				}
   171  			},
   172  		},
   173  		{
   174  			name:                       "user specified mutual tls with h2",
   175  			mtlsCtx:                    userSupplied,
   176  			discoveryType:              cluster.Cluster_EDS,
   177  			tls:                        mutualTLSSettingsWithCerts,
   178  			expectTransportSocket:      true,
   179  			expectTransportSocketMatch: false,
   180  			h2:                         true,
   181  			validateTLSContext: func(t *testing.T, ctx *tls.UpstreamTlsContext) {
   182  				rootName := "file-root:" + mutualTLSSettingsWithCerts.CaCertificates
   183  				certName := fmt.Sprintf("file-cert:%s~%s", mutualTLSSettingsWithCerts.ClientCertificate, mutualTLSSettingsWithCerts.PrivateKey)
   184  				if got := ctx.CommonTlsContext.GetCombinedValidationContext().GetValidationContextSdsSecretConfig().GetName(); rootName != got {
   185  					t.Fatalf("expected root name %v got %v", rootName, got)
   186  				}
   187  				if got := ctx.CommonTlsContext.GetTlsCertificateSdsSecretConfigs()[0].GetName(); certName != got {
   188  					t.Fatalf("expected cert name %v got %v", certName, got)
   189  				}
   190  				if got := ctx.CommonTlsContext.GetAlpnProtocols(); !reflect.DeepEqual(got, util.ALPNH2Only) {
   191  					t.Fatalf("expected alpn list %v; got %v", util.ALPNH2Only, got)
   192  				}
   193  				if got := ctx.GetSni(); got != mutualTLSSettingsWithCerts.Sni {
   194  					t.Fatalf("expected TLSContext SNI %v; got %v", mutualTLSSettingsWithCerts.Sni, got)
   195  				}
   196  			},
   197  		},
   198  		{
   199  			name:                       "auto detect with tls",
   200  			mtlsCtx:                    autoDetected,
   201  			discoveryType:              cluster.Cluster_EDS,
   202  			tls:                        istioMutualTLSSettings,
   203  			expectTransportSocket:      false,
   204  			expectTransportSocketMatch: true,
   205  			validateTLSContext: func(t *testing.T, ctx *tls.UpstreamTlsContext) {
   206  				if got := ctx.CommonTlsContext.GetAlpnProtocols(); !reflect.DeepEqual(got, util.ALPNInMeshWithMxc) {
   207  					t.Fatalf("expected alpn list %v; got %v", util.ALPNInMeshWithMxc, got)
   208  				}
   209  			},
   210  		},
   211  		{
   212  			name:                       "auto detect with tls and h2 options",
   213  			mtlsCtx:                    autoDetected,
   214  			discoveryType:              cluster.Cluster_EDS,
   215  			tls:                        istioMutualTLSSettings,
   216  			expectTransportSocket:      false,
   217  			expectTransportSocketMatch: true,
   218  			h2:                         true,
   219  			validateTLSContext: func(t *testing.T, ctx *tls.UpstreamTlsContext) {
   220  				if got := ctx.CommonTlsContext.GetAlpnProtocols(); !reflect.DeepEqual(got, util.ALPNInMeshH2WithMxc) {
   221  					t.Fatalf("expected alpn list %v; got %v", util.ALPNInMeshH2WithMxc, got)
   222  				}
   223  			},
   224  		},
   225  	}
   226  
   227  	proxy := &model.Proxy{
   228  		Type:         model.SidecarProxy,
   229  		Metadata:     &model.NodeMetadata{},
   230  		IstioVersion: &model.IstioVersion{Major: 1, Minor: 5},
   231  	}
   232  	push := model.NewPushContext()
   233  	for _, test := range tests {
   234  		t.Run(test.name, func(t *testing.T) {
   235  			cb := NewClusterBuilder(proxy, &model.PushRequest{Push: push}, model.DisabledCache{})
   236  			opts := &buildClusterOpts{
   237  				mutable: newClusterWrapper(&cluster.Cluster{
   238  					ClusterDiscoveryType: &cluster.Cluster_Type{Type: test.discoveryType},
   239  				}),
   240  				mesh: push.Mesh,
   241  			}
   242  			if test.h2 {
   243  				setH2Options(opts.mutable)
   244  			}
   245  			cb.applyUpstreamTLSSettings(opts, test.tls, test.mtlsCtx)
   246  
   247  			if test.expectTransportSocket && opts.mutable.cluster.TransportSocket == nil ||
   248  				!test.expectTransportSocket && opts.mutable.cluster.TransportSocket != nil {
   249  				t.Errorf("Expected TransportSocket %v", test.expectTransportSocket)
   250  			}
   251  			if test.expectTransportSocketMatch && opts.mutable.cluster.TransportSocketMatches == nil ||
   252  				!test.expectTransportSocketMatch && opts.mutable.cluster.TransportSocketMatches != nil {
   253  				t.Errorf("Expected TransportSocketMatch %v", test.expectTransportSocketMatch)
   254  			}
   255  
   256  			if test.validateTLSContext != nil {
   257  				ctx := &tls.UpstreamTlsContext{}
   258  				if test.expectTransportSocket {
   259  					if err := opts.mutable.cluster.TransportSocket.GetTypedConfig().UnmarshalTo(ctx); err != nil {
   260  						t.Fatal(err)
   261  					}
   262  				} else if test.expectTransportSocketMatch {
   263  					if err := opts.mutable.cluster.TransportSocketMatches[0].TransportSocket.GetTypedConfig().UnmarshalTo(ctx); err != nil {
   264  						t.Fatal(err)
   265  					}
   266  				}
   267  				test.validateTLSContext(t, ctx)
   268  			}
   269  		})
   270  	}
   271  }
   272  
   273  type expectedResult struct {
   274  	tlsContext *tls.UpstreamTlsContext
   275  	err        error
   276  }
   277  
   278  // TestBuildUpstreamClusterTLSContext tests the buildUpstreamClusterTLSContext function
   279  func TestBuildUpstreamClusterTLSContext(t *testing.T) {
   280  	clientCert := "/path/to/cert"
   281  	rootCert := "path/to/cacert"
   282  	clientKey := "/path/to/key"
   283  
   284  	credentialName := "some-fake-credential"
   285  
   286  	testCases := []struct {
   287  		name                     string
   288  		opts                     *buildClusterOpts
   289  		tls                      *networking.ClientTLSSettings
   290  		h2                       bool
   291  		router                   bool
   292  		result                   expectedResult
   293  		enableAutoSni            bool
   294  		enableVerifyCertAtClient bool
   295  	}{
   296  		{
   297  			name: "tls mode disabled",
   298  			opts: &buildClusterOpts{
   299  				mutable: newClusterWrapper(&cluster.Cluster{
   300  					Name: "test-cluster",
   301  				}),
   302  			},
   303  			tls: &networking.ClientTLSSettings{
   304  				Mode: networking.ClientTLSSettings_DISABLE,
   305  			},
   306  			result: expectedResult{nil, nil},
   307  		},
   308  		{
   309  			name: "tls mode ISTIO_MUTUAL",
   310  			opts: &buildClusterOpts{
   311  				mutable: newTestCluster(),
   312  			},
   313  			tls: &networking.ClientTLSSettings{
   314  				Mode:            networking.ClientTLSSettings_ISTIO_MUTUAL,
   315  				SubjectAltNames: []string{"SAN"},
   316  				Sni:             "some-sni.com",
   317  			},
   318  			result: expectedResult{
   319  				tlsContext: &tls.UpstreamTlsContext{
   320  					CommonTlsContext: &tls.CommonTlsContext{
   321  						TlsParams: &tls.TlsParameters{
   322  							// if not specified, envoy use TLSv1_2 as default for client.
   323  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   324  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   325  						},
   326  						TlsCertificateSdsSecretConfigs: []*tls.SdsSecretConfig{
   327  							{
   328  								Name: "default",
   329  								SdsConfig: &core.ConfigSource{
   330  									ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
   331  										ApiConfigSource: &core.ApiConfigSource{
   332  											ApiType:                   core.ApiConfigSource_GRPC,
   333  											SetNodeOnFirstMessageOnly: true,
   334  											TransportApiVersion:       core.ApiVersion_V3,
   335  											GrpcServices: []*core.GrpcService{
   336  												{
   337  													TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   338  														EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
   339  													},
   340  												},
   341  											},
   342  										},
   343  									},
   344  									InitialFetchTimeout: durationpb.New(time.Second * 0),
   345  									ResourceApiVersion:  core.ApiVersion_V3,
   346  								},
   347  							},
   348  						},
   349  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
   350  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
   351  								DefaultValidationContext: &tls.CertificateValidationContext{MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"})},
   352  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
   353  									Name: "ROOTCA",
   354  									SdsConfig: &core.ConfigSource{
   355  										ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
   356  											ApiConfigSource: &core.ApiConfigSource{
   357  												ApiType:                   core.ApiConfigSource_GRPC,
   358  												SetNodeOnFirstMessageOnly: true,
   359  												TransportApiVersion:       core.ApiVersion_V3,
   360  												GrpcServices: []*core.GrpcService{
   361  													{
   362  														TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   363  															EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
   364  														},
   365  													},
   366  												},
   367  											},
   368  										},
   369  										InitialFetchTimeout: durationpb.New(time.Second * 0),
   370  										ResourceApiVersion:  core.ApiVersion_V3,
   371  									},
   372  								},
   373  							},
   374  						},
   375  						AlpnProtocols: util.ALPNInMeshWithMxc,
   376  					},
   377  					Sni: "some-sni.com",
   378  				},
   379  				err: nil,
   380  			},
   381  		},
   382  		{
   383  			name: "tls mode ISTIO_MUTUAL and H2",
   384  			opts: &buildClusterOpts{
   385  				mutable: newTestCluster(),
   386  			},
   387  			tls: &networking.ClientTLSSettings{
   388  				Mode:            networking.ClientTLSSettings_ISTIO_MUTUAL,
   389  				SubjectAltNames: []string{"SAN"},
   390  				Sni:             "some-sni.com",
   391  			},
   392  			h2: true,
   393  			result: expectedResult{
   394  				tlsContext: &tls.UpstreamTlsContext{
   395  					CommonTlsContext: &tls.CommonTlsContext{
   396  						TlsParams: &tls.TlsParameters{
   397  							// if not specified, envoy use TLSv1_2 as default for client.
   398  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   399  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   400  						},
   401  						TlsCertificateSdsSecretConfigs: []*tls.SdsSecretConfig{
   402  							{
   403  								Name: "default",
   404  								SdsConfig: &core.ConfigSource{
   405  									ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
   406  										ApiConfigSource: &core.ApiConfigSource{
   407  											ApiType:                   core.ApiConfigSource_GRPC,
   408  											SetNodeOnFirstMessageOnly: true,
   409  											TransportApiVersion:       core.ApiVersion_V3,
   410  											GrpcServices: []*core.GrpcService{
   411  												{
   412  													TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   413  														EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
   414  													},
   415  												},
   416  											},
   417  										},
   418  									},
   419  									InitialFetchTimeout: durationpb.New(time.Second * 0),
   420  									ResourceApiVersion:  core.ApiVersion_V3,
   421  								},
   422  							},
   423  						},
   424  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
   425  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
   426  								DefaultValidationContext: &tls.CertificateValidationContext{MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"})},
   427  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
   428  									Name: "ROOTCA",
   429  									SdsConfig: &core.ConfigSource{
   430  										ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
   431  											ApiConfigSource: &core.ApiConfigSource{
   432  												ApiType:                   core.ApiConfigSource_GRPC,
   433  												SetNodeOnFirstMessageOnly: true,
   434  												TransportApiVersion:       core.ApiVersion_V3,
   435  												GrpcServices: []*core.GrpcService{
   436  													{
   437  														TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   438  															EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
   439  														},
   440  													},
   441  												},
   442  											},
   443  										},
   444  										InitialFetchTimeout: durationpb.New(time.Second * 0),
   445  										ResourceApiVersion:  core.ApiVersion_V3,
   446  									},
   447  								},
   448  							},
   449  						},
   450  						AlpnProtocols: util.ALPNInMeshH2WithMxc,
   451  					},
   452  					Sni: "some-sni.com",
   453  				},
   454  				err: nil,
   455  			},
   456  		},
   457  		{
   458  			name: "tls mode SIMPLE, with no certs specified in tls",
   459  			opts: &buildClusterOpts{
   460  				mutable: newTestCluster(),
   461  			},
   462  			tls: &networking.ClientTLSSettings{
   463  				Mode:            networking.ClientTLSSettings_SIMPLE,
   464  				SubjectAltNames: []string{"SAN"},
   465  				Sni:             "some-sni.com",
   466  			},
   467  			result: expectedResult{
   468  				tlsContext: &tls.UpstreamTlsContext{
   469  					CommonTlsContext: &tls.CommonTlsContext{
   470  						TlsParams: &tls.TlsParameters{
   471  							// if not specified, envoy use TLSv1_2 as default for client.
   472  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   473  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   474  						},
   475  						ValidationContextType: &tls.CommonTlsContext_ValidationContext{},
   476  					},
   477  					Sni: "some-sni.com",
   478  				},
   479  				err: nil,
   480  			},
   481  		},
   482  		{
   483  			name: "tls mode SIMPLE, with AutoSni enabled and no sni specified in tls",
   484  			opts: &buildClusterOpts{
   485  				mutable: newTestCluster(),
   486  			},
   487  			tls: &networking.ClientTLSSettings{
   488  				Mode:            networking.ClientTLSSettings_SIMPLE,
   489  				SubjectAltNames: []string{"SAN"},
   490  			},
   491  			result: expectedResult{
   492  				tlsContext: &tls.UpstreamTlsContext{
   493  					CommonTlsContext: &tls.CommonTlsContext{
   494  						TlsParams: &tls.TlsParameters{
   495  							// if not specified, envoy use TLSv1_2 as default for client.
   496  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   497  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   498  						},
   499  						ValidationContextType: &tls.CommonTlsContext_ValidationContext{},
   500  					},
   501  				},
   502  				err: nil,
   503  			},
   504  			enableAutoSni: true,
   505  		},
   506  		{
   507  			name: "tls mode SIMPLE, with AutoSni enabled and sni specified in tls",
   508  			opts: &buildClusterOpts{
   509  				mutable: newTestCluster(),
   510  			},
   511  			tls: &networking.ClientTLSSettings{
   512  				Mode:            networking.ClientTLSSettings_SIMPLE,
   513  				SubjectAltNames: []string{"SAN"},
   514  				Sni:             "some-sni.com",
   515  			},
   516  			result: expectedResult{
   517  				tlsContext: &tls.UpstreamTlsContext{
   518  					CommonTlsContext: &tls.CommonTlsContext{
   519  						TlsParams: &tls.TlsParameters{
   520  							// if not specified, envoy use TLSv1_2 as default for client.
   521  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   522  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   523  						},
   524  						ValidationContextType: &tls.CommonTlsContext_ValidationContext{},
   525  					},
   526  					Sni: "some-sni.com",
   527  				},
   528  				err: nil,
   529  			},
   530  			enableAutoSni: true,
   531  		},
   532  		{
   533  			name: "tls mode SIMPLE, with VerifyCert and AutoSni enabled with SubjectAltNames set",
   534  			opts: &buildClusterOpts{
   535  				mutable: newTestCluster(),
   536  			},
   537  			tls: &networking.ClientTLSSettings{
   538  				Mode:            networking.ClientTLSSettings_SIMPLE,
   539  				SubjectAltNames: []string{"SAN"},
   540  				Sni:             "some-sni.com",
   541  			},
   542  			result: expectedResult{
   543  				tlsContext: &tls.UpstreamTlsContext{
   544  					CommonTlsContext: &tls.CommonTlsContext{
   545  						TlsParams: &tls.TlsParameters{
   546  							// if not specified, envoy use TLSv1_2 as default for client.
   547  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   548  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   549  						},
   550  						ValidationContextType: &tls.CommonTlsContext_ValidationContext{},
   551  					},
   552  					Sni: "some-sni.com",
   553  				},
   554  				err: nil,
   555  			},
   556  			enableAutoSni:            true,
   557  			enableVerifyCertAtClient: true,
   558  		},
   559  		{
   560  			name: "tls mode SIMPLE, with VerifyCert and AutoSni enabled without SubjectAltNames set",
   561  			opts: &buildClusterOpts{
   562  				mutable: newTestCluster(),
   563  			},
   564  			tls: &networking.ClientTLSSettings{
   565  				Mode: networking.ClientTLSSettings_SIMPLE,
   566  				Sni:  "some-sni.com",
   567  			},
   568  			result: expectedResult{
   569  				tlsContext: &tls.UpstreamTlsContext{
   570  					CommonTlsContext: &tls.CommonTlsContext{
   571  						TlsParams: &tls.TlsParameters{
   572  							// if not specified, envoy use TLSv1_2 as default for client.
   573  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   574  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   575  						},
   576  						ValidationContextType: &tls.CommonTlsContext_ValidationContext{},
   577  					},
   578  					Sni: "some-sni.com",
   579  				},
   580  				err: nil,
   581  			},
   582  			enableAutoSni:            true,
   583  			enableVerifyCertAtClient: true,
   584  		},
   585  		{
   586  			name: "tls mode SIMPLE, with certs specified in tls",
   587  			opts: &buildClusterOpts{
   588  				mutable: newTestCluster(),
   589  			},
   590  			tls: &networking.ClientTLSSettings{
   591  				Mode:            networking.ClientTLSSettings_SIMPLE,
   592  				CaCertificates:  rootCert,
   593  				SubjectAltNames: []string{"SAN"},
   594  				Sni:             "some-sni.com",
   595  			},
   596  			result: expectedResult{
   597  				tlsContext: &tls.UpstreamTlsContext{
   598  					CommonTlsContext: &tls.CommonTlsContext{
   599  						TlsParams: &tls.TlsParameters{
   600  							// if not specified, envoy use TLSv1_2 as default for client.
   601  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   602  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   603  						},
   604  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
   605  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
   606  								DefaultValidationContext: &tls.CertificateValidationContext{MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"})},
   607  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
   608  									Name: fmt.Sprintf("file-root:%s", rootCert),
   609  									SdsConfig: &core.ConfigSource{
   610  										ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
   611  											ApiConfigSource: &core.ApiConfigSource{
   612  												ApiType:                   core.ApiConfigSource_GRPC,
   613  												SetNodeOnFirstMessageOnly: true,
   614  												TransportApiVersion:       core.ApiVersion_V3,
   615  												GrpcServices: []*core.GrpcService{
   616  													{
   617  														TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   618  															EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
   619  														},
   620  													},
   621  												},
   622  											},
   623  										},
   624  										ResourceApiVersion: core.ApiVersion_V3,
   625  									},
   626  								},
   627  							},
   628  						},
   629  					},
   630  					Sni: "some-sni.com",
   631  				},
   632  				err: nil,
   633  			},
   634  		},
   635  		{
   636  			name: "tls mode SIMPLE, with certs specified in tls, with crl",
   637  			opts: &buildClusterOpts{
   638  				mutable: newTestCluster(),
   639  			},
   640  			tls: &networking.ClientTLSSettings{
   641  				Mode:            networking.ClientTLSSettings_SIMPLE,
   642  				CaCertificates:  rootCert,
   643  				SubjectAltNames: []string{"SAN"},
   644  				Sni:             "some-sni.com",
   645  				CaCrl:           "path/to/crl",
   646  			},
   647  			result: expectedResult{
   648  				tlsContext: &tls.UpstreamTlsContext{
   649  					CommonTlsContext: &tls.CommonTlsContext{
   650  						TlsParams: &tls.TlsParameters{
   651  							// if not specified, envoy use TLSv1_2 as default for client.
   652  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   653  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   654  						},
   655  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
   656  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
   657  								DefaultValidationContext: &tls.CertificateValidationContext{
   658  									Crl: &core.DataSource{
   659  										Specifier: &core.DataSource_Filename{
   660  											Filename: "path/to/crl",
   661  										},
   662  									},
   663  									MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"}),
   664  								},
   665  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
   666  									Name: fmt.Sprintf("file-root:%s", rootCert),
   667  									SdsConfig: &core.ConfigSource{
   668  										ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
   669  											ApiConfigSource: &core.ApiConfigSource{
   670  												ApiType:                   core.ApiConfigSource_GRPC,
   671  												SetNodeOnFirstMessageOnly: true,
   672  												TransportApiVersion:       core.ApiVersion_V3,
   673  												GrpcServices: []*core.GrpcService{
   674  													{
   675  														TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   676  															EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
   677  														},
   678  													},
   679  												},
   680  											},
   681  										},
   682  										ResourceApiVersion: core.ApiVersion_V3,
   683  									},
   684  								},
   685  							},
   686  						},
   687  					},
   688  					Sni: "some-sni.com",
   689  				},
   690  				err: nil,
   691  			},
   692  		},
   693  		{
   694  			name: "tls mode SIMPLE, with certs specified in tls with h2",
   695  			opts: &buildClusterOpts{
   696  				mutable: newH2TestCluster(),
   697  			},
   698  			tls: &networking.ClientTLSSettings{
   699  				Mode:            networking.ClientTLSSettings_SIMPLE,
   700  				CaCertificates:  rootCert,
   701  				SubjectAltNames: []string{"SAN"},
   702  				Sni:             "some-sni.com",
   703  			},
   704  			h2: true,
   705  			result: expectedResult{
   706  				tlsContext: &tls.UpstreamTlsContext{
   707  					CommonTlsContext: &tls.CommonTlsContext{
   708  						TlsParams: &tls.TlsParameters{
   709  							// if not specified, envoy use TLSv1_2 as default for client.
   710  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   711  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   712  						},
   713  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
   714  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
   715  								DefaultValidationContext: &tls.CertificateValidationContext{MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"})},
   716  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
   717  									Name: fmt.Sprintf("file-root:%s", rootCert),
   718  									SdsConfig: &core.ConfigSource{
   719  										ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
   720  											ApiConfigSource: &core.ApiConfigSource{
   721  												ApiType:                   core.ApiConfigSource_GRPC,
   722  												SetNodeOnFirstMessageOnly: true,
   723  												TransportApiVersion:       core.ApiVersion_V3,
   724  												GrpcServices: []*core.GrpcService{
   725  													{
   726  														TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   727  															EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
   728  														},
   729  													},
   730  												},
   731  											},
   732  										},
   733  										ResourceApiVersion: core.ApiVersion_V3,
   734  									},
   735  								},
   736  							},
   737  						},
   738  						AlpnProtocols: util.ALPNH2Only,
   739  					},
   740  					Sni: "some-sni.com",
   741  				},
   742  				err: nil,
   743  			},
   744  		},
   745  		{
   746  			name: "tls mode SIMPLE, with certs specified in tls",
   747  			opts: &buildClusterOpts{
   748  				mutable: newTestCluster(),
   749  			},
   750  			tls: &networking.ClientTLSSettings{
   751  				Mode:            networking.ClientTLSSettings_SIMPLE,
   752  				CaCertificates:  rootCert,
   753  				SubjectAltNames: []string{"SAN"},
   754  				Sni:             "some-sni.com",
   755  			},
   756  			result: expectedResult{
   757  				tlsContext: &tls.UpstreamTlsContext{
   758  					CommonTlsContext: &tls.CommonTlsContext{
   759  						TlsParams: &tls.TlsParameters{
   760  							// if not specified, envoy use TLSv1_2 as default for client.
   761  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   762  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   763  						},
   764  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
   765  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
   766  								DefaultValidationContext: &tls.CertificateValidationContext{MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"})},
   767  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
   768  									Name: fmt.Sprintf("file-root:%s", rootCert),
   769  									SdsConfig: &core.ConfigSource{
   770  										ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
   771  											ApiConfigSource: &core.ApiConfigSource{
   772  												ApiType:                   core.ApiConfigSource_GRPC,
   773  												SetNodeOnFirstMessageOnly: true,
   774  												TransportApiVersion:       core.ApiVersion_V3,
   775  												GrpcServices: []*core.GrpcService{
   776  													{
   777  														TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   778  															EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
   779  														},
   780  													},
   781  												},
   782  											},
   783  										},
   784  										ResourceApiVersion: core.ApiVersion_V3,
   785  									},
   786  								},
   787  							},
   788  						},
   789  					},
   790  					Sni: "some-sni.com",
   791  				},
   792  				err: nil,
   793  			},
   794  		},
   795  		{
   796  			name: "tls mode SIMPLE, with SANs specified in service entries",
   797  			opts: &buildClusterOpts{
   798  				mutable:         newTestCluster(),
   799  				serviceAccounts: []string{"se-san.com"},
   800  				serviceRegistry: provider.External,
   801  			},
   802  			tls: &networking.ClientTLSSettings{
   803  				Mode:           networking.ClientTLSSettings_SIMPLE,
   804  				CaCertificates: rootCert,
   805  				Sni:            "some-sni.com",
   806  			},
   807  			result: expectedResult{
   808  				tlsContext: &tls.UpstreamTlsContext{
   809  					CommonTlsContext: &tls.CommonTlsContext{
   810  						TlsParams: &tls.TlsParameters{
   811  							// if not specified, envoy use TLSv1_2 as default for client.
   812  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   813  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   814  						},
   815  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
   816  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
   817  								DefaultValidationContext: &tls.CertificateValidationContext{MatchSubjectAltNames: util.StringToExactMatch([]string{"se-san.com"})},
   818  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
   819  									Name: fmt.Sprintf("file-root:%s", rootCert),
   820  									SdsConfig: &core.ConfigSource{
   821  										ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
   822  											ApiConfigSource: &core.ApiConfigSource{
   823  												ApiType:                   core.ApiConfigSource_GRPC,
   824  												SetNodeOnFirstMessageOnly: true,
   825  												TransportApiVersion:       core.ApiVersion_V3,
   826  												GrpcServices: []*core.GrpcService{
   827  													{
   828  														TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   829  															EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
   830  														},
   831  													},
   832  												},
   833  											},
   834  										},
   835  										ResourceApiVersion: core.ApiVersion_V3,
   836  									},
   837  								},
   838  							},
   839  						},
   840  					},
   841  					Sni: "some-sni.com",
   842  				},
   843  				err: nil,
   844  			},
   845  		},
   846  		{
   847  			name: "tls mode MUTUAL, with no client certificate",
   848  			opts: &buildClusterOpts{
   849  				mutable: newTestCluster(),
   850  			},
   851  			tls: &networking.ClientTLSSettings{
   852  				Mode:              networking.ClientTLSSettings_MUTUAL,
   853  				ClientCertificate: "",
   854  				PrivateKey:        "some-fake-key",
   855  			},
   856  			result: expectedResult{
   857  				nil,
   858  				fmt.Errorf("client cert must be provided"),
   859  			},
   860  		},
   861  		{
   862  			name: "tls mode MUTUAL, with no client key",
   863  			opts: &buildClusterOpts{
   864  				mutable: newTestCluster(),
   865  			},
   866  			tls: &networking.ClientTLSSettings{
   867  				Mode:              networking.ClientTLSSettings_MUTUAL,
   868  				ClientCertificate: "some-fake-cert",
   869  				PrivateKey:        "",
   870  			},
   871  			result: expectedResult{
   872  				nil,
   873  				fmt.Errorf("client key must be provided"),
   874  			},
   875  		},
   876  		{
   877  			name: "tls mode MUTUAL, with node metadata sdsEnabled true no root CA specified",
   878  			opts: &buildClusterOpts{
   879  				mutable: newTestCluster(),
   880  			},
   881  			tls: &networking.ClientTLSSettings{
   882  				Mode:              networking.ClientTLSSettings_MUTUAL,
   883  				ClientCertificate: clientCert,
   884  				PrivateKey:        clientKey,
   885  				SubjectAltNames:   []string{"SAN"},
   886  				Sni:               "some-sni.com",
   887  			},
   888  			result: expectedResult{
   889  				tlsContext: &tls.UpstreamTlsContext{
   890  					CommonTlsContext: &tls.CommonTlsContext{
   891  						TlsParams: &tls.TlsParameters{
   892  							// if not specified, envoy use TLSv1_2 as default for client.
   893  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   894  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   895  						},
   896  						TlsCertificateSdsSecretConfigs: []*tls.SdsSecretConfig{
   897  							{
   898  								Name: fmt.Sprintf("file-cert:%s~%s", clientCert, clientKey),
   899  								SdsConfig: &core.ConfigSource{
   900  									ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
   901  										ApiConfigSource: &core.ApiConfigSource{
   902  											ApiType:                   core.ApiConfigSource_GRPC,
   903  											SetNodeOnFirstMessageOnly: true,
   904  											TransportApiVersion:       core.ApiVersion_V3,
   905  											GrpcServices: []*core.GrpcService{
   906  												{
   907  													TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   908  														EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
   909  													},
   910  												},
   911  											},
   912  										},
   913  									},
   914  									ResourceApiVersion: core.ApiVersion_V3,
   915  								},
   916  							},
   917  						},
   918  						ValidationContextType: &tls.CommonTlsContext_ValidationContext{},
   919  					},
   920  					Sni: "some-sni.com",
   921  				},
   922  				err: nil,
   923  			},
   924  		},
   925  		{
   926  			name: "tls mode MUTUAL, with node metadata sdsEnabled true",
   927  			opts: &buildClusterOpts{
   928  				mutable: newTestCluster(),
   929  			},
   930  			tls: &networking.ClientTLSSettings{
   931  				Mode:              networking.ClientTLSSettings_MUTUAL,
   932  				ClientCertificate: clientCert,
   933  				PrivateKey:        clientKey,
   934  				CaCertificates:    rootCert,
   935  				SubjectAltNames:   []string{"SAN"},
   936  				Sni:               "some-sni.com",
   937  			},
   938  			result: expectedResult{
   939  				tlsContext: &tls.UpstreamTlsContext{
   940  					CommonTlsContext: &tls.CommonTlsContext{
   941  						TlsParams: &tls.TlsParameters{
   942  							// if not specified, envoy use TLSv1_2 as default for client.
   943  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
   944  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
   945  						},
   946  						TlsCertificateSdsSecretConfigs: []*tls.SdsSecretConfig{
   947  							{
   948  								Name: fmt.Sprintf("file-cert:%s~%s", clientCert, clientKey),
   949  								SdsConfig: &core.ConfigSource{
   950  									ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
   951  										ApiConfigSource: &core.ApiConfigSource{
   952  											ApiType:                   core.ApiConfigSource_GRPC,
   953  											SetNodeOnFirstMessageOnly: true,
   954  											TransportApiVersion:       core.ApiVersion_V3,
   955  											GrpcServices: []*core.GrpcService{
   956  												{
   957  													TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   958  														EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
   959  													},
   960  												},
   961  											},
   962  										},
   963  									},
   964  									ResourceApiVersion: core.ApiVersion_V3,
   965  								},
   966  							},
   967  						},
   968  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
   969  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
   970  								DefaultValidationContext: &tls.CertificateValidationContext{MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"})},
   971  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
   972  									Name: fmt.Sprintf("file-root:%s", rootCert),
   973  									SdsConfig: &core.ConfigSource{
   974  										ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
   975  											ApiConfigSource: &core.ApiConfigSource{
   976  												ApiType:                   core.ApiConfigSource_GRPC,
   977  												SetNodeOnFirstMessageOnly: true,
   978  												TransportApiVersion:       core.ApiVersion_V3,
   979  												GrpcServices: []*core.GrpcService{
   980  													{
   981  														TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
   982  															EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
   983  														},
   984  													},
   985  												},
   986  											},
   987  										},
   988  										ResourceApiVersion: core.ApiVersion_V3,
   989  									},
   990  								},
   991  							},
   992  						},
   993  					},
   994  					Sni: "some-sni.com",
   995  				},
   996  				err: nil,
   997  			},
   998  		},
   999  		{
  1000  			name: "tls mode MUTUAL, with node metadata sdsEnabled true, with crl",
  1001  			opts: &buildClusterOpts{
  1002  				mutable: newTestCluster(),
  1003  			},
  1004  			tls: &networking.ClientTLSSettings{
  1005  				Mode:              networking.ClientTLSSettings_MUTUAL,
  1006  				ClientCertificate: clientCert,
  1007  				PrivateKey:        clientKey,
  1008  				CaCertificates:    rootCert,
  1009  				CaCrl:             "path/to/crl",
  1010  				SubjectAltNames:   []string{"SAN"},
  1011  				Sni:               "some-sni.com",
  1012  			},
  1013  			result: expectedResult{
  1014  				tlsContext: &tls.UpstreamTlsContext{
  1015  					CommonTlsContext: &tls.CommonTlsContext{
  1016  						TlsParams: &tls.TlsParameters{
  1017  							// if not specified, envoy use TLSv1_2 as default for client.
  1018  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
  1019  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
  1020  						},
  1021  						TlsCertificateSdsSecretConfigs: []*tls.SdsSecretConfig{
  1022  							{
  1023  								Name: fmt.Sprintf("file-cert:%s~%s", clientCert, clientKey),
  1024  								SdsConfig: &core.ConfigSource{
  1025  									ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
  1026  										ApiConfigSource: &core.ApiConfigSource{
  1027  											ApiType:                   core.ApiConfigSource_GRPC,
  1028  											SetNodeOnFirstMessageOnly: true,
  1029  											TransportApiVersion:       core.ApiVersion_V3,
  1030  											GrpcServices: []*core.GrpcService{
  1031  												{
  1032  													TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
  1033  														EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
  1034  													},
  1035  												},
  1036  											},
  1037  										},
  1038  									},
  1039  									ResourceApiVersion: core.ApiVersion_V3,
  1040  								},
  1041  							},
  1042  						},
  1043  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
  1044  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
  1045  								DefaultValidationContext: &tls.CertificateValidationContext{
  1046  									Crl: &core.DataSource{
  1047  										Specifier: &core.DataSource_Filename{
  1048  											Filename: "path/to/crl",
  1049  										},
  1050  									},
  1051  									MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"}),
  1052  								},
  1053  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
  1054  									Name: fmt.Sprintf("file-root:%s", rootCert),
  1055  									SdsConfig: &core.ConfigSource{
  1056  										ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
  1057  											ApiConfigSource: &core.ApiConfigSource{
  1058  												ApiType:                   core.ApiConfigSource_GRPC,
  1059  												SetNodeOnFirstMessageOnly: true,
  1060  												TransportApiVersion:       core.ApiVersion_V3,
  1061  												GrpcServices: []*core.GrpcService{
  1062  													{
  1063  														TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
  1064  															EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
  1065  														},
  1066  													},
  1067  												},
  1068  											},
  1069  										},
  1070  										ResourceApiVersion: core.ApiVersion_V3,
  1071  									},
  1072  								},
  1073  							},
  1074  						},
  1075  					},
  1076  					Sni: "some-sni.com",
  1077  				},
  1078  				err: nil,
  1079  			},
  1080  		},
  1081  		{
  1082  			name: "tls mode SIMPLE, with CredentialName specified",
  1083  			opts: &buildClusterOpts{
  1084  				mutable: newTestCluster(),
  1085  			},
  1086  			tls: &networking.ClientTLSSettings{
  1087  				Mode:            networking.ClientTLSSettings_SIMPLE,
  1088  				CredentialName:  credentialName,
  1089  				SubjectAltNames: []string{"SAN"},
  1090  				Sni:             "some-sni.com",
  1091  			},
  1092  			router: true,
  1093  			result: expectedResult{
  1094  				tlsContext: &tls.UpstreamTlsContext{
  1095  					CommonTlsContext: &tls.CommonTlsContext{
  1096  						TlsParams: &tls.TlsParameters{
  1097  							// if not specified, envoy use TLSv1_2 as default for client.
  1098  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
  1099  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
  1100  						},
  1101  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
  1102  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
  1103  								DefaultValidationContext: &tls.CertificateValidationContext{
  1104  									MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"}),
  1105  								},
  1106  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
  1107  									Name:      "kubernetes://" + credentialName + authn_model.SdsCaSuffix,
  1108  									SdsConfig: authn_model.SDSAdsConfig,
  1109  								},
  1110  							},
  1111  						},
  1112  					},
  1113  					Sni: "some-sni.com",
  1114  				},
  1115  				err: nil,
  1116  			},
  1117  		},
  1118  		{
  1119  			name: "tls mode SIMPLE, with CredentialName specified with h2 and no SAN",
  1120  			opts: &buildClusterOpts{
  1121  				mutable: newH2TestCluster(),
  1122  			},
  1123  			tls: &networking.ClientTLSSettings{
  1124  				Mode:           networking.ClientTLSSettings_SIMPLE,
  1125  				CredentialName: credentialName,
  1126  				Sni:            "some-sni.com",
  1127  			},
  1128  			h2:     true,
  1129  			router: true,
  1130  			result: expectedResult{
  1131  				tlsContext: &tls.UpstreamTlsContext{
  1132  					CommonTlsContext: &tls.CommonTlsContext{
  1133  						TlsParams: &tls.TlsParameters{
  1134  							// if not specified, envoy use TLSv1_2 as default for client.
  1135  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
  1136  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
  1137  						},
  1138  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
  1139  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
  1140  								DefaultValidationContext: &tls.CertificateValidationContext{},
  1141  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
  1142  									Name:      "kubernetes://" + credentialName + authn_model.SdsCaSuffix,
  1143  									SdsConfig: authn_model.SDSAdsConfig,
  1144  								},
  1145  							},
  1146  						},
  1147  						AlpnProtocols: util.ALPNH2Only,
  1148  					},
  1149  					Sni: "some-sni.com",
  1150  				},
  1151  				err: nil,
  1152  			},
  1153  		},
  1154  		{
  1155  			name: "tls mode MUTUAL, with CredentialName specified",
  1156  			opts: &buildClusterOpts{
  1157  				mutable: newTestCluster(),
  1158  			},
  1159  			tls: &networking.ClientTLSSettings{
  1160  				Mode:            networking.ClientTLSSettings_MUTUAL,
  1161  				CredentialName:  credentialName,
  1162  				SubjectAltNames: []string{"SAN"},
  1163  				Sni:             "some-sni.com",
  1164  			},
  1165  			router: true,
  1166  			result: expectedResult{
  1167  				tlsContext: &tls.UpstreamTlsContext{
  1168  					CommonTlsContext: &tls.CommonTlsContext{
  1169  						TlsParams: &tls.TlsParameters{
  1170  							// if not specified, envoy use TLSv1_2 as default for client.
  1171  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
  1172  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
  1173  						},
  1174  						TlsCertificateSdsSecretConfigs: []*tls.SdsSecretConfig{
  1175  							{
  1176  								Name:      "kubernetes://" + credentialName,
  1177  								SdsConfig: authn_model.SDSAdsConfig,
  1178  							},
  1179  						},
  1180  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
  1181  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
  1182  								DefaultValidationContext: &tls.CertificateValidationContext{
  1183  									MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"}),
  1184  								},
  1185  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
  1186  									Name:      "kubernetes://" + credentialName + authn_model.SdsCaSuffix,
  1187  									SdsConfig: authn_model.SDSAdsConfig,
  1188  								},
  1189  							},
  1190  						},
  1191  					},
  1192  					Sni: "some-sni.com",
  1193  				},
  1194  				err: nil,
  1195  			},
  1196  		},
  1197  		{
  1198  			name: "tls mode MUTUAL, with CredentialName specified with h2 and no SAN",
  1199  			opts: &buildClusterOpts{
  1200  				mutable: newH2TestCluster(),
  1201  			},
  1202  			tls: &networking.ClientTLSSettings{
  1203  				Mode:           networking.ClientTLSSettings_MUTUAL,
  1204  				CredentialName: credentialName,
  1205  				Sni:            "some-sni.com",
  1206  			},
  1207  			h2:     true,
  1208  			router: true,
  1209  			result: expectedResult{
  1210  				tlsContext: &tls.UpstreamTlsContext{
  1211  					CommonTlsContext: &tls.CommonTlsContext{
  1212  						TlsParams: &tls.TlsParameters{
  1213  							// if not specified, envoy use TLSv1_2 as default for client.
  1214  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
  1215  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
  1216  						},
  1217  						TlsCertificateSdsSecretConfigs: []*tls.SdsSecretConfig{
  1218  							{
  1219  								Name:      "kubernetes://" + credentialName,
  1220  								SdsConfig: authn_model.SDSAdsConfig,
  1221  							},
  1222  						},
  1223  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
  1224  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
  1225  								DefaultValidationContext: &tls.CertificateValidationContext{},
  1226  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
  1227  									Name:      "kubernetes://" + credentialName + authn_model.SdsCaSuffix,
  1228  									SdsConfig: authn_model.SDSAdsConfig,
  1229  								},
  1230  							},
  1231  						},
  1232  						AlpnProtocols: util.ALPNH2Only,
  1233  					},
  1234  					Sni: "some-sni.com",
  1235  				},
  1236  				err: nil,
  1237  			},
  1238  		},
  1239  		{
  1240  			name: "tls mode MUTUAL, credentialName is set with proxy type Sidecar",
  1241  			opts: &buildClusterOpts{
  1242  				mutable: newTestCluster(),
  1243  			},
  1244  			tls: &networking.ClientTLSSettings{
  1245  				Mode:           networking.ClientTLSSettings_MUTUAL,
  1246  				CredentialName: "fake-cred",
  1247  			},
  1248  			result: expectedResult{
  1249  				nil,
  1250  				nil,
  1251  			},
  1252  		},
  1253  		{
  1254  			name: "tls mode SIMPLE, credentialName is set with proxy type Sidecar",
  1255  			opts: &buildClusterOpts{
  1256  				mutable: newTestCluster(),
  1257  			},
  1258  			tls: &networking.ClientTLSSettings{
  1259  				Mode:           networking.ClientTLSSettings_SIMPLE,
  1260  				CredentialName: "fake-cred",
  1261  			},
  1262  			result: expectedResult{
  1263  				nil,
  1264  				nil,
  1265  			},
  1266  		},
  1267  		{
  1268  			name: "tls mode SIMPLE, CredentialName is set with proxy type Sidecar and destinationRule has workload Selector",
  1269  			opts: &buildClusterOpts{
  1270  				mutable:          newTestCluster(),
  1271  				isDrWithSelector: true,
  1272  			},
  1273  			tls: &networking.ClientTLSSettings{
  1274  				Mode:            networking.ClientTLSSettings_SIMPLE,
  1275  				CredentialName:  credentialName,
  1276  				SubjectAltNames: []string{"SAN"},
  1277  				Sni:             "some-sni.com",
  1278  			},
  1279  			result: expectedResult{
  1280  				tlsContext: &tls.UpstreamTlsContext{
  1281  					CommonTlsContext: &tls.CommonTlsContext{
  1282  						TlsParams: &tls.TlsParameters{
  1283  							// if not specified, envoy use TLSv1_2 as default for client.
  1284  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
  1285  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
  1286  						},
  1287  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
  1288  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
  1289  								DefaultValidationContext: &tls.CertificateValidationContext{
  1290  									MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"}),
  1291  								},
  1292  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
  1293  									Name:      "kubernetes://" + credentialName + authn_model.SdsCaSuffix,
  1294  									SdsConfig: authn_model.SDSAdsConfig,
  1295  								},
  1296  							},
  1297  						},
  1298  					},
  1299  					Sni: "some-sni.com",
  1300  				},
  1301  				err: nil,
  1302  			},
  1303  		},
  1304  		{
  1305  			name: "tls mode SIMPLE, with EcdhCurves specified in Mesh Config",
  1306  			opts: &buildClusterOpts{
  1307  				mutable:          newTestCluster(),
  1308  				isDrWithSelector: true,
  1309  				mesh: &meshconfig.MeshConfig{
  1310  					TlsDefaults: &meshconfig.MeshConfig_TLSConfig{
  1311  						EcdhCurves: []string{"P-256"},
  1312  					},
  1313  				},
  1314  			},
  1315  			tls: &networking.ClientTLSSettings{
  1316  				Mode:            networking.ClientTLSSettings_SIMPLE,
  1317  				CredentialName:  credentialName,
  1318  				SubjectAltNames: []string{"SAN"},
  1319  				Sni:             "some-sni.com",
  1320  			},
  1321  			result: expectedResult{
  1322  				tlsContext: &tls.UpstreamTlsContext{
  1323  					CommonTlsContext: &tls.CommonTlsContext{
  1324  						TlsParams: &tls.TlsParameters{
  1325  							// if not specified, envoy use TLSv1_2 as default for client.
  1326  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
  1327  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
  1328  							EcdhCurves:                []string{"P-256"},
  1329  						},
  1330  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
  1331  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
  1332  								DefaultValidationContext: &tls.CertificateValidationContext{
  1333  									MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"}),
  1334  								},
  1335  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
  1336  									Name:      "kubernetes://" + credentialName + authn_model.SdsCaSuffix,
  1337  									SdsConfig: authn_model.SDSAdsConfig,
  1338  								},
  1339  							},
  1340  						},
  1341  					},
  1342  					Sni: "some-sni.com",
  1343  				},
  1344  				err: nil,
  1345  			},
  1346  		},
  1347  		{
  1348  			name: "tls mode MUTUAL, with EcdhCurves specified in Mesh Config",
  1349  			opts: &buildClusterOpts{
  1350  				mutable:          newTestCluster(),
  1351  				isDrWithSelector: true,
  1352  				mesh: &meshconfig.MeshConfig{
  1353  					TlsDefaults: &meshconfig.MeshConfig_TLSConfig{
  1354  						EcdhCurves: []string{"P-256", "P-384"},
  1355  					},
  1356  				},
  1357  			},
  1358  			tls: &networking.ClientTLSSettings{
  1359  				Mode:            networking.ClientTLSSettings_MUTUAL,
  1360  				CredentialName:  credentialName,
  1361  				SubjectAltNames: []string{"SAN"},
  1362  				Sni:             "some-sni.com",
  1363  			},
  1364  			result: expectedResult{
  1365  				tlsContext: &tls.UpstreamTlsContext{
  1366  					CommonTlsContext: &tls.CommonTlsContext{
  1367  						TlsParams: &tls.TlsParameters{
  1368  							// if not specified, envoy use TLSv1_2 as default for client.
  1369  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
  1370  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
  1371  							EcdhCurves:                []string{"P-256", "P-384"},
  1372  						},
  1373  						TlsCertificateSdsSecretConfigs: []*tls.SdsSecretConfig{
  1374  							{
  1375  								Name:      "kubernetes://" + credentialName,
  1376  								SdsConfig: authn_model.SDSAdsConfig,
  1377  							},
  1378  						},
  1379  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
  1380  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
  1381  								DefaultValidationContext: &tls.CertificateValidationContext{
  1382  									MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"}),
  1383  								},
  1384  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
  1385  									Name:      "kubernetes://" + credentialName + authn_model.SdsCaSuffix,
  1386  									SdsConfig: authn_model.SDSAdsConfig,
  1387  								},
  1388  							},
  1389  						},
  1390  					},
  1391  					Sni: "some-sni.com",
  1392  				},
  1393  				err: nil,
  1394  			},
  1395  		},
  1396  		// ecdh curves from MeshConfig should be ignored for ISTIO_MUTUAL mode
  1397  		{
  1398  			name: "tls mode ISTIO_MUTUAL with EcdhCurves specified in Mesh Config",
  1399  			opts: &buildClusterOpts{
  1400  				mutable: newTestCluster(),
  1401  				mesh: &meshconfig.MeshConfig{
  1402  					TlsDefaults: &meshconfig.MeshConfig_TLSConfig{
  1403  						EcdhCurves: []string{"P-256", "P-384"},
  1404  					},
  1405  				},
  1406  			},
  1407  			tls: &networking.ClientTLSSettings{
  1408  				Mode:            networking.ClientTLSSettings_ISTIO_MUTUAL,
  1409  				SubjectAltNames: []string{"SAN"},
  1410  				Sni:             "some-sni.com",
  1411  			},
  1412  			result: expectedResult{
  1413  				tlsContext: &tls.UpstreamTlsContext{
  1414  					CommonTlsContext: &tls.CommonTlsContext{
  1415  						TlsParams: &tls.TlsParameters{
  1416  							// if not specified, envoy use TLSv1_2 as default for client.
  1417  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
  1418  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
  1419  						},
  1420  						TlsCertificateSdsSecretConfigs: []*tls.SdsSecretConfig{
  1421  							{
  1422  								Name: "default",
  1423  								SdsConfig: &core.ConfigSource{
  1424  									ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
  1425  										ApiConfigSource: &core.ApiConfigSource{
  1426  											ApiType:                   core.ApiConfigSource_GRPC,
  1427  											SetNodeOnFirstMessageOnly: true,
  1428  											TransportApiVersion:       core.ApiVersion_V3,
  1429  											GrpcServices: []*core.GrpcService{
  1430  												{
  1431  													TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
  1432  														EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
  1433  													},
  1434  												},
  1435  											},
  1436  										},
  1437  									},
  1438  									InitialFetchTimeout: durationpb.New(time.Second * 0),
  1439  									ResourceApiVersion:  core.ApiVersion_V3,
  1440  								},
  1441  							},
  1442  						},
  1443  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
  1444  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
  1445  								DefaultValidationContext: &tls.CertificateValidationContext{MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"})},
  1446  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
  1447  									Name: "ROOTCA",
  1448  									SdsConfig: &core.ConfigSource{
  1449  										ConfigSourceSpecifier: &core.ConfigSource_ApiConfigSource{
  1450  											ApiConfigSource: &core.ApiConfigSource{
  1451  												ApiType:                   core.ApiConfigSource_GRPC,
  1452  												SetNodeOnFirstMessageOnly: true,
  1453  												TransportApiVersion:       core.ApiVersion_V3,
  1454  												GrpcServices: []*core.GrpcService{
  1455  													{
  1456  														TargetSpecifier: &core.GrpcService_EnvoyGrpc_{
  1457  															EnvoyGrpc: &core.GrpcService_EnvoyGrpc{ClusterName: "sds-grpc"},
  1458  														},
  1459  													},
  1460  												},
  1461  											},
  1462  										},
  1463  										InitialFetchTimeout: durationpb.New(time.Second * 0),
  1464  										ResourceApiVersion:  core.ApiVersion_V3,
  1465  									},
  1466  								},
  1467  							},
  1468  						},
  1469  						AlpnProtocols: util.ALPNInMeshWithMxc,
  1470  					},
  1471  					Sni: "some-sni.com",
  1472  				},
  1473  				err: nil,
  1474  			},
  1475  		},
  1476  		{
  1477  			name: "tls mode MUTUAL, CredentialName is set with proxy type Sidecar and destinationRule has workload Selector",
  1478  			opts: &buildClusterOpts{
  1479  				mutable:          newTestCluster(),
  1480  				isDrWithSelector: true,
  1481  			},
  1482  			tls: &networking.ClientTLSSettings{
  1483  				Mode:            networking.ClientTLSSettings_MUTUAL,
  1484  				CredentialName:  credentialName,
  1485  				SubjectAltNames: []string{"SAN"},
  1486  				Sni:             "some-sni.com",
  1487  			},
  1488  			result: expectedResult{
  1489  				tlsContext: &tls.UpstreamTlsContext{
  1490  					CommonTlsContext: &tls.CommonTlsContext{
  1491  						TlsParams: &tls.TlsParameters{
  1492  							// if not specified, envoy use TLSv1_2 as default for client.
  1493  							TlsMaximumProtocolVersion: tls.TlsParameters_TLSv1_3,
  1494  							TlsMinimumProtocolVersion: tls.TlsParameters_TLSv1_2,
  1495  						},
  1496  						TlsCertificateSdsSecretConfigs: []*tls.SdsSecretConfig{
  1497  							{
  1498  								Name:      "kubernetes://" + credentialName,
  1499  								SdsConfig: authn_model.SDSAdsConfig,
  1500  							},
  1501  						},
  1502  						ValidationContextType: &tls.CommonTlsContext_CombinedValidationContext{
  1503  							CombinedValidationContext: &tls.CommonTlsContext_CombinedCertificateValidationContext{
  1504  								DefaultValidationContext: &tls.CertificateValidationContext{
  1505  									MatchSubjectAltNames: util.StringToExactMatch([]string{"SAN"}),
  1506  								},
  1507  								ValidationContextSdsSecretConfig: &tls.SdsSecretConfig{
  1508  									Name:      "kubernetes://" + credentialName + authn_model.SdsCaSuffix,
  1509  									SdsConfig: authn_model.SDSAdsConfig,
  1510  								},
  1511  							},
  1512  						},
  1513  					},
  1514  					Sni: "some-sni.com",
  1515  				},
  1516  				err: nil,
  1517  			},
  1518  		},
  1519  	}
  1520  	for _, tc := range testCases {
  1521  		t.Run(tc.name, func(t *testing.T) {
  1522  			test.SetForTest(t, &features.EnableAutoSni, tc.enableAutoSni)
  1523  			test.SetForTest(t, &features.VerifyCertAtClient, tc.enableVerifyCertAtClient)
  1524  			var proxy *model.Proxy
  1525  			if tc.router {
  1526  				proxy = newGatewayProxy()
  1527  			} else {
  1528  				proxy = newSidecarProxy()
  1529  			}
  1530  			cb := NewClusterBuilder(proxy, nil, model.DisabledCache{})
  1531  			if tc.h2 {
  1532  				setH2Options(tc.opts.mutable)
  1533  			}
  1534  			ret, err := cb.buildUpstreamClusterTLSContext(tc.opts, tc.tls)
  1535  			if err != nil && tc.result.err == nil || err == nil && tc.result.err != nil {
  1536  				t.Errorf("expecting:\n err=%v but got err=%v", tc.result.err, err)
  1537  			} else if diff := cmp.Diff(tc.result.tlsContext, ret, protocmp.Transform()); diff != "" {
  1538  				t.Errorf("got diff: `%v", diff)
  1539  			}
  1540  			if tc.enableAutoSni {
  1541  				if len(tc.tls.Sni) == 0 {
  1542  					assert.Equal(t, tc.opts.mutable.httpProtocolOptions.UpstreamHttpProtocolOptions.AutoSni, true)
  1543  				}
  1544  				if tc.enableVerifyCertAtClient && len(tc.tls.Sni) == 0 && len(tc.tls.SubjectAltNames) == 0 {
  1545  					assert.Equal(t, tc.opts.mutable.httpProtocolOptions.UpstreamHttpProtocolOptions.AutoSanValidation, true)
  1546  				}
  1547  			}
  1548  		})
  1549  	}
  1550  }
  1551  
  1552  func TestBuildAutoMtlsSettings(t *testing.T) {
  1553  	tlsSettings := &networking.ClientTLSSettings{
  1554  		Mode:            networking.ClientTLSSettings_ISTIO_MUTUAL,
  1555  		SubjectAltNames: []string{"custom.foo.com"},
  1556  		Sni:             "custom.foo.com",
  1557  	}
  1558  	tests := []struct {
  1559  		name            string
  1560  		tls             *networking.ClientTLSSettings
  1561  		sans            []string
  1562  		sni             string
  1563  		proxy           *model.Proxy
  1564  		autoMTLSEnabled bool
  1565  		meshExternal    bool
  1566  		serviceMTLSMode model.MutualTLSMode
  1567  		want            *networking.ClientTLSSettings
  1568  		wantCtxType     mtlsContextType
  1569  	}{
  1570  		{
  1571  			"Destination rule TLS sni and SAN override",
  1572  			tlsSettings,
  1573  			[]string{"spiffe://foo/serviceaccount/1"},
  1574  			"foo.com",
  1575  			&model.Proxy{Metadata: &model.NodeMetadata{}},
  1576  			false, false, model.MTLSUnknown,
  1577  			tlsSettings,
  1578  			userSupplied,
  1579  		},
  1580  		{
  1581  			"Metadata cert path override ISTIO_MUTUAL",
  1582  			tlsSettings,
  1583  			[]string{"custom.foo.com"},
  1584  			"custom.foo.com",
  1585  			&model.Proxy{Metadata: &model.NodeMetadata{
  1586  				TLSClientCertChain: "/custom/chain.pem",
  1587  				TLSClientKey:       "/custom/key.pem",
  1588  				TLSClientRootCert:  "/custom/root.pem",
  1589  			}},
  1590  			false, false, model.MTLSUnknown,
  1591  			&networking.ClientTLSSettings{
  1592  				Mode:              networking.ClientTLSSettings_MUTUAL,
  1593  				PrivateKey:        "/custom/key.pem",
  1594  				ClientCertificate: "/custom/chain.pem",
  1595  				CaCertificates:    "/custom/root.pem",
  1596  				SubjectAltNames:   []string{"custom.foo.com"},
  1597  				Sni:               "custom.foo.com",
  1598  			},
  1599  			userSupplied,
  1600  		},
  1601  		{
  1602  			"Auto fill nil settings when mTLS nil for internal service in strict mode",
  1603  			nil,
  1604  			[]string{"spiffe://foo/serviceaccount/1"},
  1605  			"foo.com",
  1606  			&model.Proxy{Metadata: &model.NodeMetadata{}},
  1607  			true, false, model.MTLSStrict,
  1608  			&networking.ClientTLSSettings{
  1609  				Mode:            networking.ClientTLSSettings_ISTIO_MUTUAL,
  1610  				SubjectAltNames: []string{"spiffe://foo/serviceaccount/1"},
  1611  				Sni:             "foo.com",
  1612  			},
  1613  			autoDetected,
  1614  		},
  1615  		{
  1616  			"Auto fill nil settings when mTLS nil for internal service in permissive mode",
  1617  			nil,
  1618  			[]string{"spiffe://foo/serviceaccount/1"},
  1619  			"foo.com",
  1620  			&model.Proxy{Metadata: &model.NodeMetadata{}},
  1621  			true, false, model.MTLSPermissive,
  1622  			&networking.ClientTLSSettings{
  1623  				Mode:            networking.ClientTLSSettings_ISTIO_MUTUAL,
  1624  				SubjectAltNames: []string{"spiffe://foo/serviceaccount/1"},
  1625  				Sni:             "foo.com",
  1626  			},
  1627  			autoDetected,
  1628  		},
  1629  		{
  1630  			"Auto fill nil settings when mTLS nil for internal service in plaintext mode",
  1631  			nil,
  1632  			[]string{"spiffe://foo/serviceaccount/1"},
  1633  			"foo.com",
  1634  			&model.Proxy{Metadata: &model.NodeMetadata{}},
  1635  			true, false, model.MTLSDisable,
  1636  			nil,
  1637  			userSupplied,
  1638  		},
  1639  		{
  1640  			"Auto fill nil settings when mTLS nil for internal service in unknown mode",
  1641  			nil,
  1642  			[]string{"spiffe://foo/serviceaccount/1"},
  1643  			"foo.com",
  1644  			&model.Proxy{Metadata: &model.NodeMetadata{}},
  1645  			true, false, model.MTLSUnknown,
  1646  			nil,
  1647  			userSupplied,
  1648  		},
  1649  		{
  1650  			"Do not auto fill nil settings for external",
  1651  			nil,
  1652  			[]string{"spiffe://foo/serviceaccount/1"},
  1653  			"foo.com",
  1654  			&model.Proxy{Metadata: &model.NodeMetadata{}},
  1655  			true, true, model.MTLSUnknown,
  1656  			nil,
  1657  			userSupplied,
  1658  		},
  1659  		{
  1660  			"Do not auto fill nil settings if server mTLS is disabled",
  1661  			nil,
  1662  			[]string{"spiffe://foo/serviceaccount/1"},
  1663  			"foo.com",
  1664  			&model.Proxy{Metadata: &model.NodeMetadata{}},
  1665  			false, false, model.MTLSDisable,
  1666  			nil,
  1667  			userSupplied,
  1668  		},
  1669  		{
  1670  			"TLS nil auto build tls with metadata cert path",
  1671  			nil,
  1672  			[]string{"spiffe://foo/serviceaccount/1"},
  1673  			"foo.com",
  1674  			&model.Proxy{Metadata: &model.NodeMetadata{
  1675  				TLSClientCertChain: "/custom/chain.pem",
  1676  				TLSClientKey:       "/custom/key.pem",
  1677  				TLSClientRootCert:  "/custom/root.pem",
  1678  			}},
  1679  			true, false, model.MTLSPermissive,
  1680  			&networking.ClientTLSSettings{
  1681  				Mode:              networking.ClientTLSSettings_MUTUAL,
  1682  				ClientCertificate: "/custom/chain.pem",
  1683  				PrivateKey:        "/custom/key.pem",
  1684  				CaCertificates:    "/custom/root.pem",
  1685  				SubjectAltNames:   []string{"spiffe://foo/serviceaccount/1"},
  1686  				Sni:               "foo.com",
  1687  			},
  1688  			autoDetected,
  1689  		},
  1690  		{
  1691  			"Simple TLS",
  1692  			&networking.ClientTLSSettings{
  1693  				Mode:              networking.ClientTLSSettings_SIMPLE,
  1694  				PrivateKey:        "/custom/key.pem",
  1695  				ClientCertificate: "/custom/chain.pem",
  1696  				CaCertificates:    "/custom/root.pem",
  1697  			},
  1698  			[]string{"custom.foo.com"},
  1699  			"custom.foo.com",
  1700  			&model.Proxy{Metadata: &model.NodeMetadata{
  1701  				TLSClientCertChain: "/custom/meta/chain.pem",
  1702  				TLSClientKey:       "/custom/meta/key.pem",
  1703  				TLSClientRootCert:  "/custom/meta/root.pem",
  1704  			}},
  1705  			false, false, model.MTLSUnknown,
  1706  			&networking.ClientTLSSettings{
  1707  				Mode:              networking.ClientTLSSettings_SIMPLE,
  1708  				PrivateKey:        "/custom/key.pem",
  1709  				ClientCertificate: "/custom/chain.pem",
  1710  				CaCertificates:    "/custom/root.pem",
  1711  			},
  1712  			userSupplied,
  1713  		},
  1714  	}
  1715  
  1716  	for _, tt := range tests {
  1717  		t.Run(tt.name, func(t *testing.T) {
  1718  			cb := NewClusterBuilder(tt.proxy, nil, nil)
  1719  			gotTLS, gotCtxType := cb.buildUpstreamTLSSettings(tt.tls, tt.sans, tt.sni, tt.autoMTLSEnabled, tt.meshExternal, tt.serviceMTLSMode)
  1720  			if !reflect.DeepEqual(gotTLS, tt.want) {
  1721  				t.Errorf("cluster TLS does not match expected result want %#v, got %#v", tt.want, gotTLS)
  1722  			}
  1723  			if gotCtxType != tt.wantCtxType {
  1724  				t.Errorf("cluster TLS context type does not match expected result want %#v, got %#v", tt.wantCtxType, gotCtxType)
  1725  			}
  1726  		})
  1727  	}
  1728  }