292 lines
9.3 KiB
Bash
292 lines
9.3 KiB
Bash
#!/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 10 seconds for the orderer and peers to start
|
|
awaitSetup
|
|
sleep 10
|
|
|
|
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]}
|
|
export ORDERER_PORT_ARGS="-o $ORDERER_HOST:7050 --tls --cafile $CA_CHAINFILE --clientauth"
|
|
|
|
# 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-1))
|
|
joinChannel
|
|
COUNT=$((COUNT+1))
|
|
done
|
|
done
|
|
|
|
# Update the anchor peers
|
|
for ORG in $PEER_ORGS; do
|
|
initPeerVars $ORG 0
|
|
switchToAdminIdentity
|
|
logr "Updating anchor peers for $PEER_HOST ..."
|
|
peer channel update -c $CHANNEL_NAME -f $ANCHOR_TX_FILE $ORDERER_CONN_ARGS
|
|
done
|
|
|
|
# Install chaincode on the 1st peer in each org
|
|
for ORG in $PEER_ORGS; do
|
|
initPeerVars $ORG 0
|
|
installChaincode
|
|
done
|
|
|
|
# Instantiate chaincode on the 1st peer of the 2nd org
|
|
makePolicy
|
|
initPeerVars ${PORGS[1]} 0
|
|
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_CONN_ARGS
|
|
|
|
# Query chaincode from the 1st peer of the 1st org
|
|
initPeerVars ${PORGS[0]} 0
|
|
switchToUserIdentity
|
|
chaincodeQuery 100
|
|
|
|
# Invoke chaincode on the 1st peer of the 1st org
|
|
initPeerVars ${PORGS[0]} 0
|
|
switchToUserIdentity
|
|
logr "Sending invoke transaction to $PEER_HOST ..."
|
|
peer chaincode invoke -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}' $ORDERER_CONN_ARGS
|
|
|
|
## Install chaincode on 2nd peer of 2nd org
|
|
initPeerVars ${PORGS[1]} 1
|
|
installChaincode
|
|
|
|
# Query chaincode on 2nd peer of 2nd org
|
|
sleep 10
|
|
initPeerVars ${PORGS[1]} 1
|
|
switchToUserIdentity
|
|
chaincodeQuery 90
|
|
|
|
initPeerVars ${PORGS[0]} 0
|
|
switchToUserIdentity
|
|
|
|
# Revoke the user and generate CRL using admin's credentials
|
|
revokeFabricUserAndGenerateCRL
|
|
|
|
# Fetch config block
|
|
fetchConfigBlock
|
|
|
|
# Create config update envelope with CRL and update the config block of the channel
|
|
createConfigUpdatePayloadWithCRL
|
|
updateConfigBlock
|
|
|
|
# querying the chaincode should fail as the user is revoked
|
|
switchToUserIdentity
|
|
queryAsRevokedUser
|
|
if [ "$?" -ne 0 ]; then
|
|
logr "The revoked user $USER_NAME should have failed to query the chaincode in the channel '$CHANNEL_NAME'"
|
|
exit 1
|
|
fi
|
|
logr "Congratulations! The tests ran successfully."
|
|
|
|
done=true
|
|
}
|
|
|
|
# Enroll as a peer admin and create the channel
|
|
function createChannel {
|
|
initPeerVars ${PORGS[0]} 0
|
|
switchToAdminIdentity
|
|
logr "Creating channel '$CHANNEL_NAME' on $ORDERER_HOST ..."
|
|
peer channel create --logging-level=DEBUG -c $CHANNEL_NAME -f $CHANNEL_TX_FILE $ORDERER_CONN_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
|
|
}
|
|
|
|
function chaincodeQuery {
|
|
if [ $# -ne 1 ]; then
|
|
fatalr "Usage: chaincodeQuery <expected-value>"
|
|
fi
|
|
set +e
|
|
logr "Querying chaincode in the channel '$CHANNEL_NAME' on the 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
|
|
else
|
|
# removed the string "Query Result" from peer chaincode query command result, as a result, have to support both options until the change is merged.
|
|
VALUE=$(cat log.txt | egrep '^[0-9]+$')
|
|
if [ $? -eq 0 -a "$VALUE" = "$1" ]; then
|
|
logr "Query of channel '$CHANNEL_NAME' on peer '$PEER_HOST' was successful"
|
|
set -e
|
|
return 0
|
|
fi
|
|
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 queryAsRevokedUser {
|
|
set +e
|
|
logr "Querying the chaincode in the channel '$CHANNEL_NAME' on the peer '$PEER_HOST' as revoked user '$USER_NAME' ..."
|
|
local starttime=$(date +%s)
|
|
# Continue to poll until we get an expected 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
|
|
if [ $? -ne 0 ]; then
|
|
err=$(cat log.txt | grep "access denied")
|
|
if [ "$err" != "" ]; then
|
|
logr "Expected error occurred when the revoked user '$USER_NAME' queried the chaincode in the channel '$CHANNEL_NAME'"
|
|
set -e
|
|
return 0
|
|
fi
|
|
fi
|
|
echo -n "."
|
|
done
|
|
set -e
|
|
cat log.txt
|
|
cat log.txt >> $RUN_SUMFILE
|
|
return 1
|
|
}
|
|
|
|
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/go
|
|
}
|
|
|
|
function fetchConfigBlock {
|
|
logr "Fetching the configuration block of the channel '$CHANNEL_NAME'"
|
|
peer channel fetch config $CONFIG_BLOCK_FILE -c $CHANNEL_NAME $ORDERER_CONN_ARGS
|
|
}
|
|
|
|
function updateConfigBlock {
|
|
logr "Updating the configuration block of the channel '$CHANNEL_NAME'"
|
|
peer channel update -f $CONFIG_UPDATE_ENVELOPE_FILE -c $CHANNEL_NAME $ORDERER_CONN_ARGS
|
|
}
|
|
|
|
function createConfigUpdatePayloadWithCRL {
|
|
logr "Creating config update payload with the generated CRL for the organization '$ORG'"
|
|
# Start the configtxlator
|
|
configtxlator start &
|
|
configtxlator_pid=$!
|
|
log "configtxlator_pid:$configtxlator_pid"
|
|
logr "Sleeping 5 seconds for configtxlator to start..."
|
|
sleep 5
|
|
|
|
pushd /tmp
|
|
|
|
CTLURL=http://127.0.0.1:7059
|
|
# Convert the config block protobuf to JSON
|
|
curl -X POST --data-binary @$CONFIG_BLOCK_FILE $CTLURL/protolator/decode/common.Block > config_block.json
|
|
# Extract the config from the config block
|
|
jq .data.data[0].payload.data.config config_block.json > config.json
|
|
|
|
# Update crl in the config json
|
|
CRL=$(cat $CORE_PEER_MSPCONFIGPATH/crls/crl*.pem | base64 | tr -d '\n')
|
|
cat config.json | jq --arg org "$ORG" --arg crl "$CRL" '.channel_group.groups.Application.groups[$org].values.MSP.value.config.revocation_list = [$crl]' > updated_config.json
|
|
|
|
# Create the config diff protobuf
|
|
curl -X POST --data-binary @config.json $CTLURL/protolator/encode/common.Config > config.pb
|
|
curl -X POST --data-binary @updated_config.json $CTLURL/protolator/encode/common.Config > updated_config.pb
|
|
curl -X POST -F original=@config.pb -F updated=@updated_config.pb $CTLURL/configtxlator/compute/update-from-configs -F channel=$CHANNEL_NAME > config_update.pb
|
|
|
|
# Convert the config diff protobuf to JSON
|
|
curl -X POST --data-binary @config_update.pb $CTLURL/protolator/decode/common.ConfigUpdate > config_update.json
|
|
|
|
# Create envelope protobuf container config diff to be used in the "peer channel update" command to update the channel configuration block
|
|
echo '{"payload":{"header":{"channel_header":{"channel_id":"'"${CHANNEL_NAME}"'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' > config_update_as_envelope.json
|
|
curl -X POST --data-binary @config_update_as_envelope.json $CTLURL/protolator/encode/common.Envelope > $CONFIG_UPDATE_ENVELOPE_FILE
|
|
|
|
# Stop configtxlator
|
|
kill $configtxlator_pid
|
|
|
|
popd
|
|
}
|
|
|
|
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
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
function logr {
|
|
log $*
|
|
log $* >> $RUN_SUMPATH
|
|
}
|
|
|
|
function fatalr {
|
|
logr "FATAL: $*"
|
|
exit 1
|
|
}
|
|
|
|
main
|