Skip to content

Commit

Permalink
[FAB-8189] using orderer config from channel block
Browse files Browse the repository at this point in the history
- CA certs in OrdererGroup MSP is used
- Now, Orderer.New goes through even if orderer config
is not present in client config.


Change-Id: I4d41789527a1ffad3755766759d69235912372ee
Signed-off-by: Sudesh Shetty <sudesh.shetty@securekey.com>
  • Loading branch information
sudeshrshetty committed Feb 9, 2018
1 parent 95e3a32 commit f2b1c3b
Show file tree
Hide file tree
Showing 5 changed files with 352 additions and 21 deletions.
84 changes: 69 additions & 15 deletions pkg/fabric-client/channel/channel.go
Expand Up @@ -7,10 +7,17 @@ SPDX-License-Identifier: Apache-2.0
package channel

import (
fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"

"crypto/x509"

"encoding/pem"

"strings"

fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
"regexp"

"github.com/hyperledger/fabric-sdk-go/api/apiconfig"
"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/msp"
"github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/orderer"
"github.com/hyperledger/fabric-sdk-go/pkg/logging"
Expand Down Expand Up @@ -60,31 +67,36 @@ func New(ctx fab.Context, cfg fab.ChannelCfg) (*Channel, error) {
if err := mspManager.Setup(msps); err != nil {
return nil, errors.WithMessage(err, "MSPManager Setup failed")
}

for _, msp := range msps {
for _, cert := range msp.GetTLSRootCerts() {
addCertsToConfig(ctx.Config(), cert)
}

for _, cert := range msp.GetTLSIntermediateCerts() {
addCertsToConfig(ctx.Config(), cert)
}
}
}

c.mspManager = mspManager
c.anchorPeers = cfg.AnchorPeers()

// Add orderer if specified in config
for _, name := range cfg.Orderers() {

oID := name

// TODO: Temporary until full orderer config is retrieved
s := strings.Split(name, ":")
if len(s) > 1 {
oID = s[0]
//Get orderer config by orderer address
oCfg, err := getOrdererConfig(ctx.Config(), name)
if err != nil {
return nil, errors.Errorf("failed to retrieve orderer config...: %s", err)
}

// Figure out orderer configuration
oCfg, err := ctx.Config().OrdererConfig(oID)

// Check if retrieving orderer configuration went ok
if err != nil || oCfg == nil {
return nil, errors.Errorf("failed to retrieve orderer config: %s", err)
var o *orderer.Orderer
if oCfg == nil {
o, err = orderer.New(ctx.Config(), orderer.WithURL(resolveOrdererURL(name)), orderer.WithServerName(resolveOrdererAddress(name)))
} else {
o, err = orderer.New(ctx.Config(), orderer.FromOrdererConfig(oCfg))
}

o, err := orderer.New(ctx.Config(), orderer.FromOrdererConfig(oCfg))
if err != nil {
return nil, errors.WithMessage(err, "failed to create new orderer from config")
}
Expand Down Expand Up @@ -273,3 +285,45 @@ func (c *Channel) IsReadonly() bool {
func (c *Channel) IsInitialized() bool {
return c.initialized
}

//addCertsToConfig adds cert bytes to config TLSCACertPool
func addCertsToConfig(config apiconfig.Config, pemCerts []byte) {
for len(pemCerts) > 0 {
var block *pem.Block
block, pemCerts = pem.Decode(pemCerts)
if block == nil {
break
}
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
continue
}

cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
continue
}
config.TLSCACertPool(cert)
}
}

// getOrdererConfig returns ordererconfig for given ordererAddress (ports will be ignored)
func getOrdererConfig(config apiconfig.Config, ordererAddress string) (*apiconfig.OrdererConfig, error) {
return config.OrdererConfig(resolveOrdererAddress(ordererAddress))
}

// resolveOrdererAddress resolves order address to remove port from address if present
func resolveOrdererAddress(ordererAddress string) string {
s := strings.Split(ordererAddress, ":")
if len(s) > 1 {
return s[0]
}
return ordererAddress
}

// resolveOrdererURL resolves order URL to prefix protocol if not present
func resolveOrdererURL(ordererURL string) string {
if ok, err := regexp.MatchString(".*://", ordererURL); ok && err == nil {
return ordererURL
}
return "grpcs://" + ordererURL
}
200 changes: 200 additions & 0 deletions test/fixtures/config/config_test_no_orderer.yaml
@@ -0,0 +1,200 @@
#
# Copyright SecureKey Technologies Inc. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# The network connection profile provides client applications the information about the target
# blockchain network that are necessary for the applications to interact with it. These are all
# knowledge that must be acquired from out-of-band sources. This file provides such a source.
#
name: "global-trade-network"

#
# Any properties with an "x-" prefix will be treated as application-specific, exactly like how naming
# in HTTP headers or swagger properties work. The SDK will simply ignore these fields and leave
# them for the applications to process. This is a mechanism for different components of an application
# to exchange information that are not part of the standard schema described below. In particular,
# the "x-type" property with the "hlfv1" value example below is used by Hyperledger Composer to
# determine the type of Fabric networks (v0.6 vs. v1.0) it needs to work with.
#
x-type: "hlfv1"
x-loggingLevel: info

#
# Describe what the target network is/does.
#
description: "The network to be in if you want to stay in the global trade business"

#
# Schema version of the content. Used by the SDK to apply the corresponding parsing rules.
#
version: 1.0.0

#
# The client section used by GO SDK.
#
client:

# Which organization does this application instance belong to? The value must be the name of an org
# defined under "organizations"
organization: Org1

logging:
level: info

# Global configuration for peer, event service and orderer timeouts
peer:
timeout:
connection: 3s
queryResponse: 45s
executeTxResponse: 60s
discovery:
# Expiry period for discovery service greylist filter
# The channel client will greylist peers that are found to be offline
# to prevent re-selecting them in subsequent retries.
# This interval will define how long a peer is greylisted
greylistExpiry: 5s
eventService:
timeout:
connection: 3s
registrationResponse: 3s
orderer:
timeout:
connection: 3s
response: 5s


# Needed to load users crypto keys and certs.
cryptoconfig:
path: ${GOPATH}/src/github.com/hyperledger/fabric-sdk-go/${CRYPTOCONFIG_FIXTURES_PATH}

# Some SDKs support pluggable KV stores, the properties under "credentialStore"
# are implementation specific
credentialStore:
# [Optional]. Not used by Go SDK. Others SDKs may use it if using an alternative impl
# Could be used if SDK would require an object for properties like url, db name, etc.
path: "/tmp/hfc-kvs"

# [Optional]. Specific to the CryptoSuite implementation used by GO SDK. Software-based implementations
# requiring a key store. PKCS#11 based implementations does not.
cryptoStore:
# Specific to the underlying KeyValueStore that backs the crypto key store.
path: /tmp/msp

# [Optional]. Specific to Composer environment. Not used by SDK Go.
wallet: wallet-name

# BCCSP config for the client. Used by GO SDK.
BCCSP:
security:
enabled: true
default:
provider: "SW"
hashAlgorithm: "SHA2"
softVerify: true
ephemeral: false
level: 256

tlsCerts:
# [Optional]. Use system certificate pool when connecting to peers, orderers (for negotiating TLS) Default: false
systemCertPool: false

# [Optional]. Client key and cert for TLS handshake with peers and orderers
client:
keyfile: ${GOPATH}/src/github.com/hyperledger/fabric-sdk-go/test/fixtures/config/mutual_tls/client_sdk_go-key.pem
certfile: ${GOPATH}/src/github.com/hyperledger/fabric-sdk-go/test/fixtures/config/mutual_tls/client_sdk_go.pem

#
# [Optional]. But most apps would have this section so that channel objects can be constructed
# based on the content below. If an app is creating channels, then it likely will not need this
# section.
#
channels:
# name of the channel
mychannel:

# Required. list of peers from participating orgs
peers:
peer0.org1.example.com:
# [Optional]. will this peer be sent transaction proposals for endorsement? The peer must
# have the chaincode installed. The app can also use this property to decide which peers
# to send the chaincode install request. Default: true
endorsingPeer: true

# [Optional]. will this peer be sent query proposals? The peer must have the chaincode
# installed. The app can also use this property to decide which peers to send the
# chaincode install request. Default: true
chaincodeQuery: true

# [Optional]. will this peer be sent query proposals that do not require chaincodes, like
# queryBlock(), queryTransaction(), etc. Default: true
ledgerQuery: true

# [Optional]. will this peer be the target of the SDK's listener registration? All peers can
# produce events but the app typically only needs to connect to one to listen to events.
# Default: true
eventSource: true

# [Optional]. what chaincodes are expected to exist on this channel? The application can use
# this information to validate that the target peers are in the expected state by comparing
# this list with the query results of getInstalledChaincodes() and getInstantiatedChaincodes()
chaincodes:
# the format follows the "canonical name" of chaincodes by fabric code
- example02:v1
- marbles:1.0


#
# list of participating organizations in this network
#
organizations:
Org1:
mspid: Org1MSP

# Needed to load users crypto keys and certs for this org (absolute path or relative to global crypto path, DEV mode)
cryptoPath: peerOrganizations/org1.example.com/users/{userName}@org1.example.com/msp

peers:
- peer0.org1.example.com

# [Optional]. Certificate Authorities issue certificates for identification purposes in a Fabric based
# network. Typically certificates provisioning is done in a separate process outside of the
# runtime network. Fabric-CA is a special certificate authority that provides a REST APIs for
# dynamic certificate management (enroll, revoke, re-enroll). The following section is only for
# Fabric-CA servers.
certificateAuthorities:
- ca.org1.example.com

# [Optional]. If the application is going to make requests that are reserved to organization
# administrators, including creating/updating channels, installing/instantiating chaincodes, it
# must have access to the admin identity represented by the private key and signing certificate.
# Both properties can be the PEM string or local path to the PEM file. Note that this is mainly for
# convenience in development mode, production systems should not expose sensitive information
# this way. The SDK should allow applications to set the org admin identity via APIs, and only use
# this route as an alternative when it exists.
adminPrivateKey:
pem: "-----BEGIN PRIVATE KEY----- <etc>"
signedCert:
path: "/tmp/somepath/signed-cert.pem"


#
# List of peers to send various requests to, including endorsement, query
# and event listener registration.
#
peers:
peer0.org1.example.com:
# this URL is used to send endorsement and query requests
url: grpcs://peer0.org1.example.com:7051

# this URL is used to connect the EventHub and registering event listeners
eventUrl: grpcs://peer0.org1.example.com:7053

grpcOptions:
ssl-target-name-override: peer0.org1.example.com
grpc.http2.keepalive_time: 15

tlsCACerts:
# Certificate location absolute path
path: ${GOPATH}/src/github.com/hyperledger/fabric-sdk-go/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem

0 comments on commit f2b1c3b

Please sign in to comment.