github.com/true-sqn/fabric@v2.1.1+incompatible/internal/pkg/comm/client_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package comm_test
     8  
     9  import (
    10  	"bytes"
    11  	"context"
    12  	"crypto/tls"
    13  	"crypto/x509"
    14  	"io/ioutil"
    15  	"net"
    16  	"path/filepath"
    17  	"sync"
    18  	"sync/atomic"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/golang/protobuf/proto"
    23  	"github.com/hyperledger/fabric/common/crypto/tlsgen"
    24  	"github.com/hyperledger/fabric/common/flogging"
    25  	"github.com/hyperledger/fabric/internal/pkg/comm"
    26  	"github.com/hyperledger/fabric/internal/pkg/comm/testpb"
    27  	"github.com/pkg/errors"
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  	"google.golang.org/grpc"
    31  	"google.golang.org/grpc/connectivity"
    32  	"google.golang.org/grpc/credentials"
    33  )
    34  
    35  const testTimeout = 1 * time.Second // conservative
    36  
    37  type echoServer struct{}
    38  
    39  func (es *echoServer) EchoCall(ctx context.Context,
    40  	echo *testpb.Echo) (*testpb.Echo, error) {
    41  	return echo, nil
    42  }
    43  
    44  func TestNewGRPCClient_GoodConfig(t *testing.T) {
    45  	t.Parallel()
    46  	testCerts := loadCerts(t)
    47  
    48  	config := comm.ClientConfig{}
    49  	client, err := comm.NewGRPCClient(config)
    50  	assert.NoError(t, err)
    51  	assert.Equal(t, tls.Certificate{}, client.Certificate())
    52  	assert.False(t, client.TLSEnabled())
    53  	assert.False(t, client.MutualTLSRequired())
    54  
    55  	secOpts := comm.SecureOptions{
    56  		UseTLS: false,
    57  	}
    58  	config.SecOpts = secOpts
    59  	client, err = comm.NewGRPCClient(config)
    60  	assert.NoError(t, err)
    61  	assert.Equal(t, tls.Certificate{}, client.Certificate())
    62  	assert.False(t, client.TLSEnabled())
    63  	assert.False(t, client.MutualTLSRequired())
    64  
    65  	secOpts = comm.SecureOptions{
    66  		UseTLS:            true,
    67  		ServerRootCAs:     [][]byte{testCerts.caPEM},
    68  		RequireClientCert: false,
    69  	}
    70  	config.SecOpts = secOpts
    71  	client, err = comm.NewGRPCClient(config)
    72  	assert.NoError(t, err)
    73  	assert.True(t, client.TLSEnabled())
    74  	assert.False(t, client.MutualTLSRequired())
    75  
    76  	secOpts = comm.SecureOptions{
    77  		Certificate:       testCerts.certPEM,
    78  		Key:               testCerts.keyPEM,
    79  		UseTLS:            true,
    80  		ServerRootCAs:     [][]byte{testCerts.caPEM},
    81  		RequireClientCert: true,
    82  	}
    83  	config.SecOpts = secOpts
    84  	client, err = comm.NewGRPCClient(config)
    85  	assert.NoError(t, err)
    86  	assert.True(t, client.TLSEnabled())
    87  	assert.True(t, client.MutualTLSRequired())
    88  	assert.Equal(t, testCerts.clientCert, client.Certificate())
    89  }
    90  
    91  func TestNewGRPCClient_BadConfig(t *testing.T) {
    92  	t.Parallel()
    93  	testCerts := loadCerts(t)
    94  
    95  	// bad root cert
    96  	config := comm.ClientConfig{
    97  		SecOpts: comm.SecureOptions{
    98  			UseTLS:        true,
    99  			ServerRootCAs: [][]byte{[]byte(badPEM)},
   100  		},
   101  	}
   102  	_, err := comm.NewGRPCClient(config)
   103  	assert.Contains(t, err.Error(), "error adding root certificate")
   104  
   105  	// missing key
   106  	missing := "both Key and Certificate are required when using mutual TLS"
   107  	config.SecOpts = comm.SecureOptions{
   108  		Certificate:       []byte("cert"),
   109  		UseTLS:            true,
   110  		RequireClientCert: true,
   111  	}
   112  	_, err = comm.NewGRPCClient(config)
   113  	assert.Equal(t, missing, err.Error())
   114  
   115  	// missing cert
   116  	config.SecOpts = comm.SecureOptions{
   117  		Key:               []byte("key"),
   118  		UseTLS:            true,
   119  		RequireClientCert: true,
   120  	}
   121  	_, err = comm.NewGRPCClient(config)
   122  	assert.Equal(t, missing, err.Error())
   123  
   124  	// bad key
   125  	failed := "failed to load client certificate"
   126  	config.SecOpts = comm.SecureOptions{
   127  		Certificate:       testCerts.certPEM,
   128  		Key:               []byte(badPEM),
   129  		UseTLS:            true,
   130  		RequireClientCert: true,
   131  	}
   132  	_, err = comm.NewGRPCClient(config)
   133  	assert.Contains(t, err.Error(), failed)
   134  
   135  	// bad cert
   136  	config.SecOpts = comm.SecureOptions{
   137  		Certificate:       []byte(badPEM),
   138  		Key:               testCerts.keyPEM,
   139  		UseTLS:            true,
   140  		RequireClientCert: true,
   141  	}
   142  	_, err = comm.NewGRPCClient(config)
   143  	assert.Contains(t, err.Error(), failed)
   144  }
   145  
   146  func TestNewConnection(t *testing.T) {
   147  	t.Parallel()
   148  	testCerts := loadCerts(t)
   149  
   150  	l, err := net.Listen("tcp", "127.0.0.1:0")
   151  	require.NoError(t, err)
   152  	badAddress := l.Addr().String()
   153  	defer l.Close()
   154  
   155  	certPool := x509.NewCertPool()
   156  	ok := certPool.AppendCertsFromPEM(testCerts.caPEM)
   157  	if !ok {
   158  		t.Fatal("failed to create test root cert pool")
   159  	}
   160  
   161  	tests := []struct {
   162  		name          string
   163  		clientAddress string
   164  		config        comm.ClientConfig
   165  		serverTLS     *tls.Config
   166  		success       bool
   167  		errorMsg      string
   168  	}{
   169  		{
   170  			name: "client / server same port",
   171  			config: comm.ClientConfig{
   172  				Timeout: testTimeout,
   173  			},
   174  			success: true,
   175  		},
   176  		{
   177  			name:          "client / server wrong port",
   178  			clientAddress: badAddress,
   179  			config: comm.ClientConfig{
   180  				Timeout: time.Second,
   181  			},
   182  			success:  false,
   183  			errorMsg: "(connection refused|context deadline exceeded)",
   184  		},
   185  		{
   186  			name:          "client / server wrong port but with asynchronous should succeed",
   187  			clientAddress: badAddress,
   188  			config: comm.ClientConfig{
   189  				AsyncConnect: true,
   190  				Timeout:      testTimeout,
   191  			},
   192  			success: true,
   193  		},
   194  		{
   195  			name: "client TLS / server no TLS",
   196  			config: comm.ClientConfig{
   197  				SecOpts: comm.SecureOptions{
   198  					Certificate:       testCerts.certPEM,
   199  					Key:               testCerts.keyPEM,
   200  					UseTLS:            true,
   201  					ServerRootCAs:     [][]byte{testCerts.caPEM},
   202  					RequireClientCert: true,
   203  				},
   204  				Timeout: time.Second,
   205  			},
   206  			success:  false,
   207  			errorMsg: "context deadline exceeded",
   208  		},
   209  		{
   210  			name: "client TLS / server TLS match",
   211  			config: comm.ClientConfig{
   212  				SecOpts: comm.SecureOptions{
   213  					Certificate:   testCerts.certPEM,
   214  					Key:           testCerts.keyPEM,
   215  					UseTLS:        true,
   216  					ServerRootCAs: [][]byte{testCerts.caPEM},
   217  				},
   218  				Timeout: testTimeout,
   219  			},
   220  			serverTLS: &tls.Config{
   221  				Certificates: []tls.Certificate{testCerts.serverCert},
   222  			},
   223  			success: true,
   224  		},
   225  		{
   226  			name: "client TLS / server TLS no server roots",
   227  			config: comm.ClientConfig{
   228  				SecOpts: comm.SecureOptions{
   229  					Certificate:   testCerts.certPEM,
   230  					Key:           testCerts.keyPEM,
   231  					UseTLS:        true,
   232  					ServerRootCAs: [][]byte{},
   233  				},
   234  				Timeout: testTimeout,
   235  			},
   236  			serverTLS: &tls.Config{
   237  				Certificates: []tls.Certificate{testCerts.serverCert},
   238  			},
   239  			success:  false,
   240  			errorMsg: "context deadline exceeded",
   241  		},
   242  		{
   243  			name: "client TLS / server TLS missing client cert",
   244  			config: comm.ClientConfig{
   245  				SecOpts: comm.SecureOptions{
   246  					Certificate:   testCerts.certPEM,
   247  					Key:           testCerts.keyPEM,
   248  					UseTLS:        true,
   249  					ServerRootCAs: [][]byte{testCerts.caPEM},
   250  				},
   251  				Timeout: testTimeout,
   252  			},
   253  			serverTLS: &tls.Config{
   254  				Certificates: []tls.Certificate{testCerts.serverCert},
   255  				ClientAuth:   tls.RequireAndVerifyClientCert,
   256  				MaxVersion:   tls.VersionTLS12, // https://github.com/golang/go/issues/33368
   257  			},
   258  			success:  false,
   259  			errorMsg: "tls: bad certificate",
   260  		},
   261  		{
   262  			name: "client TLS / server TLS client cert",
   263  			config: comm.ClientConfig{
   264  				SecOpts: comm.SecureOptions{
   265  					Certificate:       testCerts.certPEM,
   266  					Key:               testCerts.keyPEM,
   267  					UseTLS:            true,
   268  					RequireClientCert: true,
   269  					ServerRootCAs:     [][]byte{testCerts.caPEM},
   270  				},
   271  				Timeout: testTimeout,
   272  			},
   273  			serverTLS: &tls.Config{
   274  				Certificates: []tls.Certificate{testCerts.serverCert},
   275  				ClientAuth:   tls.RequireAndVerifyClientCert,
   276  				ClientCAs:    certPool,
   277  			},
   278  			success: true,
   279  		},
   280  		{
   281  			name: "server TLS pinning success",
   282  			config: comm.ClientConfig{
   283  				SecOpts: comm.SecureOptions{
   284  					VerifyCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
   285  						if bytes.Equal(rawCerts[0], testCerts.serverCert.Certificate[0]) {
   286  							return nil
   287  						}
   288  						panic("mismatched certificate")
   289  					},
   290  					Certificate:       testCerts.certPEM,
   291  					Key:               testCerts.keyPEM,
   292  					UseTLS:            true,
   293  					RequireClientCert: true,
   294  					ServerRootCAs:     [][]byte{testCerts.caPEM},
   295  				},
   296  				Timeout: testTimeout,
   297  			},
   298  			serverTLS: &tls.Config{
   299  				Certificates: []tls.Certificate{testCerts.serverCert},
   300  				ClientAuth:   tls.RequireAndVerifyClientCert,
   301  				ClientCAs:    certPool,
   302  			},
   303  			success: true,
   304  		},
   305  		{
   306  			name: "server TLS pinning failure",
   307  			config: comm.ClientConfig{
   308  				SecOpts: comm.SecureOptions{
   309  					VerifyCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
   310  						return errors.New("TLS certificate mismatch")
   311  					},
   312  					Certificate:       testCerts.certPEM,
   313  					Key:               testCerts.keyPEM,
   314  					UseTLS:            true,
   315  					RequireClientCert: true,
   316  					ServerRootCAs:     [][]byte{testCerts.caPEM},
   317  				},
   318  				Timeout: testTimeout,
   319  			},
   320  			serverTLS: &tls.Config{
   321  				Certificates: []tls.Certificate{testCerts.serverCert},
   322  				ClientAuth:   tls.RequireAndVerifyClientCert,
   323  				ClientCAs:    certPool,
   324  			},
   325  			success:  false,
   326  			errorMsg: "context deadline exceeded",
   327  		},
   328  	}
   329  
   330  	for _, test := range tests {
   331  		test := test
   332  		t.Run(test.name, func(t *testing.T) {
   333  			t.Parallel()
   334  			lis, err := net.Listen("tcp", "127.0.0.1:0")
   335  			if err != nil {
   336  				t.Fatalf("error creating server for test: %v", err)
   337  			}
   338  			defer lis.Close()
   339  			serverOpts := []grpc.ServerOption{}
   340  			if test.serverTLS != nil {
   341  				serverOpts = append(serverOpts, grpc.Creds(credentials.NewTLS(test.serverTLS)))
   342  			}
   343  			srv := grpc.NewServer(serverOpts...)
   344  			defer srv.Stop()
   345  			go srv.Serve(lis)
   346  			client, err := comm.NewGRPCClient(test.config)
   347  			if err != nil {
   348  				t.Fatalf("error creating client for test: %v", err)
   349  			}
   350  			address := lis.Addr().String()
   351  			if test.clientAddress != "" {
   352  				address = test.clientAddress
   353  			}
   354  			conn, err := client.NewConnection(address)
   355  			if test.success {
   356  				assert.NoError(t, err)
   357  				assert.NotNil(t, conn)
   358  			} else {
   359  				t.Log(errors.WithStack(err))
   360  				assert.Regexp(t, test.errorMsg, err.Error())
   361  			}
   362  		})
   363  	}
   364  }
   365  
   366  func TestSetServerRootCAs(t *testing.T) {
   367  	t.Parallel()
   368  	testCerts := loadCerts(t)
   369  
   370  	config := comm.ClientConfig{
   371  		SecOpts: comm.SecureOptions{
   372  			UseTLS:        true,
   373  			ServerRootCAs: [][]byte{testCerts.caPEM},
   374  		},
   375  		Timeout: testTimeout,
   376  	}
   377  	client, err := comm.NewGRPCClient(config)
   378  	if err != nil {
   379  		t.Fatalf("error creating base client: %v", err)
   380  	}
   381  
   382  	// set up test TLS server
   383  	lis, err := net.Listen("tcp", "127.0.0.1:0")
   384  	if err != nil {
   385  		t.Fatalf("failed to create listener for test server: %v", err)
   386  	}
   387  	address := lis.Addr().String()
   388  	t.Logf("server listening on [%s]", lis.Addr().String())
   389  	t.Logf("client will use [%s]", address)
   390  	defer lis.Close()
   391  	srv := grpc.NewServer(grpc.Creds(credentials.NewTLS(&tls.Config{
   392  		Certificates: []tls.Certificate{testCerts.serverCert},
   393  	})))
   394  	defer srv.Stop()
   395  	go srv.Serve(lis)
   396  
   397  	// initial config should work
   398  	t.Log("running initial good config")
   399  	conn, err := client.NewConnection(address)
   400  	assert.NoError(t, err)
   401  	assert.NotNil(t, conn)
   402  	if conn != nil {
   403  		conn.Close()
   404  	}
   405  
   406  	// no root testCerts
   407  	t.Log("running bad config")
   408  	err = client.SetServerRootCAs([][]byte{})
   409  	assert.NoError(t, err)
   410  	// now connection should fail
   411  	_, err = client.NewConnection(address)
   412  	assert.Error(t, err)
   413  
   414  	// good root cert
   415  	t.Log("running good config")
   416  	err = client.SetServerRootCAs([][]byte{[]byte(testCerts.caPEM)})
   417  	assert.NoError(t, err)
   418  	// now connection should succeed again
   419  	conn, err = client.NewConnection(address)
   420  	assert.NoError(t, err)
   421  	assert.NotNil(t, conn)
   422  	if conn != nil {
   423  		conn.Close()
   424  	}
   425  
   426  	// bad root cert
   427  	t.Log("running bad root cert")
   428  	err = client.SetServerRootCAs([][]byte{[]byte(badPEM)})
   429  	assert.Contains(t, err.Error(), "error adding root certificate")
   430  }
   431  
   432  func TestSetMessageSize(t *testing.T) {
   433  	t.Parallel()
   434  
   435  	// setup test server
   436  	lis, err := net.Listen("tcp", "127.0.0.1:0")
   437  	if err != nil {
   438  		t.Fatalf("failed to create listener for test server: %v", err)
   439  	}
   440  	srv, err := comm.NewGRPCServerFromListener(lis, comm.ServerConfig{})
   441  	if err != nil {
   442  		t.Fatalf("failed to create test server: %v", err)
   443  	}
   444  	testpb.RegisterEchoServiceServer(srv.Server(), &echoServer{})
   445  	defer srv.Stop()
   446  	go srv.Start()
   447  
   448  	var tests = []struct {
   449  		name        string
   450  		maxRecvSize int
   451  		maxSendSize int
   452  		failRecv    bool
   453  		failSend    bool
   454  	}{
   455  		{
   456  			name:     "defaults should pass",
   457  			failRecv: false,
   458  			failSend: false,
   459  		},
   460  		{
   461  			name:        "non-defaults should pass",
   462  			failRecv:    false,
   463  			failSend:    false,
   464  			maxRecvSize: 20,
   465  			maxSendSize: 20,
   466  		},
   467  		{
   468  			name:        "recv should fail",
   469  			failRecv:    true,
   470  			failSend:    false,
   471  			maxRecvSize: 1,
   472  		},
   473  		{
   474  			name:        "send should fail",
   475  			failRecv:    false,
   476  			failSend:    true,
   477  			maxSendSize: 1,
   478  		},
   479  	}
   480  
   481  	// set up test client
   482  	client, err := comm.NewGRPCClient(comm.ClientConfig{
   483  		Timeout: testTimeout,
   484  	})
   485  	if err != nil {
   486  		t.Fatalf("error creating test client: %v", err)
   487  	}
   488  	// run tests
   489  	for _, test := range tests {
   490  		test := test
   491  		address := lis.Addr().String()
   492  		t.Run(test.name, func(t *testing.T) {
   493  			t.Log(test.name)
   494  			if test.maxRecvSize > 0 {
   495  				client.SetMaxRecvMsgSize(test.maxRecvSize)
   496  			}
   497  			if test.maxSendSize > 0 {
   498  				client.SetMaxSendMsgSize(test.maxSendSize)
   499  			}
   500  			conn, err := client.NewConnection(address)
   501  			assert.NoError(t, err)
   502  			defer conn.Close()
   503  			// create service client from conn
   504  			svcClient := testpb.NewEchoServiceClient(conn)
   505  			callCtx := context.Background()
   506  			callCtx, cancel := context.WithTimeout(callCtx, testTimeout)
   507  			defer cancel()
   508  			//invoke service
   509  			echo := &testpb.Echo{
   510  				Payload: []byte{0, 0, 0, 0, 0},
   511  			}
   512  			resp, err := svcClient.EchoCall(callCtx, echo)
   513  			if !test.failRecv && !test.failSend {
   514  				assert.NoError(t, err)
   515  				assert.True(t, proto.Equal(echo, resp))
   516  			}
   517  			if test.failSend {
   518  				t.Logf("send error: %v", err)
   519  				assert.Contains(t, err.Error(), "trying to send message larger than max")
   520  			}
   521  			if test.failRecv {
   522  				t.Logf("recv error: %v", err)
   523  				assert.Contains(t, err.Error(), "received message larger than max")
   524  			}
   525  		})
   526  	}
   527  }
   528  
   529  type testCerts struct {
   530  	caPEM      []byte
   531  	certPEM    []byte
   532  	keyPEM     []byte
   533  	clientCert tls.Certificate
   534  	serverCert tls.Certificate
   535  }
   536  
   537  func loadCerts(t *testing.T) testCerts {
   538  	t.Helper()
   539  
   540  	var certs testCerts
   541  	var err error
   542  	certs.caPEM, err = ioutil.ReadFile(filepath.Join("testdata", "certs", "Org1-cert.pem"))
   543  	if err != nil {
   544  		t.Fatalf("unexpected error reading root cert for test: %v", err)
   545  	}
   546  	certs.certPEM, err = ioutil.ReadFile(filepath.Join("testdata", "certs", "Org1-client1-cert.pem"))
   547  	if err != nil {
   548  		t.Fatalf("unexpected error reading cert for test: %v", err)
   549  	}
   550  	certs.keyPEM, err = ioutil.ReadFile(filepath.Join("testdata", "certs", "Org1-client1-key.pem"))
   551  	if err != nil {
   552  		t.Fatalf("unexpected error reading key for test: %v", err)
   553  	}
   554  	certs.clientCert, err = tls.X509KeyPair(certs.certPEM, certs.keyPEM)
   555  	if err != nil {
   556  		t.Fatalf("unexpected error loading certificate for test: %v", err)
   557  	}
   558  	certs.serverCert, err = tls.LoadX509KeyPair(
   559  		filepath.Join("testdata", "certs", "Org1-server1-cert.pem"),
   560  		filepath.Join("testdata", "certs", "Org1-server1-key.pem"),
   561  	)
   562  	assert.NoError(t, err)
   563  
   564  	return certs
   565  }
   566  
   567  func TestServerNameOverride(t *testing.T) {
   568  	tlsOption := comm.ServerNameOverride("override-name")
   569  	testConfig := &tls.Config{}
   570  	tlsOption(testConfig)
   571  	assert.Equal(t, &tls.Config{
   572  		ServerName: "override-name",
   573  	}, testConfig)
   574  }
   575  
   576  func TestCertPoolOverride(t *testing.T) {
   577  	tlsOption := comm.CertPoolOverride(&x509.CertPool{})
   578  	testConfig := &tls.Config{}
   579  	assert.NotEqual(t, &tls.Config{
   580  		RootCAs: &x509.CertPool{},
   581  	}, testConfig)
   582  	tlsOption(testConfig)
   583  	assert.Equal(t, &tls.Config{
   584  		RootCAs: &x509.CertPool{},
   585  	}, testConfig)
   586  }
   587  
   588  func TestDynamicClientTLSLoading(t *testing.T) {
   589  	t.Parallel()
   590  	ca1, err := tlsgen.NewCA()
   591  	assert.NoError(t, err)
   592  
   593  	ca2, err := tlsgen.NewCA()
   594  	assert.NoError(t, err)
   595  
   596  	clientKP, err := ca1.NewClientCertKeyPair()
   597  	assert.NoError(t, err)
   598  
   599  	serverKP, err := ca2.NewServerCertKeyPair("127.0.0.1")
   600  	assert.NoError(t, err)
   601  
   602  	client, err := comm.NewGRPCClient(comm.ClientConfig{
   603  		AsyncConnect: true,
   604  		Timeout:      time.Second * 1,
   605  		SecOpts: comm.SecureOptions{
   606  			UseTLS:        true,
   607  			ServerRootCAs: [][]byte{ca1.CertBytes()},
   608  			Certificate:   clientKP.Cert,
   609  			Key:           clientKP.Key,
   610  		},
   611  	})
   612  	assert.NoError(t, err)
   613  
   614  	server, err := comm.NewGRPCServer("127.0.0.1:0", comm.ServerConfig{
   615  		Logger: flogging.MustGetLogger("test"),
   616  		SecOpts: comm.SecureOptions{
   617  			UseTLS:      true,
   618  			Key:         serverKP.Key,
   619  			Certificate: serverKP.Cert,
   620  		},
   621  	})
   622  	assert.NoError(t, err)
   623  
   624  	var wg sync.WaitGroup
   625  	wg.Add(1)
   626  
   627  	go func() {
   628  		defer wg.Done()
   629  		server.Start()
   630  	}()
   631  
   632  	var dynamicRootCerts atomic.Value
   633  	dynamicRootCerts.Store(ca1.CertBytes())
   634  
   635  	conn, err := client.NewConnection(server.Address(), func(tlsConfig *tls.Config) {
   636  		tlsConfig.RootCAs = x509.NewCertPool()
   637  		tlsConfig.RootCAs.AppendCertsFromPEM(dynamicRootCerts.Load().([]byte))
   638  	})
   639  	assert.NoError(t, err)
   640  	assert.NotNil(t, conn)
   641  
   642  	waitForConnState := func(state connectivity.State, succeedOrFail string) {
   643  		deadline := time.Now().Add(time.Second * 30)
   644  		for conn.GetState() != state {
   645  			time.Sleep(time.Millisecond * 10)
   646  			if time.Now().After(deadline) {
   647  				t.Fatalf("Test timed out, waited for connection to %s", succeedOrFail)
   648  			}
   649  		}
   650  	}
   651  
   652  	// Poll the connection state to wait for it to fail
   653  	waitForConnState(connectivity.TransientFailure, "fail")
   654  
   655  	// Update the TLS root CAs with the good one
   656  	dynamicRootCerts.Store(ca2.CertBytes())
   657  
   658  	// Reset exponential back-off to make the test faster
   659  	conn.ResetConnectBackoff()
   660  
   661  	// Poll the connection state to wait for it to succeed
   662  	waitForConnState(connectivity.Ready, "succeed")
   663  
   664  	err = conn.Close()
   665  	assert.NoError(t, err)
   666  
   667  	server.Stop()
   668  	wg.Wait()
   669  }