github.com/true-sqn/fabric@v2.1.1+incompatible/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 "context" 11 "crypto/tls" 12 "crypto/x509" 13 "errors" 14 "io/ioutil" 15 "net" 16 "path/filepath" 17 "testing" 18 "time" 19 20 "github.com/golang/protobuf/proto" 21 cb "github.com/hyperledger/fabric-protos-go/common" 22 mspproto "github.com/hyperledger/fabric-protos-go/msp" 23 pb "github.com/hyperledger/fabric-protos-go/peer" 24 configtxtest "github.com/hyperledger/fabric/common/configtx/test" 25 "github.com/hyperledger/fabric/core/ledger/mock" 26 "github.com/hyperledger/fabric/core/ledger/util" 27 "github.com/hyperledger/fabric/core/peer" 28 "github.com/hyperledger/fabric/internal/pkg/comm" 29 "github.com/hyperledger/fabric/internal/pkg/comm/testpb" 30 "github.com/hyperledger/fabric/msp" 31 "github.com/stretchr/testify/assert" 32 "github.com/stretchr/testify/require" 33 "google.golang.org/grpc" 34 "google.golang.org/grpc/credentials" 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 certPool := x509.NewCertPool() 50 for _, rootCA := range rootCAs { 51 if !certPool.AppendCertsFromPEM(rootCA) { 52 return nil, errors.New("Failed to load root certificates") 53 } 54 } 55 return certPool, nil 56 } 57 58 // helper function to invoke the EmptyCall againt the test service 59 func invokeEmptyCall(address string, dialOptions []grpc.DialOption) (*testpb.Empty, error) { 60 //add DialOptions 61 dialOptions = append(dialOptions, grpc.WithBlock()) 62 ctx, cancel := context.WithTimeout(context.Background(), timeout) 63 defer cancel() 64 //create GRPC client conn 65 clientConn, err := grpc.DialContext(ctx, address, dialOptions...) 66 if err != nil { 67 return nil, err 68 } 69 defer clientConn.Close() 70 71 //create GRPC client 72 client := testpb.NewTestServiceClient(clientConn) 73 74 //invoke service 75 empty, err := client.EmptyCall(context.Background(), new(testpb.Empty)) 76 if err != nil { 77 return nil, err 78 } 79 80 return empty, nil 81 } 82 83 // helper function to build an MSPConfig given root certs 84 func createMSPConfig(rootCerts, tlsRootCerts, tlsIntermediateCerts [][]byte, 85 mspID string) (*mspproto.MSPConfig, error) { 86 87 fmspconf := &mspproto.FabricMSPConfig{ 88 RootCerts: rootCerts, 89 TlsRootCerts: tlsRootCerts, 90 TlsIntermediateCerts: tlsIntermediateCerts, 91 Name: mspID, 92 FabricNodeOus: &mspproto.FabricNodeOUs{ 93 Enable: true, 94 ClientOuIdentifier: &mspproto.FabricOUIdentifier{ 95 OrganizationalUnitIdentifier: "client", 96 }, 97 PeerOuIdentifier: &mspproto.FabricOUIdentifier{ 98 OrganizationalUnitIdentifier: "peer", 99 }, 100 AdminOuIdentifier: &mspproto.FabricOUIdentifier{ 101 OrganizationalUnitIdentifier: "admin", 102 }, 103 }, 104 } 105 106 fmpsjs, err := proto.Marshal(fmspconf) 107 if err != nil { 108 return nil, err 109 } 110 mspconf := &mspproto.MSPConfig{Config: fmpsjs, Type: int32(msp.FABRIC)} 111 return mspconf, nil 112 } 113 114 func createConfigBlock(chainID string, appMSPConf, ordererMSPConf *mspproto.MSPConfig, 115 appOrgID, ordererOrgID string) (*cb.Block, error) { 116 block, err := configtxtest.MakeGenesisBlockFromMSPs(chainID, appMSPConf, ordererMSPConf, appOrgID, ordererOrgID) 117 if block == nil || err != nil { 118 return block, err 119 } 120 121 txsFilter := util.NewTxValidationFlagsSetValue(len(block.Data.Data), pb.TxValidationCode_VALID) 122 block.Metadata.Metadata[cb.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter 123 124 return block, nil 125 } 126 127 func TestUpdateRootsFromConfigBlock(t *testing.T) { 128 // load test certs from testdata 129 org1CA, err := ioutil.ReadFile(filepath.Join("testdata", "Org1-cert.pem")) 130 require.NoError(t, err) 131 org1Server1Key, err := ioutil.ReadFile(filepath.Join("testdata", "Org1-server1-key.pem")) 132 require.NoError(t, err) 133 org1Server1Cert, err := ioutil.ReadFile(filepath.Join("testdata", "Org1-server1-cert.pem")) 134 require.NoError(t, err) 135 org2CA, err := ioutil.ReadFile(filepath.Join("testdata", "Org2-cert.pem")) 136 require.NoError(t, err) 137 org2Server1Key, err := ioutil.ReadFile(filepath.Join("testdata", "Org2-server1-key.pem")) 138 require.NoError(t, err) 139 org2Server1Cert, err := ioutil.ReadFile(filepath.Join("testdata", "Org2-server1-cert.pem")) 140 require.NoError(t, err) 141 org2IntermediateCA, err := ioutil.ReadFile(filepath.Join("testdata", "Org2-child1-cert.pem")) 142 require.NoError(t, err) 143 org2IntermediateServer1Key, err := ioutil.ReadFile(filepath.Join("testdata", "Org2-child1-server1-key.pem")) 144 require.NoError(t, err) 145 org2IntermediateServer1Cert, err := ioutil.ReadFile(filepath.Join("testdata", "Org2-child1-server1-cert.pem")) 146 require.NoError(t, err) 147 ordererOrgCA, err := ioutil.ReadFile(filepath.Join("testdata", "Org3-cert.pem")) 148 require.NoError(t, err) 149 ordererOrgServer1Key, err := ioutil.ReadFile(filepath.Join("testdata", "Org3-server1-key.pem")) 150 require.NoError(t, err) 151 ordererOrgServer1Cert, err := ioutil.ReadFile(filepath.Join("testdata", "Org3-server1-cert.pem")) 152 require.NoError(t, err) 153 154 // create test MSPConfigs 155 org1MSPConf, err := createMSPConfig([][]byte{org2CA}, [][]byte{org1CA}, [][]byte{}, "Org1MSP") 156 require.NoError(t, err) 157 org2MSPConf, err := createMSPConfig([][]byte{org1CA}, [][]byte{org2CA}, [][]byte{}, "Org2MSP") 158 require.NoError(t, err) 159 org2IntermediateMSPConf, err := createMSPConfig([][]byte{org1CA}, [][]byte{org2CA}, [][]byte{org2IntermediateCA}, "Org2IntermediateMSP") 160 require.NoError(t, err) 161 ordererOrgMSPConf, err := createMSPConfig([][]byte{org1CA}, [][]byte{ordererOrgCA}, [][]byte{}, "OrdererOrgMSP") 162 require.NoError(t, err) 163 164 // create test channel create blocks 165 channel1Block, err := createConfigBlock("channel1", org1MSPConf, ordererOrgMSPConf, "Org1MSP", "OrdererOrgMSP") 166 require.NoError(t, err) 167 channel2Block, err := createConfigBlock("channel2", org2MSPConf, ordererOrgMSPConf, "Org2MSP", "OrdererOrgMSP") 168 require.NoError(t, err) 169 channel3Block, err := createConfigBlock("channel3", org2IntermediateMSPConf, ordererOrgMSPConf, "Org2IntermediateMSP", "OrdererOrgMSP") 170 require.NoError(t, err) 171 172 serverConfig := comm.ServerConfig{ 173 SecOpts: comm.SecureOptions{ 174 UseTLS: true, 175 Certificate: org1Server1Cert, 176 Key: org1Server1Key, 177 ServerRootCAs: [][]byte{org1CA}, 178 RequireClientCert: true, 179 }, 180 } 181 182 peerInstance, cleanup := peer.NewTestPeer(t) 183 defer cleanup() 184 peerInstance.CredentialSupport = comm.NewCredentialSupport() 185 186 createChannel := func(t *testing.T, cid string, block *cb.Block) { 187 err = peerInstance.CreateChannel(cid, block, &mock.DeployedChaincodeInfoProvider{}, nil, nil) 188 if err != nil { 189 t.Fatalf("Failed to create config block (%s)", err) 190 } 191 t.Logf("Channel %s MSPIDs: (%s)", cid, peerInstance.GetMSPIDs(cid)) 192 } 193 194 org1CertPool, err := createCertPool([][]byte{org1CA}) 195 require.NoError(t, err) 196 197 // use server cert as client cert 198 org1ClientCert, err := tls.X509KeyPair(org1Server1Cert, org1Server1Key) 199 require.NoError(t, err) 200 201 org1Creds := credentials.NewTLS(&tls.Config{ 202 Certificates: []tls.Certificate{org1ClientCert}, 203 RootCAs: org1CertPool, 204 }) 205 206 org2ClientCert, err := tls.X509KeyPair(org2Server1Cert, org2Server1Key) 207 require.NoError(t, err) 208 org2Creds := credentials.NewTLS(&tls.Config{ 209 Certificates: []tls.Certificate{org2ClientCert}, 210 RootCAs: org1CertPool, 211 }) 212 213 org2IntermediateClientCert, err := tls.X509KeyPair(org2IntermediateServer1Cert, org2IntermediateServer1Key) 214 require.NoError(t, err) 215 org2IntermediateCreds := credentials.NewTLS(&tls.Config{ 216 Certificates: []tls.Certificate{org2IntermediateClientCert}, 217 RootCAs: org1CertPool, 218 }) 219 220 ordererOrgClientCert, err := tls.X509KeyPair(ordererOrgServer1Cert, ordererOrgServer1Key) 221 require.NoError(t, err) 222 223 ordererOrgCreds := credentials.NewTLS(&tls.Config{ 224 Certificates: []tls.Certificate{ordererOrgClientCert}, 225 RootCAs: org1CertPool, 226 }) 227 228 // basic function tests 229 var tests = []struct { 230 name string 231 serverConfig comm.ServerConfig 232 createChannel func(*testing.T) 233 goodOptions []grpc.DialOption 234 badOptions []grpc.DialOption 235 numAppCAs int 236 numOrdererCAs int 237 }{ 238 { 239 name: "MutualTLSOrg1Org1", 240 serverConfig: serverConfig, 241 createChannel: func(t *testing.T) { createChannel(t, "channel1", channel1Block) }, 242 goodOptions: []grpc.DialOption{grpc.WithTransportCredentials(org1Creds)}, 243 badOptions: []grpc.DialOption{grpc.WithTransportCredentials(ordererOrgCreds)}, 244 numAppCAs: 3, // each channel also has a DEFAULT MSP 245 numOrdererCAs: 1, 246 }, 247 { 248 name: "MutualTLSOrg1Org2", 249 serverConfig: serverConfig, 250 createChannel: func(t *testing.T) { createChannel(t, "channel2", channel2Block) }, 251 goodOptions: []grpc.DialOption{ 252 grpc.WithTransportCredentials(org2Creds), 253 }, 254 badOptions: []grpc.DialOption{ 255 grpc.WithTransportCredentials(ordererOrgCreds), 256 }, 257 numAppCAs: 6, 258 numOrdererCAs: 2, 259 }, 260 { 261 name: "MutualTLSOrg1Org2Intermediate", 262 serverConfig: serverConfig, 263 createChannel: func(t *testing.T) { createChannel(t, "channel3", channel3Block) }, 264 goodOptions: []grpc.DialOption{ 265 grpc.WithTransportCredentials(org2IntermediateCreds), 266 }, 267 badOptions: []grpc.DialOption{ 268 grpc.WithTransportCredentials(ordererOrgCreds), 269 }, 270 numAppCAs: 10, 271 numOrdererCAs: 3, 272 }, 273 } 274 275 for _, test := range tests { 276 test := test 277 t.Run(test.name, func(t *testing.T) { 278 t.Logf("Running test %s ...", test.name) 279 server, err := comm.NewGRPCServer("localhost:0", test.serverConfig) 280 if err != nil { 281 t.Fatalf("NewGRPCServer failed with error [%s]", err) 282 return 283 } 284 285 peerInstance.SetServer(server) 286 peerInstance.ServerConfig = test.serverConfig 287 288 assert.NoError(t, err, "NewGRPCServer should not have returned an error") 289 assert.NotNil(t, server, "NewGRPCServer should have created a server") 290 // register a GRPC test service 291 testpb.RegisterTestServiceServer(server.Server(), &testServiceServer{}) 292 go server.Start() 293 defer server.Stop() 294 295 // extract dynamic listen port 296 _, port, err := net.SplitHostPort(server.Listener().Addr().String()) 297 if err != nil { 298 t.Fatal(err) 299 } 300 t.Logf("listenAddress: %s", server.Listener().Addr()) 301 testAddress := "localhost:" + port 302 t.Logf("testAddress: %s", testAddress) 303 304 // invoke the EmptyCall service with good options but should fail 305 // until channel is created and root CAs are updated 306 _, err = invokeEmptyCall(testAddress, test.goodOptions) 307 assert.Error(t, err, "Expected error invoking the EmptyCall service ") 308 309 // creating channel should update the trusted client roots 310 test.createChannel(t) 311 312 // invoke the EmptyCall service with good options 313 _, err = invokeEmptyCall(testAddress, test.goodOptions) 314 assert.NoError(t, err, "Failed to invoke the EmptyCall service") 315 316 // invoke the EmptyCall service with bad options 317 _, err = invokeEmptyCall(testAddress, test.badOptions) 318 assert.Error(t, err, "Expected error using bad dial options") 319 }) 320 } 321 }