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  }