#!/bin/bash # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Permission is hereby granted, free of charge, to any person obtaining a copy of this # software and associated documentation files (the "Software"), to deal in the Software # without restriction, including without limitation the rights to use, copy, modify, # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # Creates the channel update config envelope for adding a new org. This will either be the envelope for adding the # new org to the system channel (defaulting to the name testchainid, created when the orderer is bootstrapped), or # to an application channel. For the system channel, the new org is added to the Consortiums element. For an application # channel, the new org is added to the Applications element. function main { if [ "$SYSTEM_CHANNEL" = true ]; then log "Generating the channel update config for the system channel '$CHANNEL_NAME' for the new org '$NEW_ORG'" else log "Generating the channel update config for the application channel '$CHANNEL_NAME' for the new org '$NEW_ORG'" fi # 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 export ORDERER_PORT_ARGS="-o $ORDERER_HOST:$ORDERER_PORT --tls --cafile $CA_CHAINFILE --clientauth" # Use the first peer of the first org for admin activities IFS=', ' read -r -a PORGS <<< "$PEER_ORGS" initPeerVars ${PORGS[0]} 1 # Create config update envelope with CRL and update the config block of the channel createConfigUpdateSystemChannel if [ $? -eq 1 ]; then log "Org '$NEW_ORG' already exists in the channel config in channel $CHANNEL_NAME. Config will not be updated or signed" exit 1 else log "Congratulations! The channel update config for the new org '$NEW_ORG' was successfully created. Now it must be signed by all org admins" exit 0 fi } function isOrgInChannelConfig { if [ $# -ne 1 ]; then log "Usage: isOrgInChannelConfig " exit 1 fi log "Checking whether org '$NEW_ORG' exists in the channel config" local JSONFILE=$1 # check if the org exists in the channel config local groupJQPath=''; if [ "$SYSTEM_CHANNEL" = true ]; then groupJQPath=".channel_group.groups.Consortiums.groups.SampleConsortium.groups | contains({$NEW_ORG})"; else groupJQPath=".channel_group.groups.Applications.groups | contains({$NEW_ORG})"; fi log "About to execute jq '$groupJQPath'" if cat ${JSONFILE} | jq -e "${groupJQPath}" > /dev/null; then log "Org '$NEW_ORG' exists in the channel config" return 0 else log "Org '$NEW_ORG' does not exist in the channel config" return 1 fi } # Adds a new org to the consortium configured in the system channel function createConfigUpdateSystemChannel { log "Creating config update payload for the new organization '$NEW_ORG'" # Start the configtxlator configtxlator start & configtxlator_pid=$! log "configtxlator_pid:$configtxlator_pid" log "Sleeping 5 seconds for configtxlator to start..." sleep 5 pushd /tmp #make a copy of the .json files below jsonbkdir=/$DATA/${CHANNEL_NAME}_${NEW_ORG}-`date +%Y%m%d-%H%M` mkdir $jsonbkdir 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 > ${CHANNEL_NAME}_${NEW_ORG}_config_block.json # Extract the config from the config block jq .data.data[0].payload.data.config ${CHANNEL_NAME}_${NEW_ORG}_config_block.json > ${CHANNEL_NAME}_${NEW_ORG}_config.json sudo cp ${CHANNEL_NAME}_${NEW_ORG}_config_block.json $jsonbkdir sudo cp ${CHANNEL_NAME}_${NEW_ORG}_config.json $jsonbkdir isOrgInChannelConfig ${CHANNEL_NAME}_${NEW_ORG}_config.json if [ $? -eq 0 ]; then return 1 fi # Append the new org configuration information if [ "$SYSTEM_CHANNEL" = true ]; then jq -s '.[0] * {"channel_group":{"groups":{"Consortiums":{"groups": {"SampleConsortium": {"groups": {"'${NEW_ORG}'":.[1]}}}}}}}' ${CHANNEL_NAME}_${NEW_ORG}_config.json ${DATADIR}/${NEW_ORG}.json > ${CHANNEL_NAME}_${NEW_ORG}_updated_config.json else jq -s '.[0] * {"channel_group":{"groups":{"Applications":{"groups": {"'${NEW_ORG}'":.[1]}}}}}' ${CHANNEL_NAME}_${NEW_ORG}_config.json ${DATADIR}/${NEW_ORG}.json > ${CHANNEL_NAME}_${NEW_ORG}_updated_config.json fi # copy the block config to the /data directory in case we need to update it with another config change later cp /tmp/${CHANNEL_NAME}_${NEW_ORG}_updated_config.json $jsonbkdir # Create the config diff protobuf curl -X POST --data-binary @${CHANNEL_NAME}_${NEW_ORG}_config.json $CTLURL/protolator/encode/common.Config > ${CHANNEL_NAME}_${NEW_ORG}_config.pb curl -X POST --data-binary @${CHANNEL_NAME}_${NEW_ORG}_updated_config.json $CTLURL/protolator/encode/common.Config > ${CHANNEL_NAME}_${NEW_ORG}_updated_config.pb curl -X POST -F original=@${CHANNEL_NAME}_${NEW_ORG}_config.pb -F updated=@${CHANNEL_NAME}_${NEW_ORG}_updated_config.pb $CTLURL/configtxlator/compute/update-from-configs -F channel=$CHANNEL_NAME > ${CHANNEL_NAME}_${NEW_ORG}_config_update.pb # Convert the config diff protobuf to JSON curl -X POST --data-binary @${CHANNEL_NAME}_${NEW_ORG}_config_update.pb $CTLURL/protolator/decode/common.ConfigUpdate > ${CHANNEL_NAME}_${NEW_ORG}_config_update.json cp /tmp/${CHANNEL_NAME}_${NEW_ORG}_config_update.json $jsonbkdir # 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 ${CHANNEL_NAME}_${NEW_ORG}_config_update.json)'}}}' > ${CHANNEL_NAME}_${NEW_ORG}_config_update_as_envelope.json curl -X POST --data-binary @${CHANNEL_NAME}_${NEW_ORG}_config_update_as_envelope.json $CTLURL/protolator/encode/common.Envelope > /tmp/${CHANNEL_NAME}_${NEW_ORG}_config_update_as_envelope.pb # copy to the /data directory so the file can be signed by other admins cp /tmp/${CHANNEL_NAME}_${NEW_ORG}_config_update_as_envelope.pb /$DATA cp /tmp/${CHANNEL_NAME}_${NEW_ORG}_config_update_as_envelope.pb $jsonbkdir cp /tmp/${CHANNEL_NAME}_${NEW_ORG}_config_update_as_envelope.json $jsonbkdir # Stop configtxlator kill $configtxlator_pid log "Created config update payload for the new organization '$NEW_ORG', in file /${DATA}/${CHANNEL_NAME}_${NEW_ORG}_config_update_as_envelope.pb" popd return 0 } DATADIR=/data SCRIPTS=/scripts REPO=hyperledger-on-kubernetes source $SCRIPTS/env.sh echo "Args are: " $* CHANNEL_NAME=$1 NEW_ORG=$2 SYSTEM_CHANNEL=$3 CONFIG_BLOCK_FILE=${DATADIR}/${CHANNEL_NAME}.pb main