Skip to content

Commit

Permalink
[FAB-1141] Enabling TLS in bootstrap feature
Browse files Browse the repository at this point in the history
Changed the AnchorPeer port to 7051 as it shares
the peer channel.

Now set CORE_PEER_TSL_ROOTCERT_FILE to signing orgs
cert for the signer for the peer.

Use RSA based keys for TLS certs to enable python to
golang TLS connections without handshake failures.

Change-Id: I94d653e9d9e666f90665a62bb5bbbfd376bc9b23
Signed-off-by: jeffgarratt <garratt.jeff@gmail.com>
  • Loading branch information
jeffgarratt committed Mar 15, 2017
1 parent 844fe2d commit 0308f0f
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 107 deletions.
5 changes: 4 additions & 1 deletion bddtests/compose-defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ services:
# - CORE_VM_ENDPOINT=http://172.17.0.1:2375
- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_NETWORKID=${CORE_PEER_NETWORKID}
- CORE_PEER_TLS_ENABLED=true
# This disables mutual auth for gossip
- CORE_PEER_GOSSIP_SKIPHANDSHAKE=true
volumes:
- ./volumes/peer:/var/hyperledger/bddtests/volumes/peer
- /var/run/docker.sock:/var/run/docker.sock
# Script will wait until membersrvc is up (if it exists) before starting
# $$GOPATH (double dollar) required to prevent docker-compose doing its own
# substitution before the value gets to the container
#command: sh -c "exec $$GOPATH/src/github.com/hyperledger/fabric/bddtests/scripts/start-peer.sh"
command: sh -c "sleep 2; peer node start --peer-defaultchain=false"
command: peer node start --peer-defaultchain=false

# Use these options if coverage desired for peers
#image: hyperledger/fabric-peer-coverage
Expand Down
12 changes: 12 additions & 0 deletions bddtests/docker-compose-next-4.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ services:
environment:
- ORDERER_GENERAL_LOCALMSPDIR=${ORDERER0_ORDERER_GENERAL_LOCALMSPDIR}
- ORDERER_GENERAL_LOCALMSPID=${ORDERER0_ORDERER_GENERAL_LOCALMSPID}
- ORDERER_GENERAL_TLS_ENABLED=true
- ORDERER_GENERAL_TLS_PRIVATEKEY=${ORDERER0_ORDERER_GENERAL_TLS_PRIVATEKEY}
- ORDERER_GENERAL_TLS_CERTIFICATE=${ORDERER0_ORDERER_GENERAL_TLS_CERTIFICATE}
- ORDERER_GENERAL_TLS_ROOTCAS=${ORDERER0_ORDERER_GENERAL_TLS_ROOTCAS}


peer0:
Expand All @@ -24,6 +28,8 @@ services:
- CORE_PEER_LOCALMSPID=${PEER0_CORE_PEER_LOCALMSPID}
- CORE_PEER_TLS_CERT_FILE=${PEER0_CORE_PEER_TLS_CERT_FILE}
- CORE_PEER_TLS_KEY_FILE=${PEER0_CORE_PEER_TLS_KEY_FILE}
- CORE_PEER_TLS_ROOTCERT_FILE=${PEER0_CORE_PEER_TLS_ROOTCERT_FILE}
- CORE_PEER_TLS_SERVERHOSTOVERRIDE=${PEER0_CORE_PEER_TLS_SERVERHOSTOVERRIDE}
depends_on:
- orderer0
# ports:
Expand All @@ -42,6 +48,8 @@ services:
- CORE_PEER_LOCALMSPID=${PEER1_CORE_PEER_LOCALMSPID}
- CORE_PEER_TLS_CERT_FILE=${PEER1_CORE_PEER_TLS_CERT_FILE}
- CORE_PEER_TLS_KEY_FILE=${PEER1_CORE_PEER_TLS_KEY_FILE}
- CORE_PEER_TLS_ROOTCERT_FILE=${PEER1_CORE_PEER_TLS_ROOTCERT_FILE}
- CORE_PEER_TLS_SERVERHOSTOVERRIDE=${PEER1_CORE_PEER_TLS_SERVERHOSTOVERRIDE}
depends_on:
- orderer0
- peer0
Expand All @@ -58,6 +66,8 @@ services:
- CORE_PEER_LOCALMSPID=${PEER2_CORE_PEER_LOCALMSPID}
- CORE_PEER_TLS_CERT_FILE=${PEER2_CORE_PEER_TLS_CERT_FILE}
- CORE_PEER_TLS_KEY_FILE=${PEER2_CORE_PEER_TLS_KEY_FILE}
- CORE_PEER_TLS_ROOTCERT_FILE=${PEER2_CORE_PEER_TLS_ROOTCERT_FILE}
- CORE_PEER_TLS_SERVERHOSTOVERRIDE=${PEER2_CORE_PEER_TLS_SERVERHOSTOVERRIDE}
depends_on:
- orderer0
- peer0
Expand All @@ -74,6 +84,8 @@ services:
- CORE_PEER_LOCALMSPID=${PEER3_CORE_PEER_LOCALMSPID}
- CORE_PEER_TLS_CERT_FILE=${PEER3_CORE_PEER_TLS_CERT_FILE}
- CORE_PEER_TLS_KEY_FILE=${PEER3_CORE_PEER_TLS_KEY_FILE}
- CORE_PEER_TLS_ROOTCERT_FILE=${PEER3_CORE_PEER_TLS_ROOTCERT_FILE}
- CORE_PEER_TLS_SERVERHOSTOVERRIDE=${PEER3_CORE_PEER_TLS_SERVERHOSTOVERRIDE}
depends_on:
- orderer0
- peer0
12 changes: 6 additions & 6 deletions bddtests/features/bootstrap.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Feature: Bootstrap
As a blockchain entrepreneur
I want to bootstrap a new blockchain network

#@doNotDecompose
@doNotDecompose
@generateDocs
Scenario Outline: Bootstrap a development network with 4 peers (2 orgs) and 1 orderer (1 org), each having a single independent root of trust (No fabric-ca, just openssl)
#creates 1 self-signed key/cert pair per orderer organization
Expand Down Expand Up @@ -118,7 +118,7 @@ Feature: Bootstrap

And the user "dev0Org0" creates a ConfigUpdate Tx "configUpdateTx1" using cert alias "dev0Org0App1" using signed ConfigUpdateEnvelope "createChannelConfigUpdate1"

And the user "dev0Org0" broadcasts ConfigUpdate Tx "configUpdateTx1" to orderer "orderer0" to create channel "com.acme.blockchain.jdoe.Channel1"
And the user "dev0Org0" using cert alias "dev0Org0App1" broadcasts ConfigUpdate Tx "configUpdateTx1" to orderer "orderer0" to create channel "com.acme.blockchain.jdoe.Channel1"

# Sleep as the deliver takes a bit to have the first block ready
And I wait "2" seconds
Expand Down Expand Up @@ -161,7 +161,7 @@ Feature: Bootstrap
# Under the covers, create a deployment spec, etc.
And user "dev0Org0" using cert alias "dev0Org0App1" creates a install proposal "installProposal1" for channel "com.acme.blockchain.jdoe.Channel1" using chaincode spec "cc_spec"

And user "dev0Org0" sends proposal "installProposal1" to endorsers with timeout of "30" seconds with proposal responses "installProposalResponses":
And user "dev0Org0" using cert alias "dev0Org0App1" sends proposal "installProposal1" to endorsers with timeout of "30" seconds with proposal responses "installProposalResponses":
| Endorser |
| peer0 |
| peer2 |
Expand All @@ -174,7 +174,7 @@ Feature: Bootstrap
# Under the covers, create a deployment spec, etc.
When user "dev0Org0" using cert alias "dev0Org0App1" creates a instantiate proposal "instantiateProposal1" for channel "com.acme.blockchain.jdoe.Channel1" using chaincode spec "cc_spec"

And user "dev0Org0" sends proposal "instantiateProposal1" to endorsers with timeout of "90" seconds with proposal responses "instantiateProposalResponses":
And user "dev0Org0" using cert alias "dev0Org0App1" sends proposal "instantiateProposal1" to endorsers with timeout of "30" seconds with proposal responses "instantiateProposalResponses":
| Endorser |
| peer0 |
| peer2 |
Expand Down Expand Up @@ -215,7 +215,7 @@ Feature: Bootstrap
# Under the covers, create a deployment spec, etc.
And user "dev0Org0" using cert alias "dev0Org0App1" creates a proposal "queryProposal1" for channel "com.acme.blockchain.jdoe.Channel1" using chaincode spec "querySpec1"

And user "dev0Org0" sends proposal "queryProposal1" to endorsers with timeout of "30" seconds with proposal responses "queryProposal1Responses":
And user "dev0Org0" using cert alias "dev0Org0App1" sends proposal "queryProposal1" to endorsers with timeout of "30" seconds with proposal responses "queryProposal1Responses":
| Endorser |
| peer0 |
| peer2 |
Expand All @@ -239,7 +239,7 @@ Feature: Bootstrap
# Under the covers, create a deployment spec, etc.
And user "dev0Org0" using cert alias "dev0Org0App1" creates a proposal "invokeProposal1" for channel "com.acme.blockchain.jdoe.Channel1" using chaincode spec "invocationSpec1"

And user "dev0Org0" sends proposal "invokeProposal1" to endorsers with timeout of "30" seconds with proposal responses "invokeProposal1Responses":
And user "dev0Org0" using cert alias "dev0Org0App1" sends proposal "invokeProposal1" to endorsers with timeout of "30" seconds with proposal responses "invokeProposal1Responses":
| Endorser |
| peer0 |
| peer2 |
Expand Down
59 changes: 6 additions & 53 deletions bddtests/steps/bdd_grpc_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,64 +14,17 @@
# limitations under the License.
#

import re

import bdd_test_util

import grpc

def getGRPCChannel(ipAddress):
channel = grpc.insecure_channel("{0}:{1}".format(ipAddress, 7051), options = [('grpc.max_message_length', 100*1024*1024)])
def getGRPCChannel(ipAddress, port, root_certificates, ssl_target_name_override):
# channel = grpc.insecure_channel("{0}:{1}".format(ipAddress, 7051), options = [('grpc.max_message_length', 100*1024*1024)])
# creds = grpc.ssl_channel_credentials(root_certificates=root_certificates, private_key=private_key, certificate_chain=certificate_chain)
creds = grpc.ssl_channel_credentials(root_certificates=root_certificates)
channel = grpc.secure_channel("{0}:{1}".format(ipAddress, port), creds,
options=(('grpc.ssl_target_name_override', ssl_target_name_override,),('grpc.default_authority', ssl_target_name_override,),))
print("Returning GRPC for address: {0}".format(ipAddress))
return channel

def getGRPCChannelAndUser(context, enrollId):
'''Returns a tuple of GRPC channel and UserRegistration instance. The channel is open to the composeService that the user registered with.'''
userRegistration = bdd_test_util.getUserRegistration(context, enrollId)

# Get the IP address of the server that the user registered on
ipAddress = bdd_test_util.ipFromContainerNamePart(userRegistration.composeService, context.compose_containers)

channel = getGRPCChannel(ipAddress)

return (channel, userRegistration)


def getDeployment(context, ccAlias):
'''Return a deployment with chaincode alias from prior deployment, or None if not found'''
deployment = None
if 'deployments' in context:
pass
else:
context.deployments = {}
if ccAlias in context.deployments:
deployment = context.deployments[ccAlias]
# else:
# raise Exception("Deployment alias not found: '{0}'. Are you sure you have deployed a chaincode with this alias?".format(ccAlias))
return deployment

def getArgsFromContextForUser(context, enrollId):
# Update the chaincodeSpec ctorMsg for invoke
args = []
if 'table' in context:
if context.table:
# There are function arguments
userRegistration = bdd_test_util.getUserRegistration(context, enrollId)
# Allow the user to specify expressions referencing tags in the args list
pattern = re.compile('\{(.*)\}$')
for arg in context.table[0].cells:
m = pattern.match(arg)
if m:
# tagName reference found in args list
tagName = m.groups()[0]
# make sure the tagName is found in the users tags
assert tagName in userRegistration.tags, "TagName '{0}' not found for user '{1}'".format(tagName, userRegistration.getUserName())
args.append(userRegistration.tags[tagName])
else:
#No tag referenced, pass the arg
args.append(arg)
return args

def toStringArray(items):
itemsAsStr = []
for item in items:
Expand Down
17 changes: 8 additions & 9 deletions bddtests/steps/bootstrap_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
#

from behave import *
import bdd_grpc_util
import endorser_util
import bdd_test_util
import bootstrap_util
import orderer_util
import compose
Expand Down Expand Up @@ -204,19 +202,19 @@ def step_impl(context, userName, certAlias, configUpdateTxName, createChannelSig
typeAsString="CONFIG_UPDATE")
user.setTagValue(configUpdateTxName, envelope_for_config_update)

@given(u'the user "{userName}" broadcasts ConfigUpdate Tx "{configTxName}" to orderer "{orderer}" to create channel "{channelId}"')
def step_impl(context, userName, configTxName, orderer, channelId):
@given(u'the user "{userName}" using cert alias "{certAlias}" broadcasts ConfigUpdate Tx "{configTxName}" to orderer "{orderer}" to create channel "{channelId}"')
def step_impl(context, userName, certAlias, configTxName, orderer, channelId):
directory = bootstrap_util.getDirectory(context)
user = directory.getUser(userName=userName)
configTxEnvelope = user.tags[configTxName]
bootstrap_util.broadcastCreateChannelConfigTx(context=context, composeService=orderer, chainId=channelId, user=user, configTxEnvelope=configTxEnvelope)
bootstrap_util.broadcastCreateChannelConfigTx(context=context,certAlias=certAlias, composeService=orderer, chainId=channelId, user=user, configTxEnvelope=configTxEnvelope)

@when(u'the user "{userName}" broadcasts transaction "{transactionAlias}" to orderer "{orderer}" on channel "{channelId}"')
def step_impl(context, userName, transactionAlias, orderer, channelId):
directory = bootstrap_util.getDirectory(context)
user = directory.getUser(userName=userName)
transaction = user.tags[transactionAlias]
bootstrap_util.broadcastCreateChannelConfigTx(context=context, composeService=orderer, chainId=channelId, user=user, configTxEnvelope=transaction)
bootstrap_util.broadcastCreateChannelConfigTx(context=context, certAlias=None, composeService=orderer, chainId=channelId, user=user, configTxEnvelope=transaction)


@when(u'user "{userName}" using cert alias "{certAlias}" connects to deliver function on orderer "{composeService}"')
Expand All @@ -225,7 +223,7 @@ def step_impl(context, userName, certAlias, composeService):
user = directory.getUser(userName=userName)
nodeAdminTuple = user.tags[certAlias]
cert = directory.findCertForNodeAdminTuple(nodeAdminTuple)
user.connectToDeliverFunction(context, composeService, cert, nodeAdminTuple=nodeAdminTuple)
user.connectToDeliverFunction(context, composeService, certAlias, nodeAdminTuple=nodeAdminTuple)

@when(u'user "{userName}" sends deliver a seek request on orderer "{composeService}" with properties')
def step_impl(context, userName, composeService):
Expand Down Expand Up @@ -256,8 +254,9 @@ def step_impl(context, userName, certAlias, genisisBlockName, joinChannelResult)
timeout = 10
directory = bootstrap_util.getDirectory(context)
user = directory.getUser(userName)
nodeAdminTuple = user.tags[certAlias]
# Find the cert using the cert tuple information saved for the user under certAlias
signersCert = directory.findCertForNodeAdminTuple(user.tags[certAlias])
signersCert = directory.findCertForNodeAdminTuple(nodeAdminTuple)

# Retrieve the genesis block from the returned value of deliver (Will be list with first block as genesis block)
genesisBlock = user.tags[genisisBlockName][0]
Expand All @@ -267,7 +266,7 @@ def step_impl(context, userName, certAlias, genisisBlockName, joinChannelResult)

# Send proposal to each specified endorser, waiting 'timeout' seconds for response/error
endorsers = [row['Peer'] for row in context.table.rows]
proposalResponseFutures = [endorserStub.ProcessProposal.future(signedProposal, int(timeout)) for endorserStub in endorser_util.getEndorserStubs(context, endorsers)]
proposalResponseFutures = [endorserStub.ProcessProposal.future(signedProposal, int(timeout)) for endorserStub in endorser_util.getEndorserStubs(context,composeServices=endorsers, directory=directory, nodeAdminTuple=nodeAdminTuple)]
resultsDict = dict(zip(endorsers, [respFuture.result() for respFuture in proposalResponseFutures]))
user.setTagValue(joinChannelResult, resultsDict)

Expand Down
Loading

0 comments on commit 0308f0f

Please sign in to comment.