Skip to content

Commit 0308f0f

Browse files
committed
[FAB-1141] Enabling TLS in bootstrap feature
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 <[email protected]>
1 parent 844fe2d commit 0308f0f

9 files changed

+152
-107
lines changed

bddtests/compose-defaults.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@ services:
99
# - CORE_VM_ENDPOINT=http://172.17.0.1:2375
1010
- CORE_LOGGING_LEVEL=DEBUG
1111
- CORE_PEER_NETWORKID=${CORE_PEER_NETWORKID}
12+
- CORE_PEER_TLS_ENABLED=true
13+
# This disables mutual auth for gossip
14+
- CORE_PEER_GOSSIP_SKIPHANDSHAKE=true
1215
volumes:
1316
- ./volumes/peer:/var/hyperledger/bddtests/volumes/peer
1417
- /var/run/docker.sock:/var/run/docker.sock
1518
# Script will wait until membersrvc is up (if it exists) before starting
1619
# $$GOPATH (double dollar) required to prevent docker-compose doing its own
1720
# substitution before the value gets to the container
1821
#command: sh -c "exec $$GOPATH/src/github.com/hyperledger/fabric/bddtests/scripts/start-peer.sh"
19-
command: sh -c "sleep 2; peer node start --peer-defaultchain=false"
22+
command: peer node start --peer-defaultchain=false
2023

2124
# Use these options if coverage desired for peers
2225
#image: hyperledger/fabric-peer-coverage

bddtests/docker-compose-next-4.yml

+12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ services:
99
environment:
1010
- ORDERER_GENERAL_LOCALMSPDIR=${ORDERER0_ORDERER_GENERAL_LOCALMSPDIR}
1111
- ORDERER_GENERAL_LOCALMSPID=${ORDERER0_ORDERER_GENERAL_LOCALMSPID}
12+
- ORDERER_GENERAL_TLS_ENABLED=true
13+
- ORDERER_GENERAL_TLS_PRIVATEKEY=${ORDERER0_ORDERER_GENERAL_TLS_PRIVATEKEY}
14+
- ORDERER_GENERAL_TLS_CERTIFICATE=${ORDERER0_ORDERER_GENERAL_TLS_CERTIFICATE}
15+
- ORDERER_GENERAL_TLS_ROOTCAS=${ORDERER0_ORDERER_GENERAL_TLS_ROOTCAS}
1216

1317

1418
peer0:
@@ -24,6 +28,8 @@ services:
2428
- CORE_PEER_LOCALMSPID=${PEER0_CORE_PEER_LOCALMSPID}
2529
- CORE_PEER_TLS_CERT_FILE=${PEER0_CORE_PEER_TLS_CERT_FILE}
2630
- CORE_PEER_TLS_KEY_FILE=${PEER0_CORE_PEER_TLS_KEY_FILE}
31+
- CORE_PEER_TLS_ROOTCERT_FILE=${PEER0_CORE_PEER_TLS_ROOTCERT_FILE}
32+
- CORE_PEER_TLS_SERVERHOSTOVERRIDE=${PEER0_CORE_PEER_TLS_SERVERHOSTOVERRIDE}
2733
depends_on:
2834
- orderer0
2935
# ports:
@@ -42,6 +48,8 @@ services:
4248
- CORE_PEER_LOCALMSPID=${PEER1_CORE_PEER_LOCALMSPID}
4349
- CORE_PEER_TLS_CERT_FILE=${PEER1_CORE_PEER_TLS_CERT_FILE}
4450
- CORE_PEER_TLS_KEY_FILE=${PEER1_CORE_PEER_TLS_KEY_FILE}
51+
- CORE_PEER_TLS_ROOTCERT_FILE=${PEER1_CORE_PEER_TLS_ROOTCERT_FILE}
52+
- CORE_PEER_TLS_SERVERHOSTOVERRIDE=${PEER1_CORE_PEER_TLS_SERVERHOSTOVERRIDE}
4553
depends_on:
4654
- orderer0
4755
- peer0
@@ -58,6 +66,8 @@ services:
5866
- CORE_PEER_LOCALMSPID=${PEER2_CORE_PEER_LOCALMSPID}
5967
- CORE_PEER_TLS_CERT_FILE=${PEER2_CORE_PEER_TLS_CERT_FILE}
6068
- CORE_PEER_TLS_KEY_FILE=${PEER2_CORE_PEER_TLS_KEY_FILE}
69+
- CORE_PEER_TLS_ROOTCERT_FILE=${PEER2_CORE_PEER_TLS_ROOTCERT_FILE}
70+
- CORE_PEER_TLS_SERVERHOSTOVERRIDE=${PEER2_CORE_PEER_TLS_SERVERHOSTOVERRIDE}
6171
depends_on:
6272
- orderer0
6373
- peer0
@@ -74,6 +84,8 @@ services:
7484
- CORE_PEER_LOCALMSPID=${PEER3_CORE_PEER_LOCALMSPID}
7585
- CORE_PEER_TLS_CERT_FILE=${PEER3_CORE_PEER_TLS_CERT_FILE}
7686
- CORE_PEER_TLS_KEY_FILE=${PEER3_CORE_PEER_TLS_KEY_FILE}
87+
- CORE_PEER_TLS_ROOTCERT_FILE=${PEER3_CORE_PEER_TLS_ROOTCERT_FILE}
88+
- CORE_PEER_TLS_SERVERHOSTOVERRIDE=${PEER3_CORE_PEER_TLS_SERVERHOSTOVERRIDE}
7789
depends_on:
7890
- orderer0
7991
- peer0

bddtests/features/bootstrap.feature

+6-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Feature: Bootstrap
1111
As a blockchain entrepreneur
1212
I want to bootstrap a new blockchain network
1313

14-
#@doNotDecompose
14+
@doNotDecompose
1515
@generateDocs
1616
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)
1717
#creates 1 self-signed key/cert pair per orderer organization
@@ -118,7 +118,7 @@ Feature: Bootstrap
118118

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

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

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

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

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

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

242-
And user "dev0Org0" sends proposal "invokeProposal1" to endorsers with timeout of "30" seconds with proposal responses "invokeProposal1Responses":
242+
And user "dev0Org0" using cert alias "dev0Org0App1" sends proposal "invokeProposal1" to endorsers with timeout of "30" seconds with proposal responses "invokeProposal1Responses":
243243
| Endorser |
244244
| peer0 |
245245
| peer2 |

bddtests/steps/bdd_grpc_util.py

+6-53
Original file line numberDiff line numberDiff line change
@@ -14,64 +14,17 @@
1414
# limitations under the License.
1515
#
1616

17-
import re
18-
19-
import bdd_test_util
20-
2117
import grpc
2218

23-
def getGRPCChannel(ipAddress):
24-
channel = grpc.insecure_channel("{0}:{1}".format(ipAddress, 7051), options = [('grpc.max_message_length', 100*1024*1024)])
19+
def getGRPCChannel(ipAddress, port, root_certificates, ssl_target_name_override):
20+
# channel = grpc.insecure_channel("{0}:{1}".format(ipAddress, 7051), options = [('grpc.max_message_length', 100*1024*1024)])
21+
# creds = grpc.ssl_channel_credentials(root_certificates=root_certificates, private_key=private_key, certificate_chain=certificate_chain)
22+
creds = grpc.ssl_channel_credentials(root_certificates=root_certificates)
23+
channel = grpc.secure_channel("{0}:{1}".format(ipAddress, port), creds,
24+
options=(('grpc.ssl_target_name_override', ssl_target_name_override,),('grpc.default_authority', ssl_target_name_override,),))
2525
print("Returning GRPC for address: {0}".format(ipAddress))
2626
return channel
2727

28-
def getGRPCChannelAndUser(context, enrollId):
29-
'''Returns a tuple of GRPC channel and UserRegistration instance. The channel is open to the composeService that the user registered with.'''
30-
userRegistration = bdd_test_util.getUserRegistration(context, enrollId)
31-
32-
# Get the IP address of the server that the user registered on
33-
ipAddress = bdd_test_util.ipFromContainerNamePart(userRegistration.composeService, context.compose_containers)
34-
35-
channel = getGRPCChannel(ipAddress)
36-
37-
return (channel, userRegistration)
38-
39-
40-
def getDeployment(context, ccAlias):
41-
'''Return a deployment with chaincode alias from prior deployment, or None if not found'''
42-
deployment = None
43-
if 'deployments' in context:
44-
pass
45-
else:
46-
context.deployments = {}
47-
if ccAlias in context.deployments:
48-
deployment = context.deployments[ccAlias]
49-
# else:
50-
# raise Exception("Deployment alias not found: '{0}'. Are you sure you have deployed a chaincode with this alias?".format(ccAlias))
51-
return deployment
52-
53-
def getArgsFromContextForUser(context, enrollId):
54-
# Update the chaincodeSpec ctorMsg for invoke
55-
args = []
56-
if 'table' in context:
57-
if context.table:
58-
# There are function arguments
59-
userRegistration = bdd_test_util.getUserRegistration(context, enrollId)
60-
# Allow the user to specify expressions referencing tags in the args list
61-
pattern = re.compile('\{(.*)\}$')
62-
for arg in context.table[0].cells:
63-
m = pattern.match(arg)
64-
if m:
65-
# tagName reference found in args list
66-
tagName = m.groups()[0]
67-
# make sure the tagName is found in the users tags
68-
assert tagName in userRegistration.tags, "TagName '{0}' not found for user '{1}'".format(tagName, userRegistration.getUserName())
69-
args.append(userRegistration.tags[tagName])
70-
else:
71-
#No tag referenced, pass the arg
72-
args.append(arg)
73-
return args
74-
7528
def toStringArray(items):
7629
itemsAsStr = []
7730
for item in items:

bddtests/steps/bootstrap_impl.py

+8-9
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@
1414
#
1515

1616
from behave import *
17-
import bdd_grpc_util
1817
import endorser_util
19-
import bdd_test_util
2018
import bootstrap_util
2119
import orderer_util
2220
import compose
@@ -204,19 +202,19 @@ def step_impl(context, userName, certAlias, configUpdateTxName, createChannelSig
204202
typeAsString="CONFIG_UPDATE")
205203
user.setTagValue(configUpdateTxName, envelope_for_config_update)
206204

207-
@given(u'the user "{userName}" broadcasts ConfigUpdate Tx "{configTxName}" to orderer "{orderer}" to create channel "{channelId}"')
208-
def step_impl(context, userName, configTxName, orderer, channelId):
205+
@given(u'the user "{userName}" using cert alias "{certAlias}" broadcasts ConfigUpdate Tx "{configTxName}" to orderer "{orderer}" to create channel "{channelId}"')
206+
def step_impl(context, userName, certAlias, configTxName, orderer, channelId):
209207
directory = bootstrap_util.getDirectory(context)
210208
user = directory.getUser(userName=userName)
211209
configTxEnvelope = user.tags[configTxName]
212-
bootstrap_util.broadcastCreateChannelConfigTx(context=context, composeService=orderer, chainId=channelId, user=user, configTxEnvelope=configTxEnvelope)
210+
bootstrap_util.broadcastCreateChannelConfigTx(context=context,certAlias=certAlias, composeService=orderer, chainId=channelId, user=user, configTxEnvelope=configTxEnvelope)
213211

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

221219

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

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

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

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

0 commit comments

Comments
 (0)