github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/core/peer/pkg_test.go (about) 1 /* 2 Copyright IBM Corp. 2017 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 peer_test 18 19 import ( 20 "crypto/tls" 21 "crypto/x509" 22 "errors" 23 "fmt" 24 "io/ioutil" 25 "os" 26 "path/filepath" 27 "testing" 28 "time" 29 30 "google.golang.org/grpc/credentials" 31 32 "golang.org/x/net/context" 33 "google.golang.org/grpc" 34 35 "github.com/golang/protobuf/proto" 36 configtxtest "github.com/hyperledger/fabric/common/configtx/test" 37 "github.com/hyperledger/fabric/core/comm" 38 testpb "github.com/hyperledger/fabric/core/comm/testdata/grpc" 39 "github.com/hyperledger/fabric/core/peer" 40 "github.com/hyperledger/fabric/msp" 41 cb "github.com/hyperledger/fabric/protos/common" 42 mspproto "github.com/hyperledger/fabric/protos/msp" 43 "github.com/spf13/viper" 44 "github.com/stretchr/testify/assert" 45 ) 46 47 // default timeout for grpc connections 48 var timeout = time.Second * 1 49 50 // test server to be registered with the GRPCServer 51 type testServiceServer struct{} 52 53 func (tss *testServiceServer) EmptyCall(context.Context, *testpb.Empty) (*testpb.Empty, error) { 54 return new(testpb.Empty), nil 55 } 56 57 // createCertPool creates an x509.CertPool from an array of PEM-encoded certificates 58 func createCertPool(rootCAs [][]byte) (*x509.CertPool, error) { 59 60 certPool := x509.NewCertPool() 61 for _, rootCA := range rootCAs { 62 if !certPool.AppendCertsFromPEM(rootCA) { 63 return nil, errors.New("Failed to load root certificates") 64 } 65 } 66 return certPool, nil 67 } 68 69 // helper function to invoke the EmptyCall againt the test service 70 func invokeEmptyCall(address string, dialOptions []grpc.DialOption) (*testpb.Empty, error) { 71 72 //add DialOptions 73 dialOptions = append(dialOptions, grpc.WithBlock()) 74 dialOptions = append(dialOptions, grpc.WithTimeout(timeout)) 75 //create GRPC client conn 76 clientConn, err := grpc.Dial(address, dialOptions...) 77 if err != nil { 78 return nil, err 79 } 80 defer clientConn.Close() 81 82 //create GRPC client 83 client := testpb.NewTestServiceClient(clientConn) 84 85 ctx := context.Background() 86 ctx, cancel := context.WithTimeout(ctx, timeout) 87 defer cancel() 88 89 //invoke service 90 empty, err := client.EmptyCall(ctx, new(testpb.Empty)) 91 if err != nil { 92 return nil, err 93 } 94 95 return empty, nil 96 } 97 98 // helper function to build an MSPConfig given root certs 99 func createMSPConfig(rootCerts, intermediateCerts [][]byte, 100 mspID string) (*mspproto.MSPConfig, error) { 101 102 fmspconf := &mspproto.FabricMSPConfig{ 103 RootCerts: rootCerts, 104 IntermediateCerts: intermediateCerts, 105 Name: mspID} 106 107 fmpsjs, err := proto.Marshal(fmspconf) 108 if err != nil { 109 return nil, err 110 } 111 mspconf := &mspproto.MSPConfig{Config: fmpsjs, Type: int32(msp.FABRIC)} 112 return mspconf, nil 113 } 114 115 func createConfigBlock(chainID string, appMSPConf, ordererMSPConf *mspproto.MSPConfig, 116 appOrgID, ordererOrgID string) (*cb.Block, error) { 117 block, err := configtxtest.MakeGenesisBlockFromMSPs(chainID, appMSPConf, ordererMSPConf, appOrgID, ordererOrgID) 118 return block, err 119 } 120 121 func TestUpdateRootsFromConfigBlock(t *testing.T) { 122 // load test certs from testdata 123 org1CA, err := ioutil.ReadFile(filepath.Join("testdata", "Org1-cert.pem")) 124 org1Server1Key, err := ioutil.ReadFile(filepath.Join("testdata", 125 "Org1-server1-key.pem")) 126 org1Server1Cert, err := ioutil.ReadFile(filepath.Join("testdata", 127 "Org1-server1-cert.pem")) 128 org2CA, err := ioutil.ReadFile(filepath.Join("testdata", "Org2-cert.pem")) 129 org2Server1Key, err := ioutil.ReadFile(filepath.Join("testdata", 130 "Org2-server1-key.pem")) 131 org2Server1Cert, err := ioutil.ReadFile(filepath.Join("testdata", 132 "Org2-server1-cert.pem")) 133 org2IntermediateCA, err := ioutil.ReadFile(filepath.Join("testdata", 134 "Org2-child1-cert.pem")) 135 org2IntermediateServer1Key, err := ioutil.ReadFile(filepath.Join("testdata", 136 "Org2-child1-server1-key.pem")) 137 org2IntermediateServer1Cert, err := ioutil.ReadFile(filepath.Join("testdata", 138 "Org2-child1-server1-cert.pem")) 139 ordererOrgCA, err := ioutil.ReadFile(filepath.Join("testdata", "Org3-cert.pem")) 140 ordererOrgServer1Key, err := ioutil.ReadFile(filepath.Join("testdata", 141 "Org3-server1-key.pem")) 142 ordererOrgServer1Cert, err := ioutil.ReadFile(filepath.Join("testdata", 143 "Org3-server1-cert.pem")) 144 145 if err != nil { 146 t.Fatalf("Failed to load test certificates: %v", err) 147 } 148 149 // create test MSPConfigs 150 org1MSPConf, err := createMSPConfig([][]byte{org1CA}, [][]byte{}, "Org1MSP") 151 org2MSPConf, err := createMSPConfig([][]byte{org2CA}, [][]byte{}, "Org2MSP") 152 org2IntermediateMSPConf, err := createMSPConfig([][]byte{org2CA}, 153 [][]byte{org2IntermediateCA}, "Org2IntermediateMSP") 154 ordererOrgMSPConf, err := createMSPConfig([][]byte{ordererOrgCA}, 155 [][]byte{}, "OrdererOrgMSP") 156 if err != nil { 157 t.Fatalf("Failed to create MSPConfigs (%s)", err) 158 } 159 160 // create test channel create blocks 161 channel1Block, err := createConfigBlock("channel1", org1MSPConf, 162 ordererOrgMSPConf, "Org1MSP", "OrdererOrgMSP") 163 channel2Block, err := createConfigBlock("channel2", org2MSPConf, 164 ordererOrgMSPConf, "Org2MSP", "OrdererOrgMSP") 165 channel3Block, err := createConfigBlock("channel3", org2IntermediateMSPConf, 166 ordererOrgMSPConf, "Org2IntermediateMSP", "OrdererOrgMSP") 167 168 createChannel := func(cid string, block *cb.Block) { 169 viper.Set("peer.tls.enabled", true) 170 viper.Set("peer.tls.cert.file", filepath.Join("testdata", 171 "Org1-server1-cert.pem")) 172 viper.Set("peer.tls.key.file", filepath.Join("testdata", 173 "Org1-server1-key.pem")) 174 viper.Set("peer.tls.rootcert.file", filepath.Join("testdata", 175 "Org1-cert.pem")) 176 viper.Set("peer.fileSystemPath", "/var/hyperledger/test/") 177 defer os.RemoveAll("/var/hyperledger/test/") 178 err := peer.CreateChainFromBlock(block) 179 if err != nil { 180 t.Fatalf("Failed to create config block (%s)", err) 181 } 182 t.Logf("Channel %s MSPIDs: (%s)", cid, peer.GetMSPIDs(cid)) 183 } 184 185 org1CertPool, err := createCertPool([][]byte{org1CA}) 186 187 if err != nil { 188 t.Fatalf("Failed to load root certificates into pool: %v", err) 189 } 190 191 // use server cert as client cert 192 org1ClientCert, err := tls.X509KeyPair(org1Server1Cert, org1Server1Key) 193 if err != nil { 194 t.Fatalf("Failed to load client certificate: %v", err) 195 } 196 org1Creds := credentials.NewTLS(&tls.Config{ 197 Certificates: []tls.Certificate{org1ClientCert}, 198 RootCAs: org1CertPool, 199 }) 200 org2ClientCert, err := tls.X509KeyPair(org2Server1Cert, org2Server1Key) 201 if err != nil { 202 t.Fatalf("Failed to load client certificate: %v", err) 203 } 204 org2Creds := credentials.NewTLS(&tls.Config{ 205 Certificates: []tls.Certificate{org2ClientCert}, 206 RootCAs: org1CertPool, 207 }) 208 org2IntermediateClientCert, err := tls.X509KeyPair( 209 org2IntermediateServer1Cert, org2IntermediateServer1Key) 210 if err != nil { 211 t.Fatalf("Failed to load client certificate: %v", err) 212 } 213 org2IntermediateCreds := credentials.NewTLS(&tls.Config{ 214 Certificates: []tls.Certificate{org2IntermediateClientCert}, 215 RootCAs: org1CertPool, 216 }) 217 ordererOrgClientCert, err := tls.X509KeyPair(ordererOrgServer1Cert, 218 ordererOrgServer1Key) 219 if err != nil { 220 t.Fatalf("Failed to load client certificate: %v", err) 221 } 222 ordererOrgCreds := credentials.NewTLS(&tls.Config{ 223 Certificates: []tls.Certificate{ordererOrgClientCert}, 224 RootCAs: org1CertPool, 225 }) 226 227 // basic function tests 228 var tests = []struct { 229 name string 230 listenAddress string 231 secureConfig comm.SecureServerConfig 232 createChannel func() 233 goodOptions []grpc.DialOption 234 badOptions []grpc.DialOption 235 numAppCAs int 236 numOrdererCAs int 237 }{ 238 239 { 240 name: "MutualTLSOrg1Org1", 241 listenAddress: fmt.Sprintf("localhost:%d", 4051), 242 secureConfig: comm.SecureServerConfig{ 243 UseTLS: true, 244 ServerCertificate: org1Server1Cert, 245 ServerKey: org1Server1Key, 246 ServerRootCAs: [][]byte{org1CA}, 247 RequireClientCert: true, 248 }, 249 createChannel: func() { createChannel("channel1", channel1Block) }, 250 goodOptions: []grpc.DialOption{grpc.WithTransportCredentials(org1Creds)}, 251 badOptions: []grpc.DialOption{grpc.WithTransportCredentials(ordererOrgCreds)}, 252 numAppCAs: 2, // each channel also has a DEFAULT MSP 253 numOrdererCAs: 1, 254 }, 255 { 256 name: "MutualTLSOrg1Org2", 257 listenAddress: fmt.Sprintf("localhost:%d", 4052), 258 secureConfig: comm.SecureServerConfig{ 259 UseTLS: true, 260 ServerCertificate: org1Server1Cert, 261 ServerKey: org1Server1Key, 262 ServerRootCAs: [][]byte{org1CA}, 263 RequireClientCert: true, 264 }, 265 createChannel: func() { createChannel("channel2", channel2Block) }, 266 goodOptions: []grpc.DialOption{ 267 grpc.WithTransportCredentials(org2Creds)}, 268 badOptions: []grpc.DialOption{ 269 grpc.WithTransportCredentials(ordererOrgCreds)}, 270 numAppCAs: 4, 271 numOrdererCAs: 2, 272 }, 273 { 274 name: "MutualTLSOrg1Org2Intermediate", 275 listenAddress: fmt.Sprintf("localhost:%d", 4053), 276 secureConfig: comm.SecureServerConfig{ 277 UseTLS: true, 278 ServerCertificate: org1Server1Cert, 279 ServerKey: org1Server1Key, 280 ServerRootCAs: [][]byte{org1CA}, 281 RequireClientCert: true, 282 }, 283 createChannel: func() { createChannel("channel3", channel3Block) }, 284 goodOptions: []grpc.DialOption{ 285 grpc.WithTransportCredentials(org2IntermediateCreds)}, 286 badOptions: []grpc.DialOption{ 287 grpc.WithTransportCredentials(ordererOrgCreds)}, 288 numAppCAs: 7, 289 numOrdererCAs: 3, 290 }, 291 } 292 293 for _, test := range tests { 294 test := test 295 t.Run(test.name, func(t *testing.T) { 296 t.Logf("Running test %s ...", test.name) 297 _, err := peer.CreatePeerServer(test.listenAddress, test.secureConfig) 298 if err != nil { 299 t.Fatalf("CreatePeerServer failed with error [%s]", err) 300 } else { 301 assert.NoError(t, err, "CreatePeerServer should not have returned an error") 302 // get the server from peer 303 server := peer.GetPeerServer() 304 assert.NotNil(t, server, "GetPeerServer should not return a nil value") 305 // register a GRPC test service 306 testpb.RegisterTestServiceServer(server.Server(), &testServiceServer{}) 307 go server.Start() 308 defer server.Stop() 309 310 // invoke the EmptyCall service with good options but should fail 311 // until channel is created and root CAs are updated 312 _, err = invokeEmptyCall(test.listenAddress, test.goodOptions) 313 assert.Error(t, err, "Expected error invoking the EmptyCall service ") 314 315 // creating channel should update the trusted client roots 316 test.createChannel() 317 318 // make sure we have the expected number of CAs 319 appCAs, ordererCAs := comm.GetCASupport().GetClientRootCAs() 320 assert.Equal(t, test.numAppCAs, len(appCAs), 321 "Did not find expected number of app CAs for channel") 322 assert.Equal(t, test.numOrdererCAs, len(ordererCAs), 323 "Did not find expected number of orderer CAs for channel") 324 325 // invoke the EmptyCall service with good options 326 _, err = invokeEmptyCall(test.listenAddress, test.goodOptions) 327 assert.NoError(t, err, "Failed to invoke the EmptyCall service") 328 329 // invoke the EmptyCall service with bad options 330 _, err = invokeEmptyCall(test.listenAddress, test.badOptions) 331 assert.Error(t, err, "Expected error using bad dial options") 332 } 333 }) 334 } 335 }