github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/internal/peer/common/peerclient_test.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  package common_test
     7  
     8  import (
     9  	"crypto/tls"
    10  	"fmt"
    11  	"io/ioutil"
    12  	"net"
    13  	"os"
    14  	"path"
    15  	"path/filepath"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/hechain20/hechain/common/crypto/tlsgen"
    20  	"github.com/hechain20/hechain/internal/peer/common"
    21  	"github.com/hechain20/hechain/internal/pkg/comm"
    22  	"github.com/spf13/viper"
    23  	"github.com/stretchr/testify/require"
    24  )
    25  
    26  func initPeerTestEnv(t *testing.T) (cfgPath string, cleanup func()) {
    27  	t.Helper()
    28  	cfgPath, err := ioutil.TempDir("", "peerTestEnv")
    29  	require.NoError(t, err)
    30  	certsDir := filepath.Join(cfgPath, "certs")
    31  	err = os.Mkdir(certsDir, 0o755)
    32  	require.NoError(t, err)
    33  
    34  	configFile, err := os.Create(filepath.Join(cfgPath, "test.yaml"))
    35  	require.NoError(t, err)
    36  	defer configFile.Close()
    37  
    38  	configStr := `
    39  peer:
    40    tls:
    41      rootcert:
    42        file: "certs/ca.crt"
    43      clientKey:
    44        file: "certs/client.key"
    45      clientCert:
    46        file: "certs/client.crt"
    47    client:
    48      connTimeout: 1s
    49  
    50  orderer:
    51    tls:
    52      rootcert:
    53        file: "certs/ca.crt"
    54      clientKey:
    55        file: "certs/client.key"
    56      clientCert:
    57        file: "certs/client.crt"
    58    client:
    59      connTimeout: 1s
    60  `
    61  	_, err = configFile.WriteString(configStr)
    62  	require.NoError(t, err)
    63  
    64  	os.Setenv("FABRIC_CFG_PATH", cfgPath)
    65  	viper.Reset()
    66  	_ = common.InitConfig("test")
    67  	ca, err := tlsgen.NewCA()
    68  	require.NoError(t, err)
    69  
    70  	caCrtFile := path.Join(certsDir, "ca.crt")
    71  	err = ioutil.WriteFile(caCrtFile, ca.CertBytes(), 0o644)
    72  	require.NoError(t, err)
    73  
    74  	kp, err := ca.NewClientCertKeyPair()
    75  	require.NoError(t, err)
    76  
    77  	key := path.Join(certsDir, "client.key")
    78  	err = ioutil.WriteFile(key, kp.Key, 0o644)
    79  	require.NoError(t, err)
    80  
    81  	crt := path.Join(certsDir, "client.crt")
    82  	err = ioutil.WriteFile(crt, kp.Cert, 0o644)
    83  	require.NoError(t, err)
    84  
    85  	ekey := path.Join(certsDir, "empty.key")
    86  	err = ioutil.WriteFile(ekey, []byte{}, 0o644)
    87  	require.NoError(t, err)
    88  
    89  	ecrt := path.Join(certsDir, "empty.crt")
    90  	err = ioutil.WriteFile(ecrt, []byte{}, 0o644)
    91  	require.NoError(t, err)
    92  
    93  	configFile, err = os.Create(filepath.Join(certsDir, "bad.key"))
    94  	require.NoError(t, err)
    95  	defer configFile.Close()
    96  
    97  	_, err = configFile.WriteString(`
    98  -----BEGIN PRIVATE KEY-----
    99  MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgg6BAaCpwlmg/hEP4
   100  QjUeWEu3crkxMvjq4vYh3LaDREuhRANCAAR+FujNKcGQW/CEpMU6Yp45ye2cbOwJ
   101  -----END PRIVATE KEY-----
   102  	`)
   103  	require.NoError(t, err)
   104  
   105  	return cfgPath, func() {
   106  		err := os.Unsetenv("FABRIC_CFG_PATH")
   107  		require.NoError(t, err)
   108  		defer os.RemoveAll(cfgPath)
   109  		viper.Reset()
   110  	}
   111  }
   112  
   113  func TestNewPeerClientFromEnv(t *testing.T) {
   114  	_, cleanup := initPeerTestEnv(t)
   115  	defer cleanup()
   116  
   117  	pClient, err := common.NewPeerClientFromEnv()
   118  	require.NoError(t, err)
   119  	require.NotNil(t, pClient)
   120  
   121  	viper.Set("peer.tls.enabled", true)
   122  	pClient, err = common.NewPeerClientFromEnv()
   123  	require.NoError(t, err)
   124  	require.NotNil(t, pClient)
   125  
   126  	viper.Set("peer.tls.enabled", true)
   127  	viper.Set("peer.tls.clientAuthRequired", true)
   128  	pClient, err = common.NewPeerClientFromEnv()
   129  	require.NoError(t, err)
   130  	require.NotNil(t, pClient)
   131  
   132  	// bad key file
   133  	// This used to be detected when creating the client instead
   134  	// of when the client connects.
   135  	badKeyFile := filepath.Join("certs", "bad.key")
   136  	viper.Set("peer.tls.clientKey.file", badKeyFile)
   137  	pClient, err = common.NewPeerClientFromEnv()
   138  	require.NoError(t, err)
   139  	_, err = pClient.Dial("127.0.0.1:0")
   140  	require.ErrorContains(t, err, "failed to load client certificate:")
   141  	require.ErrorContains(t, err, "tls: failed to parse private key")
   142  
   143  	// bad cert file path
   144  	viper.Set("peer.tls.clientCert.file", "./nocert.crt")
   145  	pClient, err = common.NewPeerClientFromEnv()
   146  	require.ErrorContains(t, err, "unable to load peer.tls.clientCert.file")
   147  	require.Nil(t, pClient)
   148  
   149  	// bad key file path
   150  	viper.Set("peer.tls.clientKey.file", "./nokey.key")
   151  	pClient, err = common.NewPeerClientFromEnv()
   152  	require.ErrorContains(t, err, "unable to load peer.tls.clientKey.file")
   153  	require.Nil(t, pClient)
   154  
   155  	// bad ca path
   156  	viper.Set("peer.tls.rootcert.file", "noroot.crt")
   157  	pClient, err = common.NewPeerClientFromEnv()
   158  	require.ErrorContains(t, err, "unable to load peer.tls.rootcert.file")
   159  	require.Nil(t, pClient)
   160  }
   161  
   162  func TestPeerClient(t *testing.T) {
   163  	_, cleanup := initPeerTestEnv(t)
   164  	defer cleanup()
   165  
   166  	lis, err := net.Listen("tcp", "localhost:0")
   167  	if err != nil {
   168  		t.Fatalf("error creating server for test: %v", err)
   169  	}
   170  	defer lis.Close()
   171  	srv, err := comm.NewGRPCServerFromListener(lis, comm.ServerConfig{})
   172  	if err != nil {
   173  		t.Fatalf("error creating gRPC server for test: %v", err)
   174  	}
   175  	go srv.Start()
   176  	defer srv.Stop()
   177  	viper.Set("peer.address", lis.Addr().String())
   178  	pClient1, err := common.NewPeerClientFromEnv()
   179  	if err != nil {
   180  		t.Fatalf("failed to create PeerClient for test: %v", err)
   181  	}
   182  	eClient, err := pClient1.Endorser()
   183  	require.NoError(t, err)
   184  	require.NotNil(t, eClient)
   185  	eClient, err = common.GetEndorserClient("", "")
   186  	require.NoError(t, err)
   187  	require.NotNil(t, eClient)
   188  
   189  	dClient, err := pClient1.Deliver()
   190  	require.NoError(t, err)
   191  	require.NotNil(t, dClient)
   192  	dClient, err = common.GetDeliverClient("", "")
   193  	require.NoError(t, err)
   194  	require.NotNil(t, dClient)
   195  }
   196  
   197  func TestPeerClientTimeout(t *testing.T) {
   198  	t.Run("PeerClient.GetEndorser() timeout", func(t *testing.T) {
   199  		_, cleanup := initPeerTestEnv(t)
   200  		viper.Set("peer.client.connTimeout", 10*time.Millisecond)
   201  		defer cleanup()
   202  		pClient, err := common.NewPeerClientFromEnv()
   203  		if err != nil {
   204  			t.Fatalf("failed to create PeerClient for test: %v", err)
   205  		}
   206  		_, err = pClient.Endorser()
   207  		require.Contains(t, err.Error(), "endorser client failed to connect")
   208  	})
   209  	t.Run("GetEndorserClient() timeout", func(t *testing.T) {
   210  		_, cleanup := initPeerTestEnv(t)
   211  		viper.Set("peer.client.connTimeout", 10*time.Millisecond)
   212  		defer cleanup()
   213  		_, err := common.GetEndorserClient("", "")
   214  		require.Contains(t, err.Error(), "endorser client failed to connect")
   215  	})
   216  	t.Run("PeerClient.Deliver() timeout", func(t *testing.T) {
   217  		_, cleanup := initPeerTestEnv(t)
   218  		viper.Set("peer.client.connTimeout", 10*time.Millisecond)
   219  		defer cleanup()
   220  		pClient, err := common.NewPeerClientFromEnv()
   221  		if err != nil {
   222  			t.Fatalf("failed to create PeerClient for test: %v", err)
   223  		}
   224  		_, err = pClient.Deliver()
   225  		require.Contains(t, err.Error(), "deliver client failed to connect")
   226  	})
   227  	t.Run("GetDeliverClient() timeout", func(t *testing.T) {
   228  		_, cleanup := initPeerTestEnv(t)
   229  		viper.Set("peer.client.connTimeout", 10*time.Millisecond)
   230  		defer cleanup()
   231  		_, err := common.GetDeliverClient("", "")
   232  		require.Contains(t, err.Error(), "deliver client failed to connect")
   233  	})
   234  	t.Run("PeerClient.Certificate()", func(t *testing.T) {
   235  		_, cleanup := initPeerTestEnv(t)
   236  		defer cleanup()
   237  		pClient, err := common.NewPeerClientFromEnv()
   238  		if err != nil {
   239  			t.Fatalf("failed to create PeerClient for test: %v", err)
   240  		}
   241  		cert := pClient.Certificate()
   242  		require.NotNil(t, cert)
   243  	})
   244  }
   245  
   246  func TestGetClientCertificate(t *testing.T) {
   247  	t.Run("GetClientCertificate_clientAuthRequired_disabled", func(t *testing.T) {
   248  		_, cleanup := initPeerTestEnv(t)
   249  		defer cleanup()
   250  		cert, err := common.GetClientCertificate()
   251  		require.NotEqual(t, cert, &tls.Certificate{})
   252  		require.NoError(t, err)
   253  	})
   254  
   255  	t.Run("GetClientCertificate_clientAuthRequired_enabled", func(t *testing.T) {
   256  		_, cleanup := initPeerTestEnv(t)
   257  		defer cleanup()
   258  		viper.Set("peer.tls.clientAuthRequired", true)
   259  		viper.Set("peer.tls.clientKey.file", filepath.Join("./certs", "client.key"))
   260  		viper.Set("peer.tls.clientCert.file", filepath.Join("./certs", "client.crt"))
   261  		defer viper.Reset()
   262  
   263  		cert, err := common.GetClientCertificate()
   264  		require.NoError(t, err)
   265  		require.NotEqual(t, cert, tls.Certificate{})
   266  	})
   267  
   268  	t.Run("GetClientCertificate_empty_keyfile", func(t *testing.T) {
   269  		_, cleanup := initPeerTestEnv(t)
   270  		defer cleanup()
   271  		viper.Set("peer.tls.clientAuthRequired", true)
   272  		viper.Set("peer.tls.clientKey.file", filepath.Join("./certs", "empty.key"))
   273  		viper.Set("peer.tls.clientCert.file", filepath.Join("./certs", "client.crt"))
   274  		defer viper.Reset()
   275  
   276  		cert, err := common.GetClientCertificate()
   277  		require.EqualError(t, err, "failed to load client certificate: tls: failed to find any PEM data in key input")
   278  		require.Equal(t, cert, tls.Certificate{})
   279  	})
   280  
   281  	t.Run("GetClientCertificate_empty_certfile", func(t *testing.T) {
   282  		_, cleanup := initPeerTestEnv(t)
   283  		defer cleanup()
   284  		viper.Set("peer.tls.clientAuthRequired", true)
   285  		viper.Set("peer.tls.clientKey.file", filepath.Join("./certs", "client.key"))
   286  		viper.Set("peer.tls.clientCert.file", filepath.Join("./certs", "empty.crt"))
   287  		defer viper.Reset()
   288  
   289  		cert, err := common.GetClientCertificate()
   290  		require.EqualError(t, err, "failed to load client certificate: tls: failed to find any PEM data in certificate input")
   291  		require.Equal(t, cert, tls.Certificate{})
   292  	})
   293  
   294  	t.Run("GetClientCertificate_bad_keyfilepath", func(t *testing.T) {
   295  		cfgPath, cleanup := initPeerTestEnv(t)
   296  		defer cleanup()
   297  		// bad key file path
   298  		viper.Set("peer.tls.clientAuthRequired", true)
   299  		viper.Set("peer.tls.clientKey.file", filepath.Join("./certs", "nokey.key"))
   300  		viper.Set("peer.tls.clientCert.file", filepath.Join("./certs", "client.crt"))
   301  		defer viper.Reset()
   302  
   303  		cert, err := common.GetClientCertificate()
   304  		require.EqualError(t, err, fmt.Sprintf("unable to load peer.tls.clientKey.file: open %s/certs/nokey.key: no such file or directory", cfgPath))
   305  		require.Equal(t, cert, tls.Certificate{})
   306  	})
   307  
   308  	t.Run("GetClientCertificate_missing_certfilepath", func(t *testing.T) {
   309  		// missing cert file path
   310  		viper.Set("peer.tls.clientAuthRequired", true)
   311  		viper.Set("peer.tls.clientKey.file", filepath.Join("./testdata/certs", "client.key"))
   312  		defer viper.Reset()
   313  
   314  		cert, err := common.GetClientCertificate()
   315  		require.EqualError(t, err, "unable to load peer.tls.clientKey.file: open testdata/certs/client.key: no such file or directory")
   316  		require.Equal(t, cert, tls.Certificate{})
   317  	})
   318  }
   319  
   320  func TestNewPeerClientForAddress(t *testing.T) {
   321  	cfgPath, cleanup := initPeerTestEnv(t)
   322  	defer cleanup()
   323  
   324  	// TLS disabled
   325  	viper.Set("peer.tls.enabled", false)
   326  
   327  	// success case
   328  	pClient, err := common.NewPeerClientForAddress("testPeer", "")
   329  	require.NoError(t, err)
   330  	require.NotNil(t, pClient)
   331  
   332  	// failure - no peer address supplied
   333  	pClient, err = common.NewPeerClientForAddress("", "")
   334  	require.Contains(t, err.Error(), "peer address must be set")
   335  	require.Nil(t, pClient)
   336  
   337  	// TLS enabled
   338  	viper.Set("peer.tls.enabled", true)
   339  
   340  	// Enable clientAuthRequired
   341  	viper.Set("peer.tls.clientAuthRequired", true)
   342  
   343  	// success case
   344  	pClient, err = common.NewPeerClientForAddress("tlsPeer", path.Join(cfgPath, "certs", "ca.crt"))
   345  	require.NoError(t, err)
   346  	require.NotNil(t, pClient)
   347  
   348  	// failure - bad tls root cert file
   349  	pClient, err = common.NewPeerClientForAddress("badPeer", "bad.crt")
   350  	require.Contains(t, err.Error(), "unable to load TLS root cert file from bad.crt")
   351  	require.Nil(t, pClient)
   352  
   353  	// failure - empty tls root cert file
   354  	pClient, err = common.NewPeerClientForAddress("badPeer", "")
   355  	require.Contains(t, err.Error(), "tls root cert file must be set")
   356  	require.Nil(t, pClient)
   357  
   358  	// failure - empty tls root cert file
   359  	viper.Set("peer.tls.clientCert.file", "./nocert.crt")
   360  	pClient, err = common.NewPeerClientForAddress("badPeer", "")
   361  	require.Contains(t, err.Error(), "unable to load peer.tls.clientCert.file")
   362  	require.Nil(t, pClient)
   363  
   364  	// bad key file
   365  	viper.Set("peer.tls.clientKey.file", "./nokey.key")
   366  	viper.Set("peer.client.connTimeout", time.Duration(0))
   367  	pClient, err = common.NewPeerClientForAddress("badPeer", "")
   368  	require.Contains(t, err.Error(), "unable to load peer.tls.clientKey.file")
   369  	require.Nil(t, pClient)
   370  }
   371  
   372  func TestGetClients_AddressError(t *testing.T) {
   373  	_, cleanup := initPeerTestEnv(t)
   374  	defer cleanup()
   375  
   376  	viper.Set("peer.tls.enabled", true)
   377  
   378  	// failure
   379  	eClient, err := common.GetEndorserClient("peer0", "")
   380  	require.Contains(t, err.Error(), "tls root cert file must be set")
   381  	require.Nil(t, eClient)
   382  
   383  	dClient, err := common.GetDeliverClient("peer0", "")
   384  	require.Contains(t, err.Error(), "tls root cert file must be set")
   385  	require.Nil(t, dClient)
   386  }