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 }