From 56d7b8429ce0286c27fd78205fc2887654e8c512 Mon Sep 17 00:00:00 2001 From: yacovm Date: Wed, 21 Oct 2020 01:21:48 +0300 Subject: [PATCH] Deduplicate orderer server TLS root CAs (#2030) When the orderer TLS root CAs are updated, an aggregation of all root TLS CA certificates over all channels is injected into the PredicateDialer. Then, upon client TLS handshake, a fresh TLS config object is built (for orthogonal purposes), however the operation entails parsing of all root CAs all over again. In case the orderer is part of too many channels, this induces a high and unnecessary processing overhead. This commit simply performs a deduplication of the bespoken TLS root CA certificates prior to updating the root CAs. Change-Id: I21b2ed483afc9595c2ccd7fbe9ec0cf475cc5f62 Signed-off-by: yacovm --- orderer/common/server/main.go | 20 +++++++++++++++---- orderer/common/server/main_test.go | 31 ++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/orderer/common/server/main.go b/orderer/common/server/main.go index 2b0139de8ae..9a2c69155af 100644 --- a/orderer/common/server/main.go +++ b/orderer/common/server/main.go @@ -877,16 +877,28 @@ func updateClusterDialer(rootCASupport *comm.CredentialSupport, clusterDialer *c // Iterate over all orderer root CAs for all chains and add them // to the root CAs - var clusterRootCAs [][]byte + clusterRootCAs := make(cluster.StringSet) for _, orgRootCAs := range rootCASupport.OrdererRootCAsByChainAndOrg { for _, roots := range orgRootCAs { - clusterRootCAs = append(clusterRootCAs, roots...) + for _, root := range roots { + clusterRootCAs[string(root)] = struct{}{} + } } } + // Add the local root CAs too - clusterRootCAs = append(clusterRootCAs, localClusterRootCAs...) + for _, localRoot := range localClusterRootCAs { + clusterRootCAs[string(localRoot)] = struct{}{} + } + + var clusterRootCAsBytes [][]byte + // Convert the StringSet back to a byte slice + for root := range clusterRootCAs { + clusterRootCAsBytes = append(clusterRootCAsBytes, []byte(root)) + } + // Update the cluster config with the new root CAs - clusterDialer.UpdateRootCAs(clusterRootCAs) + clusterDialer.UpdateRootCAs(clusterRootCAsBytes) } func prettyPrintStruct(i interface{}) { diff --git a/orderer/common/server/main_test.go b/orderer/common/server/main_test.go index b70ab12aa26..bd4a412bc63 100644 --- a/orderer/common/server/main_test.go +++ b/orderer/common/server/main_test.go @@ -472,6 +472,37 @@ func TestUpdateTrustedRoots(t *testing.T) { grpcServer.Listener().Close() } +func TestRootServerCertAggregation(t *testing.T) { + credSupport := &comm.CredentialSupport{ + OrdererRootCAsByChainAndOrg: make(comm.OrgRootCAs), + } + + predDialer := &cluster.PredicateDialer{ + ClientConfig: comm.ClientConfig{ + SecOpts: &comm.SecureOptions{}, + }, + } + + ca1, err := tlsgen.NewCA() + require.NoError(t, err) + + ca2, err := tlsgen.NewCA() + require.NoError(t, err) + + credSupport.OrdererRootCAsByChainAndOrg["foo"] = map[string]comm.CertificateBundle{ + "Org1": [][]byte{ca1.CertBytes()}, + } + credSupport.OrdererRootCAsByChainAndOrg["bar"] = map[string]comm.CertificateBundle{ + "Org1": [][]byte{ca1.CertBytes()}, + } + + updateClusterDialer(credSupport, predDialer, [][]byte{ca2.CertBytes(), ca2.CertBytes(), ca2.CertBytes()}) + + require.Len(t, predDialer.ClientConfig.SecOpts.ServerRootCAs, 2) + require.Contains(t, predDialer.ClientConfig.SecOpts.ServerRootCAs, ca1.CertBytes()) + require.Contains(t, predDialer.ClientConfig.SecOpts.ServerRootCAs, ca2.CertBytes()) +} + func TestConfigureClusterListener(t *testing.T) { logEntries := make(chan string, 100)