github.com/IBM-Blockchain/fabric-operator@v1.0.4/sample-network/scripts/channel.sh (about) 1 #!/bin/bash 2 # 3 # Copyright contributors to the Hyperledger Fabric Operator project 4 # 5 # SPDX-License-Identifier: Apache-2.0 6 # 7 # Licensed under the Apache License, Version 2.0 (the "License"); 8 # you may not use this file except in compliance with the License. 9 # You may obtain a copy of the License at: 10 # 11 # http://www.apache.org/licenses/LICENSE-2.0 12 # 13 # Unless required by applicable law or agreed to in writing, software 14 # distributed under the License is distributed on an "AS IS" BASIS, 15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 # See the License for the specific language governing permissions and 17 # limitations under the License. 18 # 19 20 # todo: Refuse to overwrite an existing admin enrollment ? 21 22 23 function channel_command_group() { 24 # set -x 25 26 COMMAND=$1 27 shift 28 29 if [ "${COMMAND}" == "create" ]; then 30 log "Creating channel \"${CHANNEL_NAME}\":" 31 channel_up 32 log "🏁 - Channel is ready." 33 34 else 35 print_help 36 exit 1 37 fi 38 } 39 40 function channel_up() { 41 set -x 42 43 enroll_org_admins 44 45 create_channel_msp 46 create_genesis_block 47 48 join_channel_orderers 49 join_channel_peers 50 } 51 52 # create an enrollment MSP config.yaml 53 function create_msp_config_yaml() { 54 local ca_name=$1 55 local ca_cert_name=$2 56 local msp_dir=$3 57 echo "Creating msp config ${msp_dir}/config.yaml with cert ${ca_cert_name}" 58 59 cat << EOF > ${msp_dir}/config.yaml 60 NodeOUs: 61 Enable: true 62 ClientOUIdentifier: 63 Certificate: cacerts/${ca_cert_name} 64 OrganizationalUnitIdentifier: client 65 PeerOUIdentifier: 66 Certificate: cacerts/${ca_cert_name} 67 OrganizationalUnitIdentifier: peer 68 AdminOUIdentifier: 69 Certificate: cacerts/${ca_cert_name} 70 OrganizationalUnitIdentifier: admin 71 OrdererOUIdentifier: 72 Certificate: cacerts/${ca_cert_name} 73 OrganizationalUnitIdentifier: orderer 74 EOF 75 } 76 77 function get_connection_profile() { 78 local node_name=$1 79 local connection_profile=$2 80 81 mkdir -p $(dirname ${connection_profile}) 82 83 echo "writing $node_name connection profile to $connection_profile" 84 85 kubectl -n $NS get cm/${node_name}-connection-profile -o json \ 86 | jq -r .binaryData.\"profile.json\" \ 87 | base64 -d \ 88 > ${connection_profile} 89 } 90 91 function enroll_org_admin() { 92 local type=$1 93 local org=$2 94 local username=$3 95 local password=$4 96 97 echo "Enrolling $type org admin $username" 98 99 ENROLLMENTS_DIR=${TEMP_DIR}/enrollments 100 ORG_ADMIN_DIR=${ENROLLMENTS_DIR}/${org}/users/${username} 101 102 # skip the enrollment if the admin certificate is available. 103 if [ -f "${ORG_ADMIN_DIR}/msp/keystore/key.pem" ]; then 104 echo "Found an existing admin enrollment at ${ORG_ADMIN_DIR}" 105 return 106 fi 107 108 # Retrieve the CA information from Kubernetes 109 CA_NAME=${org}-ca 110 CA_DIR=${TEMP_DIR}/cas/${CA_NAME} 111 CONNECTION_PROFILE=${CA_DIR}/connection-profile.json 112 113 get_connection_profile $CA_NAME $CONNECTION_PROFILE 114 115 # extract the CA enrollment URL and tls cert from the org connection profile 116 CA_AUTH=${username}:${password} 117 CA_ENDPOINT=$(jq -r .endpoints.api $CONNECTION_PROFILE) 118 CA_HOST=$(echo ${CA_ENDPOINT} | cut -d/ -f3 | tr ':' '\n' | head -1) 119 CA_PORT=$(echo ${CA_ENDPOINT} | cut -d/ -f3 | tr ':' '\n' | tail -1) 120 CA_URL=https://${CA_AUTH}@${CA_HOST}:${CA_PORT} 121 122 jq -r .tls.cert $CONNECTION_PROFILE | base64 -d >& $CA_DIR/tls-cert.pem 123 124 # enroll the admin user 125 FABRIC_CA_CLIENT_HOME=${ORG_ADMIN_DIR} fabric-ca-client enroll --url ${CA_URL} --tls.certfiles ${CA_DIR}/tls-cert.pem 126 127 # Construct an msp config.yaml 128 CA_CERT_NAME=${NS}-${CA_NAME}-ca-$(echo $INGRESS_DOMAIN | tr -s . -)-${CA_PORT}.pem 129 130 create_msp_config_yaml ${CA_NAME} ${CA_CERT_NAME} ${ORG_ADMIN_DIR}/msp 131 132 # private keys are hashed by name, but we only support one enrollment. 133 # test-network examples refer to this as "server.key", which is incorrect. 134 # This is the private key used to endorse transactions using the admin's 135 # public key. 136 mv ${ORG_ADMIN_DIR}/msp/keystore/*_sk ${ORG_ADMIN_DIR}/msp/keystore/key.pem 137 138 139 # enroll the admin user at the TLS CA - used for the channel admin API 140 FABRIC_CA_CLIENT_HOME=${ORG_ADMIN_DIR} \ 141 fabric-ca-client enroll \ 142 --url ${CA_URL} \ 143 --tls.certfiles ${CA_DIR}/tls-cert.pem \ 144 --mspdir ${ORG_ADMIN_DIR}/tls \ 145 --caname tlsca 146 147 mv ${ORG_ADMIN_DIR}/tls/keystore/*_sk ${ORG_ADMIN_DIR}/tls/keystore/key.pem 148 } 149 150 function enroll_org_admins() { 151 push_fn "Enrolling org admin users" 152 153 enroll_org_admin orderer org0 org0admin org0adminpw 154 enroll_org_admin peer org1 org1admin org1adminpw 155 enroll_org_admin peer org2 org2admin org2adminpw 156 157 pop_fn 158 } 159 160 function create_channel_org_msp() { 161 local type=$1 162 local org=$2 163 echo "Creating channel org $org MSP" 164 165 CA_DIR=${TEMP_DIR}/cas/${org}-ca 166 ORG_MSP_DIR=${TEMP_DIR}/channel-msp/${type}Organizations/${org}/msp 167 168 mkdir -p ${ORG_MSP_DIR}/cacerts 169 mkdir -p ${ORG_MSP_DIR}/tlscacerts 170 171 jq -r .ca.signcerts ${CA_DIR}/connection-profile.json | base64 -d >& ${ORG_MSP_DIR}/cacerts/ca-signcert.pem 172 jq -r .tlsca.signcerts ${CA_DIR}/connection-profile.json | base64 -d >& ${ORG_MSP_DIR}/tlscacerts/tlsca-signcert.pem 173 174 create_msp_config_yaml ${org}-ca ca-signcert.pem ${ORG_MSP_DIR} 175 } 176 177 function create_channel_msp() { 178 push_fn "Creating channel MSP" 179 180 create_channel_org_msp orderer org0 181 create_channel_org_msp peer org1 182 create_channel_org_msp peer org2 183 184 extract_orderer_tls_cert org0 orderersnode1 185 extract_orderer_tls_cert org0 orderersnode2 186 extract_orderer_tls_cert org0 orderersnode3 187 188 pop_fn 189 } 190 191 function extract_orderer_tls_cert() { 192 local org=$1 193 local orderer=$2 194 195 echo "Extracting TLS cert for $org $orderer" 196 197 ORDERER_NAME=${org}-${orderer} 198 ORDERER_DIR=${TEMP_DIR}/channel-msp/ordererOrganizations/${org}/orderers/${ORDERER_NAME} 199 ORDERER_TLS_DIR=${ORDERER_DIR}/tls 200 CONNECTION_PROFILE=${ORDERER_DIR}/connection-profile.json 201 202 get_connection_profile $ORDERER_NAME $CONNECTION_PROFILE 203 204 mkdir -p $ORDERER_TLS_DIR/signcerts 205 206 jq -r .tls.signcerts ${CONNECTION_PROFILE} \ 207 | base64 -d \ 208 >& $ORDERER_TLS_DIR/signcerts/tls-cert.pem 209 } 210 211 function create_genesis_block() { 212 push_fn "Creating channel genesis block" 213 214 mkdir -p ${TEMP_DIR}/config 215 cp ${PWD}/config/core.yaml ${TEMP_DIR}/config/ 216 217 # The channel configtx file needs to specify dynamic elements from the environment, 218 # for instance, the ${INGRESS_DOMAIN} for ingress controller and service endpoints. 219 cat ${PWD}/config/configtx-template.yaml | envsubst > ${TEMP_DIR}/config/configtx.yaml 220 221 FABRIC_CFG_PATH=${TEMP_DIR}/config \ 222 configtxgen \ 223 -profile TwoOrgsApplicationGenesis \ 224 -channelID $CHANNEL_NAME \ 225 -outputBlock ${TEMP_DIR}/genesis_block.pb 226 227 # configtxgen -inspectBlock ${TEMP_DIR}/genesis_block.pb 228 229 pop_fn 230 } 231 232 function join_channel_orderers() { 233 push_fn "Joining orderers to channel ${CHANNEL_NAME}" 234 235 join_channel_orderer org0 orderersnode1 236 join_channel_orderer org0 orderersnode2 237 join_channel_orderer org0 orderersnode3 238 239 # todo: readiness / liveiness equivalent for channel? Needs a little bit to settle before peers can join. 240 sleep 10 241 242 pop_fn 243 } 244 245 # Request from the channel ADMIN api that the orderer joins the target channel 246 function join_channel_orderer() { 247 local org=$1 248 local orderer=$2 249 250 # The client certificate presented in this case is the admin USER TLS enrollment key. This is a stronger assertion 251 # of identity than the Docker Compose network, which transmits the orderer NODE TLS key pair directly 252 253 osnadmin channel join \ 254 --orderer-address ${NS}-${org}-${orderer}-admin.${INGRESS_DOMAIN} \ 255 --ca-file ${TEMP_DIR}/channel-msp/ordererOrganizations/${org}/orderers/${org}-${orderer}/tls/signcerts/tls-cert.pem \ 256 --client-cert ${TEMP_DIR}/enrollments/${org}/users/${org}admin/tls/signcerts/cert.pem \ 257 --client-key ${TEMP_DIR}/enrollments/${org}/users/${org}admin/tls/keystore/key.pem \ 258 --channelID ${CHANNEL_NAME} \ 259 --config-block ${TEMP_DIR}/genesis_block.pb 260 } 261 262 function join_channel_peers() { 263 join_org_peers 1 264 join_org_peers 2 265 } 266 267 function join_org_peers() { 268 local orgnum=$1 269 push_fn "Joining org${orgnum} peers to channel ${CHANNEL_NAME}" 270 271 # Join peers to channel 272 join_channel_peer $orgnum 1 273 #join_channel_peer $orgnum 2 274 275 pop_fn 276 } 277 278 function join_channel_peer() { 279 local orgnum=$1 280 local peernum=$2 281 282 export_peer_context $orgnum $peernum 283 284 peer channel join \ 285 --blockpath ${TEMP_DIR}/genesis_block.pb 286 }