go_study/fabric-main/internal/peer/common/peerclient_test.go

383 lines
12 KiB
Go

/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package common_test
import (
"crypto/tls"
"fmt"
"io/ioutil"
"net"
"os"
"path"
"path/filepath"
"testing"
"time"
"github.com/hyperledger/fabric/common/crypto/tlsgen"
"github.com/hyperledger/fabric/internal/peer/common"
"github.com/hyperledger/fabric/internal/pkg/comm"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
)
func initPeerTestEnv(t *testing.T) (cfgPath string, cleanup func()) {
t.Helper()
cfgPath = t.TempDir()
certsDir := filepath.Join(cfgPath, "certs")
err := os.Mkdir(certsDir, 0o755)
require.NoError(t, err)
configFile, err := os.Create(filepath.Join(cfgPath, "test.yaml"))
require.NoError(t, err)
defer configFile.Close()
configStr := `
peer:
tls:
rootcert:
file: "certs/ca.crt"
clientKey:
file: "certs/client.key"
clientCert:
file: "certs/client.crt"
client:
connTimeout: 1s
orderer:
tls:
rootcert:
file: "certs/ca.crt"
clientKey:
file: "certs/client.key"
clientCert:
file: "certs/client.crt"
client:
connTimeout: 1s
`
_, err = configFile.WriteString(configStr)
require.NoError(t, err)
t.Setenv("FABRIC_CFG_PATH", cfgPath)
viper.Reset()
_ = common.InitConfig("test")
ca, err := tlsgen.NewCA()
require.NoError(t, err)
caCrtFile := path.Join(certsDir, "ca.crt")
err = ioutil.WriteFile(caCrtFile, ca.CertBytes(), 0o644)
require.NoError(t, err)
kp, err := ca.NewClientCertKeyPair()
require.NoError(t, err)
key := path.Join(certsDir, "client.key")
err = ioutil.WriteFile(key, kp.Key, 0o644)
require.NoError(t, err)
crt := path.Join(certsDir, "client.crt")
err = ioutil.WriteFile(crt, kp.Cert, 0o644)
require.NoError(t, err)
ekey := path.Join(certsDir, "empty.key")
err = ioutil.WriteFile(ekey, []byte{}, 0o644)
require.NoError(t, err)
ecrt := path.Join(certsDir, "empty.crt")
err = ioutil.WriteFile(ecrt, []byte{}, 0o644)
require.NoError(t, err)
configFile, err = os.Create(filepath.Join(certsDir, "bad.key"))
require.NoError(t, err)
defer configFile.Close()
_, err = configFile.WriteString(`
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgg6BAaCpwlmg/hEP4
QjUeWEu3crkxMvjq4vYh3LaDREuhRANCAAR+FujNKcGQW/CEpMU6Yp45ye2cbOwJ
-----END PRIVATE KEY-----
`)
require.NoError(t, err)
return cfgPath, func() {
viper.Reset()
}
}
func TestNewPeerClientFromEnv(t *testing.T) {
_, cleanup := initPeerTestEnv(t)
defer cleanup()
pClient, err := common.NewPeerClientFromEnv()
require.NoError(t, err)
require.NotNil(t, pClient)
viper.Set("peer.tls.enabled", true)
pClient, err = common.NewPeerClientFromEnv()
require.NoError(t, err)
require.NotNil(t, pClient)
viper.Set("peer.tls.enabled", true)
viper.Set("peer.tls.clientAuthRequired", true)
pClient, err = common.NewPeerClientFromEnv()
require.NoError(t, err)
require.NotNil(t, pClient)
// bad key file
// This used to be detected when creating the client instead
// of when the client connects.
badKeyFile := filepath.Join("certs", "bad.key")
viper.Set("peer.tls.clientKey.file", badKeyFile)
pClient, err = common.NewPeerClientFromEnv()
require.NoError(t, err)
_, err = pClient.Dial("127.0.0.1:0")
require.ErrorContains(t, err, "failed to load client certificate:")
require.ErrorContains(t, err, "tls: failed to parse private key")
// bad cert file path
viper.Set("peer.tls.clientCert.file", "./nocert.crt")
pClient, err = common.NewPeerClientFromEnv()
require.ErrorContains(t, err, "unable to load peer.tls.clientCert.file")
require.Nil(t, pClient)
// bad key file path
viper.Set("peer.tls.clientKey.file", "./nokey.key")
pClient, err = common.NewPeerClientFromEnv()
require.ErrorContains(t, err, "unable to load peer.tls.clientKey.file")
require.Nil(t, pClient)
// bad ca path
viper.Set("peer.tls.rootcert.file", "noroot.crt")
pClient, err = common.NewPeerClientFromEnv()
require.ErrorContains(t, err, "unable to load peer.tls.rootcert.file")
require.Nil(t, pClient)
}
func TestPeerClient(t *testing.T) {
_, cleanup := initPeerTestEnv(t)
defer cleanup()
lis, err := net.Listen("tcp", "localhost:0")
if err != nil {
t.Fatalf("error creating server for test: %v", err)
}
defer lis.Close()
srv, err := comm.NewGRPCServerFromListener(lis, comm.ServerConfig{})
if err != nil {
t.Fatalf("error creating gRPC server for test: %v", err)
}
go srv.Start()
defer srv.Stop()
viper.Set("peer.address", lis.Addr().String())
pClient1, err := common.NewPeerClientFromEnv()
if err != nil {
t.Fatalf("failed to create PeerClient for test: %v", err)
}
eClient, err := pClient1.Endorser()
require.NoError(t, err)
require.NotNil(t, eClient)
eClient, err = common.GetEndorserClient("", "")
require.NoError(t, err)
require.NotNil(t, eClient)
dClient, err := pClient1.Deliver()
require.NoError(t, err)
require.NotNil(t, dClient)
dClient, err = common.GetDeliverClient("", "")
require.NoError(t, err)
require.NotNil(t, dClient)
}
func TestPeerClientTimeout(t *testing.T) {
t.Run("PeerClient.GetEndorser() timeout", func(t *testing.T) {
_, cleanup := initPeerTestEnv(t)
viper.Set("peer.client.connTimeout", 10*time.Millisecond)
defer cleanup()
pClient, err := common.NewPeerClientFromEnv()
if err != nil {
t.Fatalf("failed to create PeerClient for test: %v", err)
}
_, err = pClient.Endorser()
require.Contains(t, err.Error(), "endorser client failed to connect")
})
t.Run("GetEndorserClient() timeout", func(t *testing.T) {
_, cleanup := initPeerTestEnv(t)
viper.Set("peer.client.connTimeout", 10*time.Millisecond)
defer cleanup()
_, err := common.GetEndorserClient("", "")
require.Contains(t, err.Error(), "endorser client failed to connect")
})
t.Run("PeerClient.Deliver() timeout", func(t *testing.T) {
_, cleanup := initPeerTestEnv(t)
viper.Set("peer.client.connTimeout", 10*time.Millisecond)
defer cleanup()
pClient, err := common.NewPeerClientFromEnv()
if err != nil {
t.Fatalf("failed to create PeerClient for test: %v", err)
}
_, err = pClient.Deliver()
require.Contains(t, err.Error(), "deliver client failed to connect")
})
t.Run("GetDeliverClient() timeout", func(t *testing.T) {
_, cleanup := initPeerTestEnv(t)
viper.Set("peer.client.connTimeout", 10*time.Millisecond)
defer cleanup()
_, err := common.GetDeliverClient("", "")
require.Contains(t, err.Error(), "deliver client failed to connect")
})
t.Run("PeerClient.Certificate()", func(t *testing.T) {
_, cleanup := initPeerTestEnv(t)
defer cleanup()
pClient, err := common.NewPeerClientFromEnv()
if err != nil {
t.Fatalf("failed to create PeerClient for test: %v", err)
}
cert := pClient.Certificate()
require.NotNil(t, cert)
})
}
func TestGetClientCertificate(t *testing.T) {
t.Run("GetClientCertificate_clientAuthRequired_disabled", func(t *testing.T) {
_, cleanup := initPeerTestEnv(t)
defer cleanup()
cert, err := common.GetClientCertificate()
require.NotEqual(t, cert, &tls.Certificate{})
require.NoError(t, err)
})
t.Run("GetClientCertificate_clientAuthRequired_enabled", func(t *testing.T) {
_, cleanup := initPeerTestEnv(t)
defer cleanup()
viper.Set("peer.tls.clientAuthRequired", true)
viper.Set("peer.tls.clientKey.file", filepath.Join("./certs", "client.key"))
viper.Set("peer.tls.clientCert.file", filepath.Join("./certs", "client.crt"))
defer viper.Reset()
cert, err := common.GetClientCertificate()
require.NoError(t, err)
require.NotEqual(t, cert, tls.Certificate{})
})
t.Run("GetClientCertificate_empty_keyfile", func(t *testing.T) {
_, cleanup := initPeerTestEnv(t)
defer cleanup()
viper.Set("peer.tls.clientAuthRequired", true)
viper.Set("peer.tls.clientKey.file", filepath.Join("./certs", "empty.key"))
viper.Set("peer.tls.clientCert.file", filepath.Join("./certs", "client.crt"))
defer viper.Reset()
cert, err := common.GetClientCertificate()
require.EqualError(t, err, "failed to load client certificate: tls: failed to find any PEM data in key input")
require.Equal(t, cert, tls.Certificate{})
})
t.Run("GetClientCertificate_empty_certfile", func(t *testing.T) {
_, cleanup := initPeerTestEnv(t)
defer cleanup()
viper.Set("peer.tls.clientAuthRequired", true)
viper.Set("peer.tls.clientKey.file", filepath.Join("./certs", "client.key"))
viper.Set("peer.tls.clientCert.file", filepath.Join("./certs", "empty.crt"))
defer viper.Reset()
cert, err := common.GetClientCertificate()
require.EqualError(t, err, "failed to load client certificate: tls: failed to find any PEM data in certificate input")
require.Equal(t, cert, tls.Certificate{})
})
t.Run("GetClientCertificate_bad_keyfilepath", func(t *testing.T) {
cfgPath, cleanup := initPeerTestEnv(t)
defer cleanup()
// bad key file path
viper.Set("peer.tls.clientAuthRequired", true)
viper.Set("peer.tls.clientKey.file", filepath.Join("./certs", "nokey.key"))
viper.Set("peer.tls.clientCert.file", filepath.Join("./certs", "client.crt"))
defer viper.Reset()
cert, err := common.GetClientCertificate()
require.EqualError(t, err, fmt.Sprintf("unable to load peer.tls.clientKey.file: open %s/certs/nokey.key: no such file or directory", cfgPath))
require.Equal(t, cert, tls.Certificate{})
})
t.Run("GetClientCertificate_missing_certfilepath", func(t *testing.T) {
// missing cert file path
viper.Set("peer.tls.clientAuthRequired", true)
viper.Set("peer.tls.clientKey.file", filepath.Join("./testdata/certs", "client.key"))
defer viper.Reset()
cert, err := common.GetClientCertificate()
require.EqualError(t, err, "unable to load peer.tls.clientKey.file: open testdata/certs/client.key: no such file or directory")
require.Equal(t, cert, tls.Certificate{})
})
}
func TestNewPeerClientForAddress(t *testing.T) {
cfgPath, cleanup := initPeerTestEnv(t)
defer cleanup()
// TLS disabled
viper.Set("peer.tls.enabled", false)
// success case
pClient, err := common.NewPeerClientForAddress("testPeer", "")
require.NoError(t, err)
require.NotNil(t, pClient)
// failure - no peer address supplied
pClient, err = common.NewPeerClientForAddress("", "")
require.Contains(t, err.Error(), "peer address must be set")
require.Nil(t, pClient)
// TLS enabled
viper.Set("peer.tls.enabled", true)
// Enable clientAuthRequired
viper.Set("peer.tls.clientAuthRequired", true)
// success case
pClient, err = common.NewPeerClientForAddress("tlsPeer", path.Join(cfgPath, "certs", "ca.crt"))
require.NoError(t, err)
require.NotNil(t, pClient)
// failure - bad tls root cert file
pClient, err = common.NewPeerClientForAddress("badPeer", "bad.crt")
require.Contains(t, err.Error(), "unable to load TLS root cert file from bad.crt")
require.Nil(t, pClient)
// failure - empty tls root cert file
pClient, err = common.NewPeerClientForAddress("badPeer", "")
require.Contains(t, err.Error(), "tls root cert file must be set")
require.Nil(t, pClient)
// failure - empty tls root cert file
viper.Set("peer.tls.clientCert.file", "./nocert.crt")
pClient, err = common.NewPeerClientForAddress("badPeer", "")
require.Contains(t, err.Error(), "unable to load peer.tls.clientCert.file")
require.Nil(t, pClient)
// bad key file
viper.Set("peer.tls.clientKey.file", "./nokey.key")
viper.Set("peer.client.connTimeout", time.Duration(0))
pClient, err = common.NewPeerClientForAddress("badPeer", "")
require.Contains(t, err.Error(), "unable to load peer.tls.clientKey.file")
require.Nil(t, pClient)
}
func TestGetClients_AddressError(t *testing.T) {
_, cleanup := initPeerTestEnv(t)
defer cleanup()
viper.Set("peer.tls.enabled", true)
// failure
eClient, err := common.GetEndorserClient("peer0", "")
require.Contains(t, err.Error(), "tls root cert file must be set")
require.Nil(t, eClient)
dClient, err := common.GetDeliverClient("peer0", "")
require.Contains(t, err.Error(), "tls root cert file must be set")
require.Nil(t, dClient)
}