github.com/hashicorp/packer@v1.14.3/scripts/codesign_example.sh (about) 1 #! /usr/bin/env bash 2 # Copyright (c) HashiCorp, Inc. 3 # SPDX-License-Identifier: BUSL-1.1 4 5 set -euo pipefail 6 7 # first makes some assertions about the environment and set some shared 8 # variables before starting the script. 9 if ! command -v jq > /dev/null 2>&1; then 10 echo "This script requires jq to work properly." 11 exit 1 12 fi 13 14 if ! command -v sha256sum > /dev/null 2>&1; then 15 if !command -v gsha256sum > /dev/null 2>&1; then 16 echo "This script requires sha256sum (linux) or gsha256sum (osx) to work properly." 17 exit 1 18 else 19 SHASUM_PROG=gsha256sum 20 fi 21 else 22 SHASUM_PROG=sha256sum 23 fi 24 25 PRODUCT_NAME="${PRODUCT_NAME:-""}" 26 if [ -z "$PRODUCT_NAME" ]; then 27 echo "Missing required product name: ${PRODUCT_NAME}" 28 exit 1 29 fi 30 31 TARGET_ZIP="${TARGET_ZIP:-""}" 32 if [ -z "$TARGET_ZIP" ]; then 33 echo "Missing required target path" 34 exit 1 35 fi 36 37 # Artifactory configuration 38 ARTIFACTORY_ENDPOINT="${ARTIFACTORY_ENDPOINT:-"https://artifactory.hashicorp.engineering/artifactory"}" 39 ARTIFACTORY_INPUT_REPO="${ARTIFACTORY_INPUT_REPO:-"hc-signing-input"}" 40 ARTIFACTORY_OUTPUT_REPO="${ARTIFACTORY_OUTPUT_REPO:-"hc-signing-output"}" 41 42 ARTIFACTORY_TOKEN="${ARTIFACTORY_TOKEN:-""}" 43 ARTIFACTORY_USER="${ARTIFACTORY_USER:-""}" 44 45 if [[ -z "$ARTIFACTORY_TOKEN" || -z "$ARTIFACTORY_USER" ]]; then 46 echo "Missing required Artifactory credentials" 47 exit 1 48 fi 49 50 # Create the sign/notarize ID "SN_ID" 51 if command -v uuidgen > /dev/null 2>&1; then 52 uuid="$(uuidgen)" 53 elif [ -f /proc/sys/kernel/random/uuid ]; then 54 uuid="$(cat /proc/sys/kernel/random/uuid)" 55 else 56 echo "This script needs some way to generate a uuid." 57 exit 1 58 fi 59 SN_ID="$uuid" 60 61 # CircleCI configuration 62 CIRCLE_ENDPOINT="${CIRCLE_ENDPOINT:-"https://circleci.com/api/v2"}" 63 CIRCLE_PROJECT="${CIRCLE_PROJECT:-"project/github/hashicorp/circle-codesign"}" 64 65 CIRCLE_TOKEN="${CIRCLE_TOKEN:-""}" 66 if [ -z "$CIRCLE_TOKEN" ]; then 67 echo "Missing required CircleCI credentials" 68 exit 1 69 fi 70 71 # Next, upload an unsigned zip file to the Artifactory at 72 # https://artifactory.hashicorp.engineering/artifactory/hc-signing-input/{PRODUCT}/{ID}.zip 73 echo "Uploading unsigned zip to ${ARTIFACTORY_ENDPOINT}/${ARTIFACTORY_INPUT_REPO}/${PRODUCT_NAME}/${SN_ID}.zip" 74 75 curl --show-error --silent --fail \ 76 --user "${ARTIFACTORY_USER}:${ARTIFACTORY_TOKEN}" \ 77 --request PUT \ 78 "${ARTIFACTORY_ENDPOINT}/${ARTIFACTORY_INPUT_REPO}/${PRODUCT_NAME}/${SN_ID}.zip" \ 79 --upload-file "$TARGET_ZIP" > /dev/null 80 81 # Next, start the CircleCI Pipeline, then wait for a Workflow 82 # to start. 83 echo "Executing CircleCI job" 84 85 res="$(curl --show-error --silent --fail --user "${CIRCLE_TOKEN}:" \ 86 --request POST \ 87 --header 'Content-Type: application/json' \ 88 --header 'Accept: application/json' \ 89 --data "{ \"branch\": \"main\" ,\"parameters\": { \"PRODUCT\": \"${PRODUCT_NAME}\", \"PKG_NAME\": \"${SN_ID}.zip\" } }" \ 90 "${CIRCLE_ENDPOINT}/${CIRCLE_PROJECT}/pipeline")" 91 pipeline_id="$(echo "$res" | jq -r '.id')" 92 echo "CircleCI Pipeline $pipeline_id started" 93 94 echo -n "Retrieving CircleCI Workflow ID" 95 # 24 * 5 seconds = 2 minutes 96 counter=12 97 workflow_id="" 98 # wait until a Workflow ID is found 99 until [ "$workflow_id" != "" ]; do 100 echo -n "." 101 workflow_id=$(curl --silent --fail --user "${CIRCLE_TOKEN}:" \ 102 --request GET \ 103 --header 'Accept: application/json' \ 104 "${CIRCLE_ENDPOINT}/pipeline/${pipeline_id}/workflow" \ 105 | jq -r '.items[].id' 106 ) 107 if [ "$counter" -eq "0" ]; then 108 echo "Tried too many times, but Pipeline ${pipeline_id} still has no Workflows" 109 exit 1 110 fi 111 counter=$((counter - 1)) 112 sleep 5 113 done 114 echo "" 115 116 echo "CircleCI Workflow $workflow_id started" 117 118 # Next, wait for the Workflow to reach a terminal state, then fails if it isn't 119 # "success" 120 echo -n "Waiting for CircleCI Workflow ID: ${workflow_id}" 121 # 360 * 5 seconds = 30 minutes 122 counter=360 123 finished="not_run" 124 # wait for one of the terminal states: ["success", "failed", "error", "canceled"] 125 until [[ "$finished" == "success" || "$finished" == "failed" || "$finished" == "error" || "$finished" == "canceled" ]]; do 126 echo -n "." 127 finished=$(curl --silent --fail --user "${CIRCLE_TOKEN}:" \ 128 --header 'Accept: application/json' \ 129 "${CIRCLE_ENDPOINT}/workflow/${workflow_id}" \ 130 | jq -r '.status' 131 ) 132 if [ "$counter" -eq "0" ]; then 133 echo "Tried too many times, but workflow is still in state ${finished}" 134 exit 1 135 fi 136 counter=$((counter - 1)) 137 sleep 5 138 done 139 echo "" 140 141 if [ "$finished" != "success" ]; then 142 echo "Workflow ID ${workflow_id} ${finished}" 143 exit 1 144 fi 145 146 # Next, download the signed zip from Artifactory at 147 # https://artifactory.hashicorp.engineering/artifactory/hc-signing-output/{PRODUCT}/{ID}.zip 148 echo "Retrieving signed zip from ${ARTIFACTORY_ENDPOINT}/${ARTIFACTORY_OUTPUT_REPO}/${PRODUCT_NAME}/${SN_ID}.zip" 149 150 curl --show-error --silent --fail --user "${ARTIFACTORY_USER}:${ARTIFACTORY_TOKEN}" \ 151 --request GET \ 152 "${ARTIFACTORY_ENDPOINT}/${ARTIFACTORY_OUTPUT_REPO}/${PRODUCT_NAME}/${SN_ID}.zip" \ 153 --output "signed_${SN_ID}.zip" 154 155 signed_checksum=$( 156 curl --silent --show-error --fail --user "${ARTIFACTORY_USER}:${ARTIFACTORY_TOKEN}" \ 157 --head \ 158 "${ARTIFACTORY_ENDPOINT}/${ARTIFACTORY_OUTPUT_REPO}/${PRODUCT_NAME}/${SN_ID}.zip" \ 159 | grep -i "x-checksum-sha256" | awk 'gsub("[\r\n]", "", $2) {print $2;}' 160 ) 161 162 echo "${signed_checksum} signed_${SN_ID}.zip" | $SHASUM_PROG -c 163 if [ $? -ne 0 ]; then 164 exit 1 165 fi 166 167 mv "signed_${SN_ID}.zip" "$TARGET_ZIP"