github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/xds/server_test.go (about) 1 /* 2 * 3 * Copyright 2020 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package xds 20 21 import ( 22 "context" 23 "errors" 24 "fmt" 25 "net" 26 "reflect" 27 "strings" 28 "testing" 29 "time" 30 31 grpc "github.com/hxx258456/ccgo/grpc" 32 "github.com/hxx258456/ccgo/grpc/connectivity" 33 "github.com/hxx258456/ccgo/grpc/credentials/insecure" 34 "github.com/hxx258456/ccgo/grpc/credentials/tls/certprovider" 35 "github.com/hxx258456/ccgo/grpc/credentials/xds" 36 "github.com/hxx258456/ccgo/grpc/internal/grpctest" 37 "github.com/hxx258456/ccgo/grpc/internal/testutils" 38 _ "github.com/hxx258456/ccgo/grpc/xds/internal/httpfilter/router" 39 xdstestutils "github.com/hxx258456/ccgo/grpc/xds/internal/testutils" 40 "github.com/hxx258456/ccgo/grpc/xds/internal/testutils/e2e" 41 "github.com/hxx258456/ccgo/grpc/xds/internal/testutils/fakeclient" 42 "github.com/hxx258456/ccgo/grpc/xds/internal/xdsclient" 43 "github.com/hxx258456/ccgo/grpc/xds/internal/xdsclient/bootstrap" 44 "github.com/hxx258456/ccgo/grpc/xds/internal/xdsclient/xdsresource" 45 46 wrapperspb "github.com/golang/protobuf/ptypes/wrappers" 47 v3corepb "github.com/hxx258456/ccgo/go-control-plane/envoy/config/core/v3" 48 v3listenerpb "github.com/hxx258456/ccgo/go-control-plane/envoy/config/listener/v3" 49 v3routepb "github.com/hxx258456/ccgo/go-control-plane/envoy/config/route/v3" 50 v3httppb "github.com/hxx258456/ccgo/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" 51 v3tlspb "github.com/hxx258456/ccgo/go-control-plane/envoy/extensions/transport_sockets/tls/v3" 52 ) 53 54 const ( 55 defaultTestTimeout = 5 * time.Second 56 defaultTestShortTimeout = 10 * time.Millisecond 57 testServerListenerResourceNameTemplate = "/path/to/resource/%s/%s" 58 ) 59 60 var listenerWithFilterChains = &v3listenerpb.Listener{ 61 FilterChains: []*v3listenerpb.FilterChain{ 62 { 63 FilterChainMatch: &v3listenerpb.FilterChainMatch{ 64 PrefixRanges: []*v3corepb.CidrRange{ 65 { 66 AddressPrefix: "192.168.0.0", 67 PrefixLen: &wrapperspb.UInt32Value{ 68 Value: uint32(16), 69 }, 70 }, 71 }, 72 SourceType: v3listenerpb.FilterChainMatch_SAME_IP_OR_LOOPBACK, 73 SourcePrefixRanges: []*v3corepb.CidrRange{ 74 { 75 AddressPrefix: "192.168.0.0", 76 PrefixLen: &wrapperspb.UInt32Value{ 77 Value: uint32(16), 78 }, 79 }, 80 }, 81 SourcePorts: []uint32{80}, 82 }, 83 TransportSocket: &v3corepb.TransportSocket{ 84 Name: "envoy.transport_sockets.tls", 85 ConfigType: &v3corepb.TransportSocket_TypedConfig{ 86 TypedConfig: testutils.MarshalAny(&v3tlspb.DownstreamTlsContext{ 87 CommonTlsContext: &v3tlspb.CommonTlsContext{ 88 TlsCertificateCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{ 89 InstanceName: "identityPluginInstance", 90 CertificateName: "identityCertName", 91 }, 92 }, 93 }), 94 }, 95 }, 96 Filters: []*v3listenerpb.Filter{ 97 { 98 Name: "filter-1", 99 ConfigType: &v3listenerpb.Filter_TypedConfig{ 100 TypedConfig: testutils.MarshalAny(&v3httppb.HttpConnectionManager{ 101 RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{ 102 RouteConfig: &v3routepb.RouteConfiguration{ 103 Name: "routeName", 104 VirtualHosts: []*v3routepb.VirtualHost{{ 105 Domains: []string{"lds.target.good:3333"}, 106 Routes: []*v3routepb.Route{{ 107 Match: &v3routepb.RouteMatch{ 108 PathSpecifier: &v3routepb.RouteMatch_Prefix{Prefix: "/"}, 109 }, 110 Action: &v3routepb.Route_NonForwardingAction{}, 111 }}}}}, 112 }, 113 HttpFilters: []*v3httppb.HttpFilter{e2e.RouterHTTPFilter}, 114 }), 115 }, 116 }, 117 }, 118 }, 119 }, 120 } 121 122 type s struct { 123 grpctest.Tester 124 } 125 126 func Test(t *testing.T) { 127 grpctest.RunSubTests(t, s{}) 128 } 129 130 type fakeGRPCServer struct { 131 done chan struct{} 132 registerServiceCh *testutils.Channel 133 serveCh *testutils.Channel 134 stopCh *testutils.Channel 135 gracefulStopCh *testutils.Channel 136 } 137 138 func (f *fakeGRPCServer) RegisterService(*grpc.ServiceDesc, interface{}) { 139 f.registerServiceCh.Send(nil) 140 } 141 142 func (f *fakeGRPCServer) Serve(lis net.Listener) error { 143 f.serveCh.Send(nil) 144 <-f.done 145 lis.Close() 146 return nil 147 } 148 149 func (f *fakeGRPCServer) Stop() { 150 close(f.done) 151 f.stopCh.Send(nil) 152 } 153 func (f *fakeGRPCServer) GracefulStop() { 154 close(f.done) 155 f.gracefulStopCh.Send(nil) 156 } 157 158 func (f *fakeGRPCServer) GetServiceInfo() map[string]grpc.ServiceInfo { 159 panic("implement me") 160 } 161 162 func newFakeGRPCServer() *fakeGRPCServer { 163 return &fakeGRPCServer{ 164 done: make(chan struct{}), 165 registerServiceCh: testutils.NewChannel(), 166 serveCh: testutils.NewChannel(), 167 stopCh: testutils.NewChannel(), 168 gracefulStopCh: testutils.NewChannel(), 169 } 170 } 171 172 func splitHostPort(hostport string) (string, string) { 173 addr, port, err := net.SplitHostPort(hostport) 174 if err != nil { 175 panic(fmt.Sprintf("listener address %q does not parse: %v", hostport, err)) 176 } 177 return addr, port 178 } 179 180 func (s) TestNewServer(t *testing.T) { 181 xdsCreds, err := xds.NewServerCredentials(xds.ServerOptions{FallbackCreds: insecure.NewCredentials()}) 182 if err != nil { 183 t.Fatalf("failed to create xds server credentials: %v", err) 184 } 185 186 tests := []struct { 187 desc string 188 serverOpts []grpc.ServerOption 189 wantXDSCredsInUse bool 190 }{ 191 { 192 desc: "without_xds_creds", 193 serverOpts: []grpc.ServerOption{grpc.Creds(insecure.NewCredentials())}, 194 }, 195 { 196 desc: "with_xds_creds", 197 serverOpts: []grpc.ServerOption{grpc.Creds(xdsCreds)}, 198 wantXDSCredsInUse: true, 199 }, 200 } 201 202 for _, test := range tests { 203 t.Run(test.desc, func(t *testing.T) { 204 // The xds package adds a couple of server options (unary and stream 205 // interceptors) to the server options passed in by the user. 206 wantServerOpts := len(test.serverOpts) + 2 207 208 origNewGRPCServer := newGRPCServer 209 newGRPCServer = func(opts ...grpc.ServerOption) grpcServer { 210 if got := len(opts); got != wantServerOpts { 211 t.Fatalf("%d ServerOptions passed to grpc.Server, want %d", got, wantServerOpts) 212 } 213 // Verify that the user passed ServerOptions are forwarded as is. 214 if !reflect.DeepEqual(opts[2:], test.serverOpts) { 215 t.Fatalf("got ServerOptions %v, want %v", opts[2:], test.serverOpts) 216 } 217 return grpc.NewServer(opts...) 218 } 219 defer func() { 220 newGRPCServer = origNewGRPCServer 221 }() 222 223 s := NewGRPCServer(test.serverOpts...) 224 defer s.Stop() 225 226 if s.xdsCredsInUse != test.wantXDSCredsInUse { 227 t.Fatalf("xdsCredsInUse is %v, want %v", s.xdsCredsInUse, test.wantXDSCredsInUse) 228 } 229 }) 230 } 231 } 232 233 func (s) TestRegisterService(t *testing.T) { 234 fs := newFakeGRPCServer() 235 236 origNewGRPCServer := newGRPCServer 237 newGRPCServer = func(opts ...grpc.ServerOption) grpcServer { return fs } 238 defer func() { newGRPCServer = origNewGRPCServer }() 239 240 s := NewGRPCServer() 241 defer s.Stop() 242 243 s.RegisterService(&grpc.ServiceDesc{}, nil) 244 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 245 defer cancel() 246 if _, err := fs.registerServiceCh.Receive(ctx); err != nil { 247 t.Fatalf("timeout when expecting RegisterService() to called on grpc.Server: %v", err) 248 } 249 } 250 251 const ( 252 fakeProvider1Name = "fake-certificate-provider-1" 253 fakeProvider2Name = "fake-certificate-provider-2" 254 fakeConfig = "my fake config" 255 ) 256 257 var ( 258 fpb1, fpb2 *fakeProviderBuilder 259 certProviderConfigs map[string]*certprovider.BuildableConfig 260 ) 261 262 func init() { 263 fpb1 = &fakeProviderBuilder{ 264 name: fakeProvider1Name, 265 buildCh: testutils.NewChannel(), 266 } 267 fpb2 = &fakeProviderBuilder{ 268 name: fakeProvider2Name, 269 buildCh: testutils.NewChannel(), 270 } 271 cfg1, _ := fpb1.ParseConfig(fakeConfig + "1111") 272 cfg2, _ := fpb2.ParseConfig(fakeConfig + "2222") 273 certProviderConfigs = map[string]*certprovider.BuildableConfig{ 274 "default1": cfg1, 275 "default2": cfg2, 276 } 277 certprovider.Register(fpb1) 278 certprovider.Register(fpb2) 279 } 280 281 // fakeProviderBuilder builds new instances of fakeProvider and interprets the 282 // config provided to it as a string. 283 type fakeProviderBuilder struct { 284 name string 285 buildCh *testutils.Channel 286 } 287 288 func (b *fakeProviderBuilder) ParseConfig(config interface{}) (*certprovider.BuildableConfig, error) { 289 s, ok := config.(string) 290 if !ok { 291 return nil, fmt.Errorf("providerBuilder %s received config of type %T, want string", b.name, config) 292 } 293 return certprovider.NewBuildableConfig(b.name, []byte(s), func(certprovider.BuildOptions) certprovider.Provider { 294 b.buildCh.Send(nil) 295 return &fakeProvider{ 296 Distributor: certprovider.NewDistributor(), 297 config: s, 298 } 299 }), nil 300 } 301 302 func (b *fakeProviderBuilder) Name() string { 303 return b.name 304 } 305 306 // fakeProvider is an implementation of the Provider interface which provides a 307 // method for tests to invoke to push new key materials. 308 type fakeProvider struct { 309 *certprovider.Distributor 310 config string 311 } 312 313 // Close helps implement the Provider interface. 314 func (p *fakeProvider) Close() { 315 p.Distributor.Stop() 316 } 317 318 // setupOverrides sets up overrides for bootstrap config, new xdsClient creation 319 // and new gRPC.Server creation. 320 func setupOverrides() (*fakeGRPCServer, *testutils.Channel, func()) { 321 clientCh := testutils.NewChannel() 322 origNewXDSClient := newXDSClient 323 newXDSClient = func() (xdsclient.XDSClient, error) { 324 c := fakeclient.NewClient() 325 c.SetBootstrapConfig(&bootstrap.Config{ 326 XDSServer: &bootstrap.ServerConfig{ 327 ServerURI: "dummyBalancer", 328 Creds: grpc.WithTransportCredentials(insecure.NewCredentials()), 329 NodeProto: xdstestutils.EmptyNodeProtoV3, 330 }, 331 ServerListenerResourceNameTemplate: testServerListenerResourceNameTemplate, 332 CertProviderConfigs: certProviderConfigs, 333 }) 334 clientCh.Send(c) 335 return c, nil 336 } 337 338 fs := newFakeGRPCServer() 339 origNewGRPCServer := newGRPCServer 340 newGRPCServer = func(opts ...grpc.ServerOption) grpcServer { return fs } 341 342 return fs, clientCh, func() { 343 newXDSClient = origNewXDSClient 344 newGRPCServer = origNewGRPCServer 345 } 346 } 347 348 // setupOverridesForXDSCreds overrides only the xdsClient creation with a fake 349 // one. Tests that use xdsCredentials need a real grpc.Server instead of a fake 350 // one, because the xDS-enabled server needs to read configured creds from the 351 // underlying grpc.Server to confirm whether xdsCreds were configured. 352 func setupOverridesForXDSCreds(includeCertProviderCfg bool) (*testutils.Channel, func()) { 353 clientCh := testutils.NewChannel() 354 origNewXDSClient := newXDSClient 355 newXDSClient = func() (xdsclient.XDSClient, error) { 356 c := fakeclient.NewClient() 357 bc := &bootstrap.Config{ 358 XDSServer: &bootstrap.ServerConfig{ 359 ServerURI: "dummyBalancer", 360 Creds: grpc.WithTransportCredentials(insecure.NewCredentials()), 361 NodeProto: xdstestutils.EmptyNodeProtoV3, 362 }, 363 ServerListenerResourceNameTemplate: testServerListenerResourceNameTemplate, 364 } 365 if includeCertProviderCfg { 366 bc.CertProviderConfigs = certProviderConfigs 367 } 368 c.SetBootstrapConfig(bc) 369 clientCh.Send(c) 370 return c, nil 371 } 372 373 return clientCh, func() { newXDSClient = origNewXDSClient } 374 } 375 376 // TestServeSuccess tests the successful case of calling Serve(). 377 // The following sequence of events happen: 378 // 1. Create a new GRPCServer and call Serve() in a goroutine. 379 // 2. Make sure an xdsClient is created, and an LDS watch is registered. 380 // 3. Push an error response from the xdsClient, and make sure that Serve() does 381 // not exit. 382 // 4. Push a good response from the xdsClient, and make sure that Serve() on the 383 // underlying grpc.Server is called. 384 func (s) TestServeSuccess(t *testing.T) { 385 fs, clientCh, cleanup := setupOverrides() 386 defer cleanup() 387 388 // Create a new xDS-enabled gRPC server and pass it a server option to get 389 // notified about serving mode changes. 390 modeChangeCh := testutils.NewChannel() 391 modeChangeOption := ServingModeCallback(func(addr net.Addr, args ServingModeChangeArgs) { 392 t.Logf("server mode change callback invoked for listener %q with mode %q and error %v", addr.String(), args.Mode, args.Err) 393 modeChangeCh.Send(args.Mode) 394 }) 395 server := NewGRPCServer(modeChangeOption) 396 defer server.Stop() 397 398 lis, err := testutils.LocalTCPListener() 399 if err != nil { 400 t.Fatalf("testutils.LocalTCPListener() failed: %v", err) 401 } 402 403 // Call Serve() in a goroutine, and push on a channel when Serve returns. 404 serveDone := testutils.NewChannel() 405 go func() { 406 if err := server.Serve(lis); err != nil { 407 t.Error(err) 408 } 409 serveDone.Send(nil) 410 }() 411 412 // Wait for an xdsClient to be created. 413 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 414 defer cancel() 415 c, err := clientCh.Receive(ctx) 416 if err != nil { 417 t.Fatalf("error when waiting for new xdsClient to be created: %v", err) 418 } 419 client := c.(*fakeclient.Client) 420 421 // Wait for a listener watch to be registered on the xdsClient. 422 name, err := client.WaitForWatchListener(ctx) 423 if err != nil { 424 t.Fatalf("error when waiting for a ListenerWatch: %v", err) 425 } 426 wantName := strings.Replace(testServerListenerResourceNameTemplate, "%s", lis.Addr().String(), -1) 427 if name != wantName { 428 t.Fatalf("LDS watch registered for name %q, want %q", name, wantName) 429 } 430 431 // Push an error to the registered listener watch callback and make sure 432 // that Serve does not return. 433 client.InvokeWatchListenerCallback(xdsresource.ListenerUpdate{}, xdsresource.NewErrorf(xdsresource.ErrorTypeResourceNotFound, "LDS resource not found")) 434 sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 435 defer sCancel() 436 if _, err := serveDone.Receive(sCtx); err != context.DeadlineExceeded { 437 t.Fatal("Serve() returned after a bad LDS response") 438 } 439 440 // Make sure the serving mode changes appropriately. 441 v, err := modeChangeCh.Receive(ctx) 442 if err != nil { 443 t.Fatalf("error when waiting for serving mode to change: %v", err) 444 } 445 if mode := v.(connectivity.ServingMode); mode != connectivity.ServingModeNotServing { 446 t.Fatalf("server mode is %q, want %q", mode, connectivity.ServingModeNotServing) 447 } 448 449 // Push a good LDS response, and wait for Serve() to be invoked on the 450 // underlying grpc.Server. 451 fcm, err := xdsresource.NewFilterChainManager(listenerWithFilterChains, nil) 452 if err != nil { 453 t.Fatalf("xdsclient.NewFilterChainManager() failed with error: %v", err) 454 } 455 addr, port := splitHostPort(lis.Addr().String()) 456 client.InvokeWatchListenerCallback(xdsresource.ListenerUpdate{ 457 RouteConfigName: "routeconfig", 458 InboundListenerCfg: &xdsresource.InboundListenerConfig{ 459 Address: addr, 460 Port: port, 461 FilterChains: fcm, 462 }, 463 }, nil) 464 if _, err := fs.serveCh.Receive(ctx); err != nil { 465 t.Fatalf("error when waiting for Serve() to be invoked on the grpc.Server") 466 } 467 468 // Make sure the serving mode changes appropriately. 469 v, err = modeChangeCh.Receive(ctx) 470 if err != nil { 471 t.Fatalf("error when waiting for serving mode to change: %v", err) 472 } 473 if mode := v.(connectivity.ServingMode); mode != connectivity.ServingModeServing { 474 t.Fatalf("server mode is %q, want %q", mode, connectivity.ServingModeServing) 475 } 476 477 // Push an update to the registered listener watch callback with a Listener 478 // resource whose host:port does not match the actual listening address and 479 // port. This will push the listener to "not-serving" mode. 480 client.InvokeWatchListenerCallback(xdsresource.ListenerUpdate{ 481 RouteConfigName: "routeconfig", 482 InboundListenerCfg: &xdsresource.InboundListenerConfig{ 483 Address: "10.20.30.40", 484 Port: "666", 485 FilterChains: fcm, 486 }, 487 }, nil) 488 sCtx, sCancel = context.WithTimeout(context.Background(), defaultTestShortTimeout) 489 defer sCancel() 490 if _, err := serveDone.Receive(sCtx); err != context.DeadlineExceeded { 491 t.Fatal("Serve() returned after a bad LDS response") 492 } 493 494 // Make sure the serving mode changes appropriately. 495 v, err = modeChangeCh.Receive(ctx) 496 if err != nil { 497 t.Fatalf("error when waiting for serving mode to change: %v", err) 498 } 499 if mode := v.(connectivity.ServingMode); mode != connectivity.ServingModeNotServing { 500 t.Fatalf("server mode is %q, want %q", mode, connectivity.ServingModeNotServing) 501 } 502 } 503 504 // TestServeWithStop tests the case where Stop() is called before an LDS update 505 // is received. This should cause Serve() to exit before calling Serve() on the 506 // underlying grpc.Server. 507 func (s) TestServeWithStop(t *testing.T) { 508 fs, clientCh, cleanup := setupOverrides() 509 defer cleanup() 510 511 // Note that we are not deferring the Stop() here since we explicitly call 512 // it after the LDS watch has been registered. 513 server := NewGRPCServer() 514 515 lis, err := testutils.LocalTCPListener() 516 if err != nil { 517 t.Fatalf("testutils.LocalTCPListener() failed: %v", err) 518 } 519 520 // Call Serve() in a goroutine, and push on a channel when Serve returns. 521 serveDone := testutils.NewChannel() 522 go func() { 523 if err := server.Serve(lis); err != nil { 524 t.Error(err) 525 } 526 serveDone.Send(nil) 527 }() 528 529 // Wait for an xdsClient to be created. 530 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 531 defer cancel() 532 c, err := clientCh.Receive(ctx) 533 if err != nil { 534 t.Fatalf("error when waiting for new xdsClient to be created: %v", err) 535 } 536 client := c.(*fakeclient.Client) 537 538 // Wait for a listener watch to be registered on the xdsClient. 539 name, err := client.WaitForWatchListener(ctx) 540 if err != nil { 541 server.Stop() 542 t.Fatalf("error when waiting for a ListenerWatch: %v", err) 543 } 544 wantName := strings.Replace(testServerListenerResourceNameTemplate, "%s", lis.Addr().String(), -1) 545 if name != wantName { 546 server.Stop() 547 t.Fatalf("LDS watch registered for name %q, wantPrefix %q", name, wantName) 548 } 549 550 // Call Stop() on the server before a listener update is received, and 551 // expect Serve() to exit. 552 server.Stop() 553 if _, err := serveDone.Receive(ctx); err != nil { 554 t.Fatalf("error when waiting for Serve() to exit") 555 } 556 557 // Make sure that Serve() on the underlying grpc.Server is not called. 558 sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 559 defer sCancel() 560 if _, err := fs.serveCh.Receive(sCtx); err != context.DeadlineExceeded { 561 t.Fatal("Serve() called on underlying grpc.Server") 562 } 563 } 564 565 // TestServeBootstrapFailure tests the case where xDS bootstrap fails and 566 // verifies that Serve() exits with a non-nil error. 567 func (s) TestServeBootstrapFailure(t *testing.T) { 568 // Since we have not setup fakes for anything, this will attempt to do real 569 // xDS bootstrap and that will fail because the bootstrap environment 570 // variable is not set. 571 server := NewGRPCServer() 572 defer server.Stop() 573 574 lis, err := testutils.LocalTCPListener() 575 if err != nil { 576 t.Fatalf("testutils.LocalTCPListener() failed: %v", err) 577 } 578 579 serveDone := testutils.NewChannel() 580 go func() { serveDone.Send(server.Serve(lis)) }() 581 582 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 583 defer cancel() 584 v, err := serveDone.Receive(ctx) 585 if err != nil { 586 t.Fatalf("error when waiting for Serve() to exit: %v", err) 587 } 588 if err, ok := v.(error); !ok || err == nil { 589 t.Fatal("Serve() did not exit with error") 590 } 591 } 592 593 // TestServeBootstrapConfigInvalid tests the cases where the bootstrap config 594 // does not contain expected fields. Verifies that the call to Serve() fails. 595 func (s) TestServeBootstrapConfigInvalid(t *testing.T) { 596 tests := []struct { 597 desc string 598 bootstrapConfig *bootstrap.Config 599 }{ 600 { 601 desc: "bootstrap config is missing", 602 bootstrapConfig: nil, 603 }, 604 { 605 desc: "certificate provider config is missing", 606 bootstrapConfig: &bootstrap.Config{ 607 XDSServer: &bootstrap.ServerConfig{ 608 ServerURI: "dummyBalancer", 609 Creds: grpc.WithTransportCredentials(insecure.NewCredentials()), 610 NodeProto: xdstestutils.EmptyNodeProtoV3, 611 }, 612 ServerListenerResourceNameTemplate: testServerListenerResourceNameTemplate, 613 }, 614 }, 615 { 616 desc: "server_listener_resource_name_template is missing", 617 bootstrapConfig: &bootstrap.Config{ 618 XDSServer: &bootstrap.ServerConfig{ 619 ServerURI: "dummyBalancer", 620 Creds: grpc.WithTransportCredentials(insecure.NewCredentials()), 621 NodeProto: xdstestutils.EmptyNodeProtoV3, 622 }, 623 CertProviderConfigs: certProviderConfigs, 624 }, 625 }, 626 } 627 628 for _, test := range tests { 629 t.Run(test.desc, func(t *testing.T) { 630 // Override the xdsClient creation with one that returns a fake 631 // xdsClient with the specified bootstrap configuration. 632 clientCh := testutils.NewChannel() 633 origNewXDSClient := newXDSClient 634 newXDSClient = func() (xdsclient.XDSClient, error) { 635 c := fakeclient.NewClient() 636 c.SetBootstrapConfig(test.bootstrapConfig) 637 clientCh.Send(c) 638 return c, nil 639 } 640 defer func() { newXDSClient = origNewXDSClient }() 641 642 xdsCreds, err := xds.NewServerCredentials(xds.ServerOptions{FallbackCreds: insecure.NewCredentials()}) 643 if err != nil { 644 t.Fatalf("failed to create xds server credentials: %v", err) 645 } 646 server := NewGRPCServer(grpc.Creds(xdsCreds)) 647 defer server.Stop() 648 649 lis, err := testutils.LocalTCPListener() 650 if err != nil { 651 t.Fatalf("testutils.LocalTCPListener() failed: %v", err) 652 } 653 654 serveDone := testutils.NewChannel() 655 go func() { 656 err := server.Serve(lis) 657 serveDone.Send(err) 658 }() 659 660 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 661 defer cancel() 662 v, err := serveDone.Receive(ctx) 663 if err != nil { 664 t.Fatalf("error when waiting for Serve() to exit: %v", err) 665 } 666 if err, ok := v.(error); !ok || err == nil { 667 t.Fatal("Serve() did not exit with error") 668 } 669 }) 670 } 671 } 672 673 // TestServeNewClientFailure tests the case where xds client creation fails and 674 // verifies that Server() exits with a non-nil error. 675 func (s) TestServeNewClientFailure(t *testing.T) { 676 origNewXDSClient := newXDSClient 677 newXDSClient = func() (xdsclient.XDSClient, error) { 678 return nil, errors.New("xdsClient creation failed") 679 } 680 defer func() { newXDSClient = origNewXDSClient }() 681 682 server := NewGRPCServer() 683 defer server.Stop() 684 685 lis, err := testutils.LocalTCPListener() 686 if err != nil { 687 t.Fatalf("testutils.LocalTCPListener() failed: %v", err) 688 } 689 690 serveDone := testutils.NewChannel() 691 go func() { 692 err := server.Serve(lis) 693 serveDone.Send(err) 694 }() 695 696 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 697 defer cancel() 698 v, err := serveDone.Receive(ctx) 699 if err != nil { 700 t.Fatalf("error when waiting for Serve() to exit: %v", err) 701 } 702 if err, ok := v.(error); !ok || err == nil { 703 t.Fatal("Serve() did not exit with error") 704 } 705 } 706 707 // TestHandleListenerUpdate_NoXDSCreds tests the case where an xds-enabled gRPC 708 // server is not configured with xDS credentials. Verifies that the security 709 // config received as part of a Listener update is not acted upon. 710 func (s) TestHandleListenerUpdate_NoXDSCreds(t *testing.T) { 711 fs, clientCh, cleanup := setupOverrides() 712 defer cleanup() 713 714 server := NewGRPCServer() 715 defer server.Stop() 716 717 lis, err := testutils.LocalTCPListener() 718 if err != nil { 719 t.Fatalf("testutils.LocalTCPListener() failed: %v", err) 720 } 721 722 // Call Serve() in a goroutine, and push on a channel when Serve returns. 723 serveDone := testutils.NewChannel() 724 go func() { 725 if err := server.Serve(lis); err != nil { 726 t.Error(err) 727 } 728 serveDone.Send(nil) 729 }() 730 731 // Wait for an xdsClient to be created. 732 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 733 defer cancel() 734 c, err := clientCh.Receive(ctx) 735 if err != nil { 736 t.Fatalf("error when waiting for new xdsClient to be created: %v", err) 737 } 738 client := c.(*fakeclient.Client) 739 740 // Wait for a listener watch to be registered on the xdsClient. 741 name, err := client.WaitForWatchListener(ctx) 742 if err != nil { 743 t.Fatalf("error when waiting for a ListenerWatch: %v", err) 744 } 745 wantName := strings.Replace(testServerListenerResourceNameTemplate, "%s", lis.Addr().String(), -1) 746 if name != wantName { 747 t.Fatalf("LDS watch registered for name %q, want %q", name, wantName) 748 } 749 750 // Push a good LDS response with security config, and wait for Serve() to be 751 // invoked on the underlying grpc.Server. Also make sure that certificate 752 // providers are not created. 753 fcm, err := xdsresource.NewFilterChainManager(&v3listenerpb.Listener{ 754 FilterChains: []*v3listenerpb.FilterChain{ 755 { 756 TransportSocket: &v3corepb.TransportSocket{ 757 Name: "envoy.transport_sockets.tls", 758 ConfigType: &v3corepb.TransportSocket_TypedConfig{ 759 TypedConfig: testutils.MarshalAny(&v3tlspb.DownstreamTlsContext{ 760 CommonTlsContext: &v3tlspb.CommonTlsContext{ 761 TlsCertificateCertificateProviderInstance: &v3tlspb.CommonTlsContext_CertificateProviderInstance{ 762 InstanceName: "identityPluginInstance", 763 CertificateName: "identityCertName", 764 }, 765 }, 766 }), 767 }, 768 }, 769 Filters: []*v3listenerpb.Filter{ 770 { 771 Name: "filter-1", 772 ConfigType: &v3listenerpb.Filter_TypedConfig{ 773 TypedConfig: testutils.MarshalAny(&v3httppb.HttpConnectionManager{ 774 RouteSpecifier: &v3httppb.HttpConnectionManager_RouteConfig{ 775 RouteConfig: &v3routepb.RouteConfiguration{ 776 Name: "routeName", 777 VirtualHosts: []*v3routepb.VirtualHost{{ 778 Domains: []string{"lds.target.good:3333"}, 779 Routes: []*v3routepb.Route{{ 780 Match: &v3routepb.RouteMatch{ 781 PathSpecifier: &v3routepb.RouteMatch_Prefix{Prefix: "/"}, 782 }, 783 Action: &v3routepb.Route_NonForwardingAction{}, 784 }}}}}, 785 }, 786 HttpFilters: []*v3httppb.HttpFilter{e2e.RouterHTTPFilter}, 787 }), 788 }, 789 }, 790 }, 791 }, 792 }, 793 }, nil) 794 if err != nil { 795 t.Fatalf("xdsclient.NewFilterChainManager() failed with error: %v", err) 796 } 797 addr, port := splitHostPort(lis.Addr().String()) 798 client.InvokeWatchListenerCallback(xdsresource.ListenerUpdate{ 799 RouteConfigName: "routeconfig", 800 InboundListenerCfg: &xdsresource.InboundListenerConfig{ 801 Address: addr, 802 Port: port, 803 FilterChains: fcm, 804 }, 805 }, nil) 806 if _, err := fs.serveCh.Receive(ctx); err != nil { 807 t.Fatalf("error when waiting for Serve() to be invoked on the grpc.Server") 808 } 809 810 // Make sure the security configuration is not acted upon. 811 if err := verifyCertProviderNotCreated(); err != nil { 812 t.Fatal(err) 813 } 814 } 815 816 // TestHandleListenerUpdate_ErrorUpdate tests the case where an xds-enabled gRPC 817 // server is configured with xDS credentials, but receives a Listener update 818 // with an error. Verifies that no certificate providers are created. 819 func (s) TestHandleListenerUpdate_ErrorUpdate(t *testing.T) { 820 clientCh, cleanup := setupOverridesForXDSCreds(true) 821 defer cleanup() 822 823 xdsCreds, err := xds.NewServerCredentials(xds.ServerOptions{FallbackCreds: insecure.NewCredentials()}) 824 if err != nil { 825 t.Fatalf("failed to create xds server credentials: %v", err) 826 } 827 828 server := NewGRPCServer(grpc.Creds(xdsCreds)) 829 defer server.Stop() 830 831 lis, err := testutils.LocalTCPListener() 832 if err != nil { 833 t.Fatalf("testutils.LocalTCPListener() failed: %v", err) 834 } 835 836 // Call Serve() in a goroutine, and push on a channel when Serve returns. 837 serveDone := testutils.NewChannel() 838 go func() { 839 if err := server.Serve(lis); err != nil { 840 t.Error(err) 841 } 842 serveDone.Send(nil) 843 }() 844 845 // Wait for an xdsClient to be created. 846 ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) 847 defer cancel() 848 c, err := clientCh.Receive(ctx) 849 if err != nil { 850 t.Fatalf("error when waiting for new xdsClient to be created: %v", err) 851 } 852 client := c.(*fakeclient.Client) 853 854 // Wait for a listener watch to be registered on the xdsClient. 855 name, err := client.WaitForWatchListener(ctx) 856 if err != nil { 857 t.Fatalf("error when waiting for a ListenerWatch: %v", err) 858 } 859 wantName := strings.Replace(testServerListenerResourceNameTemplate, "%s", lis.Addr().String(), -1) 860 if name != wantName { 861 t.Fatalf("LDS watch registered for name %q, want %q", name, wantName) 862 } 863 864 // Push an error to the registered listener watch callback and make sure 865 // that Serve does not return. 866 client.InvokeWatchListenerCallback(xdsresource.ListenerUpdate{}, errors.New("LDS error")) 867 sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 868 defer sCancel() 869 if _, err := serveDone.Receive(sCtx); err != context.DeadlineExceeded { 870 t.Fatal("Serve() returned after a bad LDS response") 871 } 872 873 // Also make sure that no certificate providers are created. 874 if err := verifyCertProviderNotCreated(); err != nil { 875 t.Fatal(err) 876 } 877 } 878 879 func verifyCertProviderNotCreated() error { 880 sCtx, sCancel := context.WithTimeout(context.Background(), defaultTestShortTimeout) 881 defer sCancel() 882 if _, err := fpb1.buildCh.Receive(sCtx); err != context.DeadlineExceeded { 883 return errors.New("certificate provider created when no xDS creds were specified") 884 } 885 sCtx, sCancel = context.WithTimeout(context.Background(), defaultTestShortTimeout) 886 defer sCancel() 887 if _, err := fpb2.buildCh.Receive(sCtx); err != context.DeadlineExceeded { 888 return errors.New("certificate provider created when no xDS creds were specified") 889 } 890 return nil 891 }