pkg_test.go 11.4 KB
Newer Older
1
/*
2
Copyright IBM Corp. All Rights Reserved.
3

4
SPDX-License-Identifier: Apache-2.0
5
6
7
8
9
10
11
12
13
*/

package peer_test

import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"io/ioutil"
14
	"net"
15
	"os"
16
17
18
19
20
21
22
23
24
	"path/filepath"
	"testing"
	"time"

	"google.golang.org/grpc/credentials"

	"golang.org/x/net/context"
	"google.golang.org/grpc"

25
26
	"github.com/golang/protobuf/proto"
	configtxtest "github.com/hyperledger/fabric/common/configtx/test"
27
28
	"github.com/hyperledger/fabric/core/comm"
	testpb "github.com/hyperledger/fabric/core/comm/testdata/grpc"
29
	"github.com/hyperledger/fabric/core/ledger/util"
30
	"github.com/hyperledger/fabric/core/peer"
31
32
33
	"github.com/hyperledger/fabric/msp"
	cb "github.com/hyperledger/fabric/protos/common"
	mspproto "github.com/hyperledger/fabric/protos/msp"
34
	pb "github.com/hyperledger/fabric/protos/peer"
35
	"github.com/spf13/viper"
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
	"github.com/stretchr/testify/assert"
)

// default timeout for grpc connections
var timeout = time.Second * 1

// test server to be registered with the GRPCServer
type testServiceServer struct{}

func (tss *testServiceServer) EmptyCall(context.Context, *testpb.Empty) (*testpb.Empty, error) {
	return new(testpb.Empty), nil
}

// createCertPool creates an x509.CertPool from an array of PEM-encoded certificates
func createCertPool(rootCAs [][]byte) (*x509.CertPool, error) {
	certPool := x509.NewCertPool()
	for _, rootCA := range rootCAs {
		if !certPool.AppendCertsFromPEM(rootCA) {
			return nil, errors.New("Failed to load root certificates")
		}
	}
	return certPool, nil
}

// helper function to invoke the EmptyCall againt the test service
func invokeEmptyCall(address string, dialOptions []grpc.DialOption) (*testpb.Empty, error) {
	//add DialOptions
	dialOptions = append(dialOptions, grpc.WithBlock())
64
65
	ctx := context.Background()
	ctx, _ = context.WithTimeout(ctx, timeout)
66
	//create GRPC client conn
67
	clientConn, err := grpc.DialContext(ctx, address, dialOptions...)
68
69
70
71
72
73
74
75
	if err != nil {
		return nil, err
	}
	defer clientConn.Close()

	//create GRPC client
	client := testpb.NewTestServiceClient(clientConn)

76
77
	callCtx := context.Background()
	callCtx, cancel := context.WithTimeout(callCtx, timeout)
78
79
80
	defer cancel()

	//invoke service
81
	empty, err := client.EmptyCall(callCtx, new(testpb.Empty))
82
83
84
85
86
87
88
	if err != nil {
		return nil, err
	}

	return empty, nil
}

89
// helper function to build an MSPConfig given root certs
90
func createMSPConfig(rootCerts, tlsRootCerts, tlsIntermediateCerts [][]byte,
91
92
	mspID string) (*mspproto.MSPConfig, error) {

93
	fmspconf := &mspproto.FabricMSPConfig{
94
95
96
97
		RootCerts:            rootCerts,
		TlsRootCerts:         tlsRootCerts,
		TlsIntermediateCerts: tlsIntermediateCerts,
		Name:                 mspID}
98
99
100
101
102
103
104
105

	fmpsjs, err := proto.Marshal(fmspconf)
	if err != nil {
		return nil, err
	}
	mspconf := &mspproto.MSPConfig{Config: fmpsjs, Type: int32(msp.FABRIC)}
	return mspconf, nil
}
106

107
108
109
func createConfigBlock(chainID string, appMSPConf, ordererMSPConf *mspproto.MSPConfig,
	appOrgID, ordererOrgID string) (*cb.Block, error) {
	block, err := configtxtest.MakeGenesisBlockFromMSPs(chainID, appMSPConf, ordererMSPConf, appOrgID, ordererOrgID)
110
111
112
113
114
115
116
117
	if block == nil || err != nil {
		return block, err
	}

	txsFilter := util.NewTxValidationFlagsSetValue(len(block.Data.Data), pb.TxValidationCode_VALID)
	block.Metadata.Metadata[cb.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter

	return block, nil
118
}
119

120
func TestUpdateRootsFromConfigBlock(t *testing.T) {
121
122
	// load test certs from testdata
	org1CA, err := ioutil.ReadFile(filepath.Join("testdata", "Org1-cert.pem"))
123
124
125
126
	org1Server1Key, err := ioutil.ReadFile(filepath.Join("testdata",
		"Org1-server1-key.pem"))
	org1Server1Cert, err := ioutil.ReadFile(filepath.Join("testdata",
		"Org1-server1-cert.pem"))
127
	org2CA, err := ioutil.ReadFile(filepath.Join("testdata", "Org2-cert.pem"))
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
	org2Server1Key, err := ioutil.ReadFile(filepath.Join("testdata",
		"Org2-server1-key.pem"))
	org2Server1Cert, err := ioutil.ReadFile(filepath.Join("testdata",
		"Org2-server1-cert.pem"))
	org2IntermediateCA, err := ioutil.ReadFile(filepath.Join("testdata",
		"Org2-child1-cert.pem"))
	org2IntermediateServer1Key, err := ioutil.ReadFile(filepath.Join("testdata",
		"Org2-child1-server1-key.pem"))
	org2IntermediateServer1Cert, err := ioutil.ReadFile(filepath.Join("testdata",
		"Org2-child1-server1-cert.pem"))
	ordererOrgCA, err := ioutil.ReadFile(filepath.Join("testdata", "Org3-cert.pem"))
	ordererOrgServer1Key, err := ioutil.ReadFile(filepath.Join("testdata",
		"Org3-server1-key.pem"))
	ordererOrgServer1Cert, err := ioutil.ReadFile(filepath.Join("testdata",
		"Org3-server1-cert.pem"))
143
144
145
146
147

	if err != nil {
		t.Fatalf("Failed to load test certificates: %v", err)
	}

148
	// create test MSPConfigs
149
150
151
152
153
154
155
156
	org1MSPConf, err := createMSPConfig([][]byte{org2CA}, [][]byte{org1CA},
		[][]byte{}, "Org1MSP")
	org2MSPConf, err := createMSPConfig([][]byte{org1CA}, [][]byte{org2CA},
		[][]byte{}, "Org2MSP")
	org2IntermediateMSPConf, err := createMSPConfig([][]byte{org1CA},
		[][]byte{org2CA}, [][]byte{org2IntermediateCA}, "Org2IntermediateMSP")
	ordererOrgMSPConf, err := createMSPConfig([][]byte{org1CA},
		[][]byte{ordererOrgCA}, [][]byte{}, "OrdererOrgMSP")
157
158
159
160
161
	if err != nil {
		t.Fatalf("Failed to create MSPConfigs (%s)", err)
	}

	// create test channel create blocks
162
163
164
165
166
167
	channel1Block, err := createConfigBlock("channel1", org1MSPConf,
		ordererOrgMSPConf, "Org1MSP", "OrdererOrgMSP")
	channel2Block, err := createConfigBlock("channel2", org2MSPConf,
		ordererOrgMSPConf, "Org2MSP", "OrdererOrgMSP")
	channel3Block, err := createConfigBlock("channel3", org2IntermediateMSPConf,
		ordererOrgMSPConf, "Org2IntermediateMSP", "OrdererOrgMSP")
168
169
170

	createChannel := func(cid string, block *cb.Block) {
		viper.Set("peer.tls.enabled", true)
171
172
173
174
175
176
177
178
		viper.Set("peer.tls.cert.file", filepath.Join("testdata",
			"Org1-server1-cert.pem"))
		viper.Set("peer.tls.key.file", filepath.Join("testdata",
			"Org1-server1-key.pem"))
		viper.Set("peer.tls.rootcert.file", filepath.Join("testdata",
			"Org1-cert.pem"))
		viper.Set("peer.fileSystemPath", "/var/hyperledger/test/")
		defer os.RemoveAll("/var/hyperledger/test/")
179
		err := peer.Default.CreateChainFromBlock(block, nil)
180
181
182
		if err != nil {
			t.Fatalf("Failed to create config block (%s)", err)
		}
183
		t.Logf("Channel %s MSPIDs: (%s)", cid, peer.Default.GetMSPIDs(cid))
184
185
	}

186
187
188
189
190
191
192
	org1CertPool, err := createCertPool([][]byte{org1CA})

	if err != nil {
		t.Fatalf("Failed to load root certificates into pool: %v", err)
	}

	// use server cert as client cert
193
	org1ClientCert, err := tls.X509KeyPair(org1Server1Cert, org1Server1Key)
194
195
196
	if err != nil {
		t.Fatalf("Failed to load client certificate: %v", err)
	}
197
	org1Creds := credentials.NewTLS(&tls.Config{
198
199
200
		Certificates: []tls.Certificate{org1ClientCert},
		RootCAs:      org1CertPool,
	})
201
202
203
204
	org2ClientCert, err := tls.X509KeyPair(org2Server1Cert, org2Server1Key)
	if err != nil {
		t.Fatalf("Failed to load client certificate: %v", err)
	}
205
	org2Creds := credentials.NewTLS(&tls.Config{
206
207
208
		Certificates: []tls.Certificate{org2ClientCert},
		RootCAs:      org1CertPool,
	})
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
	org2IntermediateClientCert, err := tls.X509KeyPair(
		org2IntermediateServer1Cert, org2IntermediateServer1Key)
	if err != nil {
		t.Fatalf("Failed to load client certificate: %v", err)
	}
	org2IntermediateCreds := credentials.NewTLS(&tls.Config{
		Certificates: []tls.Certificate{org2IntermediateClientCert},
		RootCAs:      org1CertPool,
	})
	ordererOrgClientCert, err := tls.X509KeyPair(ordererOrgServer1Cert,
		ordererOrgServer1Key)
	if err != nil {
		t.Fatalf("Failed to load client certificate: %v", err)
	}
	ordererOrgCreds := credentials.NewTLS(&tls.Config{
		Certificates: []tls.Certificate{ordererOrgClientCert},
		RootCAs:      org1CertPool,
	})
227
228
229
230

	// basic function tests
	var tests = []struct {
		name          string
231
		serverConfig  comm.ServerConfig
232
		createChannel func()
233
234
		goodOptions   []grpc.DialOption
		badOptions    []grpc.DialOption
235
236
		numAppCAs     int
		numOrdererCAs int
237
	}{
238

239
		{
240
			name: "MutualTLSOrg1Org1",
241
242
243
			serverConfig: comm.ServerConfig{
				SecOpts: &comm.SecureOptions{
					UseTLS:            true,
244
245
					Certificate:       org1Server1Cert,
					Key:               org1Server1Key,
246
247
248
					ServerRootCAs:     [][]byte{org1CA},
					RequireClientCert: true,
				},
249
			},
250
			createChannel: func() { createChannel("channel1", channel1Block) },
251
			goodOptions:   []grpc.DialOption{grpc.WithTransportCredentials(org1Creds)},
252
			badOptions:    []grpc.DialOption{grpc.WithTransportCredentials(ordererOrgCreds)},
253
			numAppCAs:     3, // each channel also has a DEFAULT MSP
254
			numOrdererCAs: 1,
255
256
		},
		{
257
			name: "MutualTLSOrg1Org2",
258
259
260
			serverConfig: comm.ServerConfig{
				SecOpts: &comm.SecureOptions{
					UseTLS:            true,
261
262
					Certificate:       org1Server1Cert,
					Key:               org1Server1Key,
263
264
265
					ServerRootCAs:     [][]byte{org1CA},
					RequireClientCert: true,
				},
266
			},
267
268
269
270
271
			createChannel: func() { createChannel("channel2", channel2Block) },
			goodOptions: []grpc.DialOption{
				grpc.WithTransportCredentials(org2Creds)},
			badOptions: []grpc.DialOption{
				grpc.WithTransportCredentials(ordererOrgCreds)},
272
			numAppCAs:     6,
273
			numOrdererCAs: 2,
274
275
		},
		{
276
			name: "MutualTLSOrg1Org2Intermediate",
277
278
279
			serverConfig: comm.ServerConfig{
				SecOpts: &comm.SecureOptions{
					UseTLS:            true,
280
281
					Certificate:       org1Server1Cert,
					Key:               org1Server1Key,
282
283
284
					ServerRootCAs:     [][]byte{org1CA},
					RequireClientCert: true,
				},
285
			},
286
287
288
289
290
			createChannel: func() { createChannel("channel3", channel3Block) },
			goodOptions: []grpc.DialOption{
				grpc.WithTransportCredentials(org2IntermediateCreds)},
			badOptions: []grpc.DialOption{
				grpc.WithTransportCredentials(ordererOrgCreds)},
291
			numAppCAs:     10,
292
			numOrdererCAs: 3,
293
294
295
296
297
298
299
		},
	}

	for _, test := range tests {
		test := test
		t.Run(test.name, func(t *testing.T) {
			t.Logf("Running test %s ...", test.name)
300
			server, err := peer.NewPeerServer("localhost:0", test.serverConfig)
301
			if err != nil {
302
				t.Fatalf("NewPeerServer failed with error [%s]", err)
303
			} else {
304
305
				assert.NoError(t, err, "NewPeerServer should not have returned an error")
				assert.NotNil(t, server, "NewPeerServer should have created a server")
306
				// register a GRPC test service
307
308
309
				testpb.RegisterTestServiceServer(server.Server(), &testServiceServer{})
				go server.Start()
				defer server.Stop()
310

311
312
313
314
315
316
317
318
319
				// extract dynamic listen port
				_, port, err := net.SplitHostPort(server.Listener().Addr().String())
				if err != nil {
					t.Fatal(err)
				}
				t.Logf("listenAddress: %s", server.Listener().Addr())
				testAddress := "localhost:" + port
				t.Logf("testAddress: %s", testAddress)

320
321
				// invoke the EmptyCall service with good options but should fail
				// until channel is created and root CAs are updated
322
				_, err = invokeEmptyCall(testAddress, test.goodOptions)
323
324
				assert.Error(t, err, "Expected error invoking the EmptyCall service ")

325
326
				// creating channel should update the trusted client roots
				test.createChannel()
327
328

				// make sure we have the expected number of CAs
329
				appCAs, ordererCAs := comm.GetCredentialSupport().GetClientRootCAs()
330
331
332
333
334
				assert.Equal(t, test.numAppCAs, len(appCAs),
					"Did not find expected number of app CAs for channel")
				assert.Equal(t, test.numOrdererCAs, len(ordererCAs),
					"Did not find expected number of orderer CAs for channel")

335
				// invoke the EmptyCall service with good options
336
				_, err = invokeEmptyCall(testAddress, test.goodOptions)
337
				assert.NoError(t, err, "Failed to invoke the EmptyCall service")
338

339
				// invoke the EmptyCall service with bad options
340
				_, err = invokeEmptyCall(testAddress, test.badOptions)
341
				assert.Error(t, err, "Expected error using bad dial options")
342
343
344
345
			}
		})
	}
}