github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/core/peer/pkg_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package peer_test
     8  
     9  import (
    10  	"crypto/tls"
    11  	"crypto/x509"
    12  	"errors"
    13  	"fmt"
    14  	"io/ioutil"
    15  	"os"
    16  	"path/filepath"
    17  	"testing"
    18  	"time"
    19  
    20  	"google.golang.org/grpc/credentials"
    21  
    22  	"golang.org/x/net/context"
    23  	"google.golang.org/grpc"
    24  
    25  	"github.com/golang/protobuf/proto"
    26  	configtxtest "github.com/hyperledger/fabric/common/configtx/test"
    27  	"github.com/hyperledger/fabric/core/comm"
    28  	testpb "github.com/hyperledger/fabric/core/comm/testdata/grpc"
    29  	"github.com/hyperledger/fabric/core/peer"
    30  	"github.com/hyperledger/fabric/msp"
    31  	cb "github.com/hyperledger/fabric/protos/common"
    32  	mspproto "github.com/hyperledger/fabric/protos/msp"
    33  	"github.com/spf13/viper"
    34  	"github.com/stretchr/testify/assert"
    35  )
    36  
    37  // default timeout for grpc connections
    38  var timeout = time.Second * 1
    39  
    40  // test server to be registered with the GRPCServer
    41  type testServiceServer struct{}
    42  
    43  func (tss *testServiceServer) EmptyCall(context.Context, *testpb.Empty) (*testpb.Empty, error) {
    44  	return new(testpb.Empty), nil
    45  }
    46  
    47  // createCertPool creates an x509.CertPool from an array of PEM-encoded certificates
    48  func createCertPool(rootCAs [][]byte) (*x509.CertPool, error) {
    49  
    50  	certPool := x509.NewCertPool()
    51  	for _, rootCA := range rootCAs {
    52  		if !certPool.AppendCertsFromPEM(rootCA) {
    53  			return nil, errors.New("Failed to load root certificates")
    54  		}
    55  	}
    56  	return certPool, nil
    57  }
    58  
    59  // helper function to invoke the EmptyCall againt the test service
    60  func invokeEmptyCall(address string, dialOptions []grpc.DialOption) (*testpb.Empty, error) {
    61  
    62  	//add DialOptions
    63  	dialOptions = append(dialOptions, grpc.WithBlock())
    64  	dialOptions = append(dialOptions, grpc.WithTimeout(timeout))
    65  	//create GRPC client conn
    66  	clientConn, err := grpc.Dial(address, dialOptions...)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  	defer clientConn.Close()
    71  
    72  	//create GRPC client
    73  	client := testpb.NewTestServiceClient(clientConn)
    74  
    75  	ctx := context.Background()
    76  	ctx, cancel := context.WithTimeout(ctx, timeout)
    77  	defer cancel()
    78  
    79  	//invoke service
    80  	empty, err := client.EmptyCall(ctx, new(testpb.Empty))
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  
    85  	return empty, nil
    86  }
    87  
    88  // helper function to build an MSPConfig given root certs
    89  func createMSPConfig(rootCerts, tlsRootCerts, tlsIntermediateCerts [][]byte,
    90  	mspID string) (*mspproto.MSPConfig, error) {
    91  
    92  	fmspconf := &mspproto.FabricMSPConfig{
    93  		RootCerts:            rootCerts,
    94  		TlsRootCerts:         tlsRootCerts,
    95  		TlsIntermediateCerts: tlsIntermediateCerts,
    96  		Name:                 mspID}
    97  
    98  	fmpsjs, err := proto.Marshal(fmspconf)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	mspconf := &mspproto.MSPConfig{Config: fmpsjs, Type: int32(msp.FABRIC)}
   103  	return mspconf, nil
   104  }
   105  
   106  func createConfigBlock(chainID string, appMSPConf, ordererMSPConf *mspproto.MSPConfig,
   107  	appOrgID, ordererOrgID string) (*cb.Block, error) {
   108  	block, err := configtxtest.MakeGenesisBlockFromMSPs(chainID, appMSPConf, ordererMSPConf, appOrgID, ordererOrgID)
   109  	return block, err
   110  }
   111  
   112  func TestUpdateRootsFromConfigBlock(t *testing.T) {
   113  	// load test certs from testdata
   114  	org1CA, err := ioutil.ReadFile(filepath.Join("testdata", "Org1-cert.pem"))
   115  	org1Server1Key, err := ioutil.ReadFile(filepath.Join("testdata",
   116  		"Org1-server1-key.pem"))
   117  	org1Server1Cert, err := ioutil.ReadFile(filepath.Join("testdata",
   118  		"Org1-server1-cert.pem"))
   119  	org2CA, err := ioutil.ReadFile(filepath.Join("testdata", "Org2-cert.pem"))
   120  	org2Server1Key, err := ioutil.ReadFile(filepath.Join("testdata",
   121  		"Org2-server1-key.pem"))
   122  	org2Server1Cert, err := ioutil.ReadFile(filepath.Join("testdata",
   123  		"Org2-server1-cert.pem"))
   124  	org2IntermediateCA, err := ioutil.ReadFile(filepath.Join("testdata",
   125  		"Org2-child1-cert.pem"))
   126  	org2IntermediateServer1Key, err := ioutil.ReadFile(filepath.Join("testdata",
   127  		"Org2-child1-server1-key.pem"))
   128  	org2IntermediateServer1Cert, err := ioutil.ReadFile(filepath.Join("testdata",
   129  		"Org2-child1-server1-cert.pem"))
   130  	ordererOrgCA, err := ioutil.ReadFile(filepath.Join("testdata", "Org3-cert.pem"))
   131  	ordererOrgServer1Key, err := ioutil.ReadFile(filepath.Join("testdata",
   132  		"Org3-server1-key.pem"))
   133  	ordererOrgServer1Cert, err := ioutil.ReadFile(filepath.Join("testdata",
   134  		"Org3-server1-cert.pem"))
   135  
   136  	if err != nil {
   137  		t.Fatalf("Failed to load test certificates: %v", err)
   138  	}
   139  
   140  	// create test MSPConfigs
   141  	org1MSPConf, err := createMSPConfig([][]byte{org2CA}, [][]byte{org1CA},
   142  		[][]byte{}, "Org1MSP")
   143  	org2MSPConf, err := createMSPConfig([][]byte{org1CA}, [][]byte{org2CA},
   144  		[][]byte{}, "Org2MSP")
   145  	org2IntermediateMSPConf, err := createMSPConfig([][]byte{org1CA},
   146  		[][]byte{org2CA}, [][]byte{org2IntermediateCA}, "Org2IntermediateMSP")
   147  	ordererOrgMSPConf, err := createMSPConfig([][]byte{org1CA},
   148  		[][]byte{ordererOrgCA}, [][]byte{}, "OrdererOrgMSP")
   149  	if err != nil {
   150  		t.Fatalf("Failed to create MSPConfigs (%s)", err)
   151  	}
   152  
   153  	// create test channel create blocks
   154  	channel1Block, err := createConfigBlock("channel1", org1MSPConf,
   155  		ordererOrgMSPConf, "Org1MSP", "OrdererOrgMSP")
   156  	channel2Block, err := createConfigBlock("channel2", org2MSPConf,
   157  		ordererOrgMSPConf, "Org2MSP", "OrdererOrgMSP")
   158  	channel3Block, err := createConfigBlock("channel3", org2IntermediateMSPConf,
   159  		ordererOrgMSPConf, "Org2IntermediateMSP", "OrdererOrgMSP")
   160  
   161  	createChannel := func(cid string, block *cb.Block) {
   162  		viper.Set("peer.tls.enabled", true)
   163  		viper.Set("peer.tls.cert.file", filepath.Join("testdata",
   164  			"Org1-server1-cert.pem"))
   165  		viper.Set("peer.tls.key.file", filepath.Join("testdata",
   166  			"Org1-server1-key.pem"))
   167  		viper.Set("peer.tls.rootcert.file", filepath.Join("testdata",
   168  			"Org1-cert.pem"))
   169  		viper.Set("peer.fileSystemPath", "/var/hyperledger/test/")
   170  		defer os.RemoveAll("/var/hyperledger/test/")
   171  		err := peer.CreateChainFromBlock(block)
   172  		if err != nil {
   173  			t.Fatalf("Failed to create config block (%s)", err)
   174  		}
   175  		t.Logf("Channel %s MSPIDs: (%s)", cid, peer.GetMSPIDs(cid))
   176  	}
   177  
   178  	org1CertPool, err := createCertPool([][]byte{org1CA})
   179  
   180  	if err != nil {
   181  		t.Fatalf("Failed to load root certificates into pool: %v", err)
   182  	}
   183  
   184  	// use server cert as client cert
   185  	org1ClientCert, err := tls.X509KeyPair(org1Server1Cert, org1Server1Key)
   186  	if err != nil {
   187  		t.Fatalf("Failed to load client certificate: %v", err)
   188  	}
   189  	org1Creds := credentials.NewTLS(&tls.Config{
   190  		Certificates: []tls.Certificate{org1ClientCert},
   191  		RootCAs:      org1CertPool,
   192  	})
   193  	org2ClientCert, err := tls.X509KeyPair(org2Server1Cert, org2Server1Key)
   194  	if err != nil {
   195  		t.Fatalf("Failed to load client certificate: %v", err)
   196  	}
   197  	org2Creds := credentials.NewTLS(&tls.Config{
   198  		Certificates: []tls.Certificate{org2ClientCert},
   199  		RootCAs:      org1CertPool,
   200  	})
   201  	org2IntermediateClientCert, err := tls.X509KeyPair(
   202  		org2IntermediateServer1Cert, org2IntermediateServer1Key)
   203  	if err != nil {
   204  		t.Fatalf("Failed to load client certificate: %v", err)
   205  	}
   206  	org2IntermediateCreds := credentials.NewTLS(&tls.Config{
   207  		Certificates: []tls.Certificate{org2IntermediateClientCert},
   208  		RootCAs:      org1CertPool,
   209  	})
   210  	ordererOrgClientCert, err := tls.X509KeyPair(ordererOrgServer1Cert,
   211  		ordererOrgServer1Key)
   212  	if err != nil {
   213  		t.Fatalf("Failed to load client certificate: %v", err)
   214  	}
   215  	ordererOrgCreds := credentials.NewTLS(&tls.Config{
   216  		Certificates: []tls.Certificate{ordererOrgClientCert},
   217  		RootCAs:      org1CertPool,
   218  	})
   219  
   220  	// basic function tests
   221  	var tests = []struct {
   222  		name          string
   223  		listenAddress string
   224  		secureConfig  comm.SecureServerConfig
   225  		createChannel func()
   226  		goodOptions   []grpc.DialOption
   227  		badOptions    []grpc.DialOption
   228  		numAppCAs     int
   229  		numOrdererCAs int
   230  	}{
   231  
   232  		{
   233  			name:          "MutualTLSOrg1Org1",
   234  			listenAddress: fmt.Sprintf("localhost:%d", 4051),
   235  			secureConfig: comm.SecureServerConfig{
   236  				UseTLS:            true,
   237  				ServerCertificate: org1Server1Cert,
   238  				ServerKey:         org1Server1Key,
   239  				ServerRootCAs:     [][]byte{org1CA},
   240  				RequireClientCert: true,
   241  			},
   242  			createChannel: func() { createChannel("channel1", channel1Block) },
   243  			goodOptions:   []grpc.DialOption{grpc.WithTransportCredentials(org1Creds)},
   244  			badOptions:    []grpc.DialOption{grpc.WithTransportCredentials(ordererOrgCreds)},
   245  			numAppCAs:     2, // each channel also has a DEFAULT MSP
   246  			numOrdererCAs: 1,
   247  		},
   248  		{
   249  			name:          "MutualTLSOrg1Org2",
   250  			listenAddress: fmt.Sprintf("localhost:%d", 4052),
   251  			secureConfig: comm.SecureServerConfig{
   252  				UseTLS:            true,
   253  				ServerCertificate: org1Server1Cert,
   254  				ServerKey:         org1Server1Key,
   255  				ServerRootCAs:     [][]byte{org1CA},
   256  				RequireClientCert: true,
   257  			},
   258  			createChannel: func() { createChannel("channel2", channel2Block) },
   259  			goodOptions: []grpc.DialOption{
   260  				grpc.WithTransportCredentials(org2Creds)},
   261  			badOptions: []grpc.DialOption{
   262  				grpc.WithTransportCredentials(ordererOrgCreds)},
   263  			numAppCAs:     4,
   264  			numOrdererCAs: 2,
   265  		},
   266  		{
   267  			name:          "MutualTLSOrg1Org2Intermediate",
   268  			listenAddress: fmt.Sprintf("localhost:%d", 4053),
   269  			secureConfig: comm.SecureServerConfig{
   270  				UseTLS:            true,
   271  				ServerCertificate: org1Server1Cert,
   272  				ServerKey:         org1Server1Key,
   273  				ServerRootCAs:     [][]byte{org1CA},
   274  				RequireClientCert: true,
   275  			},
   276  			createChannel: func() { createChannel("channel3", channel3Block) },
   277  			goodOptions: []grpc.DialOption{
   278  				grpc.WithTransportCredentials(org2IntermediateCreds)},
   279  			badOptions: []grpc.DialOption{
   280  				grpc.WithTransportCredentials(ordererOrgCreds)},
   281  			numAppCAs:     7,
   282  			numOrdererCAs: 3,
   283  		},
   284  	}
   285  
   286  	for _, test := range tests {
   287  		test := test
   288  		t.Run(test.name, func(t *testing.T) {
   289  			t.Logf("Running test %s ...", test.name)
   290  			_, err := peer.CreatePeerServer(test.listenAddress, test.secureConfig)
   291  			if err != nil {
   292  				t.Fatalf("CreatePeerServer failed with error [%s]", err)
   293  			} else {
   294  				assert.NoError(t, err, "CreatePeerServer should not have returned an error")
   295  				// get the server from peer
   296  				server := peer.GetPeerServer()
   297  				assert.NotNil(t, server, "GetPeerServer should not return a nil value")
   298  				// register a GRPC test service
   299  				testpb.RegisterTestServiceServer(server.Server(), &testServiceServer{})
   300  				go server.Start()
   301  				defer server.Stop()
   302  
   303  				// invoke the EmptyCall service with good options but should fail
   304  				// until channel is created and root CAs are updated
   305  				_, err = invokeEmptyCall(test.listenAddress, test.goodOptions)
   306  				assert.Error(t, err, "Expected error invoking the EmptyCall service ")
   307  
   308  				// creating channel should update the trusted client roots
   309  				test.createChannel()
   310  
   311  				// make sure we have the expected number of CAs
   312  				appCAs, ordererCAs := comm.GetCASupport().GetClientRootCAs()
   313  				assert.Equal(t, test.numAppCAs, len(appCAs),
   314  					"Did not find expected number of app CAs for channel")
   315  				assert.Equal(t, test.numOrdererCAs, len(ordererCAs),
   316  					"Did not find expected number of orderer CAs for channel")
   317  
   318  				// invoke the EmptyCall service with good options
   319  				_, err = invokeEmptyCall(test.listenAddress, test.goodOptions)
   320  				assert.NoError(t, err, "Failed to invoke the EmptyCall service")
   321  
   322  				// invoke the EmptyCall service with bad options
   323  				_, err = invokeEmptyCall(test.listenAddress, test.badOptions)
   324  				assert.Error(t, err, "Expected error using bad dial options")
   325  			}
   326  		})
   327  	}
   328  }