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 }