github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/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 "path/filepath" 26 "testing" 27 "time" 28 29 "google.golang.org/grpc/credentials" 30 31 "golang.org/x/net/context" 32 "google.golang.org/grpc" 33 34 "github.com/golang/protobuf/proto" 35 configtxtest "github.com/hyperledger/fabric/common/configtx/test" 36 "github.com/hyperledger/fabric/core/comm" 37 testpb "github.com/hyperledger/fabric/core/comm/testdata/grpc" 38 "github.com/hyperledger/fabric/core/peer" 39 "github.com/hyperledger/fabric/msp" 40 cb "github.com/hyperledger/fabric/protos/common" 41 mspproto "github.com/hyperledger/fabric/protos/msp" 42 "github.com/spf13/viper" 43 "github.com/stretchr/testify/assert" 44 ) 45 46 // default timeout for grpc connections 47 var timeout = time.Second * 1 48 49 // test server to be registered with the GRPCServer 50 type testServiceServer struct{} 51 52 func (tss *testServiceServer) EmptyCall(context.Context, *testpb.Empty) (*testpb.Empty, error) { 53 return new(testpb.Empty), nil 54 } 55 56 // createCertPool creates an x509.CertPool from an array of PEM-encoded certificates 57 func createCertPool(rootCAs [][]byte) (*x509.CertPool, error) { 58 59 certPool := x509.NewCertPool() 60 for _, rootCA := range rootCAs { 61 if !certPool.AppendCertsFromPEM(rootCA) { 62 return nil, errors.New("Failed to load root certificates") 63 } 64 } 65 return certPool, nil 66 } 67 68 // helper function to invoke the EmptyCall againt the test service 69 func invokeEmptyCall(address string, dialOptions []grpc.DialOption) (*testpb.Empty, error) { 70 71 //add DialOptions 72 dialOptions = append(dialOptions, grpc.WithBlock()) 73 dialOptions = append(dialOptions, grpc.WithTimeout(timeout)) 74 //create GRPC client conn 75 clientConn, err := grpc.Dial(address, dialOptions...) 76 if err != nil { 77 return nil, err 78 } 79 defer clientConn.Close() 80 81 //create GRPC client 82 client := testpb.NewTestServiceClient(clientConn) 83 84 ctx := context.Background() 85 ctx, cancel := context.WithTimeout(ctx, timeout) 86 defer cancel() 87 88 //invoke service 89 empty, err := client.EmptyCall(ctx, new(testpb.Empty)) 90 if err != nil { 91 return nil, err 92 } 93 94 return empty, nil 95 } 96 97 // helper function to build an MSPConfig given root certs 98 func createMSPConfig(rootCerts [][]byte, mspID string) (*mspproto.MSPConfig, error) { 99 fmspconf := &mspproto.FabricMSPConfig{ 100 RootCerts: rootCerts, 101 Name: mspID} 102 103 fmpsjs, err := proto.Marshal(fmspconf) 104 if err != nil { 105 return nil, err 106 } 107 mspconf := &mspproto.MSPConfig{Config: fmpsjs, Type: int32(msp.FABRIC)} 108 return mspconf, nil 109 } 110 111 func createConfigBlock(chainID string, appMSPConf, ordererMSPConf *mspproto.MSPConfig, 112 appOrgID, ordererOrgID string) (*cb.Block, error) { 113 block, err := configtxtest.MakeGenesisBlockFromMSPs(chainID, appMSPConf, ordererMSPConf, appOrgID, ordererOrgID) 114 return block, err 115 } 116 117 func TestCreatePeerServer(t *testing.T) { 118 // load test certs from testdata 119 org1CA, err := ioutil.ReadFile(filepath.Join("testdata", "Org1-cert.pem")) 120 org1Server1Key, err := ioutil.ReadFile(filepath.Join("testdata", "Org1-server1-key.pem")) 121 org1Server1Cert, err := ioutil.ReadFile(filepath.Join("testdata", "Org1-server1-cert.pem")) 122 org1Server2Key, err := ioutil.ReadFile(filepath.Join("testdata", "Org1-server2-key.pem")) 123 org1Server2Cert, err := ioutil.ReadFile(filepath.Join("testdata", "Org1-server2-cert.pem")) 124 org2CA, err := ioutil.ReadFile(filepath.Join("testdata", "Org2-cert.pem")) 125 org2Server1Key, err := ioutil.ReadFile(filepath.Join("testdata", "Org2-server1-key.pem")) 126 org2Server1Cert, err := ioutil.ReadFile(filepath.Join("testdata", "Org2-server1-cert.pem")) 127 org3CA, err := ioutil.ReadFile(filepath.Join("testdata", "Org3-cert.pem")) 128 129 if err != nil { 130 t.Fatalf("Failed to load test certificates: %v", err) 131 } 132 133 // create test MSPConfigs 134 org1MSPConf, err := createMSPConfig([][]byte{org1CA}, "Org1MSP") 135 org2MSPConf, err := createMSPConfig([][]byte{org2CA}, "Org2MSP") 136 org3MSPConf, err := createMSPConfig([][]byte{org3CA}, "Org3MSP") 137 if err != nil { 138 t.Fatalf("Failed to create MSPConfigs (%s)", err) 139 } 140 141 // create test channel create blocks 142 channel1Block, err := createConfigBlock("channel1", org1MSPConf, org3MSPConf, "Org1MSP", "Org3MSP") 143 channel2Block, err := createConfigBlock("channel2", org2MSPConf, org3MSPConf, "Org2MSP", "Org3MSP") 144 145 createChannel := func(cid string, block *cb.Block) { 146 viper.Set("peer.tls.enabled", true) 147 viper.Set("peer.tls.cert.file", filepath.Join("testdata", "Org1-server1-cert.pem")) 148 viper.Set("peer.tls.key.file", filepath.Join("testdata", "Org1-server1-key.pem")) 149 viper.Set("peer.tls.rootcert.file", filepath.Join("testdata", "Org1-cert.pem")) 150 err := peer.CreateChainFromBlock(block) 151 if err != nil { 152 t.Fatalf("Failed to create config block (%s)", err) 153 } 154 t.Logf("Channel %s MSPIDs: (%s)", cid, peer.GetMSPIDs(cid)) 155 appCAs, orgCAs := comm.GetCASupport().GetClientRootCAs() 156 t.Logf("appCAs after update for channel %s: %d", cid, len(appCAs)) 157 t.Logf("orgCAs after update for channel %s: %d", cid, len(orgCAs)) 158 } 159 160 org1CertPool, err := createCertPool([][]byte{org1CA}) 161 org2CertPool, err := createCertPool([][]byte{org2CA}) 162 163 if err != nil { 164 t.Fatalf("Failed to load root certificates into pool: %v", err) 165 } 166 167 org1Creds := credentials.NewClientTLSFromCert(org1CertPool, "") 168 org2Creds := credentials.NewClientTLSFromCert(org2CertPool, "") 169 170 // use server cert as client cert 171 org1ClientCert, err := tls.X509KeyPair(org1Server2Cert, org1Server2Key) 172 if err != nil { 173 t.Fatalf("Failed to load client certificate: %v", err) 174 } 175 org1Org1Creds := credentials.NewTLS(&tls.Config{ 176 Certificates: []tls.Certificate{org1ClientCert}, 177 RootCAs: org1CertPool, 178 }) 179 org2ClientCert, err := tls.X509KeyPair(org2Server1Cert, org2Server1Key) 180 if err != nil { 181 t.Fatalf("Failed to load client certificate: %v", err) 182 } 183 org1Org2Creds := credentials.NewTLS(&tls.Config{ 184 Certificates: []tls.Certificate{org2ClientCert}, 185 RootCAs: org1CertPool, 186 }) 187 188 // basic function tests 189 var tests = []struct { 190 name string 191 listenAddress string 192 secureConfig comm.SecureServerConfig 193 expectError bool 194 createChannel func() 195 goodOptions []grpc.DialOption 196 badOptions []grpc.DialOption 197 }{ 198 199 { 200 name: "NoTLS", 201 listenAddress: fmt.Sprintf("localhost:%d", 4050), 202 secureConfig: comm.SecureServerConfig{ 203 UseTLS: false, 204 }, 205 expectError: false, 206 createChannel: func() {}, 207 goodOptions: []grpc.DialOption{grpc.WithInsecure()}, 208 badOptions: []grpc.DialOption{grpc.WithTransportCredentials(org1Creds)}, 209 }, 210 { 211 name: "ServerTLSOrg1", 212 listenAddress: fmt.Sprintf("localhost:%d", 4051), 213 secureConfig: comm.SecureServerConfig{ 214 UseTLS: true, 215 ServerCertificate: org1Server1Cert, 216 ServerKey: org1Server1Key, 217 ServerRootCAs: [][]byte{org1CA}, 218 }, 219 expectError: false, 220 createChannel: func() {}, 221 goodOptions: []grpc.DialOption{grpc.WithTransportCredentials(org1Creds)}, 222 badOptions: []grpc.DialOption{grpc.WithTransportCredentials(org2Creds)}, 223 }, 224 { 225 name: "MutualTLSOrg1Org1", 226 listenAddress: fmt.Sprintf("localhost:%d", 4052), 227 secureConfig: comm.SecureServerConfig{ 228 UseTLS: true, 229 ServerCertificate: org1Server1Cert, 230 ServerKey: org1Server1Key, 231 ServerRootCAs: [][]byte{org1CA}, 232 RequireClientCert: true, 233 }, 234 expectError: false, 235 createChannel: func() { createChannel("channel1", channel1Block) }, 236 goodOptions: []grpc.DialOption{grpc.WithTransportCredentials(org1Org1Creds)}, 237 badOptions: []grpc.DialOption{grpc.WithTransportCredentials(org1Org2Creds)}, 238 }, 239 { 240 name: "MutualTLSOrg1Org2", 241 listenAddress: fmt.Sprintf("localhost:%d", 4053), 242 secureConfig: comm.SecureServerConfig{ 243 UseTLS: true, 244 ServerCertificate: org1Server1Cert, 245 ServerKey: org1Server1Key, 246 ServerRootCAs: [][]byte{org1CA}, 247 RequireClientCert: true, 248 }, 249 expectError: false, 250 createChannel: func() { createChannel("channel2", channel2Block) }, 251 goodOptions: []grpc.DialOption{grpc.WithTransportCredentials(org1Org2Creds)}, 252 badOptions: []grpc.DialOption{grpc.WithTransportCredentials(org1Creds)}, 253 }, 254 } 255 256 for _, test := range tests { 257 test := test 258 t.Run(test.name, func(t *testing.T) { 259 t.Logf("Running test %s ...", test.name) 260 _, err := peer.CreatePeerServer(test.listenAddress, test.secureConfig) 261 // check to see whether to not we expect an error 262 // we don't check the exact error because the comm package covers these cases 263 if test.expectError { 264 assert.Error(t, err, "CreatePeerServer should have returned an error") 265 } else { 266 assert.NoError(t, err, "CreatePeerServer should not have returned an error") 267 // get the server from peer 268 server := peer.GetPeerServer() 269 assert.NotNil(t, server, "GetPeerServer should not return a nil value") 270 // register a GRPC test service 271 testpb.RegisterTestServiceServer(server.Server(), &testServiceServer{}) 272 go server.Start() 273 defer server.Stop() 274 275 // invoke the EmptyCall service with bad options 276 _, err = invokeEmptyCall(test.listenAddress, test.badOptions) 277 assert.Error(t, err, "Expected error using bad dial options") 278 // creating channel should update the trusted client roots 279 test.createChannel() 280 // invoke the EmptyCall service with good options 281 _, err = invokeEmptyCall(test.listenAddress, test.goodOptions) 282 assert.NoError(t, err, "Failed to invoke the EmptyCall service") 283 284 } 285 }) 286 } 287 }