Skip to content

Commit 8126b2e

Browse files
committed
[FAB-1141] Bootstrap now creates local MSP config
The boostrap feature now configures the local MSP folders (cacerts, signcerts, and keystore) properly. Added GenesisMethod parameter to orderer base docker compose file. Removed pre-V1 security configuration from docker compose file. Changed discovery configuration in docker compose to gossip mechanism. Change-Id: Ib97fca264eb5c93b81464ab3d76c55ccedd085ac Signed-off-by: jeffgarratt <[email protected]>
1 parent 75e960a commit 8126b2e

7 files changed

+113
-29
lines changed

bddtests/compose-defaults.yml

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ services:
1010
# TODO: This is currently required due to BUG in variant logic based upon log level.
1111
- CORE_LOGGING_LEVEL=DEBUG
1212
- CORE_PEER_NETWORKID=${CORE_PEER_NETWORKID}
13+
volumes:
14+
- ./volumes/peer:/var/hyperledger/bddtests/volumes/peer
1315
# Script will wait until membersrvc is up (if it exists) before starting
1416
# $$GOPATH (double dollar) required to prevent docker-compose doing its own
1517
# substitution before the value gets to the container
@@ -22,3 +24,7 @@ services:
2224
membersrvc:
2325
image: hyperledger/fabric-membersrvc
2426
command: membersrvc
27+
28+
volumes:
29+
30+
peer:

bddtests/docker-compose-next-4.yml

+14-18
Original file line numberDiff line numberDiff line change
@@ -13,64 +13,60 @@ services:
1313
service: orderer0
1414

1515

16-
vp0:
16+
peer0:
1717
extends:
1818
file: docker-compose-next.yml
1919
service: vpNext
2020
environment:
2121
- CORE_PEER_ID=vp0
2222
- CORE_PEER_PROFILE_ENABLED=true
2323
- CORE_PEER_COMMITTER_LEDGER_ORDERER=orderer0:7050
24-
- CORE_SECURITY_ENROLLID=test_vp0
25-
- CORE_SECURITY_ENROLLSECRET=MwYpmSRjupbT
24+
- CORE_PEER_MSPCONFIGPATH=${PEER0_CORE_PEER_MSPCFGPATH}
2625
depends_on:
2726
- membersrvc0
2827
- orderer0
2928
# ports:
3029
# - 7050:6060
3130

3231

33-
vp1:
32+
peer1:
3433
extends:
3534
file: docker-compose-next.yml
3635
service: vpNext
3736
environment:
3837
- CORE_PEER_ID=vp1
39-
- CORE_PEER_DISCOVERY_ROOTNODE=vp0:7051
38+
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0:7051
4039
- CORE_PEER_COMMITTER_LEDGER_ORDERER=orderer0:7050
41-
- CORE_SECURITY_ENROLLID=test_vp1
42-
- CORE_SECURITY_ENROLLSECRET=5wgHK9qqYaPy
40+
- CORE_PEER_MSPCONFIGPATH=${PEER1_CORE_PEER_MSPCFGPATH}
4341
depends_on:
4442
- membersrvc0
4543
- orderer0
46-
- vp0
44+
- peer0
4745

48-
vp2:
46+
peer2:
4947
extends:
5048
file: docker-compose-next.yml
5149
service: vpNext
5250
environment:
5351
- CORE_PEER_ID=vp2
54-
- CORE_PEER_DISCOVERY_ROOTNODE=vp0:7051
52+
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0:7051
5553
- CORE_PEER_COMMITTER_LEDGER_ORDERER=orderer0:7050
56-
- CORE_SECURITY_ENROLLID=test_vp2
57-
- CORE_SECURITY_ENROLLSECRET=vQelbRvja7cJ
54+
- CORE_PEER_MSPCONFIGPATH=${PEER2_CORE_PEER_MSPCFGPATH}
5855
depends_on:
5956
- membersrvc0
6057
- orderer0
61-
- vp0
58+
- peer0
6259

63-
vp3:
60+
peer3:
6461
extends:
6562
file: docker-compose-next.yml
6663
service: vpNext
6764
environment:
6865
- CORE_PEER_ID=vp3
69-
- CORE_PEER_DISCOVERY_ROOTNODE=vp0:7051
66+
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0:7051
7067
- CORE_PEER_COMMITTER_LEDGER_ORDERER=orderer0:7050
71-
- CORE_SECURITY_ENROLLID=test_vp3
72-
- CORE_SECURITY_ENROLLSECRET=9LKqKH5peurL
68+
- CORE_PEER_MSPCONFIGPATH=${PEER3_CORE_PEER_MSPCFGPATH}
7369
depends_on:
7470
- membersrvc0
7571
- orderer0
76-
- vp0
72+
- peer0

bddtests/docker-compose-orderer-base.yml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ services:
1111
- ORDERER_GENERAL_MAXWINDOWSIZE=1000
1212
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
1313
- ORDERER_GENERAL_LOGLEVEL=debug
14+
- ORDERER_GENERAL_GENESISMETHOD=provisional
1415
- ORDERER_GENERAL_GENESISIFILE=${ORDERER_GENERAL_GENESISIFILE}
1516
- ORDERER_RAMLEDGER_HISTORY_SIZE=100
1617
volumes:

bddtests/features/bootstrap.feature

+10-10
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ Feature: Bootstrap
2525
# | User | Orderer | Organization |
2626

2727
And the peer network has organizations:
28-
| peerOrg0 |
28+
| Organization |
29+
| peerOrg0 |
2930

3031
And a ordererBootstrapAdmin is identified and given access to all public certificates and orderer node info
3132
# Order info includes orderer admin/orderer information and address (host:port) from previous steps
@@ -37,18 +38,17 @@ Feature: Bootstrap
3738

3839
# to be used for setting the orderer genesis block path parameter in composition
3940
And the orderer admins use the genesis block for chain "<OrdererSystemChainId>" to configure orderers
40-
And we compose "<ComposeFile>"
41-
42-
4341

4442
# We now have an orderer network with NO peers. Now need to configure and start the peer network
45-
And user requests role of peer admin by creating a key and csr for peer and acquires signed certificate from organization:
46-
| peer0Admin | peer0 | peerOrg0 |
47-
48-
# We now have an orderer network with NO peers. Now need to configure and start the peer network
49-
And user requests role of peer signer by creating a key and csr for peer and acquires signed certificate from organization:
50-
| peer0Signer | peer0 | peerOrg0 |
43+
# This can be currently automated through folder creation of the proper form and placing PEMs.
44+
And user requests role for peer by creating a key and csr for peer and acquires signed certificate from organization:
45+
| User | Peer | Organization |
46+
| peer0Signer | peer0 | peerOrg0 |
47+
| peer1Signer | peer1 | peerOrg0 |
48+
| peer2Signer | peer2 | peerOrg0 |
49+
| peer3Signer | peer3 | peerOrg0 |
5150

51+
And we compose "<ComposeFile>"
5252

5353
And peer admins get the genesis block for chain 'chain1' from chainBoostrapAdmin
5454
And the peer admins inspect and approve the genesis block for chain 'chain1'

bddtests/steps/bootstrap_impl.py

+8
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ def step_impl(context):
3333
for row in context.table.rows:
3434
directory.registerOrdererAdminTuple(row['User'], row['Orderer'], row['Organization'])
3535

36+
@given(u'user requests role for peer by creating a key and csr for peer and acquires signed certificate from organization')
37+
def step_impl(context):
38+
assert 'table' in context, "Expected table with triplet of User/Peer/Organization"
39+
directory = bootstrap_util.getDirectory(context)
40+
for row in context.table.rows:
41+
directory.registerOrdererAdminTuple(row['User'], row['Peer'], row['Organization'])
42+
3643
@given(u'the peer network has organizations')
3744
def step_impl(context):
3845
assert 'table' in context, "Expected table of peer network organizations"
@@ -50,6 +57,7 @@ def step_impl(context):
5057
def step_impl(context, ordererSystemChainId, networkConfigPolicy, consensusType):
5158
genesisBlock = bootstrap_util.createGenesisBlock(context, ordererSystemChainId, networkConfigPolicy, consensusType)
5259
bootstrap_util.OrdererGensisBlockCompositionCallback(context, genesisBlock)
60+
bootstrap_util.PeerCompositionCallback(context)
5361

5462
@given(u'the orderer admins inspect and approve the genesis block for chain "{chainId}"')
5563
def step_impl(context, chainId):

bddtests/steps/bootstrap_util.py

+63
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ def __init__(self, name):
137137
# Which networks this organization belongs to
138138
self.networks = []
139139

140+
def getSelfSignedCert(self):
141+
return self.signedCert
142+
140143
def createCertificate(self, certReq):
141144
numYrs = 1
142145
return createCertificate(certReq, (self.signedCert, self.pKey), 1000, (0, 60*60*24*365*numYrs))
@@ -413,6 +416,66 @@ def getEnv(self, composition, context, env):
413416
env["ORDERER_GENERAL_GENESISIFILE"]=self.getGenesisFilePath(composition, pathType=PathType.Container)
414417

415418

419+
class PeerCompositionCallback(compose.CompositionCallback):
420+
'Responsible for setting up Peer nodes upon composition'
421+
422+
def __init__(self, context):
423+
self.context = context
424+
self.volumeRootPathInContainer="/var/hyperledger/bddtests"
425+
compose.Composition.RegisterCallbackInContext(context, self)
426+
427+
def getVolumePath(self, composition, pathType=PathType.Local):
428+
assert pathType in PathType, "Expected pathType of {0}".format(PathType)
429+
basePath = "."
430+
if pathType == PathType.Container:
431+
basePath = self.volumeRootPathInContainer
432+
return "{0}/volumes/peer/{1}".format(basePath, composition.projectName)
433+
434+
def getPeerList(self, composition):
435+
return [serviceName for serviceName in composition.getServiceNames() if "peer" in serviceName]
436+
437+
def getLocalMspConfigPath(self, composition, peerService, pathType=PathType.Local):
438+
return "{0}/{1}/localMspConfig".format(self.getVolumePath(composition, pathType), peerService)
439+
440+
def _createLocalMspConfigDirs(self, mspConfigPath):
441+
os.makedirs("{0}/{1}".format(mspConfigPath, "signcerts"))
442+
os.makedirs("{0}/{1}".format(mspConfigPath, "admincerts"))
443+
os.makedirs("{0}/{1}".format(mspConfigPath, "cacerts"))
444+
os.makedirs("{0}/{1}".format(mspConfigPath, "keystore"))
445+
446+
447+
def composing(self, composition, context):
448+
'Will copy local MSP info over at this point for each peer node'
449+
450+
directory = getDirectory(context)
451+
452+
for peerService in self.getPeerList(composition):
453+
localMspConfigPath = self.getLocalMspConfigPath(composition, peerService)
454+
self._createLocalMspConfigDirs(localMspConfigPath)
455+
# Loop through directory and place Peer Organization Certs into cacerts folder
456+
for peerOrg in [org for orgName,org in directory.organizations.items() if Network.Peer in org.networks]:
457+
with open("{0}/cacerts/{1}.pem".format(localMspConfigPath, peerOrg.name), "w") as f:
458+
f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, peerOrg.getSelfSignedCert()))
459+
460+
# Find the peer signer Tuple for this peer and add to signcerts folder
461+
for pnt, cert in [(peerNodeTuple,cert) for peerNodeTuple,cert in directory.ordererAdminTuples.items() if peerService in peerNodeTuple.user and "signer" in peerNodeTuple.user.lower()]:
462+
# Put the PEM file in the signcerts folder
463+
with open("{0}/signcerts/{1}.pem".format(localMspConfigPath, pnt.user), "w") as f:
464+
f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
465+
# Put the associated private key into the keystore folder
466+
user = directory.getUser(pnt.user, shouldCreate=False)
467+
with open("{0}/keystore/{1}.pem".format(localMspConfigPath, pnt.user), "w") as f:
468+
f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, user.pKey))
469+
470+
471+
def decomposing(self, composition, context):
472+
'Will remove the orderer volume path folder for the context'
473+
shutil.rmtree(self.getVolumePath(composition))
474+
475+
def getEnv(self, composition, context, env):
476+
for peerService in self.getPeerList(composition):
477+
localMspConfigPath = self.getLocalMspConfigPath(composition, peerService, pathType=PathType.Container)
478+
env["{0}_CORE_PEER_MSPCFGPATH".format(peerService.upper())]=localMspConfigPath
416479

417480
def setOrdererBootstrapGenesisBlock(genesisBlock):
418481
'Responsible for setting the GensisBlock for the Orderer nodes upon composition'

bddtests/steps/compose.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,19 @@ def __init__(self, context, composeFilesYaml, projectName = GetUUID()):
6464
self.context = context
6565
self.containerDataList = []
6666
self.composeFilesYaml = composeFilesYaml
67+
self.serviceNames = []
68+
self.serviceNames = self._collectServiceNames()
6769
[callback.composing(self, context) for callback in Composition.GetCompositionCallbacksFromContext(context)]
6870
self.issueCommand(["up", "--force-recreate", "-d"])
6971

72+
def _collectServiceNames(self):
73+
'First collect the services names.'
74+
servicesList = [service for service in self.issueCommand(["config", "--services"]).splitlines() if "WARNING" not in service]
75+
return servicesList
76+
77+
def getServiceNames(self):
78+
return list(self.serviceNames)
79+
7080
def parseComposeFilesArg(self, composeFileArgs):
7181
args = [arg for sublist in [["-f", file] for file in [file if not os.path.isdir(file) else os.path.join(file, 'docker-compose.yml') for file in composeFileArgs.split()]] for arg in sublist]
7282
return args
@@ -92,7 +102,7 @@ def issueCommand(self, args):
92102
output, error, returncode = \
93103
bdd_test_util.cli_call(["docker-compose"] + cmdArgs, expect_success=True, env=self.getEnv())
94104
# Don't rebuild if ps command
95-
if args[0] !="ps":
105+
if args[0] !="ps" and args[0] !="config":
96106
self.rebuildContainerData()
97107
return output
98108

0 commit comments

Comments
 (0)