github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/xds/internal/balancer/cdsbalancer/cdsbalancer_security_test.go (about)

     1  /*
     2   * Copyright 2020 gRPC authors.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package cdsbalancer
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"regexp"
    24  	"testing"
    25  
    26  	"github.com/google/go-cmp/cmp"
    27  	"github.com/hxx258456/ccgo/grpc/attributes"
    28  	"github.com/hxx258456/ccgo/grpc/balancer"
    29  	"github.com/hxx258456/ccgo/grpc/credentials/local"
    30  	"github.com/hxx258456/ccgo/grpc/credentials/tls/certprovider"
    31  	"github.com/hxx258456/ccgo/grpc/credentials/xds"
    32  	"github.com/hxx258456/ccgo/grpc/internal"
    33  	xdscredsinternal "github.com/hxx258456/ccgo/grpc/internal/credentials/xds"
    34  	"github.com/hxx258456/ccgo/grpc/internal/testutils"
    35  	"github.com/hxx258456/ccgo/grpc/internal/xds/matcher"
    36  	"github.com/hxx258456/ccgo/grpc/resolver"
    37  	"github.com/hxx258456/ccgo/grpc/xds/internal/testutils/fakeclient"
    38  	"github.com/hxx258456/ccgo/grpc/xds/internal/xdsclient/bootstrap"
    39  	"github.com/hxx258456/ccgo/grpc/xds/internal/xdsclient/xdsresource"
    40  )
    41  
    42  const (
    43  	fakeProvider1Name = "fake-certificate-provider-1"
    44  	fakeProvider2Name = "fake-certificate-provider-2"
    45  	fakeConfig        = "my fake config"
    46  	testSAN           = "test-san"
    47  )
    48  
    49  var (
    50  	testSANMatchers = []matcher.StringMatcher{
    51  		matcher.StringMatcherForTesting(newStringP(testSAN), nil, nil, nil, nil, true),
    52  		matcher.StringMatcherForTesting(nil, newStringP(testSAN), nil, nil, nil, false),
    53  		matcher.StringMatcherForTesting(nil, nil, newStringP(testSAN), nil, nil, false),
    54  		matcher.StringMatcherForTesting(nil, nil, nil, nil, regexp.MustCompile(testSAN), false),
    55  		matcher.StringMatcherForTesting(nil, nil, nil, newStringP(testSAN), nil, false),
    56  	}
    57  	fpb1, fpb2                   *fakeProviderBuilder
    58  	bootstrapConfig              *bootstrap.Config
    59  	cdsUpdateWithGoodSecurityCfg = xdsresource.ClusterUpdate{
    60  		ClusterName: serviceName,
    61  		SecurityCfg: &xdsresource.SecurityConfig{
    62  			RootInstanceName:       "default1",
    63  			IdentityInstanceName:   "default2",
    64  			SubjectAltNameMatchers: testSANMatchers,
    65  		},
    66  	}
    67  	cdsUpdateWithMissingSecurityCfg = xdsresource.ClusterUpdate{
    68  		ClusterName: serviceName,
    69  		SecurityCfg: &xdsresource.SecurityConfig{
    70  			RootInstanceName: "not-default",
    71  		},
    72  	}
    73  )
    74  
    75  func newStringP(s string) *string {
    76  	return &s
    77  }
    78  
    79  func init() {
    80  	fpb1 = &fakeProviderBuilder{name: fakeProvider1Name}
    81  	fpb2 = &fakeProviderBuilder{name: fakeProvider2Name}
    82  	cfg1, _ := fpb1.ParseConfig(fakeConfig + "1111")
    83  	cfg2, _ := fpb2.ParseConfig(fakeConfig + "2222")
    84  	bootstrapConfig = &bootstrap.Config{
    85  		CertProviderConfigs: map[string]*certprovider.BuildableConfig{
    86  			"default1": cfg1,
    87  			"default2": cfg2,
    88  		},
    89  	}
    90  	certprovider.Register(fpb1)
    91  	certprovider.Register(fpb2)
    92  }
    93  
    94  // fakeProviderBuilder builds new instances of fakeProvider and interprets the
    95  // config provided to it as a string.
    96  type fakeProviderBuilder struct {
    97  	name string
    98  }
    99  
   100  func (b *fakeProviderBuilder) ParseConfig(config interface{}) (*certprovider.BuildableConfig, error) {
   101  	s, ok := config.(string)
   102  	if !ok {
   103  		return nil, fmt.Errorf("providerBuilder %s received config of type %T, want string", b.name, config)
   104  	}
   105  	return certprovider.NewBuildableConfig(b.name, []byte(s), func(certprovider.BuildOptions) certprovider.Provider {
   106  		return &fakeProvider{
   107  			Distributor: certprovider.NewDistributor(),
   108  			config:      s,
   109  		}
   110  	}), nil
   111  }
   112  
   113  func (b *fakeProviderBuilder) Name() string {
   114  	return b.name
   115  }
   116  
   117  // fakeProvider is an implementation of the Provider interface which provides a
   118  // method for tests to invoke to push new key materials.
   119  type fakeProvider struct {
   120  	*certprovider.Distributor
   121  	config string
   122  }
   123  
   124  // Close helps implement the Provider interface.
   125  func (p *fakeProvider) Close() {
   126  	p.Distributor.Stop()
   127  }
   128  
   129  // setupWithXDSCreds performs all the setup steps required for tests which use
   130  // xDSCredentials.
   131  func setupWithXDSCreds(t *testing.T) (*fakeclient.Client, *cdsBalancer, *testEDSBalancer, *testutils.TestClientConn, func()) {
   132  	t.Helper()
   133  	xdsC := fakeclient.NewClient()
   134  	builder := balancer.Get(cdsName)
   135  	if builder == nil {
   136  		t.Fatalf("balancer.Get(%q) returned nil", cdsName)
   137  	}
   138  	// Create and pass xdsCredentials while building the CDS balancer.
   139  	creds, err := xds.NewClientCredentials(xds.ClientOptions{
   140  		FallbackCreds: local.NewCredentials(), // Placeholder fallback credentials.
   141  	})
   142  	if err != nil {
   143  		t.Fatalf("Failed to create xDS client creds: %v", err)
   144  	}
   145  	// Create a new CDS balancer and pass it a fake balancer.ClientConn which we
   146  	// can use to inspect the different calls made by the balancer.
   147  	tcc := testutils.NewTestClientConn(t)
   148  	cdsB := builder.Build(tcc, balancer.BuildOptions{DialCreds: creds})
   149  
   150  	// Override the creation of the EDS balancer to return a fake EDS balancer
   151  	// implementation.
   152  	edsB := newTestEDSBalancer()
   153  	oldEDSBalancerBuilder := newChildBalancer
   154  	newChildBalancer = func(cc balancer.ClientConn, opts balancer.BuildOptions) (balancer.Balancer, error) {
   155  		edsB.parentCC = cc
   156  		return edsB, nil
   157  	}
   158  
   159  	// Push a ClientConnState update to the CDS balancer with a cluster name.
   160  	if err := cdsB.UpdateClientConnState(cdsCCS(clusterName, xdsC)); err != nil {
   161  		t.Fatalf("cdsBalancer.UpdateClientConnState failed with error: %v", err)
   162  	}
   163  
   164  	// Make sure the CDS balancer registers a Cluster watch with the xDS client
   165  	// passed via attributes in the above update.
   166  	ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   167  	defer ctxCancel()
   168  	gotCluster, err := xdsC.WaitForWatchCluster(ctx)
   169  	if err != nil {
   170  		t.Fatalf("xdsClient.WatchCDS failed with error: %v", err)
   171  	}
   172  	if gotCluster != clusterName {
   173  		t.Fatalf("xdsClient.WatchCDS called for cluster: %v, want: %v", gotCluster, clusterName)
   174  	}
   175  
   176  	return xdsC, cdsB.(*cdsBalancer), edsB, tcc, func() {
   177  		newChildBalancer = oldEDSBalancerBuilder
   178  		xdsC.Close()
   179  	}
   180  }
   181  
   182  // makeNewSubConn invokes the NewSubConn() call on the balancer.ClientConn
   183  // passed to the EDS balancer, and verifies that the CDS balancer forwards the
   184  // call appropriately to its parent balancer.ClientConn with or without
   185  // attributes bases on the value of wantFallback.
   186  func makeNewSubConn(ctx context.Context, edsCC balancer.ClientConn, parentCC *testutils.TestClientConn, wantFallback bool) (balancer.SubConn, error) {
   187  	dummyAddr := "foo-address"
   188  	addrs := []resolver.Address{{Addr: dummyAddr}}
   189  	sc, err := edsCC.NewSubConn(addrs, balancer.NewSubConnOptions{})
   190  	if err != nil {
   191  		return nil, fmt.Errorf("NewSubConn(%+v) on parent ClientConn failed: %v", addrs, err)
   192  	}
   193  
   194  	select {
   195  	case <-ctx.Done():
   196  		return nil, errors.New("timeout when waiting for new SubConn")
   197  	case gotAddrs := <-parentCC.NewSubConnAddrsCh:
   198  		if len(gotAddrs) != 1 {
   199  			return nil, fmt.Errorf("NewSubConn expected 1 address, got %d", len(gotAddrs))
   200  		}
   201  		if got, want := gotAddrs[0].Addr, addrs[0].Addr; got != want {
   202  			return nil, fmt.Errorf("resolver.Address passed to parent ClientConn has address %q, want %q", got, want)
   203  		}
   204  		getHI := internal.GetXDSHandshakeInfoForTesting.(func(attr *attributes.Attributes) *xdscredsinternal.HandshakeInfo)
   205  		hi := getHI(gotAddrs[0].Attributes)
   206  		if hi == nil {
   207  			return nil, errors.New("resolver.Address passed to parent ClientConn doesn't contain attributes")
   208  		}
   209  		if gotFallback := hi.UseFallbackCreds(); gotFallback != wantFallback {
   210  			return nil, fmt.Errorf("resolver.Address HandshakeInfo uses fallback creds? %v, want %v", gotFallback, wantFallback)
   211  		}
   212  		if !wantFallback {
   213  			if diff := cmp.Diff(testSANMatchers, hi.GetSANMatchersForTesting(), cmp.AllowUnexported(regexp.Regexp{})); diff != "" {
   214  				return nil, fmt.Errorf("unexpected diff in the list of SAN matchers (-got, +want):\n%s", diff)
   215  			}
   216  		}
   217  	}
   218  	return sc, nil
   219  }
   220  
   221  // TestSecurityConfigWithoutXDSCreds tests the case where xdsCredentials are not
   222  // in use, but the CDS balancer receives a Cluster update with security
   223  // configuration. Verifies that no certificate providers are created, and that
   224  // the address attributes added as part of the intercepted NewSubConn() method
   225  // indicate the use of fallback credentials.
   226  func (s) TestSecurityConfigWithoutXDSCreds(t *testing.T) {
   227  	// This creates a CDS balancer, pushes a ClientConnState update with a fake
   228  	// xdsClient, and makes sure that the CDS balancer registers a watch on the
   229  	// provided xdsClient.
   230  	xdsC, cdsB, edsB, tcc, cancel := setupWithWatch(t)
   231  	defer func() {
   232  		cancel()
   233  		cdsB.Close()
   234  	}()
   235  
   236  	// Override the provider builder function to push on a channel. We do not
   237  	// expect this function to be called as part of this test.
   238  	providerCh := testutils.NewChannel()
   239  	origBuildProvider := buildProvider
   240  	buildProvider = func(c map[string]*certprovider.BuildableConfig, id, cert string, wi, wr bool) (certprovider.Provider, error) {
   241  		p, err := origBuildProvider(c, id, cert, wi, wr)
   242  		providerCh.Send(nil)
   243  		return p, err
   244  	}
   245  	defer func() { buildProvider = origBuildProvider }()
   246  
   247  	// Here we invoke the watch callback registered on the fake xdsClient. This
   248  	// will trigger the watch handler on the CDS balancer, which will attempt to
   249  	// create a new EDS balancer. The fake EDS balancer created above will be
   250  	// returned to the CDS balancer, because we have overridden the
   251  	// newChildBalancer function as part of test setup.
   252  	cdsUpdate := xdsresource.ClusterUpdate{ClusterName: serviceName}
   253  	wantCCS := edsCCS(serviceName, nil, false, nil)
   254  	ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   255  	defer ctxCancel()
   256  	if err := invokeWatchCbAndWait(ctx, xdsC, cdsWatchInfo{cdsUpdate, nil}, wantCCS, edsB); err != nil {
   257  		t.Fatal(err)
   258  	}
   259  
   260  	// Make a NewSubConn and verify that the HandshakeInfo does not contain any
   261  	// certificate providers, forcing the credentials implementation to use
   262  	// fallback creds.
   263  	if _, err := makeNewSubConn(ctx, edsB.parentCC, tcc, true); err != nil {
   264  		t.Fatal(err)
   265  	}
   266  
   267  	// Again, since xdsCredentials are not in use, no certificate providers
   268  	// should have been initialized by the CDS balancer.
   269  	sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout)
   270  	defer sCancel()
   271  	if _, err := providerCh.Receive(sCtx); err != context.DeadlineExceeded {
   272  		t.Fatal("cds balancer created certificate providers when not using xds credentials")
   273  	}
   274  }
   275  
   276  // TestNoSecurityConfigWithXDSCreds tests the case where xdsCredentials are in
   277  // use, but the CDS balancer receives a Cluster update without security
   278  // configuration. Verifies that no certificate providers are created, and that
   279  // the address attributes added as part of the intercepted NewSubConn() method
   280  // indicate the use of fallback credentials.
   281  func (s) TestNoSecurityConfigWithXDSCreds(t *testing.T) {
   282  	// This creates a CDS balancer which uses xdsCredentials, pushes a
   283  	// ClientConnState update with a fake xdsClient, and makes sure that the CDS
   284  	// balancer registers a watch on the provided xdsClient.
   285  	xdsC, cdsB, edsB, tcc, cancel := setupWithXDSCreds(t)
   286  	defer func() {
   287  		cancel()
   288  		cdsB.Close()
   289  	}()
   290  
   291  	// Override the provider builder function to push on a channel. We do not
   292  	// expect this function to be called as part of this test.
   293  	providerCh := testutils.NewChannel()
   294  	origBuildProvider := buildProvider
   295  	buildProvider = func(c map[string]*certprovider.BuildableConfig, id, cert string, wi, wr bool) (certprovider.Provider, error) {
   296  		p, err := origBuildProvider(c, id, cert, wi, wr)
   297  		providerCh.Send(nil)
   298  		return p, err
   299  	}
   300  	defer func() { buildProvider = origBuildProvider }()
   301  
   302  	// Here we invoke the watch callback registered on the fake xdsClient. This
   303  	// will trigger the watch handler on the CDS balancer, which will attempt to
   304  	// create a new EDS balancer. The fake EDS balancer created above will be
   305  	// returned to the CDS balancer, because we have overridden the
   306  	// newChildBalancer function as part of test setup. No security config is
   307  	// passed to the CDS balancer as part of this update.
   308  	cdsUpdate := xdsresource.ClusterUpdate{ClusterName: serviceName}
   309  	wantCCS := edsCCS(serviceName, nil, false, nil)
   310  	ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   311  	defer ctxCancel()
   312  	if err := invokeWatchCbAndWait(ctx, xdsC, cdsWatchInfo{cdsUpdate, nil}, wantCCS, edsB); err != nil {
   313  		t.Fatal(err)
   314  	}
   315  
   316  	// Make a NewSubConn and verify that the HandshakeInfo does not contain any
   317  	// certificate providers, forcing the credentials implementation to use
   318  	// fallback creds.
   319  	if _, err := makeNewSubConn(ctx, edsB.parentCC, tcc, true); err != nil {
   320  		t.Fatal(err)
   321  	}
   322  
   323  	// Again, since no security configuration was received, no certificate
   324  	// providers should have been initialized by the CDS balancer.
   325  	sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout)
   326  	defer sCancel()
   327  	if _, err := providerCh.Receive(sCtx); err != context.DeadlineExceeded {
   328  		t.Fatal("cds balancer created certificate providers when not using xds credentials")
   329  	}
   330  }
   331  
   332  // TestSecurityConfigNotFoundInBootstrap tests the case where the security
   333  // config returned by the xDS server cannot be resolved based on the contents of
   334  // the bootstrap config. Verifies that the balancer puts the channel in a failed
   335  // state, and returns an error picker.
   336  func (s) TestSecurityConfigNotFoundInBootstrap(t *testing.T) {
   337  	// We test two cases here:
   338  	// 0: Bootstrap contains security config. But received plugin instance name
   339  	//    is not found in the bootstrap config.
   340  	// 1: Bootstrap contains no security config.
   341  	for i := 0; i < 2; i++ {
   342  		// This creates a CDS balancer which uses xdsCredentials, pushes a
   343  		// ClientConnState update with a fake xdsClient, and makes sure that the CDS
   344  		// balancer registers a watch on the provided xdsClient.
   345  		xdsC, cdsB, edsB, tcc, cancel := setupWithXDSCreds(t)
   346  		defer func() {
   347  			cancel()
   348  			cdsB.Close()
   349  		}()
   350  
   351  		if i == 0 {
   352  			// Set the bootstrap config used by the fake client.
   353  			xdsC.SetBootstrapConfig(bootstrapConfig)
   354  		}
   355  
   356  		// Here we invoke the watch callback registered on the fake xdsClient. A bad
   357  		// security config is passed here. So, we expect the CDS balancer to not
   358  		// create an EDS balancer and instead reject this update and put the channel
   359  		// in a bad state.
   360  		xdsC.InvokeWatchClusterCallback(cdsUpdateWithMissingSecurityCfg, nil)
   361  
   362  		// The CDS balancer has not yet created an EDS balancer. So, this bad
   363  		// watcher update should not be forwarded forwarded to our fake EDS balancer
   364  		// as an error.
   365  		sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout)
   366  		defer sCancel()
   367  		if err := edsB.waitForResolverError(sCtx, nil); err != context.DeadlineExceeded {
   368  			t.Fatal("eds balancer shouldn't get error (shouldn't be built yet)")
   369  		}
   370  
   371  		// Make sure the CDS balancer reports an error picker.
   372  		ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   373  		defer ctxCancel()
   374  		if err := tcc.WaitForErrPicker(ctx); err != nil {
   375  			t.Fatal(err)
   376  		}
   377  	}
   378  }
   379  
   380  // TestCertproviderStoreError tests the case where the certprovider.Store
   381  // returns an error when the CDS balancer attempts to create a provider.
   382  func (s) TestCertproviderStoreError(t *testing.T) {
   383  	// This creates a CDS balancer which uses xdsCredentials, pushes a
   384  	// ClientConnState update with a fake xdsClient, and makes sure that the CDS
   385  	// balancer registers a watch on the provided xdsClient.
   386  	xdsC, cdsB, edsB, tcc, cancel := setupWithXDSCreds(t)
   387  	defer func() {
   388  		cancel()
   389  		cdsB.Close()
   390  	}()
   391  
   392  	// Override the provider builder function to return an error.
   393  	origBuildProvider := buildProvider
   394  	buildProvider = func(c map[string]*certprovider.BuildableConfig, id, cert string, wi, wr bool) (certprovider.Provider, error) {
   395  		return nil, errors.New("certprovider store error")
   396  	}
   397  	defer func() { buildProvider = origBuildProvider }()
   398  
   399  	// Set the bootstrap config used by the fake client.
   400  	xdsC.SetBootstrapConfig(bootstrapConfig)
   401  
   402  	// Here we invoke the watch callback registered on the fake xdsClient. Even
   403  	// though the received update is good, the certprovider.Store is configured
   404  	// to return an error. So, CDS balancer should reject this config and report
   405  	// an error.
   406  	xdsC.InvokeWatchClusterCallback(cdsUpdateWithGoodSecurityCfg, nil)
   407  
   408  	// The CDS balancer has not yet created an EDS balancer. So, this bad
   409  	// watcher update should not be forwarded forwarded to our fake EDS balancer
   410  	// as an error.
   411  	sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout)
   412  	defer sCancel()
   413  	if err := edsB.waitForResolverError(sCtx, nil); err != context.DeadlineExceeded {
   414  		t.Fatal("eds balancer shouldn't get error (shouldn't be built yet)")
   415  	}
   416  
   417  	// Make sure the CDS balancer reports an error picker.
   418  	ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   419  	defer ctxCancel()
   420  	if err := tcc.WaitForErrPicker(ctx); err != nil {
   421  		t.Fatal(err)
   422  	}
   423  }
   424  
   425  func (s) TestSecurityConfigUpdate_BadToGood(t *testing.T) {
   426  	// This creates a CDS balancer which uses xdsCredentials, pushes a
   427  	// ClientConnState update with a fake xdsClient, and makes sure that the CDS
   428  	// balancer registers a watch on the provided xdsClient.
   429  	xdsC, cdsB, edsB, tcc, cancel := setupWithXDSCreds(t)
   430  	defer func() {
   431  		cancel()
   432  		cdsB.Close()
   433  	}()
   434  
   435  	// Set the bootstrap config used by the fake client.
   436  	xdsC.SetBootstrapConfig(bootstrapConfig)
   437  
   438  	// Here we invoke the watch callback registered on the fake xdsClient. A bad
   439  	// security config is passed here. So, we expect the CDS balancer to not
   440  	// create an EDS balancer and instead reject this update and put the channel
   441  	// in a bad state.
   442  	xdsC.InvokeWatchClusterCallback(cdsUpdateWithMissingSecurityCfg, nil)
   443  
   444  	// The CDS balancer has not yet created an EDS balancer. So, this bad
   445  	// watcher update should not be forwarded forwarded to our fake EDS balancer
   446  	// as an error.
   447  	sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout)
   448  	defer sCancel()
   449  	if err := edsB.waitForResolverError(sCtx, nil); err != context.DeadlineExceeded {
   450  		t.Fatal("eds balancer shouldn't get error (shouldn't be built yet)")
   451  	}
   452  
   453  	// Make sure the CDS balancer reports an error picker.
   454  	ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   455  	defer ctxCancel()
   456  	if err := tcc.WaitForErrPicker(ctx); err != nil {
   457  		t.Fatal(err)
   458  	}
   459  
   460  	// Here we invoke the watch callback registered on the fake xdsClient. This
   461  	// will trigger the watch handler on the CDS balancer, which will attempt to
   462  	// create a new EDS balancer. The fake EDS balancer created above will be
   463  	// returned to the CDS balancer, because we have overridden the
   464  	// newChildBalancer function as part of test setup.
   465  	wantCCS := edsCCS(serviceName, nil, false, nil)
   466  	if err := invokeWatchCbAndWait(ctx, xdsC, cdsWatchInfo{cdsUpdateWithGoodSecurityCfg, nil}, wantCCS, edsB); err != nil {
   467  		t.Fatal(err)
   468  	}
   469  
   470  	// Make a NewSubConn and verify that attributes are added.
   471  	if _, err := makeNewSubConn(ctx, edsB.parentCC, tcc, false); err != nil {
   472  		t.Fatal(err)
   473  	}
   474  }
   475  
   476  // TestGoodSecurityConfig tests the case where the CDS balancer receives
   477  // security configuration as part of the Cluster resource which can be
   478  // successfully resolved using the bootstrap file contents. Verifies that
   479  // certificate providers are created, and that the NewSubConn() call adds
   480  // appropriate address attributes.
   481  func (s) TestGoodSecurityConfig(t *testing.T) {
   482  	// This creates a CDS balancer which uses xdsCredentials, pushes a
   483  	// ClientConnState update with a fake xdsClient, and makes sure that the CDS
   484  	// balancer registers a watch on the provided xdsClient.
   485  	xdsC, cdsB, edsB, tcc, cancel := setupWithXDSCreds(t)
   486  	defer func() {
   487  		cancel()
   488  		cdsB.Close()
   489  	}()
   490  
   491  	// Set the bootstrap config used by the fake client.
   492  	xdsC.SetBootstrapConfig(bootstrapConfig)
   493  
   494  	// Here we invoke the watch callback registered on the fake xdsClient. This
   495  	// will trigger the watch handler on the CDS balancer, which will attempt to
   496  	// create a new EDS balancer. The fake EDS balancer created above will be
   497  	// returned to the CDS balancer, because we have overridden the
   498  	// newChildBalancer function as part of test setup.
   499  	wantCCS := edsCCS(serviceName, nil, false, nil)
   500  	ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   501  	defer ctxCancel()
   502  	if err := invokeWatchCbAndWait(ctx, xdsC, cdsWatchInfo{cdsUpdateWithGoodSecurityCfg, nil}, wantCCS, edsB); err != nil {
   503  		t.Fatal(err)
   504  	}
   505  
   506  	// Make a NewSubConn and verify that attributes are added.
   507  	sc, err := makeNewSubConn(ctx, edsB.parentCC, tcc, false)
   508  	if err != nil {
   509  		t.Fatal(err)
   510  	}
   511  
   512  	// Invoke UpdateAddresses and verify that attributes are added.
   513  	dummyAddr := "bar-address"
   514  	addrs := []resolver.Address{{Addr: dummyAddr}}
   515  	edsB.parentCC.UpdateAddresses(sc, addrs)
   516  	select {
   517  	case <-ctx.Done():
   518  		t.Fatal("timeout when waiting for addresses to be updated on the subConn")
   519  	case gotAddrs := <-tcc.UpdateAddressesAddrsCh:
   520  		if len(gotAddrs) != 1 {
   521  			t.Fatalf("UpdateAddresses expected 1 address, got %d", len(gotAddrs))
   522  		}
   523  		if got, want := gotAddrs[0].Addr, addrs[0].Addr; got != want {
   524  			t.Fatalf("resolver.Address passed to parent ClientConn through UpdateAddresses() has address %q, want %q", got, want)
   525  		}
   526  		getHI := internal.GetXDSHandshakeInfoForTesting.(func(attr *attributes.Attributes) *xdscredsinternal.HandshakeInfo)
   527  		hi := getHI(gotAddrs[0].Attributes)
   528  		if hi == nil {
   529  			t.Fatal("resolver.Address passed to parent ClientConn through UpdateAddresses() doesn't contain attributes")
   530  		}
   531  	}
   532  }
   533  
   534  func (s) TestSecurityConfigUpdate_GoodToFallback(t *testing.T) {
   535  	// This creates a CDS balancer which uses xdsCredentials, pushes a
   536  	// ClientConnState update with a fake xdsClient, and makes sure that the CDS
   537  	// balancer registers a watch on the provided xdsClient.
   538  	xdsC, cdsB, edsB, tcc, cancel := setupWithXDSCreds(t)
   539  	defer func() {
   540  		cancel()
   541  		cdsB.Close()
   542  	}()
   543  
   544  	// Set the bootstrap config used by the fake client.
   545  	xdsC.SetBootstrapConfig(bootstrapConfig)
   546  
   547  	// Here we invoke the watch callback registered on the fake xdsClient. This
   548  	// will trigger the watch handler on the CDS balancer, which will attempt to
   549  	// create a new EDS balancer. The fake EDS balancer created above will be
   550  	// returned to the CDS balancer, because we have overridden the
   551  	// newChildBalancer function as part of test setup.
   552  	wantCCS := edsCCS(serviceName, nil, false, nil)
   553  	ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   554  	defer ctxCancel()
   555  	if err := invokeWatchCbAndWait(ctx, xdsC, cdsWatchInfo{cdsUpdateWithGoodSecurityCfg, nil}, wantCCS, edsB); err != nil {
   556  		t.Fatal(err)
   557  	}
   558  
   559  	// Make a NewSubConn and verify that attributes are added.
   560  	if _, err := makeNewSubConn(ctx, edsB.parentCC, tcc, false); err != nil {
   561  		t.Fatal(err)
   562  	}
   563  
   564  	// Here we invoke the watch callback registered on the fake xdsClient with
   565  	// an update which contains bad security config. So, we expect the CDS
   566  	// balancer to forward this error to the EDS balancer and eventually the
   567  	// channel needs to be put in a bad state.
   568  	cdsUpdate := xdsresource.ClusterUpdate{ClusterName: serviceName}
   569  	if err := invokeWatchCbAndWait(ctx, xdsC, cdsWatchInfo{cdsUpdate, nil}, wantCCS, edsB); err != nil {
   570  		t.Fatal(err)
   571  	}
   572  
   573  	// Make a NewSubConn and verify that fallback creds are used.
   574  	if _, err := makeNewSubConn(ctx, edsB.parentCC, tcc, true); err != nil {
   575  		t.Fatal(err)
   576  	}
   577  }
   578  
   579  // TestSecurityConfigUpdate_GoodToBad tests the case where the first security
   580  // config returned by the xDS server is successful, but the second update cannot
   581  // be resolved based on the contents of the bootstrap config. Verifies that the
   582  // error is forwarded to the EDS balancer (which was created as part of the
   583  // first successful update).
   584  func (s) TestSecurityConfigUpdate_GoodToBad(t *testing.T) {
   585  	// This creates a CDS balancer which uses xdsCredentials, pushes a
   586  	// ClientConnState update with a fake xdsClient, and makes sure that the CDS
   587  	// balancer registers a watch on the provided xdsClient.
   588  	xdsC, cdsB, edsB, tcc, cancel := setupWithXDSCreds(t)
   589  	defer func() {
   590  		cancel()
   591  		cdsB.Close()
   592  	}()
   593  
   594  	// Set the bootstrap config used by the fake client.
   595  	xdsC.SetBootstrapConfig(bootstrapConfig)
   596  
   597  	// Here we invoke the watch callback registered on the fake xdsClient. This
   598  	// will trigger the watch handler on the CDS balancer, which will attempt to
   599  	// create a new EDS balancer. The fake EDS balancer created above will be
   600  	// returned to the CDS balancer, because we have overridden the
   601  	// newChildBalancer function as part of test setup.
   602  	wantCCS := edsCCS(serviceName, nil, false, nil)
   603  	ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   604  	defer ctxCancel()
   605  	if err := invokeWatchCbAndWait(ctx, xdsC, cdsWatchInfo{cdsUpdateWithGoodSecurityCfg, nil}, wantCCS, edsB); err != nil {
   606  		t.Fatal(err)
   607  	}
   608  
   609  	// Make a NewSubConn and verify that attributes are added.
   610  	if _, err := makeNewSubConn(ctx, edsB.parentCC, tcc, false); err != nil {
   611  		t.Fatal(err)
   612  	}
   613  
   614  	// Here we invoke the watch callback registered on the fake xdsClient with
   615  	// an update which contains bad security config. So, we expect the CDS
   616  	// balancer to forward this error to the EDS balancer and eventually the
   617  	// channel needs to be put in a bad state.
   618  	xdsC.InvokeWatchClusterCallback(cdsUpdateWithMissingSecurityCfg, nil)
   619  
   620  	// We manually check that an error is forwarded to the EDS balancer instead
   621  	// of using one of the helper methods on the testEDSBalancer, because all we
   622  	// care here is whether an error is sent to it or not. We don't care about
   623  	// the exact error.
   624  	gotErr, err := edsB.resolverErrCh.Receive(ctx)
   625  	if err != nil {
   626  		t.Fatal("timeout waiting for CDS balancer to forward error to EDS balancer upon receipt of bad security config")
   627  	}
   628  	if gotErr == nil {
   629  		t.Fatal("CDS balancer did not forward error to EDS balancer upon receipt of bad security config")
   630  	}
   631  
   632  	// Since the error being pushed here is not a resource-not-found-error, the
   633  	// registered watch should not be cancelled.
   634  	sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout)
   635  	defer sCancel()
   636  	if _, err := xdsC.WaitForCancelClusterWatch(sCtx); err != context.DeadlineExceeded {
   637  		t.Fatal("cluster watch cancelled for a non-resource-not-found-error")
   638  	}
   639  }
   640  
   641  // TestSecurityConfigUpdate_GoodToGood tests the case where the CDS balancer
   642  // receives two different but successful updates with security configuration.
   643  // Verifies that appropriate providers are created, and that address attributes
   644  // are added.
   645  func (s) TestSecurityConfigUpdate_GoodToGood(t *testing.T) {
   646  	// This creates a CDS balancer which uses xdsCredentials, pushes a
   647  	// ClientConnState update with a fake xdsClient, and makes sure that the CDS
   648  	// balancer registers a watch on the provided xdsClient.
   649  	xdsC, cdsB, edsB, tcc, cancel := setupWithXDSCreds(t)
   650  	defer func() {
   651  		cancel()
   652  		cdsB.Close()
   653  	}()
   654  
   655  	// Override the provider builder function to push on a channel.
   656  	providerCh := testutils.NewChannel()
   657  	origBuildProvider := buildProvider
   658  	buildProvider = func(c map[string]*certprovider.BuildableConfig, id, cert string, wi, wr bool) (certprovider.Provider, error) {
   659  		p, err := origBuildProvider(c, id, cert, wi, wr)
   660  		providerCh.Send(nil)
   661  		return p, err
   662  	}
   663  	defer func() { buildProvider = origBuildProvider }()
   664  
   665  	// Set the bootstrap config used by the fake client.
   666  	xdsC.SetBootstrapConfig(bootstrapConfig)
   667  
   668  	// Here we invoke the watch callback registered on the fake xdsClient. This
   669  	// will trigger the watch handler on the CDS balancer, which will attempt to
   670  	// create a new EDS balancer. The fake EDS balancer created above will be
   671  	// returned to the CDS balancer, because we have overridden the
   672  	// newChildBalancer function as part of test setup.
   673  	cdsUpdate := xdsresource.ClusterUpdate{
   674  		ClusterName: serviceName,
   675  		SecurityCfg: &xdsresource.SecurityConfig{
   676  			RootInstanceName:       "default1",
   677  			SubjectAltNameMatchers: testSANMatchers,
   678  		},
   679  	}
   680  	wantCCS := edsCCS(serviceName, nil, false, nil)
   681  	ctx, ctxCancel := context.WithTimeout(context.Background(), defaultTestTimeout)
   682  	defer ctxCancel()
   683  	if err := invokeWatchCbAndWait(ctx, xdsC, cdsWatchInfo{cdsUpdate, nil}, wantCCS, edsB); err != nil {
   684  		t.Fatal(err)
   685  	}
   686  
   687  	// We specified only the root provider. So, expect only one provider here.
   688  	if _, err := providerCh.Receive(ctx); err != nil {
   689  		t.Fatalf("Failed to create certificate provider upon receipt of security config")
   690  	}
   691  
   692  	// Make a NewSubConn and verify that attributes are added.
   693  	if _, err := makeNewSubConn(ctx, edsB.parentCC, tcc, false); err != nil {
   694  		t.Fatal(err)
   695  	}
   696  
   697  	// Push another update with a new security configuration.
   698  	cdsUpdate = xdsresource.ClusterUpdate{
   699  		ClusterName: serviceName,
   700  		SecurityCfg: &xdsresource.SecurityConfig{
   701  			RootInstanceName:       "default2",
   702  			SubjectAltNameMatchers: testSANMatchers,
   703  		},
   704  	}
   705  	if err := invokeWatchCbAndWait(ctx, xdsC, cdsWatchInfo{cdsUpdate, nil}, wantCCS, edsB); err != nil {
   706  		t.Fatal(err)
   707  	}
   708  
   709  	// We specified only the root provider. So, expect only one provider here.
   710  	if _, err := providerCh.Receive(ctx); err != nil {
   711  		t.Fatalf("Failed to create certificate provider upon receipt of security config")
   712  	}
   713  
   714  	// Make a NewSubConn and verify that attributes are added.
   715  	if _, err := makeNewSubConn(ctx, edsB.parentCC, tcc, false); err != nil {
   716  		t.Fatal(err)
   717  	}
   718  
   719  	// The HandshakeInfo type does not expose its internals. So, we cannot
   720  	// verify that the HandshakeInfo carried by the attributes have actually
   721  	// been changed. This will be covered in e2e/interop tests.
   722  	// TODO(easwars): Remove this TODO once appropriate e2e/intertop tests have
   723  	// been added.
   724  }