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 }