Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gateway support for mutual TLS networks #3235

Merged
merged 1 commit into from
Feb 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions internal/peer/node/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,7 @@ func serve(args []string) error {
serverEndorser,
discoveryService,
peerInstance,
&serverConfig.SecOpts,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one small thing - here you passed the server config, not the client config.
This would mean that you do not honor the tls.clientKey and tls.clientCert.

We probably need to check if the client TLS config is defined, and if so, then use it instead and only otherwise fallback on the server TLS config.

aclProvider,
coreConfig.LocalMSPID,
coreConfig.GatewayOptions,
Expand Down
21 changes: 18 additions & 3 deletions internal/pkg/gateway/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/hyperledger/fabric/gossip/api"
"github.com/hyperledger/fabric/gossip/common"
gdiscovery "github.com/hyperledger/fabric/gossip/discovery"
"github.com/hyperledger/fabric/internal/pkg/comm"
"github.com/hyperledger/fabric/internal/pkg/gateway/commit"
"github.com/hyperledger/fabric/internal/pkg/gateway/config"
"github.com/hyperledger/fabric/internal/pkg/gateway/mocks"
Expand Down Expand Up @@ -1764,9 +1765,12 @@ func TestNilArgs(t *testing.T) {
&mocks.CommitFinder{},
&mocks.ACLChecker{},
&mocks.LedgerProvider{},
common.PKIidType("id1"),
"localhost:7051",
gdiscovery.NetworkMember{
PKIid: common.PKIidType("id1"),
Endpoint: "localhost:7051",
},
"msp1",
&comm.SecureOptions{},
config.GetOptions(viper.New()),
)
ctx := context.Background()
Expand Down Expand Up @@ -1905,7 +1909,12 @@ func prepareTest(t *testing.T, tt *testDef) *preparedTest {
EndorsementTimeout: endorsementTimeout,
}

server := newServer(localEndorser, disc, mockFinder, mockPolicy, mockLedgerProvider, common.PKIidType("id1"), "localhost:7051", "msp1", options)
member := gdiscovery.NetworkMember{
PKIid: common.PKIidType("id1"),
Endpoint: "localhost:7051",
}

server := newServer(localEndorser, disc, mockFinder, mockPolicy, mockLedgerProvider, member, "msp1", &comm.SecureOptions{}, options)

dialer := &mocks.Dialer{}
dialer.Returns(nil, nil)
Expand Down Expand Up @@ -2100,6 +2109,10 @@ func createMockPeer(t *testing.T, endorser *endorserState) *dp.Peer {

func createEndpointFactory(t *testing.T, definition *endpointDef, dialer dialer) *endpointFactory {
var endpoint string
ca, err := tlsgen.NewCA()
require.NoError(t, err, "failed to create CA")
pair, err := ca.NewClientCertKeyPair()
require.NoError(t, err, "failed to create client key pair")
return &endpointFactory{
timeout: 5 * time.Second,
connectEndorser: func(conn *grpc.ClientConn) peer.EndorserClient {
Expand Down Expand Up @@ -2127,6 +2140,8 @@ func createEndpointFactory(t *testing.T, definition *endpointDef, dialer dialer)
endpoint = target
return dialer(ctx, target, opts...)
},
clientKey: pair.Key,
clientCert: pair.Cert,
}
}

Expand Down
6 changes: 5 additions & 1 deletion internal/pkg/gateway/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ type endpointFactory struct {
connectEndorser endorserConnector
connectOrderer ordererConnector
dialer dialer
clientCert []byte
clientKey []byte
}

func (ef *endpointFactory) newEndorser(pkiid common.PKIidType, address, mspid string, tlsRootCerts [][]byte) (*endorser, error) {
Expand Down Expand Up @@ -97,7 +99,9 @@ func (ef *endpointFactory) newConnection(address string, tlsRootCerts [][]byte)
SecOpts: comm.SecureOptions{
UseTLS: len(tlsRootCerts) > 0,
ServerRootCAs: tlsRootCerts,
RequireClientCert: false,
RequireClientCert: true,
Certificate: ef.clientCert,
Key: ef.clientKey,
},
DialTimeout: ef.timeout,
}
Expand Down
55 changes: 55 additions & 0 deletions internal/pkg/gateway/endpoint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package gateway

import (
"testing"
"time"

"github.com/hyperledger/fabric/common/crypto/tlsgen"
"github.com/hyperledger/fabric/gossip/common"
"github.com/hyperledger/fabric/internal/pkg/comm"
"github.com/stretchr/testify/require"
)

func TestMutualTLS(t *testing.T) {
ca, err := tlsgen.NewCA()
require.NoError(t, err, "failed to create CA")

serverPair, err := ca.NewServerCertKeyPair("127.0.0.1")
require.NoError(t, err, "failed to create server key pair")

clientPair, err := ca.NewClientCertKeyPair()
require.NoError(t, err, "failed to create client key pair")

rootTLSCert := ca.CertBytes()

server, err := comm.NewGRPCServer("127.0.0.1:0", comm.ServerConfig{
SecOpts: comm.SecureOptions{
UseTLS: true,
RequireClientCert: true,
Certificate: serverPair.Cert,
Key: serverPair.Key,
ClientRootCAs: [][]byte{rootTLSCert},
},
})
require.NoError(t, err)

go server.Start()
defer server.Stop()

factory := &endpointFactory{
timeout: 10 * time.Second,
clientCert: clientPair.Cert,
clientKey: clientPair.Key,
}

endorser, err := factory.newEndorser(common.PKIidType{}, server.Address(), "msp1", [][]byte{rootTLSCert})
require.NoError(t, err, "failed to make mTLS connection to server")

err = endorser.closeConnection()
require.NoError(t, err, "failed to close connection")
}
15 changes: 8 additions & 7 deletions internal/pkg/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import (
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/common/ledger"
"github.com/hyperledger/fabric/core/peer"
"github.com/hyperledger/fabric/gossip/common"
gdiscovery "github.com/hyperledger/fabric/gossip/discovery"
"github.com/hyperledger/fabric/internal/pkg/comm"
"github.com/hyperledger/fabric/internal/pkg/gateway/commit"
"github.com/hyperledger/fabric/internal/pkg/gateway/config"
"google.golang.org/grpc"
Expand Down Expand Up @@ -51,7 +52,7 @@ type LedgerProvider interface {
}

// CreateServer creates an embedded instance of the Gateway.
func CreateServer(localEndorser peerproto.EndorserServer, discovery Discovery, peerInstance *peer.Peer, policy ACLChecker, localMSPID string, options config.Options) *Server {
func CreateServer(localEndorser peerproto.EndorserServer, discovery Discovery, peerInstance *peer.Peer, secureOptions *comm.SecureOptions, policy ACLChecker, localMSPID string, options config.Options) *Server {
adapter := &peerAdapter{
Peer: peerInstance,
}
Expand All @@ -65,9 +66,9 @@ func CreateServer(localEndorser peerproto.EndorserServer, discovery Discovery, p
commit.NewFinder(adapter, notifier),
policy,
adapter,
peerInstance.GossipService.SelfMembershipInfo().PKIid,
peerInstance.GossipService.SelfMembershipInfo().Endpoint,
peerInstance.GossipService.SelfMembershipInfo(),
localMSPID,
secureOptions,
options,
)

Expand All @@ -76,13 +77,13 @@ func CreateServer(localEndorser peerproto.EndorserServer, discovery Discovery, p
return server
}

func newServer(localEndorser peerproto.EndorserClient, discovery Discovery, finder CommitFinder, policy ACLChecker, ledgerProvider LedgerProvider, localPKIID common.PKIidType, localEndpoint, localMSPID string, options config.Options) *Server {
func newServer(localEndorser peerproto.EndorserClient, discovery Discovery, finder CommitFinder, policy ACLChecker, ledgerProvider LedgerProvider, localInfo gdiscovery.NetworkMember, localMSPID string, secureOptions *comm.SecureOptions, options config.Options) *Server {
return &Server{
registry: &registry{
localEndorser: &endorser{client: localEndorser, endpointConfig: &endpointConfig{pkiid: localPKIID, address: localEndpoint, mspid: localMSPID}},
localEndorser: &endorser{client: localEndorser, endpointConfig: &endpointConfig{pkiid: localInfo.PKIid, address: localInfo.Endpoint, mspid: localMSPID}},
discovery: discovery,
logger: logger,
endpointFactory: &endpointFactory{timeout: options.DialTimeout},
endpointFactory: &endpointFactory{timeout: options.DialTimeout, clientCert: secureOptions.Certificate, clientKey: secureOptions.Key},
remoteEndorsers: map[string]*endorser{},
channelInitialized: map[string]bool{},
},
Expand Down