[FAB-6050] Adding fabric-ca sample

This sample uses fabric-ca to run an end-to-end test similar
to the BYFN sample. However, instead of using cryptogen, it
uses fabric-ca. All private keys are generated dynamically in
the container in which they are used.

This sample also demonstrates how to use abac
(Attribute-Based Access Control) to make access decisions.
See chaincode/abac/abac.go.

Change-Id: I5eddc9e35908e409ac07266c3183ce89a5a6cd82
Signed-off-by: Keith Smith <bksmith@us.ibm.com>
This commit is contained in:
Keith Smith 2017-09-06 18:47:36 -04:00
parent 7cca09f047
commit caf5c33db2
15 changed files with 1604 additions and 0 deletions

206
chaincode/abac/abac.go Normal file
View file

@ -0,0 +1,206 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/core/chaincode/lib/cid"
pb "github.com/hyperledger/fabric/protos/peer"
)
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
// Init initializes the chaincode
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("abac Init")
//
// Demonstrate the use of Attribute-Based Access Control (ABAC) by checking
// to see if the caller has the "abac.init" attribute with a value of true;
// if not, return an error.
//
err := cid.AssertAttributeValue(stub, "abac.init", "true")
if err != nil {
return shim.Error(err.Error())
}
_, args := stub.GetFunctionAndParameters()
var A, B string // Entities
var Aval, Bval int // Asset holdings
if len(args) != 4 {
return shim.Error("Incorrect number of arguments. Expecting 4")
}
// Initialize the chaincode
A = args[0]
Aval, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
B = args[2]
Bval, err = strconv.Atoi(args[3])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
// Write the state to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error(err.Error())
}
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("abac Invoke")
function, args := stub.GetFunctionAndParameters()
if function == "invoke" {
// Make payment of X units from A to B
return t.invoke(stub, args)
} else if function == "delete" {
// Deletes an entity from its state
return t.delete(stub, args)
} else if function == "query" {
// the old "Query" is now implemtned in invoke
return t.query(stub, args)
}
return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"")
}
// Transaction makes payment of X units from A to B
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A, B string // Entities
var Aval, Bval int // Asset holdings
var X int // Transaction value
var err error
if len(args) != 3 {
return shim.Error("Incorrect number of arguments. Expecting 3")
}
A = args[0]
B = args[1]
// Get the state from the ledger
// TODO: will be nice to have a GetAllState call to ledger
Avalbytes, err := stub.GetState(A)
if err != nil {
return shim.Error("Failed to get state")
}
if Avalbytes == nil {
return shim.Error("Entity not found")
}
Aval, _ = strconv.Atoi(string(Avalbytes))
Bvalbytes, err := stub.GetState(B)
if err != nil {
return shim.Error("Failed to get state")
}
if Bvalbytes == nil {
return shim.Error("Entity not found")
}
Bval, _ = strconv.Atoi(string(Bvalbytes))
// Perform the execution
X, err = strconv.Atoi(args[2])
if err != nil {
return shim.Error("Invalid transaction amount, expecting a integer value")
}
Aval = Aval - X
Bval = Bval + X
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
// Write the state back to the ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error(err.Error())
}
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
// Deletes an entity from state
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
A := args[0]
// Delete the key from the state in ledger
err := stub.DelState(A)
if err != nil {
return shim.Error("Failed to delete state")
}
return shim.Success(nil)
}
// query callback representing the query of a chaincode
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var A string // Entities
var err error
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
}
A = args[0]
// Get the state from the ledger
Avalbytes, err := stub.GetState(A)
if err != nil {
jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
return shim.Error(jsonResp)
}
if Avalbytes == nil {
jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
return shim.Error(jsonResp)
}
jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
fmt.Printf("Query Response:%s\n", jsonResp)
return shim.Success(Avalbytes)
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}

1
fabric-ca/.env Normal file
View file

@ -0,0 +1 @@
COMPOSE_PROJECT_NAME=net

2
fabric-ca/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
docker-compose.yml
data

88
fabric-ca/README.md Executable file
View file

@ -0,0 +1,88 @@
# Hyperledger Fabric CA sample
The Hyperledger Fabric CA sample demonstrates the following:
* How to use the Hyperledger Fabric CA client and server to generate all crypto
material rather than using cryptogen. The cryptogen tool is not intended for
a production environment because it generates all private keys in one location
which must then be copied to the appropriate host or container. This sample demonstrates
how to generate crypto material for orderers, peers, administrators, and end
users so that private keys never leave the host or container in which they are generated.
* How to use Attribute-Based Access Control (ABAC). See fabric-samples/chaincode/abac/abac.go and
note the use of the *github.com/hyperledger/fabric/core/chaincode/lib/cid* package to extract
attributes from the invoker's identity. Only identities with the *abac.init* attribute value of
*true* can successfully call the *Init* function to instantiate the chaincode.
## Running this sample
1. The following images are required to run this sample:
*hyperledger/fabric-ca-orderer*, *hyperledger/fabric-ca-peer*, and *hyperledger/fabric-ca-tools*.
These images are new in the v1.1.0 release of the *github.com/hyperledger/fabric-ca*.
In order to run this sample prior to the v1.1.0 release, you must build these
images manually as follows:
a) pull the master branch of the *github.com/hyperledger/fabric* and
*github.com/hyperledger/fabric-ca* repositories;
b) make sure these repositories are on your GOPATH;
c) run the *build-images.sh* script provided with this sample.
2. To run this sample, simply run the *start.sh* script. You may do this multiple times in a row as needed
since the *start.sh* script cleans up before starting each time.
3. To stop the containers which are started by the *start.sh* script, you may run the *stop.sh* script.
## Understanding this sample
There are some variables at the top of *fabric-samples/fabric-ca/scripts/env.sh* script which
define the names and topology of this sample. You may modify these as described in the comments
of the script in order to customize this sample. By default, there are three organizations.
The orderer organization is *org0*, and two peer organizations are *org1* and *org2*.
The *start.sh* script first builds the *docker-compose.yml* file (by invoking the
*makeDocker.sh* script) and then starts the docker containers.
The *data* directory is a volume mount for all containers.
This volume mount is not be needed in a real scenario, but it is used by this sample
for the following reasons:
a) so that all containers can write their logs to a common directory
(i.e. *the *data/logs* directory) to make debugging easier;
b) to synchronize the sequence in which containers start as described below
(for example, an intermediate CA in an *ica* container must wait for the
corresponding root CA in a *rca* container to write its certificate to
the *data* directory);
c) to access bootstrap certificates required by clients to connect over TLS.
The containers defined in the *docker-compose.yml* file are started in the
following sequence.
1. The *rca* (root CA) containers start first, one for each organization.
An *rca* container runs the fabric-ca-server for the root CA of an
organization. The root CA certificate is written to the *data* directory
and is used when an intermediate CA must connect to it over TLS.
2. The *ica* (Intermediate CA) containers start next. An *ica* container
runs the fabric-ca-server for the intermediate CA of an organization.
Each of these containers enrolls with a corresponding root CA.
The intermediate CA certificate is also written to the *data* directory.
3. The *setup* container registers identities with the intermediate CAs,
generates the genesis block, and other artifacts needed to setup the
blockchain network. This is performed by the
*fabric-samples/fabric-ca/scripts/run-fabric.sh* script. Note that the
admin identity is registered with **abac.init=true:ecert**
(see the *registerPeerIdentities* function of this script). This causes
the admin's enrollment certificate (ECert) to have an attribute named "abac.init"
with a value of "true". Note further that the chaincode used by this sample
requires this attribute be included in the certificate of the identity that
invokes its Init function. See the chaincode at *fabric-samples/chaincode/abac/abac.go*).
For more information on Attribute-Based Access Control (ABAC), see
https://github.com/hyperledger/fabric/tree/release/core/chaincode/lib/cid/README.md.
4. The orderer and peer containers are started. The naming of these containers
is straight-forward as is their log files in the *data/logs* directory.
5. The *run* container is started which runs the actual test case. It creates
a channel, peers join the channel, chaincode is installed and instantiated,
and the chaincode is queried and invoked. See the *main* function of the
*fabric-samples/fabric-ca/scripts/run-fabric.sh* script for more details.
<a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>

54
fabric-ca/build-images.sh Executable file
View file

@ -0,0 +1,54 @@
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# This script builds the images required to run this sample.
#
function assertOnMasterBranch {
if [ "`git rev-parse --abbrev-ref HEAD`" != "master" ]; then
fatal "You must switch to the master branch in `pwd`"
fi
}
set -e
SDIR=$(dirname "$0")
source $SDIR/scripts/env.sh
# Delete docker containers
dockerContainers=$(docker ps -a | awk '$2~/hyperledger/ {print $1}')
if [ "$dockerContainers" != "" ]; then
log "Deleting existing docker containers ..."
docker rm -f $dockerContainers > /dev/null
fi
# Remove chaincode docker images
chaincodeImages=`docker images | grep "^dev-peer" | awk '{print $3}'`
if [ "$chaincodeImages" != "" ]; then
log "Removing chaincode docker images ..."
docker rmi $chaincodeImages > /dev/null
fi
# Perform docker clean for fabric-ca
log "Cleaning fabric-ca docker images ..."
cd $GOPATH/src/github.com/hyperledger/fabric-ca
assertOnMasterBranch
make docker-clean
# Perform docker clean for fabric and rebuild
log "Cleaning and rebuilding fabric docker images ..."
cd $GOPATH/src/github.com/hyperledger/fabric
assertOnMasterBranch
make docker-clean docker
# Perform docker clean for fabric and rebuild against latest fabric images just built
log "Rebuilding fabric-ca docker images ..."
cd $GOPATH/src/github.com/hyperledger/fabric-ca
FABRIC_TAG=latest make docker
log "Setup completed successfully. You may run the tests multiple times by running start.sh."

261
fabric-ca/makeDocker.sh Executable file
View file

@ -0,0 +1,261 @@
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# This script builds the docker compose file needed to run this sample.
#
SDIR=$(dirname "$0")
source $SDIR/scripts/env.sh
function main {
{
writeHeader
writeRootFabricCA
if $USE_INTERMEDIATE_CA; then
writeIntermediateFabricCA
fi
writeSetupFabric
writeStartFabric
writeRunFabric
} > $SDIR/docker-compose.yml
log "Created docker-compose.yml"
}
# Write services for the root fabric CA servers
function writeRootFabricCA {
for ORG in $ORGS; do
initOrgVars $ORG
writeRootCA
done
}
# Write services for the intermediate fabric CA servers
function writeIntermediateFabricCA {
for ORG in $ORGS; do
initOrgVars $ORG
writeIntermediateCA
done
}
# Write a service to setup the fabric artifacts (e.g. genesis block, etc)
function writeSetupFabric {
echo " setup:
container_name: setup
image: hyperledger/fabric-ca-tools
command: /bin/bash -c '/scripts/setup-fabric.sh 2>&1 | tee /$SETUP_LOGFILE; sleep 99999'
volumes:
- ./scripts:/scripts
- ./$DATA:/$DATA
networks:
- $NETWORK
depends_on:"
for ORG in $ORGS; do
initOrgVars $ORG
echo " - $CA_NAME"
done
echo ""
}
# Write services for fabric orderer and peer containers
function writeStartFabric {
for ORG in $ORDERER_ORGS; do
COUNT=1
while [[ "$COUNT" -le $NUM_ORDERERS ]]; do
initOrdererVars $ORG $COUNT
writeOrderer
COUNT=$((COUNT+1))
done
done
for ORG in $PEER_ORGS; do
COUNT=1
while [[ "$COUNT" -le $NUM_PEERS ]]; do
initPeerVars $ORG $COUNT
writePeer
COUNT=$((COUNT+1))
done
done
}
# Write a service to run a fabric test including creating a channel,
# installing chaincode, invoking and querying
function writeRunFabric {
# Set samples directory relative to this script
SAMPLES_DIR=$(dirname $(cd ${SDIR} && pwd))
# Set fabric directory relative to GOPATH
FABRIC_DIR=${GOPATH}/src/github.com/hyperledger/fabric
echo " run:
container_name: run
image: hyperledger/fabric-ca-tools
environment:
- GOPATH=/opt/gopath
command: /bin/bash -c 'sleep 3;/scripts/run-fabric.sh 2>&1 | tee /$RUN_LOGFILE; sleep 99999'
volumes:
- ./scripts:/scripts
- ./$DATA:/$DATA
- ${SAMPLES_DIR}:/opt/gopath/src/github.com/hyperledger/fabric-samples
- ${FABRIC_DIR}:/opt/gopath/src/github.com/hyperledger/fabric
networks:
- $NETWORK
depends_on:"
for ORG in $ORDERER_ORGS; do
COUNT=1
while [[ "$COUNT" -le $NUM_ORDERERS ]]; do
initOrdererVars $ORG $COUNT
echo " - $ORDERER_NAME"
COUNT=$((COUNT+1))
done
done
for ORG in $PEER_ORGS; do
COUNT=1
while [[ "$COUNT" -le $NUM_PEERS ]]; do
initPeerVars $ORG $COUNT
echo " - $PEER_NAME"
COUNT=$((COUNT+1))
done
done
}
function writeRootCA {
echo " $ROOT_CA_NAME:
container_name: $ROOT_CA_NAME
image: hyperledger/fabric-ca
command: /bin/bash -c '/scripts/start-root-ca.sh 2>&1 | tee /$ROOT_CA_LOGFILE'
environment:
- FABRIC_CA_SERVER_HOME=/etc/hyperledger/fabric-ca
- FABRIC_CA_SERVER_TLS_ENABLED=true
- FABRIC_CA_SERVER_CSR_CN=$ROOT_CA_NAME
- FABRIC_CA_SERVER_CSR_HOSTS=$ROOT_CA_HOST
- FABRIC_CA_SERVER_DEBUG=true
- BOOTSTRAP_USER_PASS=$ROOT_CA_ADMIN_USER_PASS
- TARGET_CERTFILE=$ROOT_CA_CERTFILE
volumes:
- ./scripts:/scripts
- ./$DATA:/$DATA
networks:
- $NETWORK
"
}
function writeIntermediateCA {
echo " $INT_CA_NAME:
container_name: $INT_CA_NAME
image: hyperledger/fabric-ca
command: /bin/bash -c '/scripts/start-intermediate-ca.sh $ORG 2>&1 | tee /$INT_CA_LOGFILE'
environment:
- FABRIC_CA_SERVER_HOME=/etc/hyperledger/fabric-ca
- FABRIC_CA_SERVER_CA_NAME=$INT_CA_NAME
- FABRIC_CA_SERVER_INTERMEDIATE_TLS_CERTFILES=$ROOT_CA_CERTFILE
- FABRIC_CA_SERVER_CSR_HOSTS=$INT_CA_HOST
- FABRIC_CA_SERVER_TLS_ENABLED=true
- FABRIC_CA_SERVER_DEBUG=true
- BOOTSTRAP_USER_PASS=$INT_CA_ADMIN_USER_PASS
- PARENT_URL=https://$ROOT_CA_ADMIN_USER_PASS@$ROOT_CA_HOST:7054
- TARGET_CHAINFILE=$INT_CA_CHAINFILE
- ORG=$ORG
volumes:
- ./scripts:/scripts
- ./$DATA:/$DATA
networks:
- $NETWORK
depends_on:
- $ROOT_CA_NAME
"
}
function writeOrderer {
MYHOME=/etc/hyperledger/orderer
echo " $ORDERER_NAME:
container_name: $ORDERER_NAME
image: hyperledger/fabric-ca-orderer
environment:
- FABRIC_CA_CLIENT_HOME=$MYHOME
- FABRIC_CA_CLIENT_TLS_CERTFILES=$CA_CHAINFILE
- ENROLLMENT_URL=https://$ORDERER_NAME_PASS@$CA_HOST:7054
- ORDERER_HOME=$MYHOME
- ORDERER_HOST=$ORDERER_HOST
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
- ORDERER_GENERAL_GENESISMETHOD=file
- ORDERER_GENERAL_GENESISFILE=$GENESIS_BLOCK_FILE
- ORDERER_GENERAL_LOCALMSPID=$ORG_MSP_ID
- ORDERER_GENERAL_LOCALMSPDIR=$MYHOME/msp
- ORDERER_GENERAL_TLS_ENABLED=true
- ORDERER_GENERAL_TLS_PRIVATEKEY=$MYHOME/tls/server.key
- ORDERER_GENERAL_TLS_CERTIFICATE=$MYHOME/tls/server.crt
- ORDERER_GENERAL_TLS_ROOTCAS=[$CA_CHAINFILE]
- ORDERER_GENERAL_LOGLEVEL=debug
- ORDERER_DEBUG_BROADCASTTRACEDIR=$LOGDIR
- ORG=$ORG
- ORG_ADMIN_CERT=$ORG_ADMIN_CERT
command: /bin/bash -c '/scripts/start-orderer.sh 2>&1 | tee /$ORDERER_LOGFILE'
volumes:
- ./scripts:/scripts
- ./$DATA:/$DATA
networks:
- $NETWORK
depends_on:
- setup
"
}
function writePeer {
MYHOME=/opt/gopath/src/github.com/hyperledger/fabric/peer
echo " $PEER_NAME:
container_name: $PEER_NAME
image: hyperledger/fabric-ca-peer
environment:
- FABRIC_CA_CLIENT_HOME=$MYHOME
- FABRIC_CA_CLIENT_TLS_CERTFILES=$CA_CHAINFILE
- ENROLLMENT_URL=https://$PEER_NAME_PASS@$CA_HOST:7054
- PEER_HOME=$MYHOME
- PEER_HOST=$PEER_HOST
- PEER_NAME_PASS=$PEER_NAME_PASS
- CORE_PEER_ID=$PEER_HOST
- CORE_PEER_ADDRESS=$PEER_HOST:7051
- CORE_PEER_LOCALMSPID=$ORG_MSP_ID
- CORE_PEER_MSPCONFIGPATH=$MYHOME/msp
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=net_${NETWORK}
- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_PROFILE_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=$MYHOME/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=$MYHOME/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=$CA_CHAINFILE
- CORE_PEER_GOSSIP_USELEADERELECTION=true
- CORE_PEER_GOSSIP_ORGLEADER=false
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=$PEER_HOST:7051
- CORE_PEER_GOSSIP_SKIPHANDSHAKE=true
- ORG=$ORG
- ORG_ADMIN_CERT=$ORG_ADMIN_CERT"
if [ $NUM -gt 1 ]; then
echo " - CORE_PEER_GOSSIP_BOOTSTRAP=peer1-${ORG}:7051"
fi
echo " working_dir: $MYHOME
command: /bin/bash -c '/scripts/start-peer.sh 2>&1 | tee /$PEER_LOGFILE'
volumes:
- ./scripts:/scripts
- ./$DATA:/$DATA
- /var/run:/host/var/run
networks:
- $NETWORK
depends_on:
- setup
"
}
function writeHeader {
echo "version: '2'
networks:
$NETWORK:
services:
"
}
main

322
fabric-ca/scripts/env.sh Executable file
View file

@ -0,0 +1,322 @@
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# The following variables describe the topology and may be modified to provide
# different organization names or the number of peers in each peer organization.
#
# Name of the docker-compose network
NETWORK=fabric-ca
# Names of the orderer organizations
ORDERER_ORGS="org0"
# Names of the peer organizations
PEER_ORGS="org1 org2"
# Number of peers in each peer organization
NUM_PEERS=2
#
# The remainder of this file contains variables which typically would not be changed.
#
# All org names
ORGS="$ORDERER_ORGS $PEER_ORGS"
# Set to true to populate the "admincerts" folder of MSPs
ADMINCERTS=true
# Number of orderer nodes
NUM_ORDERERS=1
# The volume mount to share data between containers
DATA=data
# The path to the genesis block
GENESIS_BLOCK_FILE=/$DATA/genesis.block
# The path to a channel transaction
CHANNEL_TX_FILE=/$DATA/channel.tx
# Name of test channel
CHANNEL_NAME=mychannel
# Query timeout in seconds
QUERY_TIMEOUT=15
# Log directory
LOGDIR=$DATA/logs
LOGPATH=/$LOGDIR
# Name of a the file to create when setup is successful
SETUP_SUCCESS_FILE=${LOGDIR}/setup.successful
# The setup container's log file
SETUP_LOGFILE=${LOGDIR}/setup.log
# The run container's log file
RUN_LOGFILE=${LOGDIR}/run.log
# The run container's summary log file
RUN_SUMFILE=${LOGDIR}/run.sum
RUN_SUMPATH=/${RUN_SUMFILE}
# Run success and failure files
RUN_SUCCESS_FILE=${LOGDIR}/run.success
RUN_FAIL_FILE=${LOGDIR}/run.fail
# Affiliation is not used to limit users in this sample, so just put
# all identities in the same affiliation.
export FABRIC_CA_CLIENT_ID_AFFILIATION=org1
# Set to true to enable use of intermediate CAs
USE_INTERMEDIATE_CA=true
# initOrgVars <ORG>
function initOrgVars {
if [ $# -ne 1 ]; then
echo "Usage: initOrgVars <ORG>"
exit 1
fi
ORG=$1
ORG_CONTAINER_NAME=${ORG//./-}
ROOT_CA_HOST=rca-${ORG}
ROOT_CA_NAME=rca-${ORG}
ROOT_CA_LOGFILE=$LOGDIR/${ROOT_CA_NAME}.log
INT_CA_HOST=ica-${ORG}
INT_CA_NAME=ica-${ORG}
INT_CA_LOGFILE=$LOGDIR/${INT_CA_NAME}.log
# Root CA admin identity
ROOT_CA_ADMIN_USER=rca-${ORG}-admin
ROOT_CA_ADMIN_PASS=${ROOT_CA_ADMIN_USER}pw
ROOT_CA_ADMIN_USER_PASS=${ROOT_CA_ADMIN_USER}:${ROOT_CA_ADMIN_PASS}
# Root CA intermediate identity to bootstrap the intermediate CA
ROOT_CA_INT_USER=ica-${ORG}
ROOT_CA_INT_PASS=${ROOT_CA_INT_USER}pw
ROOT_CA_INT_USER_PASS=${ROOT_CA_INT_USER}:${ROOT_CA_INT_PASS}
# Intermediate CA admin identity
INT_CA_ADMIN_USER=ica-${ORG}-admin
INT_CA_ADMIN_PASS=${INT_CA_ADMIN_USER}pw
INT_CA_ADMIN_USER_PASS=${INT_CA_ADMIN_USER}:${INT_CA_ADMIN_PASS}
# Admin identity for the org
ADMIN_NAME=admin-${ORG}
ADMIN_PASS=${ADMIN_NAME}pw
# Typical user identity for the org
USER_NAME=user-${ORG}
USER_PASS=${USER_NAME}pw
ROOT_CA_CERTFILE=/${DATA}/${ORG}-ca-cert.pem
INT_CA_CHAINFILE=/${DATA}/${ORG}-ca-chain.pem
ANCHOR_TX_FILE=/${DATA}/orgs/${ORG}/anchors.tx
ORG_MSP_ID=${ORG}MSP
ORG_MSP_DIR=/${DATA}/orgs/${ORG}/msp
ORG_ADMIN_CERT=${ORG_MSP_DIR}/admincerts/cert.pem
ORG_ADMIN_HOME=/${DATA}/orgs/$ORG/admin
if $USE_INTERMEDIATE_CA; then
CA_NAME=$INT_CA_NAME
CA_HOST=$INT_CA_HOST
CA_CHAINFILE=$INT_CA_CHAINFILE
CA_ADMIN_USER_PASS=$INT_CA_ADMIN_USER_PASS
CA_LOGFILE=$INT_CA_LOGFILE
else
CA_NAME=$ROOT_CA_NAME
CA_HOST=$ROOT_CA_HOST
CA_CHAINFILE=$ROOT_CA_CERTFILE
CA_ADMIN_USER_PASS=$ROOT_CA_ADMIN_USER_PASS
CA_LOGFILE=$ROOT_CA_LOGFILE
fi
}
# initOrdererVars <NUM>
function initOrdererVars {
if [ $# -ne 2 ]; then
echo "Usage: initOrdererVars <ORG> <NUM>"
exit 1
fi
initOrgVars $1
NUM=$2
ORDERER_HOST=orderer${NUM}-${ORG}
ORDERER_NAME=orderer${NUM}-${ORG}
ORDERER_PASS=${ORDERER_NAME}pw
ORDERER_NAME_PASS=${ORDERER_NAME}:${ORDERER_PASS}
ORDERER_LOGFILE=$LOGDIR/${ORDERER_NAME}.log
MYHOME=/etc/hyperledger/orderer
export FABRIC_CA_CLIENT=$MYHOME
export ORDERER_GENERAL_LOGLEVEL=debug
export ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
export ORDERER_GENERAL_GENESISMETHOD=file
export ORDERER_GENERAL_GENESISFILE=$GENESIS_BLOCK_FILE
export ORDERER_GENERAL_LOCALMSPID=$ORG_MSP_ID
export ORDERER_GENERAL_LOCALMSPDIR=$MYHOME/msp
# enabled TLS
export ORDERER_GENERAL_TLS_ENABLED=true
TLSDIR=$MYHOME/tls
export ORDERER_GENERAL_TLS_PRIVATEKEY=$TLSDIR/server.key
export ORDERER_GENERAL_TLS_CERTIFICATE=$TLSDIR/server.crt
export ORDERER_GENERAL_TLS_ROOTCAS=[$INT_CA_CHAINFILE]
}
# initPeerVars <ORG> <NUM>
function initPeerVars {
if [ $# -ne 2 ]; then
echo "Usage: initPeerVars <ORG> <NUM>: $*"
exit 1
fi
initOrgVars $1
NUM=$2
PEER_HOST=peer${NUM}-${ORG}
PEER_NAME=peer${NUM}-${ORG}
PEER_PASS=${PEER_NAME}pw
PEER_NAME_PASS=${PEER_NAME}:${PEER_PASS}
PEER_LOGFILE=$LOGDIR/${PEER_NAME}.log
MYHOME=/opt/gopath/src/github.com/hyperledger/fabric/peer
TLSDIR=$MYHOME/tls
export FABRIC_CA_CLIENT=$MYHOME
export CORE_PEER_ID=$PEER_HOST
export CORE_PEER_ADDRESS=$PEER_HOST:7051
export CORE_PEER_LOCALMSPID=$ORG_MSP_ID
export CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
# the following setting starts chaincode containers on the same
# bridge network as the peers
# https://docs.docker.com/compose/networking/
#export CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_${NETWORK}
export CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=net_${NETWORK}
# export CORE_LOGGING_LEVEL=ERROR
export CORE_LOGGING_LEVEL=DEBUG
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_PROFILE_ENABLED=true
export CORE_PEER_TLS_CERT_FILE=$TLSDIR/server.crt
export CORE_PEER_TLS_KEY_FILE=$TLSDIR/server.key
export CORE_PEER_TLS_ROOTCERT_FILE=$INT_CA_CHAINFILE
# gossip variables
export CORE_PEER_GOSSIP_USELEADERELECTION=true
export CORE_PEER_GOSSIP_ORGLEADER=false
export CORE_PEER_GOSSIP_EXTERNALENDPOINT=$PEER_HOST:7051
if [ $NUM -gt 1 ]; then
# Point the non-anchor peers to the anchor peer, which is always the 1st peer
export CORE_PEER_GOSSIP_BOOTSTRAP=peer1-${ORG}:7051
fi
}
# Switch to the current org's admin identity. Enroll if not previously enrolled.
function switchToAdminIdentity {
if [ ! -d $ORG_ADMIN_HOME ]; then
dowait "$CA_NAME to start" 10 $CA_LOGFILE $CA_CHAINFILE
log "Enrolling admin '$ADMIN_NAME' with $CA_HOST ..."
export FABRIC_CA_CLIENT_HOME=$ORG_ADMIN_HOME
export FABRIC_CA_CLIENT_TLS_CERTFILES=$CA_CHAINFILE
fabric-ca-client enroll -d -u https://$ADMIN_NAME:$ADMIN_PASS@$CA_HOST:7054
# If admincerts are required in the MSP, copy the cert there now and to my local MSP also
if [ $ADMINCERTS ]; then
mkdir -p $(dirname "${ORG_ADMIN_CERT}")
cp $ORG_ADMIN_HOME/msp/signcerts/* $ORG_ADMIN_CERT
mkdir $ORG_ADMIN_HOME/msp/admincerts
cp $ORG_ADMIN_HOME/msp/signcerts/* $ORG_ADMIN_HOME/msp/admincerts
fi
fi
export CORE_PEER_MSPCONFIGPATH=$ORG_ADMIN_HOME/msp
}
# Switch to the current org's user identity. Enroll if not previously enrolled.
function switchToUserIdentity {
export FABRIC_CA_CLIENT_HOME=/etc/hyperledger/fabric/orgs/$ORG/user
export CORE_PEER_MSPCONFIGPATH=$FABRIC_CA_CLIENT_HOME/msp
if [ ! -d $FABRIC_CA_CLIENT_HOME ]; then
dowait "$CA_NAME to start" 10 $CA_LOGFILE $CA_CHAINFILE
log "Enrolling user for organization $ORG with home directory $FABRIC_CA_CLIENT_HOME ..."
export FABRIC_CA_CLIENT_TLS_CERTFILES=$CA_CHAINFILE
fabric-ca-client enroll -d -u https://$USER_NAME:$USER_PASS@$CA_HOST:7054
# Set up admincerts directory if required
if [ $ADMINCERTS ]; then
ACDIR=$CORE_PEER_MSPCONFIGPATH/admincerts
mkdir -p $ACDIR
cp $ORG_ADMIN_HOME/msp/signcerts/* $ACDIR
fi
fi
}
# Copy the org's admin cert into some target MSP directory
# This is only required if ADMINCERTS is enabled.
function copyAdminCert {
if [ $# -ne 1 ]; then
fatal "Usage: copyAdminCert <targetMSPDIR>"
fi
if $ADMINCERTS; then
dstDir=$1/admincerts
mkdir -p $dstDir
dowait "$ORG administator to enroll" 10 $SETUP_LOGFILE $ORG_ADMIN_CERT
cp $ORG_ADMIN_CERT $dstDir
fi
}
# Create the TLS directories of the MSP folder if they don't exist.
# The fabric-ca-client should do this.
function finishMSPSetup {
if [ $# -ne 1 ]; then
fatal "Usage: finishMSPSetup <targetMSPDIR>"
fi
if [ ! -d $1/tlscacerts ]; then
mkdir $1/tlscacerts
cp $1/cacerts/* $1/tlscacerts
if [ -d $1/intermediatecerts ]; then
mkdir $1/tlsintermediatecerts
cp $1/intermediatecerts/* $1/tlsintermediatecerts
fi
fi
}
function awaitSetup {
dowait "the 'setup' container to finish registering identities, creating the genesis block and other artifacts" $1 $SETUP_LOGFILE /$SETUP_SUCCESS_FILE
}
# Wait for one or more files to exist
# Usage: dowait <what> <timeoutInSecs> <errorLogFile> <file> [<file> ...]
function dowait {
if [ $# -lt 4 ]; then
fatal "Usage: dowait: $*"
fi
local what=$1
local secs=$2
local logFile=$3
shift 3
local logit=true
local starttime=$(date +%s)
for file in $*; do
until [ -f $file ]; do
if [ "$logit" = true ]; then
log -n "Waiting for $what ..."
logit=false
fi
sleep 1
if [ "$(($(date +%s)-starttime))" -gt "$secs" ]; then
echo ""
fatal "Failed waiting for $what ($file not found); see $logFile"
fi
echo -n "."
done
done
echo ""
}
# log a message
function log {
if [ "$1" = "-n" ]; then
shift
echo -n "##### `date '+%Y-%m-%d %H:%M:%S'` $*"
else
echo "##### `date '+%Y-%m-%d %H:%M:%S'` $*"
fi
}
# fatal a message
function fatal {
log "FATAL: $*"
exit 1
}

191
fabric-ca/scripts/run-fabric.sh Executable file
View file

@ -0,0 +1,191 @@
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
set -e
source $(dirname "$0")/env.sh
function main {
done=false
# Wait for setup to complete and then wait another 5 seconds for the orderer and peers to start
awaitSetup 10
sleep 5
trap finish EXIT
mkdir -p $LOGPATH
logr "The docker 'run' container has started"
# Set ORDERER_PORT_ARGS to the args needed to communicate with the 1st orderer
IFS=', ' read -r -a OORGS <<< "$ORDERER_ORGS"
initOrdererVars ${OORGS[0]} 1
ORDERER_PORT_ARGS="-o $ORDERER_HOST:7050 --tls true --cafile $CA_CHAINFILE"
# Convert PEER_ORGS to an array named PORGS
IFS=', ' read -r -a PORGS <<< "$PEER_ORGS"
# Create the channel
createChannel
# All peers join the channel
for ORG in $PEER_ORGS; do
local COUNT=1
while [[ "$COUNT" -le $NUM_PEERS ]]; do
initPeerVars $ORG $COUNT
joinChannel
COUNT=$((COUNT+1))
done
done
# Update the anchor peers
for ORG in $PEER_ORGS; do
initPeerVars $ORG 1
switchToAdminIdentity
logr "Updating anchor peers for $PEER_HOST ..."
peer channel update -c $CHANNEL_NAME -f $ANCHOR_TX_FILE $ORDERER_PORT_ARGS
done
# Install chaincode on the 1st peer in each org
for ORG in $PEER_ORGS; do
initPeerVars $ORG 1
installChaincode
done
# Instantiate chaincode on the 1st peer of the 2nd org
makePolicy
initPeerVars ${PORGS[1]} 1
switchToAdminIdentity
logr "Instantiating chaincode on $PEER_HOST ..."
peer chaincode instantiate -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "$POLICY" $ORDERER_PORT_ARGS
# Query chaincode from the 1st peer of the 1st org
initPeerVars ${PORGS[0]} 1
switchToUserIdentity
chaincodeQuery 100
# Invoke chaincode on the 1st peer of the 1st org
initPeerVars ${PORGS[0]} 1
switchToUserIdentity
logr "Sending invoke transaction to $PEER_HOST ..."
peer chaincode invoke -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}' $ORDERER_PORT_ARGS
## Install chaincode on 2nd peer of 2nd org
initPeerVars ${PORGS[1]} 2
installChaincode
# Query chaincode on 2nd peer of 2nd org
sleep 10
initPeerVars ${PORGS[1]} 2
switchToUserIdentity
chaincodeQuery 90
logr "Congratulations! The tests ran successfully."
done=true
}
# Enroll as a peer admin and create the channel
function createChannel {
initPeerVars ${PORGS[0]} 1
switchToAdminIdentity
logr "Creating channel '$CHANNEL_NAME' on $ORDERER_HOST ..."
peer channel create --logging-level=DEBUG -c $CHANNEL_NAME -f $CHANNEL_TX_FILE $ORDERER_PORT_ARGS
}
# Enroll as a fabric admin and join the channel
function joinChannel {
switchToAdminIdentity
set +e
local COUNT=1
MAX_RETRY=10
while true; do
logr "Peer $PEER_HOST is attempting to join channel '$CHANNEL_NAME' (attempt #${COUNT}) ..."
peer channel join -b $CHANNEL_NAME.block
if [ $? -eq 0 ]; then
set -e
logr "Peer $PEER_HOST successfully joined channel '$CHANNEL_NAME'"
return
fi
if [ $COUNT -gt $MAX_RETRY ]; then
fatalr "Peer $PEER_HOST failed to join channel '$CHANNEL_NAME' in $MAX_RETRY retries"
fi
COUNT=$((COUNT+1))
sleep 1
done
}
chaincodeQuery () {
if [ $# -ne 1 ]; then
fatalr "Usage: chaincodeQuery <expected-value>"
fi
set +e
logr "Querying chaincode in channel '$CHANNEL_NAME' on peer '$PEER_HOST' ..."
local rc=1
local starttime=$(date +%s)
# Continue to poll until we get a successful response or reach QUERY_TIMEOUT
while test "$(($(date +%s)-starttime))" -lt "$QUERY_TIMEOUT"; do
sleep 1
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' >& log.txt
VALUE=$(cat log.txt | awk '/Query Result/ {print $NF}')
if [ $? -eq 0 -a "$VALUE" = "$1" ]; then
logr "Query of channel '$CHANNEL_NAME' on peer '$PEER_HOST' was successful"
set -e
return 0
fi
echo -n "."
done
cat log.txt
cat log.txt >> $RUN_SUMFILE
fatalr "Failed to query channel '$CHANNEL_NAME' on peer '$PEER_HOST'; expected value was $1 and found $VALUE"
}
function makePolicy {
POLICY="OR("
local COUNT=0
for ORG in $PEER_ORGS; do
if [ $COUNT -ne 0 ]; then
POLICY="${POLICY},"
fi
initOrgVars $ORG
POLICY="${POLICY}'${ORG_MSP_ID}.member'"
COUNT=$((COUNT+1))
done
POLICY="${POLICY})"
log "policy: $POLICY"
}
function installChaincode {
switchToAdminIdentity
logr "Installing chaincode on $PEER_HOST ..."
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric-samples/chaincode/abac
}
function finish {
if [ "$done" = true ]; then
logr "See $RUN_LOGFILE for more details"
touch /$RUN_SUCCESS_FILE
else
logr "Tests did not complete successfully; see $RUN_LOGFILE for more details"
touch /$RUN_FAIL_FILE
fi
}
function logr {
log $*
log $* >> $RUN_SUMPATH
}
function fatalr {
logr "FATAL: $*"
exit 1
}
main

288
fabric-ca/scripts/setup-fabric.sh Executable file
View file

@ -0,0 +1,288 @@
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# This script does the following:
# 1) registers orderer and peer identities with intermediate fabric-ca-servers
# 2) Builds the channel artifacts (e.g. genesis block, etc)
#
function main {
sleep 1
log "Beginning building channel artifacts ..."
registerIdentities
getCACerts
makeConfigTxYaml
generateChannelArtifacts
log "Finished building channel artifacts"
touch /$SETUP_SUCCESS_FILE
}
# Enroll as the CA admin
function enrollCAAdmin {
dowait "$CA_NAME to start" 10 $CA_LOGFILE $CA_CHAINFILE
log "Enrolling with $CA_NAME as bootstrap identity ..."
export FABRIC_CA_CLIENT_HOME=$HOME/cas/$CA_NAME
export FABRIC_CA_CLIENT_TLS_CERTFILES=$CA_CHAINFILE
fabric-ca-client enroll -d -u https://$CA_ADMIN_USER_PASS@$CA_HOST:7054
}
function registerIdentities {
log "Registering identities ..."
registerOrdererIdentities
registerPeerIdentities
}
# Register any identities associated with the orderer
function registerOrdererIdentities {
for ORG in $ORDERER_ORGS; do
initOrgVars $ORG
enrollCAAdmin
local COUNT=1
while [[ "$COUNT" -le $NUM_ORDERERS ]]; do
initOrdererVars $ORG $COUNT
log "Registering $ORDERER_NAME with $CA_NAME"
fabric-ca-client register -d --id.name $ORDERER_NAME --id.secret $ORDERER_PASS
COUNT=$((COUNT+1))
done
log "Registering admin identity with $CA_NAME"
# The admin identity has the "hf.admin" attribute which is added to ECert by default
fabric-ca-client register -d --id.name $ADMIN_NAME --id.secret $ADMIN_PASS --id.attrs "hf.admin=true:ecert"
done
}
# Register any identities associated with a peer
function registerPeerIdentities {
for ORG in $PEER_ORGS; do
initOrgVars $ORG
enrollCAAdmin
local COUNT=1
while [[ "$COUNT" -le $NUM_PEERS ]]; do
initPeerVars $ORG $COUNT
log "Registering $PEER_NAME with $CA_NAME"
fabric-ca-client register -d --id.name $PEER_NAME --id.secret $PEER_PASS
COUNT=$((COUNT+1))
done
log "Registering admin identity with $CA_NAME"
# The admin identity has the "hf.admin" attribute which is added to ECert by default
fabric-ca-client register -d --id.name $ADMIN_NAME --id.secret $ADMIN_PASS --id.attrs "hf.admin=true:ecert,abac.init=true:ecert"
log "Registering user identity with $CA_NAME"
fabric-ca-client register -d --id.name $USER_NAME --id.secret $USER_PASS
done
}
function getCACerts {
log "Getting CA certificates ..."
for ORG in $ORGS; do
initOrgVars $ORG
log "Getting CA certs for organization $ORG and storing in $ORG_MSP_DIR"
export FABRIC_CA_CLIENT_TLS_CERTFILES=$CA_CHAINFILE
fabric-ca-client getcacert -d -u https://$CA_HOST:7054 -M $ORG_MSP_DIR
finishMSPSetup $ORG_MSP_DIR
# If ADMINCERTS is true, we need to enroll the admin now to populate the admincerts directory
if [ $ADMINCERTS ]; then
switchToAdminIdentity
fi
done
}
# printOrg
function printOrg {
echo "
- &$ORG_CONTAINER_NAME
Name: $ORG
# ID to load the MSP definition as
ID: $ORG_MSP_ID
# MSPDir is the filesystem path which contains the MSP configuration
MSPDir: $ORG_MSP_DIR"
}
# printOrdererOrg <ORG>
function printOrdererOrg {
initOrgVars $1
printOrg
}
# printPeerOrg <ORG> <COUNT>
function printPeerOrg {
initPeerVars $1 $2
printOrg
echo "
AnchorPeers:
# AnchorPeers defines the location of peers which can be used
# for cross org gossip communication. Note, this value is only
# encoded in the genesis block in the Application section context
- Host: $PEER_HOST
Port: 7051"
}
function makeConfigTxYaml {
{
echo "################################################################################
#
# Profile
#
# - Different configuration profiles may be encoded here to be specified
# as parameters to the configtxgen tool
#
################################################################################
Profiles:
OrgsOrdererGenesis:
Orderer:
# Orderer Type: The orderer implementation to start
# Available types are \"solo\" and \"kafka\"
OrdererType: solo
Addresses:"
for ORG in $ORDERER_ORGS; do
local COUNT=1
while [[ "$COUNT" -le $NUM_ORDERERS ]]; do
initOrdererVars $ORG $COUNT
echo " - $ORDERER_HOST:7050"
COUNT=$((COUNT+1))
done
done
echo "
# Batch Timeout: The amount of time to wait before creating a batch
BatchTimeout: 2s
# Batch Size: Controls the number of messages batched into a block
BatchSize:
# Max Message Count: The maximum number of messages to permit in a batch
MaxMessageCount: 10
# Absolute Max Bytes: The absolute maximum number of bytes allowed for
# the serialized messages in a batch.
AbsoluteMaxBytes: 99 MB
# Preferred Max Bytes: The preferred maximum number of bytes allowed for
# the serialized messages in a batch. A message larger than the preferred
# max bytes will result in a batch larger than preferred max bytes.
PreferredMaxBytes: 512 KB
Kafka:
# Brokers: A list of Kafka brokers to which the orderer connects
# NOTE: Use IP:port notation
Brokers:
- 127.0.0.1:9092
# Organizations is the list of orgs which are defined as participants on
# the orderer side of the network
Organizations:"
for ORG in $ORDERER_ORGS; do
initOrgVars $ORG
echo " - *${ORG_CONTAINER_NAME}"
done
echo "
Consortiums:
SampleConsortium:
Organizations:"
for ORG in $PEER_ORGS; do
initOrgVars $ORG
echo " - *${ORG_CONTAINER_NAME}"
done
echo "
OrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:"
for ORG in $PEER_ORGS; do
initOrgVars $ORG
echo " - *${ORG_CONTAINER_NAME}"
done
echo "
################################################################################
#
# Section: Organizations
#
# - This section defines the different organizational identities which will
# be referenced later in the configuration.
#
################################################################################
Organizations:"
for ORG in $ORDERER_ORGS; do
printOrdererOrg $ORG
done
for ORG in $PEER_ORGS; do
printPeerOrg $ORG 1
done
echo "
################################################################################
#
# SECTION: Application
#
# This section defines the values to encode into a config transaction or
# genesis block for application related parameters
#
################################################################################
Application: &ApplicationDefaults
# Organizations is the list of orgs which are defined as participants on
# the application side of the network
Organizations:
"
} > /etc/hyperledger/fabric/configtx.yaml
# Copy it to the data directory to make debugging easier
cp /etc/hyperledger/fabric/configtx.yaml /$DATA
}
function generateChannelArtifacts() {
which configtxgen
if [ "$?" -ne 0 ]; then
fatal "configtxgen tool not found. exiting"
fi
log "Generating orderer genesis block at $GENESIS_BLOCK_FILE"
# Note: For some unknown reason (at least for now) the block file can't be
# named orderer.genesis.block or the orderer will fail to launch!
configtxgen -profile OrgsOrdererGenesis -outputBlock $GENESIS_BLOCK_FILE
if [ "$?" -ne 0 ]; then
fatal "Failed to generate orderer genesis block"
fi
log "Generating channel configuration transaction at $CHANNEL_TX_FILE"
configtxgen -profile OrgsChannel -outputCreateChannelTx $CHANNEL_TX_FILE -channelID $CHANNEL_NAME
if [ "$?" -ne 0 ]; then
fatal "Failed to generate channel configuration transaction"
fi
for ORG in $PEER_ORGS; do
initOrgVars $ORG
log "Generating anchor peer update transaction for $ORG at $ANCHOR_TX_FILE"
configtxgen -profile OrgsChannel -outputAnchorPeersUpdate $ANCHOR_TX_FILE \
-channelID $CHANNEL_NAME -asOrg $ORG
if [ "$?" -ne 0 ]; then
fatal "Failed to generate anchor peer update for $ORG"
fi
done
}
set -e
SDIR=$(dirname "$0")
source $SDIR/env.sh
main

View file

@ -0,0 +1,24 @@
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
source $(dirname "$0")/env.sh
initOrgVars $ORG
set -e
dowait "Root CA certificate file to be created" 10 $ROOT_CA_CERTFILE $ROOT_CA_LOGFILE
sleep 2
# Initialize the intermediate CA
fabric-ca-server init -b $BOOTSTRAP_USER_PASS -u $PARENT_URL
# Copy the intermediate CA's certificate chain to the data directory to be used by others
cp $FABRIC_CA_SERVER_HOME/ca-chain.pem $TARGET_CHAINFILE
# Start the intermediate CA
fabric-ca-server start

View file

@ -0,0 +1,37 @@
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
set -e
source $(dirname "$0")/env.sh
# Wait for setup to complete sucessfully
awaitSetup 10
# Enroll to get orderer's TLS cert (using the "tls" profile)
fabric-ca-client enroll -d --enrollment.profile tls -u $ENROLLMENT_URL -M /tmp/tls --csr.hosts $ORDERER_HOST
# Copy the TLS key and cert to the appropriate place
TLSDIR=$ORDERER_HOME/tls
mkdir -p $TLSDIR
cp /tmp/tls/keystore/* $ORDERER_GENERAL_TLS_PRIVATEKEY
cp /tmp/tls/signcerts/* $ORDERER_GENERAL_TLS_CERTIFICATE
rm -rf /tmp/tls
# Enroll again to get the orderer's enrollment certificate (default profile)
fabric-ca-client enroll -d -u $ENROLLMENT_URL -M $ORDERER_GENERAL_LOCALMSPDIR
# Finish setting up the local MSP for the orderer
finishMSPSetup $ORDERER_GENERAL_LOCALMSPDIR
copyAdminCert $ORDERER_GENERAL_LOCALMSPDIR
# Wait for the genesis block to be created
dowait "genesis block to be created" 10 $SETUP_LOGFILE $ORDERER_GENERAL_GENESISFILE
# Start the orderer
env | grep ORDERER
orderer

32
fabric-ca/scripts/start-peer.sh Executable file
View file

@ -0,0 +1,32 @@
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
set -e
source $(dirname "$0")/env.sh
awaitSetup 10
# Enroll the peer to get a TLS cert
fabric-ca-client enroll -d --enrollment.profile tls -u $ENROLLMENT_URL -M /tmp/tls --csr.hosts $PEER_HOST
# Copy the TLS key and cert to the appropriate place
TLSDIR=$PEER_HOME/tls
mkdir -p $TLSDIR
cp /tmp/tls/signcerts/* $CORE_PEER_TLS_CERT_FILE
cp /tmp/tls/keystore/* $CORE_PEER_TLS_KEY_FILE
rm -rf /tmp/tls
# Enroll the peer to get an enrollment certificate and set up the core's local MSP directory
fabric-ca-client enroll -d -u $ENROLLMENT_URL -M $CORE_PEER_MSPCONFIGPATH
finishMSPSetup $CORE_PEER_MSPCONFIGPATH
copyAdminCert $CORE_PEER_MSPCONFIGPATH
# Start the peer
log "Starting peer '$CORE_PEER_ID' with MSP at '$CORE_PEER_MSPCONFIGPATH'"
env | grep CORE
peer node start

View file

@ -0,0 +1,17 @@
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
set -e
# Initialize the root CA
fabric-ca-server init -b $BOOTSTRAP_USER_PASS
# Copy the root CA's signing certificate to the data directory to be used by others
cp $FABRIC_CA_SERVER_HOME/ca-cert.pem $TARGET_CERTFILE
# Start the root CA
fabric-ca-server start

67
fabric-ca/start.sh Executable file
View file

@ -0,0 +1,67 @@
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# This script does everything required to run the fabric CA sample.
#
set -e
SDIR=$(dirname "$0")
source ${SDIR}/scripts/env.sh
cd ${SDIR}
# Delete docker containers
dockerContainers=$(docker ps -a | awk '$2~/hyperledger/ {print $1}')
if [ "$dockerContainers" != "" ]; then
log "Deleting existing docker containers ..."
docker rm -f $dockerContainers > /dev/null
fi
# Remove chaincode docker images
chaincodeImages=`docker images | grep "^dev-peer" | awk '{print $3}'`
if [ "$chaincodeImages" != "" ]; then
log "Removing chaincode docker images ..."
docker rmi -f $chaincodeImages > /dev/null
fi
# Start with a clean data directory
DDIR=${SDIR}/${DATA}
if [ -d ${DDIR} ]; then
log "Cleaning up the data directory from previous run at $DDIR"
rm -rf ${SDIR}/data
fi
mkdir -p ${DDIR}/logs
# Create the docker-compose file
${SDIR}/makeDocker.sh
# Create the docker containers
log "Creating docker containers ..."
docker-compose up -d
# Wait for the setup container to complete
dowait "the 'setup' container to finish registering identities, creating the genesis block and other artifacts" 10 $SDIR/$SETUP_LOGFILE $SDIR/$SETUP_SUCCESS_FILE
# Wait for the run container to start and then tails it's summary log
dowait "the docker 'run' container to start" 15 ${SDIR}/${SETUP_LOGFILE} ${SDIR}/${RUN_SUMFILE}
tail -f ${SDIR}/${RUN_SUMFILE}&
TAIL_PID=$!
# Wait for the run container to complete
while true; do
if [ -f ${SDIR}/${RUN_SUCCESS_FILE} ]; then
kill -9 $TAIL_PID
exit 0
elif [ -f ${SDIR}/${RUN_FAIL_FILE} ]; then
kill -9 $TAIL_PID
exit 1
else
sleep 1
fi
done

14
fabric-ca/stop.sh Executable file
View file

@ -0,0 +1,14 @@
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
set -e
SDIR=$(dirname "$0")
source $SDIR/scripts/env.sh
log "Stopping docker containers ..."
docker-compose down
log "Docker containers have been stopped"