Skip to content

Commit

Permalink
[FAB-5232] Add SDK TLS Cert Pool
Browse files Browse the repository at this point in the history
- Expose NewTransactionProposal method for testing

Change-Id: If18bcccf5b686bad666ae591c5c49d81e50b5504
Signed-off-by: Divyank Katira <[email protected]>
  • Loading branch information
d1vyank committed Jul 11, 2017
1 parent af9c616 commit 45480e5
Show file tree
Hide file tree
Showing 17 changed files with 93 additions and 134 deletions.
2 changes: 1 addition & 1 deletion api/apiconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ type Config interface {
PeersConfig(org string) ([]PeerConfig, error)
NetworkConfig() (*NetworkConfig, error)
IsTLSEnabled() bool
SetTLSCACertPool(*x509.CertPool)
TLSCACertPool(tlsCertificate string) (*x509.CertPool, error)
TLSCACertPoolFromRoots(ordererRootCAs [][]byte) (*x509.CertPool, error)
IsSecurityEnabled() bool
TcertBatchSize() int
SecurityAlgorithm() string
Expand Down
23 changes: 10 additions & 13 deletions api/apiconfig/mocks/mockconfig.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions api/apifabclient/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ type Peer interface {
// Peer Properties
Name() string
SetName(name string)
// MSPID gets the Peer mspID.
MSPID() string
// SetMSPID sets the Peer mspID.
SetMSPID(mspID string)
Roles() []string
SetRoles(roles []string)
URL() string
Expand Down
39 changes: 16 additions & 23 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const cmdRoot = "fabric_sdk"

// Config represents the configuration for the client
type Config struct {
tlsCertPool *x509.CertPool
networkConfig *apiconfig.NetworkConfig
networkConfigCached bool
}
Expand Down Expand Up @@ -80,7 +81,7 @@ func InitConfigWithCmdRoot(configFile string, cmdRootPrefix string) (*Config, er
}
logging.SetBackend(backendFormatter).SetLevel(logging.Level(logLevel), "fabric_sdk_go")

return &Config{}, nil
return &Config{tlsCertPool: x509.NewCertPool()}, nil
}

// CAConfig returns the CA configuration.
Expand Down Expand Up @@ -148,7 +149,7 @@ func (c *Config) MspID(org string) (string, error) {

// FabricClientViper returns the internal viper instance used by the
// SDK to read configuration options
func (c *Config) FabricClientViper() *viper.Viper {
func FabricClientViper() *viper.Viper {
return myViper
}

Expand Down Expand Up @@ -262,10 +263,18 @@ func (c *Config) IsTLSEnabled() bool {
return myViper.GetBool("client.tls.enabled")
}

// TLSCACertPool ...
// TODO: Should be related to configuration.
// SetTLSCACertPool allows a user to set a global cert pool with a set of
// root TLS CAs that will be used for all outgoing connections
func (c *Config) SetTLSCACertPool(certPool *x509.CertPool) {
if certPool == nil {
certPool = x509.NewCertPool()
}
c.tlsCertPool = certPool
}

// TLSCACertPool returns the configured cert pool. If a tlsCertificate path
// is provided, the certficate is added to the pool
func (c *Config) TLSCACertPool(tlsCertificate string) (*x509.CertPool, error) {
certPool := x509.NewCertPool()
if tlsCertificate != "" {
rawData, err := ioutil.ReadFile(tlsCertificate)
if err != nil {
Expand All @@ -277,26 +286,10 @@ func (c *Config) TLSCACertPool(tlsCertificate string) (*x509.CertPool, error) {
return nil, err
}

certPool.AddCert(cert)
}

return certPool, nil
}

// TLSCACertPoolFromRoots ...
func (c *Config) TLSCACertPoolFromRoots(ordererRootCAs [][]byte) (*x509.CertPool, error) {
certPool := x509.NewCertPool()

for _, root := range ordererRootCAs {
cert, err := loadCAKey(root)
if err != nil {
return nil, err
}

certPool.AddCert(cert)
c.tlsCertPool.AddCert(cert)
}

return certPool, nil
return c.tlsCertPool, nil
}

// IsSecurityEnabled ...
Expand Down
19 changes: 0 additions & 19 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,25 +200,6 @@ func TestTLSACAConfig(t *testing.T) {
if err == nil {
t.Fatalf("TLS CA cert pool was supposed to fail when provided with wrong cert file")
}

//Test TLSCA Cert Pool from roots(Negative test case)
samplebytes := [][]byte{
[]byte(validRootCA),
}
_, err = configImpl.TLSCACertPoolFromRoots(samplebytes)
if err != nil {
t.Fatalf("TLS CA cert pool fetch failed, reason %v", err)
}

//Test TLSCA Cert Pool from roots(Negative test case)
samplebytes = [][]byte{
[]byte("sample invalid string"),
}
_, err = configImpl.TLSCACertPoolFromRoots(samplebytes)
if err == nil {
t.Fatalf("TLS CA cert pool was supposed to fail")
}

}

func TestOrdererConfig(t *testing.T) {
Expand Down
5 changes: 2 additions & 3 deletions pkg/fabric-ca-client/mocks/mockconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,8 @@ func (c *MockConfig) TLSCACertPool(tlsCertificate string) (*x509.CertPool, error
return nil, nil
}

// TLSCACertPoolFromRoots ...
func (c *MockConfig) TLSCACertPoolFromRoots(ordererRootCAs [][]byte) (*x509.CertPool, error) {
return nil, nil
// SetTLSCACertPool ...
func (c *MockConfig) SetTLSCACertPool(pool *x509.CertPool) {
}

// IsSecurityEnabled ...
Expand Down
2 changes: 1 addition & 1 deletion pkg/fabric-client/channel/txnproposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (c *Channel) SendTransactionProposal(request apitxn.ChaincodeInvokeRequest)
// TODO: return the entire request or just the txn ID?
func sendTransactionProposal(channelID string, request apitxn.ChaincodeInvokeRequest, clientContext ClientContext) ([]*apitxn.TransactionProposalResponse, apitxn.TransactionID, error) {
if err := validateChaincodeInvokeRequest(request); err != nil {
return nil, apitxn.TransactionID{}, fmt.Errorf("Required parameters are empty")
return nil, apitxn.TransactionID{}, fmt.Errorf("Required parameters are empty: %s", err)
}

request, err := chaincodeInvokeRequestAddTxnID(request, clientContext)
Expand Down
3 changes: 1 addition & 2 deletions pkg/fabric-client/channel/txnproposer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ func TestCreateTransactionProposal(t *testing.T) {
ChaincodeID: "qscc",
}

tProposal, err := newTransactionProposal("", request, channel.ClientContext())

tProposal, err := newTransactionProposal(channel.Name(), request, channel.clientContext)
if err != nil {
t.Fatal("Create Transaction Proposal Failed", err)
}
Expand Down
8 changes: 2 additions & 6 deletions pkg/fabric-client/mocks/mockconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,8 @@ func (c *MockConfig) TLSCACertPool(tlsCertificate string) (*x509.CertPool, error
return nil, nil
}

// TLSCACertPoolFromRoots ...
func (c *MockConfig) TLSCACertPoolFromRoots(ordererRootCAs [][]byte) (*x509.CertPool, error) {
if c.errorCase {
return nil, fmt.Errorf("just to test error scenario")
}
return nil, nil
// SetTLSCACertPool ...
func (c *MockConfig) SetTLSCACertPool(pool *x509.CertPool) {
}

// IsSecurityEnabled ...
Expand Down
9 changes: 9 additions & 0 deletions pkg/fabric-client/mocks/mockpeer.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ func (p *MockPeer) SetName(name string) {
p.MockName = name
}

// MSPID gets the Peer mspID.
func (p *MockPeer) MSPID() string {
return ""
}

// SetMSPID sets the Peer mspID.
func (p *MockPeer) SetMSPID(mspID string) {
}

// Roles returns the mock peer's mock roles
func (p *MockPeer) Roles() []string {
return p.MockRoles
Expand Down
48 changes: 10 additions & 38 deletions pkg/fabric-client/orderer/orderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ SPDX-License-Identifier: Apache-2.0
package orderer

import (
"crypto/x509"
"fmt"
"time"

Expand All @@ -30,31 +29,21 @@ type Orderer struct {
grpcDialOption []grpc.DialOption
}

// CreateNewOrdererWithRootCAs Returns a new Orderer instance using the passed in orderer root CAs
func CreateNewOrdererWithRootCAs(url string, ordererRootCAs [][]byte, serverHostOverride string, config config.Config) (*Orderer, error) {
// NewOrderer Returns a Orderer instance
func NewOrderer(url string, certificate string, serverHostOverride string, config config.Config) (*Orderer, error) {
var opts []grpc.DialOption
opts = append(opts, grpc.WithTimeout(time.Second*3))
if config.IsTLSEnabled() {
tlsCaCertPool, err := config.TLSCACertPoolFromRoots(ordererRootCAs)
tlsCaCertPool, err := config.TLSCACertPool(certificate)
if err != nil {
return nil, err
}
return createNewOrdererWithCertPool(url, tlsCaCertPool, serverHostOverride), nil
creds := credentials.NewClientTLSFromCert(tlsCaCertPool, serverHostOverride)
opts = append(opts, grpc.WithTransportCredentials(creds))
} else {
opts = append(opts, grpc.WithInsecure())
}
return createNewOrdererWithoutTLS(url), nil
}

func createNewOrdererWithoutTLS(url string) *Orderer {
var opts []grpc.DialOption
opts = append(opts, grpc.WithTimeout(time.Second*3))
opts = append(opts, grpc.WithInsecure())
return &Orderer{url: url, grpcDialOption: opts}
}

func createNewOrdererWithCertPool(url string, tlsCaCertPool *x509.CertPool, serverHostOverride string) *Orderer {
var opts []grpc.DialOption
opts = append(opts, grpc.WithTimeout(time.Second*3))
creds := credentials.NewClientTLSFromCert(tlsCaCertPool, serverHostOverride)
opts = append(opts, grpc.WithTransportCredentials(creds))
return &Orderer{url: url, grpcDialOption: opts}
return &Orderer{url: url, grpcDialOption: opts}, nil
}

// URL Get the Orderer url. Required property for the instance objects.
Expand Down Expand Up @@ -182,20 +171,3 @@ func (o *Orderer) SendDeliver(envelope *fab.SignedEnvelope) (chan *common.Block,

return responses, errors
}

// NewOrderer Returns a Orderer instance
func NewOrderer(url string, certificate string, serverHostOverride string, config config.Config) (*Orderer, error) {
var opts []grpc.DialOption
opts = append(opts, grpc.WithTimeout(time.Second*3))
if config.IsTLSEnabled() {
tlsCaCertPool, err := config.TLSCACertPool(certificate)
if err != nil {
return nil, err
}
creds := credentials.NewClientTLSFromCert(tlsCaCertPool, serverHostOverride)
opts = append(opts, grpc.WithTransportCredentials(creds))
} else {
opts = append(opts, grpc.WithInsecure())
}
return &Orderer{url: url, grpcDialOption: opts}, nil
}
26 changes: 0 additions & 26 deletions pkg/fabric-client/orderer/orderer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,32 +227,6 @@ func startCustomizedMockServer(t *testing.T, serverURL string, grpcServer *grpc.
return addr
}

func TestCreateNewOrdererWithRootCAs(t *testing.T) {

rootCA := [][]byte{
[]byte(validRootCA),
}

//Without TLS
ordr, err := CreateNewOrdererWithRootCAs("", rootCA, "", mocks.NewMockConfig())
if ordr == nil || err != nil {
t.Fatalf("TestCreateNewOrdererWithRootCAs Failed, cause : [ %s ]", err)
}

//With TLS
ordr, err = CreateNewOrdererWithRootCAs("", rootCA, "", mocks.NewMockConfigCustomized(true, false))
if ordr == nil || err != nil {
t.Fatalf("TestCreateNewOrdererWithRootCAs Failed, cause : [ %s ]", err)
}

//With TLS, With invalid rootCA
ordr, err = CreateNewOrdererWithRootCAs("", [][]byte{}, "", mocks.NewMockConfigCustomized(true, true))
if ordr != nil || err == nil {
t.Fatal("TestCreateNewOrdererWithRootCAs Failed, was expecting error")
}

}

func TestNewOrdererWithTLS(t *testing.T) {

//Positive Test case
Expand Down
11 changes: 11 additions & 0 deletions pkg/fabric-client/peer/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const (
type Peer struct {
processor apitxn.ProposalProcessor
name string
mspID string
roles []string
enrollmentCertificate *pem.Block
url string
Expand Down Expand Up @@ -73,6 +74,16 @@ func (p *Peer) SetName(name string) {
p.name = name
}

// MSPID gets the Peer mspID.
func (p *Peer) MSPID() string {
return p.mspID
}

// SetMSPID sets the Peer mspID.
func (p *Peer) SetMSPID(mspID string) {
p.mspID = mspID
}

// Roles gets the user’s roles the Peer participates in. It’s an array of possible values
// in “client”, and “auditor”. The member service defines two more roles reserved
// for peer membership: “peer” and “validator”, which are not exposed to the applications.
Expand Down
20 changes: 20 additions & 0 deletions pkg/fabric-client/peer/peer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func TestNewPeerTLSFromCert(t *testing.T) {
certPool := x509.NewCertPool()
config.EXPECT().IsTLSEnabled().Return(true)
config.EXPECT().TLSCACertPool("cert").Return(certPool, nil)
config.EXPECT().TLSCACertPool("").Return(certPool, nil)

url := "0.0.0.0:1234"
// TODO - test actual parameters and test server name override
Expand Down Expand Up @@ -78,6 +79,7 @@ func TestNewPeerTLSFromCertBad(t *testing.T) {
config := mock_apiconfig.NewMockConfig(mockCtrl)

config.EXPECT().IsTLSEnabled().Return(true)
config.EXPECT().TLSCACertPool("").Return(x509.NewCertPool(), nil)

url := "0.0.0.0:1234"
_, err := NewPeerTLSFromCert(url, "", "", config)
Expand Down Expand Up @@ -167,6 +169,24 @@ func TestNames(t *testing.T) {
}
}

func TestMSPIDs(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
config := mock_apiconfig.NewMockConfig(mockCtrl)
config.EXPECT().IsTLSEnabled().Return(false)

peer, err := NewPeer(peer1URL, config)
if err != nil {
t.Fatalf("Failed to create NewPeer error(%v)", err)
}
testMSP := "orgN"
peer.SetMSPID(testMSP)

if peer.MSPID() != testMSP {
t.Fatalf("Unexpected peer msp id")
}
}

// Test that peer is proxy for proposal processor interface
func TestProposalProcessorSendProposal(t *testing.T) {
mockCtrl := gomock.NewController(t)
Expand Down
Loading

0 comments on commit 45480e5

Please sign in to comment.