Skip to content

Commit

Permalink
[FAB-7699] Embedded pems and functional params support
Browse files Browse the repository at this point in the history
Change-Id: Ie59c3197a76481a991891ea2df39be2283077e00
Signed-off-by: Emil Nikolov <emil.e.nikolov@gmail.com>
  • Loading branch information
e-nikolov committed Jan 16, 2018
1 parent 370f8cc commit 4c444f7
Show file tree
Hide file tree
Showing 40 changed files with 1,357 additions and 285 deletions.
2 changes: 1 addition & 1 deletion api/apiconfig/configprovider.go
Expand Up @@ -36,7 +36,7 @@ type Config interface {
ChannelPeers(name string) ([]ChannelPeer, error)
ChannelOrderers(name string) ([]OrdererConfig, error)
SetTLSCACertPool(*x509.CertPool)
TLSCACertPool(tlsCertificate string) (*x509.CertPool, error)
TLSCACertPool(certConfig ...*x509.Certificate) (*x509.CertPool, error)
IsSecurityEnabled() bool
SecurityAlgorithm() string
SecurityLevel() int
Expand Down
12 changes: 8 additions & 4 deletions api/apiconfig/mocks/mockconfig.gen.go

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

58 changes: 58 additions & 0 deletions api/apiconfig/mocks/mockconfig.go
@@ -0,0 +1,58 @@
/*
Copyright SecureKey Technologies Inc., Unchain B.V. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package mock_apiconfig

import (
tls "crypto/tls"
x509 "crypto/x509"
"time"

"github.com/golang/mock/gomock"
"github.com/hyperledger/fabric-sdk-go/api/apiconfig"
"github.com/hyperledger/fabric-sdk-go/pkg/errors"
)

// GoodCert is a mock of a good certificate
var GoodCert = &x509.Certificate{Raw: []byte{0, 1, 2}}

// BadCert is a mock of a bad certificate
var BadCert = &x509.Certificate{Raw: []byte{1, 2}}

// TLSCert is a mock of a tls.Certificate{}
var TLSCert = tls.Certificate{Certificate: [][]byte{{3}, {4}}}

// CertPool is a mock of a *x509.CertPool
var CertPool = x509.NewCertPool()

// ErrorMessage is a mock error message
const ErrorMessage = "default error message"

// DefaultMockConfig returns a default mock config for testing
func DefaultMockConfig(mockCtrl *gomock.Controller) *MockConfig {
config := NewMockConfig(mockCtrl)

config.EXPECT().TLSCACertPool(GoodCert).Return(CertPool, nil).AnyTimes()
config.EXPECT().TLSCACertPool(BadCert).Return(CertPool, errors.New(ErrorMessage)).AnyTimes()
config.EXPECT().TLSCACertPool().Return(CertPool, nil).AnyTimes()
config.EXPECT().TimeoutOrDefault(apiconfig.Endorser).Return(time.Second * 5).AnyTimes()
config.EXPECT().TLSClientCerts().Return([]tls.Certificate{TLSCert}, nil).AnyTimes()

return config
}

// BadTLSClientMockConfig returns a mock config for testing with TLSClientCerts() that always returns an error
func BadTLSClientMockConfig(mockCtrl *gomock.Controller) *MockConfig {
config := NewMockConfig(mockCtrl)

config.EXPECT().TLSCACertPool(GoodCert).Return(CertPool, nil).AnyTimes()
config.EXPECT().TLSCACertPool(BadCert).Return(CertPool, errors.New(ErrorMessage)).AnyTimes()
config.EXPECT().TLSCACertPool().Return(CertPool, nil).AnyTimes()
config.EXPECT().TimeoutOrDefault(apiconfig.Endorser).Return(time.Second * 5).AnyTimes()
config.EXPECT().TLSClientCerts().Return(nil, errors.Errorf(ErrorMessage)).AnyTimes()

return config
}
53 changes: 53 additions & 0 deletions api/apiconfig/network.go
Expand Up @@ -6,6 +6,14 @@ SPDX-License-Identifier: Apache-2.0

package apiconfig

import (
"crypto/x509"
"encoding/pem"
"io/ioutil"

"github.com/hyperledger/fabric-sdk-go/pkg/errors"
)

// NetworkConfig provides a static definition of a Hyperledger Fabric network
type NetworkConfig struct {
Name string
Expand Down Expand Up @@ -136,6 +144,51 @@ type TLSConfig struct {
Pem string
}

// Bytes returns the tls certificate as a byte array by loading it either from the embedded Pem or Path
func (cfg TLSConfig) Bytes() ([]byte, error) {
var bytes []byte
var err error

if cfg.Pem != "" {
bytes = []byte(cfg.Pem)
} else if cfg.Path != "" {
bytes, err = ioutil.ReadFile(cfg.Path)

if err != nil {
return nil, errors.Wrapf(err, "failed to load pem bytes from path %s", cfg.Path)
}
}

return bytes, nil
}

// TLSCert returns the tls certificate as a *x509.Certificate by loading it either from the embedded Pem or Path
func (cfg TLSConfig) TLSCert() (*x509.Certificate, error) {
bytes, err := cfg.Bytes()

if err != nil {
return nil, err
}

return loadCert(bytes)
}

// loadCAKey
func loadCert(rawData []byte) (*x509.Certificate, error) {
block, _ := pem.Decode(rawData)

if block != nil {
pub, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, errors.Wrap(err, "certificate parsing failed")
}

return pub, nil
}

return nil, errors.New("pem data missing")
}

// MutualTLSConfig Mutual TLS configurations
type MutualTLSConfig struct {
Pem []string
Expand Down
4 changes: 3 additions & 1 deletion api/apicore/fabric.go
Expand Up @@ -7,14 +7,16 @@ SPDX-License-Identifier: Apache-2.0
package apicore

import (
"crypto/x509"

"github.com/hyperledger/fabric-sdk-go/api/apiconfig"
"github.com/hyperledger/fabric-sdk-go/api/apifabclient"
)

// FabricProvider allows overriding of fabric objects such as peer and user
type FabricProvider interface {
NewClient(user apifabclient.User) (apifabclient.FabricClient, error)
NewPeer(url string, certificate string, serverHostOverride string) (apifabclient.Peer, error)
NewPeer(url string, certificate *x509.Certificate, serverHostOverride string) (apifabclient.Peer, error)
NewPeerFromConfig(peerCfg *apiconfig.NetworkPeer) (apifabclient.Peer, error)
// EnrollUser(orgID, name, pwd string) (apifabca.User, error)
NewUser(name string, signingIdentity *apifabclient.SigningIdentity) (apifabclient.User, error)
Expand Down
4 changes: 3 additions & 1 deletion api/apifabclient/event.go
Expand Up @@ -7,6 +7,8 @@ SPDX-License-Identifier: Apache-2.0
package apifabclient

import (
"crypto/x509"

"github.com/hyperledger/fabric-sdk-go/api/apitxn"
common "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
ehpb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer"
Expand All @@ -15,7 +17,7 @@ import (

// EventHub ...
type EventHub interface {
SetPeerAddr(peerURL string, certificate string, serverHostOverride string)
SetPeerAddr(peerURL string, certificate *x509.Certificate, serverHostOverride string)
IsConnected() bool
Connect() error
Disconnect() error
Expand Down
4 changes: 2 additions & 2 deletions def/factory/defclient/sessfactory.go
Expand Up @@ -122,9 +122,9 @@ func getChannel(client fab.FabricClient, channelID string) (fab.Channel, error)

for _, ordererCfg := range chOrderers {

orderer, err := orderer.NewOrdererFromConfig(&ordererCfg, client.Config())
orderer, err := orderer.New(client.Config(), orderer.FromOrdererConfig(&ordererCfg))
if err != nil {
return nil, errors.WithMessage(err, "NewOrderer failed")
return nil, errors.WithMessage(err, "creating orderer failed")
}
err = channel.AddOrderer(orderer)
if err != nil {
Expand Down
8 changes: 5 additions & 3 deletions def/provider/fabpvdr/fabpvdr.go
Expand Up @@ -7,6 +7,8 @@ SPDX-License-Identifier: Apache-2.0
package fabpvdr

import (
"crypto/x509"

"github.com/hyperledger/fabric-sdk-go/api/apiconfig"
"github.com/hyperledger/fabric-sdk-go/api/apicryptosuite"
"github.com/hyperledger/fabric-sdk-go/api/apifabca"
Expand Down Expand Up @@ -65,13 +67,13 @@ func (f *FabricProvider) NewUser(name string, signingIdentity *apifabclient.Sign
}

// NewPeer returns a new default implementation of Peer
func (f *FabricProvider) NewPeer(url string, certificate string, serverHostOverride string) (apifabclient.Peer, error) {
return peerImpl.NewPeerTLSFromCert(url, certificate, serverHostOverride, f.config)
func (f *FabricProvider) NewPeer(url string, certificate *x509.Certificate, serverHostOverride string) (apifabclient.Peer, error) {
return peerImpl.New(f.config, peerImpl.WithURL(url), peerImpl.WithTLSCert(certificate), peerImpl.WithServerName(serverHostOverride))
}

// NewPeerFromConfig returns a new default implementation of Peer based configuration
func (f *FabricProvider) NewPeerFromConfig(peerCfg *apiconfig.NetworkPeer) (apifabclient.Peer, error) {
return peerImpl.NewPeerFromConfig(peerCfg, f.config)
return peerImpl.New(f.config, peerImpl.FromPeerConfig(peerCfg))
}

/*
Expand Down
4 changes: 3 additions & 1 deletion def/provider/fabpvdr/fabpvdr_test.go
Expand Up @@ -11,6 +11,7 @@ import (
"testing"

"github.com/hyperledger/fabric-sdk-go/api/apiconfig"
"github.com/hyperledger/fabric-sdk-go/api/apiconfig/mocks"
"github.com/hyperledger/fabric-sdk-go/api/apifabclient"
"github.com/hyperledger/fabric-sdk-go/pkg/cryptosuite/bccsp/sw"
fabricCAClient "github.com/hyperledger/fabric-sdk-go/pkg/fabric-ca-client"
Expand Down Expand Up @@ -88,7 +89,7 @@ func TestNewPeer(t *testing.T) {

url := "grpcs://localhost:8080"

peer, err := p.NewPeer(url, "ABCD", "")
peer, err := p.NewPeer(url, mock_apiconfig.GoodCert, "")
if err != nil {
t.Fatalf("Unexpected error creating peer %v", err)
}
Expand Down Expand Up @@ -122,6 +123,7 @@ func TestNewPeerFromConfig(t *testing.T) {
}

peer, err := p.NewPeerFromConfig(&peerCfg)

if err != nil {
t.Fatalf("Unexpected error creating peer %v", err)
}
Expand Down
15 changes: 9 additions & 6 deletions pkg/config/comm/comm.go
Expand Up @@ -9,21 +9,24 @@ package comm
import (
"crypto/tls"

"crypto/x509"

"github.com/hyperledger/fabric-sdk-go/api/apiconfig"
cutil "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric-sdk-go/pkg/errors"
)

// TLSConfig returns the appropriate config for TLS including the root CAs,
// certs for mutual TLS, and server host override
func TLSConfig(certificate string, serverhostoverride string, config apiconfig.Config) (*tls.Config, error) {
certPool, _ := config.TLSCACertPool("")
// certs for mutual TLS, and server host override. Works with certs loaded either from a path or embedded pem.
func TLSConfig(cert *x509.Certificate, serverName string, config apiconfig.Config) (*tls.Config, error) {
certPool, _ := config.TLSCACertPool()

if len(certificate) == 0 && (certPool == nil || len(certPool.Subjects()) == 0) {
if cert == nil && (certPool == nil || len(certPool.Subjects()) == 0) {
return nil, errors.New("certificate is required")
}

tlsCaCertPool, err := config.TLSCACertPool(certificate)
tlsCaCertPool, err := config.TLSCACertPool(cert)

if err != nil {
return nil, err
}
Expand All @@ -33,7 +36,7 @@ func TLSConfig(certificate string, serverhostoverride string, config apiconfig.C
return nil, errors.Errorf("Error loading cert/key pair for TLS client credentials: %v", err)
}

return &tls.Config{RootCAs: tlsCaCertPool, Certificates: clientCerts, ServerName: serverhostoverride}, nil
return &tls.Config{RootCAs: tlsCaCertPool, Certificates: clientCerts, ServerName: serverName}, nil
}

// TLSCertHash is a utility method to calculate the SHA256 hash of the configured certificate (for usage in channel headers)
Expand Down

0 comments on commit 4c444f7

Please sign in to comment.