github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/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  	//some random port
    80  	peerAddress := GetPeerTestingAddress("10287")
    81  	var tmpConn *grpc.ClientConn
    82  	var err error
    83  	if TLSEnabled() {
    84  		tmpConn, err = NewClientConnectionWithAddress(peerAddress, true, true, InitTLSForPeer())
    85  	}
    86  	tmpConn, err = NewClientConnectionWithAddress(peerAddress, true, false, nil)
    87  	if err == nil {
    88  		fmt.Printf("error connection to server -  at host:port = %s\n", peerAddress)
    89  		t.Error("error connection to server - connection should fail")
    90  		tmpConn.Close()
    91  	}
    92  }
    93  
    94  // utility function to load up our test root certificates from testdata/certs
    95  func loadRootCAs() [][]byte {
    96  
    97  	rootCAs := [][]byte{}
    98  	for i := 1; i <= numOrgs; i++ {
    99  		root, err := ioutil.ReadFile(fmt.Sprintf(orgCACert, i))
   100  		if err != nil {
   101  			return [][]byte{}
   102  		}
   103  		rootCAs = append(rootCAs, root)
   104  		for j := 1; j <= numChildOrgs; j++ {
   105  			root, err := ioutil.ReadFile(fmt.Sprintf(childCACert, i, j))
   106  			if err != nil {
   107  				return [][]byte{}
   108  			}
   109  			rootCAs = append(rootCAs, root)
   110  		}
   111  	}
   112  	return rootCAs
   113  }
   114  
   115  func TestCASupport(t *testing.T) {
   116  
   117  	rootCAs := loadRootCAs()
   118  	t.Logf("loaded %d root certificates", len(rootCAs))
   119  	if len(rootCAs) != 6 {
   120  		t.Fatalf("failed to load root certificates")
   121  	}
   122  
   123  	cas := GetCASupport()
   124  	cas.AppRootCAsByChain["channel1"] = [][]byte{rootCAs[0]}
   125  	cas.AppRootCAsByChain["channel2"] = [][]byte{rootCAs[1]}
   126  	cas.AppRootCAsByChain["channel3"] = [][]byte{rootCAs[2]}
   127  	cas.OrdererRootCAsByChain["channel1"] = [][]byte{(rootCAs[3])}
   128  	cas.OrdererRootCAsByChain["channel2"] = [][]byte{rootCAs[4]}
   129  	cas.ServerRootCAs = [][]byte{rootCAs[5]}
   130  	cas.ClientRootCAs = [][]byte{rootCAs[5]}
   131  
   132  	appServerRoots, ordererServerRoots := cas.GetServerRootCAs()
   133  	t.Logf("%d appServerRoots | %d ordererServerRoots", len(appServerRoots),
   134  		len(ordererServerRoots))
   135  	assert.Equal(t, 4, len(appServerRoots), "Expected 4 app server root CAs")
   136  	assert.Equal(t, 2, len(ordererServerRoots), "Expected 2 orderer server root CAs")
   137  
   138  	appClientRoots, ordererClientRoots := cas.GetClientRootCAs()
   139  	t.Logf("%d appClientRoots | %d ordererClientRoots", len(appClientRoots),
   140  		len(ordererClientRoots))
   141  	assert.Equal(t, 4, len(appClientRoots), "Expected 4 app client root CAs")
   142  	assert.Equal(t, 2, len(ordererClientRoots), "Expected 4 orderer client root CAs")
   143  
   144  	// make sure we really have a singleton
   145  	casClone := GetCASupport()
   146  	assert.Exactly(t, casClone, cas, "Expected GetCASupport to be a singleton")
   147  
   148  	creds, _ := cas.GetDeliverServiceCredentials("channel1")
   149  	assert.Equal(t, "1.2", creds.Info().SecurityVersion,
   150  		"Expected Security version to be 1.2")
   151  	creds = cas.GetPeerCredentials(tls.Certificate{})
   152  	assert.Equal(t, "1.2", creds.Info().SecurityVersion,
   153  		"Expected Security version to be 1.2")
   154  
   155  	// append some bad certs and make sure things still work
   156  	cas.ServerRootCAs = append(cas.ServerRootCAs, []byte("badcert"))
   157  	cas.ServerRootCAs = append(cas.ServerRootCAs, []byte(badPEM))
   158  	creds, _ = cas.GetDeliverServiceCredentials("channel1")
   159  	assert.Equal(t, "1.2", creds.Info().SecurityVersion,
   160  		"Expected Security version to be 1.2")
   161  	creds = cas.GetPeerCredentials(tls.Certificate{})
   162  	assert.Equal(t, "1.2", creds.Info().SecurityVersion,
   163  		"Expected Security version to be 1.2")
   164  
   165  }
   166  
   167  type srv struct {
   168  	port int
   169  	GRPCServer
   170  	caCert   []byte
   171  	serviced uint32
   172  }
   173  
   174  func (s *srv) assertServiced(t *testing.T) {
   175  	assert.Equal(t, uint32(1), atomic.LoadUint32(&s.serviced))
   176  	atomic.StoreUint32(&s.serviced, 0)
   177  }
   178  
   179  func (s *srv) EmptyCall(context.Context, *testpb.Empty) (*testpb.Empty, error) {
   180  	atomic.StoreUint32(&s.serviced, 1)
   181  	return &testpb.Empty{}, nil
   182  }
   183  
   184  func newServer(org string, port int) *srv {
   185  	certs := map[string][]byte{
   186  		"ca.crt":     nil,
   187  		"server.crt": nil,
   188  		"server.key": nil,
   189  	}
   190  	for suffix := range certs {
   191  		fName := filepath.Join("testdata", "impersonation", org, suffix)
   192  		cert, err := ioutil.ReadFile(fName)
   193  		if err != nil {
   194  			panic(fmt.Errorf("Failed reading %s: %v", fName, err))
   195  		}
   196  		certs[suffix] = cert
   197  	}
   198  	l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
   199  	if err != nil {
   200  		panic(fmt.Errorf("Failed listening on port %d: %v", port, err))
   201  	}
   202  	gSrv, err := NewGRPCServerFromListener(l, SecureServerConfig{
   203  		ServerCertificate: certs["server.crt"],
   204  		ServerKey:         certs["server.key"],
   205  		UseTLS:            true,
   206  	})
   207  	if err != nil {
   208  		panic(fmt.Errorf("Failed starting gRPC server: %v", err))
   209  	}
   210  	s := &srv{
   211  		port:       port,
   212  		caCert:     certs["ca.crt"],
   213  		GRPCServer: gSrv,
   214  	}
   215  	testpb.RegisterTestServiceServer(gSrv.Server(), s)
   216  	go s.Start()
   217  	return s
   218  }
   219  
   220  func TestImpersonation(t *testing.T) {
   221  	// Scenario: We have 2 organizations: orgA, orgB
   222  	// and each of them are in their respected channels- A, B.
   223  	// The test would obtain credentials.TransportCredentials by calling GetDeliverServiceCredentials.
   224  	// Each organization would have its own gRPC server (srvA and srvB) with a TLS certificate
   225  	// signed by its root CA and with a SAN entry of 'localhost'.
   226  	// We test the following assertions:
   227  	// 1) Invocation with GetDeliverServiceCredentials("A") to srvA succeeds
   228  	// 2) Invocation with GetDeliverServiceCredentials("B") to srvB succeeds
   229  	// 3) Invocation with GetDeliverServiceCredentials("A") to srvB fails
   230  	// 4) Invocation with GetDeliverServiceCredentials("B") to srvA fails
   231  
   232  	osA := newServer("orgA", 7070)
   233  	defer osA.Stop()
   234  	osB := newServer("orgB", 7080)
   235  	defer osB.Stop()
   236  	time.Sleep(time.Second)
   237  
   238  	cas := GetCASupport()
   239  	_, err := GetCASupport().GetDeliverServiceCredentials("C")
   240  	assert.Error(t, err)
   241  
   242  	cas.OrdererRootCAsByChain["A"] = [][]byte{osA.caCert}
   243  	cas.OrdererRootCAsByChain["B"] = [][]byte{osB.caCert}
   244  
   245  	testInvoke(t, "A", osA, true)
   246  	testInvoke(t, "B", osB, true)
   247  	testInvoke(t, "A", osB, false)
   248  	testInvoke(t, "B", osA, false)
   249  
   250  }
   251  
   252  func testInvoke(t *testing.T, channelID string, s *srv, shouldSucceed bool) {
   253  	creds, err := GetCASupport().GetDeliverServiceCredentials(channelID)
   254  	assert.NoError(t, err)
   255  	endpoint := fmt.Sprintf("localhost:%d", s.port)
   256  	conn, err := grpc.Dial(endpoint, grpc.WithTimeout(time.Second*3), grpc.WithTransportCredentials(creds), grpc.WithBlock())
   257  	if shouldSucceed {
   258  		assert.NoError(t, err)
   259  		defer conn.Close()
   260  	} else {
   261  		assert.Error(t, err)
   262  		assert.Contains(t, err.Error(), "certificate signed by unknown authority")
   263  		return
   264  	}
   265  	client := testpb.NewTestServiceClient(conn)
   266  	_, err = client.EmptyCall(context.Background(), &testpb.Empty{})
   267  	assert.NoError(t, err)
   268  	s.assertServiced(t)
   269  }