github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/core/comm/connection_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package comm
    18  
    19  import (
    20  	"crypto/tls"
    21  	"fmt"
    22  	"io/ioutil"
    23  	"net"
    24  	"path/filepath"
    25  	"sync/atomic"
    26  	"testing"
    27  	"time"
    28  
    29  	testpb "github.com/hyperledger/fabric/core/comm/testdata/grpc"
    30  	"github.com/hyperledger/fabric/core/testutil"
    31  	"github.com/spf13/viper"
    32  	"github.com/stretchr/testify/assert"
    33  	"golang.org/x/net/context"
    34  	"google.golang.org/grpc"
    35  )
    36  
    37  const (
    38  	numOrgs      = 2
    39  	numChildOrgs = 2
    40  )
    41  
    42  //string for cert filenames
    43  var (
    44  	orgCACert   = filepath.Join("testdata", "certs", "Org%d-cert.pem")
    45  	childCACert = filepath.Join("testdata", "certs", "Org%d-child%d-cert.pem")
    46  )
    47  
    48  var badPEM = `-----BEGIN CERTIFICATE-----
    49  MIICRDCCAemgAwIBAgIJALwW//dz2ZBvMAoGCCqGSM49BAMCMH4xCzAJBgNVBAYT
    50  AlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2Nv
    51  MRgwFgYDVQQKDA9MaW51eEZvdW5kYXRpb24xFDASBgNVBAsMC0h5cGVybGVkZ2Vy
    52  MRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMTYxMjA0MjIzMDE4WhcNMjYxMjAyMjIz
    53  MDE4WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UE
    54  BwwNU2FuIEZyYW5jaXNjbzEYMBYGA1UECgwPTGludXhGb3VuZGF0aW9uMRQwEgYD
    55  VQQLDAtIeXBlcmxlZGdlcjESMBAGA1UEAwwJbG9jYWxob3N0MFkwEwYHKoZIzj0C
    56  -----END CERTIFICATE-----
    57  `
    58  
    59  func TestConnection_Correct(t *testing.T) {
    60  	testutil.SetupTestConfig()
    61  	viper.Set("ledger.blockchain.deploy-system-chaincode", "false")
    62  	peerAddress := GetPeerTestingAddress("7051")
    63  	var tmpConn *grpc.ClientConn
    64  	var err error
    65  	if TLSEnabled() {
    66  		tmpConn, err = NewClientConnectionWithAddress(peerAddress, true, true, InitTLSForPeer())
    67  	}
    68  	tmpConn, err = NewClientConnectionWithAddress(peerAddress, true, false, nil)
    69  	if err != nil {
    70  		t.Fatalf("error connection to server at host:port = %s\n", peerAddress)
    71  	}
    72  
    73  	tmpConn.Close()
    74  }
    75  
    76  func TestConnection_WrongAddress(t *testing.T) {
    77  	testutil.SetupTestConfig()
    78  	viper.Set("ledger.blockchain.deploy-system-chaincode", "false")
    79  	peerAddress := GetPeerTestingAddress("7052")
    80  	var tmpConn *grpc.ClientConn
    81  	var err error
    82  	if TLSEnabled() {
    83  		tmpConn, err = NewClientConnectionWithAddress(peerAddress, true, true, InitTLSForPeer())
    84  	}
    85  	tmpConn, err = NewClientConnectionWithAddress(peerAddress, true, false, nil)
    86  	if err == nil {
    87  		fmt.Printf("error connection to server -  at host:port = %s\n", peerAddress)
    88  		t.Error("error connection to server - connection should fail")
    89  		tmpConn.Close()
    90  	}
    91  }
    92  
    93  // utility function to load up our test root certificates from testdata/certs
    94  func loadRootCAs() [][]byte {
    95  
    96  	rootCAs := [][]byte{}
    97  	for i := 1; i <= numOrgs; i++ {
    98  		root, err := ioutil.ReadFile(fmt.Sprintf(orgCACert, i))
    99  		if err != nil {
   100  			return [][]byte{}
   101  		}
   102  		rootCAs = append(rootCAs, root)
   103  		for j := 1; j <= numChildOrgs; j++ {
   104  			root, err := ioutil.ReadFile(fmt.Sprintf(childCACert, i, j))
   105  			if err != nil {
   106  				return [][]byte{}
   107  			}
   108  			rootCAs = append(rootCAs, root)
   109  		}
   110  	}
   111  	return rootCAs
   112  }
   113  
   114  func TestCASupport(t *testing.T) {
   115  
   116  	rootCAs := loadRootCAs()
   117  	t.Logf("loaded %d root certificates", len(rootCAs))
   118  	if len(rootCAs) != 6 {
   119  		t.Fatalf("failed to load root certificates")
   120  	}
   121  
   122  	cas := GetCASupport()
   123  	cas.AppRootCAsByChain["channel1"] = [][]byte{rootCAs[0]}
   124  	cas.AppRootCAsByChain["channel2"] = [][]byte{rootCAs[1]}
   125  	cas.AppRootCAsByChain["channel3"] = [][]byte{rootCAs[2]}
   126  	cas.OrdererRootCAsByChain["channel1"] = [][]byte{(rootCAs[3])}
   127  	cas.OrdererRootCAsByChain["channel2"] = [][]byte{rootCAs[4]}
   128  	cas.ServerRootCAs = [][]byte{rootCAs[5]}
   129  	cas.ClientRootCAs = [][]byte{rootCAs[5]}
   130  
   131  	appServerRoots, ordererServerRoots := cas.GetServerRootCAs()
   132  	t.Logf("%d appServerRoots | %d ordererServerRoots", len(appServerRoots),
   133  		len(ordererServerRoots))
   134  	assert.Equal(t, 4, len(appServerRoots), "Expected 4 app server root CAs")
   135  	assert.Equal(t, 2, len(ordererServerRoots), "Expected 2 orderer server root CAs")
   136  
   137  	appClientRoots, ordererClientRoots := cas.GetClientRootCAs()
   138  	t.Logf("%d appClientRoots | %d ordererClientRoots", len(appClientRoots),
   139  		len(ordererClientRoots))
   140  	assert.Equal(t, 4, len(appClientRoots), "Expected 4 app client root CAs")
   141  	assert.Equal(t, 2, len(ordererClientRoots), "Expected 4 orderer client root CAs")
   142  
   143  	// make sure we really have a singleton
   144  	casClone := GetCASupport()
   145  	assert.Exactly(t, casClone, cas, "Expected GetCASupport to be a singleton")
   146  
   147  	creds, _ := cas.GetDeliverServiceCredentials("channel1")
   148  	assert.Equal(t, "1.2", creds.Info().SecurityVersion,
   149  		"Expected Security version to be 1.2")
   150  	creds = cas.GetPeerCredentials(tls.Certificate{})
   151  	assert.Equal(t, "1.2", creds.Info().SecurityVersion,
   152  		"Expected Security version to be 1.2")
   153  
   154  	// append some bad certs and make sure things still work
   155  	cas.ServerRootCAs = append(cas.ServerRootCAs, []byte("badcert"))
   156  	cas.ServerRootCAs = append(cas.ServerRootCAs, []byte(badPEM))
   157  	creds, _ = cas.GetDeliverServiceCredentials("channel1")
   158  	assert.Equal(t, "1.2", creds.Info().SecurityVersion,
   159  		"Expected Security version to be 1.2")
   160  	creds = cas.GetPeerCredentials(tls.Certificate{})
   161  	assert.Equal(t, "1.2", creds.Info().SecurityVersion,
   162  		"Expected Security version to be 1.2")
   163  
   164  }
   165  
   166  type srv struct {
   167  	port int
   168  	GRPCServer
   169  	caCert   []byte
   170  	serviced uint32
   171  }
   172  
   173  func (s *srv) assertServiced(t *testing.T) {
   174  	assert.Equal(t, uint32(1), atomic.LoadUint32(&s.serviced))
   175  	atomic.StoreUint32(&s.serviced, 0)
   176  }
   177  
   178  func (s *srv) EmptyCall(context.Context, *testpb.Empty) (*testpb.Empty, error) {
   179  	atomic.StoreUint32(&s.serviced, 1)
   180  	return &testpb.Empty{}, nil
   181  }
   182  
   183  func newServer(org string, port int) *srv {
   184  	certs := map[string][]byte{
   185  		"ca.crt":     nil,
   186  		"server.crt": nil,
   187  		"server.key": nil,
   188  	}
   189  	for suffix := range certs {
   190  		fName := filepath.Join("testdata", "impersonation", org, suffix)
   191  		cert, err := ioutil.ReadFile(fName)
   192  		if err != nil {
   193  			panic(fmt.Errorf("Failed reading %s: %v", fName, err))
   194  		}
   195  		certs[suffix] = cert
   196  	}
   197  	l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
   198  	if err != nil {
   199  		panic(fmt.Errorf("Failed listening on port %d: %v", port, err))
   200  	}
   201  	gSrv, err := NewGRPCServerFromListener(l, SecureServerConfig{
   202  		ServerCertificate: certs["server.crt"],
   203  		ServerKey:         certs["server.key"],
   204  		UseTLS:            true,
   205  	})
   206  	if err != nil {
   207  		panic(fmt.Errorf("Failed starting gRPC server: %v", err))
   208  	}
   209  	s := &srv{
   210  		port:       port,
   211  		caCert:     certs["ca.crt"],
   212  		GRPCServer: gSrv,
   213  	}
   214  	testpb.RegisterTestServiceServer(gSrv.Server(), s)
   215  	go s.Start()
   216  	return s
   217  }
   218  
   219  func TestImpersonation(t *testing.T) {
   220  	// Scenario: We have 2 organizations: orgA, orgB
   221  	// and each of them are in their respected channels- A, B.
   222  	// The test would obtain credentials.TransportCredentials by calling GetDeliverServiceCredentials.
   223  	// Each organization would have its own gRPC server (srvA and srvB) with a TLS certificate
   224  	// signed by its root CA and with a SAN entry of 'localhost'.
   225  	// We test the following assertions:
   226  	// 1) Invocation with GetDeliverServiceCredentials("A") to srvA succeeds
   227  	// 2) Invocation with GetDeliverServiceCredentials("B") to srvB succeeds
   228  	// 3) Invocation with GetDeliverServiceCredentials("A") to srvB fails
   229  	// 4) Invocation with GetDeliverServiceCredentials("B") to srvA fails
   230  
   231  	osA := newServer("orgA", 7070)
   232  	defer osA.Stop()
   233  	osB := newServer("orgB", 7080)
   234  	defer osB.Stop()
   235  	time.Sleep(time.Second)
   236  
   237  	cas := GetCASupport()
   238  	_, err := GetCASupport().GetDeliverServiceCredentials("C")
   239  	assert.Error(t, err)
   240  
   241  	cas.OrdererRootCAsByChain["A"] = [][]byte{osA.caCert}
   242  	cas.OrdererRootCAsByChain["B"] = [][]byte{osB.caCert}
   243  
   244  	testInvoke(t, "A", osA, true)
   245  	testInvoke(t, "B", osB, true)
   246  	testInvoke(t, "A", osB, false)
   247  	testInvoke(t, "B", osA, false)
   248  
   249  }
   250  
   251  func testInvoke(t *testing.T, channelID string, s *srv, shouldSucceed bool) {
   252  	creds, err := GetCASupport().GetDeliverServiceCredentials(channelID)
   253  	assert.NoError(t, err)
   254  	endpoint := fmt.Sprintf("localhost:%d", s.port)
   255  	conn, err := grpc.Dial(endpoint, grpc.WithTimeout(time.Second*3), grpc.WithTransportCredentials(creds), grpc.WithBlock())
   256  	if shouldSucceed {
   257  		assert.NoError(t, err)
   258  		defer conn.Close()
   259  	} else {
   260  		assert.Error(t, err)
   261  		assert.Contains(t, err.Error(), "certificate signed by unknown authority")
   262  		return
   263  	}
   264  	client := testpb.NewTestServiceClient(conn)
   265  	_, err = client.EmptyCall(context.Background(), &testpb.Empty{})
   266  	assert.NoError(t, err)
   267  	s.assertServiced(t)
   268  }