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 }