#!/usr/bin/env bash set -euo pipefail shopt -s inherit_errexit # This script handles the upload of OS images and their corresponding image info. POSITIONAL_ARGS=() ref="" upload_signed_measurements=0 fake_sign=0 while [[ $# -gt 0 ]]; do case $1 in --ref) ref="$2" shift # past argument shift # past value ;; --upload-measurements) upload_signed_measurements=1 shift # past argument ;; --fake-sign) fake_sign=1 shift # past argument ;; -*) echo "Unknown option $1" exit 1 ;; *) POSITIONAL_ARGS+=("$1") # save positional arg shift # past argument ;; esac done set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters if [[ $# -ne 0 ]]; then echo "Unknown positional arguments: $*" exit 1 fi if [[ -z ${ref} ]]; then echo "Missing required argument --ref" exit 1 fi version_file=$(realpath @@VERSION@@) stat "${version_file}" >> /dev/null version=$(cat "${version_file}") uplosi=$(realpath @@UPLOSI@@) stat "${uplosi}" >> /dev/null systemd_dissect=$(realpath @@DISSECT_TOOLCHAIN@@) stat "${systemd_dissect}" >> /dev/null export DISSECT_TOOLCHAIN="${systemd_dissect}" cosign=$(realpath @@COSIGN@@) stat "${cosign}" >> /dev/null rekor_cli=$(realpath @@REKOR_CLI@@) stat "${rekor_cli}" >> /dev/null upload_cli=$(realpath @@UPLOAD_CLI@@) stat "${upload_cli}" >> /dev/null measured_boot=$(realpath @@MEASURED_BOOT@@) stat "${measured_boot}" >> /dev/null parallel=$(realpath @@PARALLEL@@) stat "${parallel}" >> /dev/null FILES=(@@FILES@@) workspace=$(mktemp -d) # shellcheck disable=SC2064 trap "rm -rf ${workspace}" EXIT echo Uploading "${#FILES[@]}" OS images. This may take a while... >&2 "${parallel}" --will-cite \ "${upload_cli}" uplosi \ --uplosi-path "${uplosi}" \ --version "${version}" \ --ref "${ref}" \ --raw-image {} \ --out "${workspace}/image-upload-{#}.json" \ ::: "${FILES[@]}" "${upload_cli}" info "${workspace}/"image-upload-*.json if [[ ${upload_signed_measurements} -eq 0 ]]; then echo "Skipping signed measurements upload. Enable by setting --upload-measurements" >&2 exit 0 fi echo Uploading signed measurements. This requires sudo and a signing key. >&2 i=1 for file in "${FILES[@]}"; do combined_name=$(basename "$(dirname "${file}")") IFS="_" read -r csp attestation_variant stream <<< "${combined_name}" sudo -E "${measured_boot}" "${file}" "${workspace}/pcrs-${i}.json" sudo chown "$(id -u -n)" "${workspace}/pcrs-${i}.json" "${upload_cli}" measurements envelope \ --in "${workspace}/pcrs-${i}.json" \ --out "${workspace}/pcrs-${i}.json" \ --version "ref/${ref}/stream/${stream}/${version}" \ --csp "${csp}" \ --attestation-variant "${attestation_variant}" i=$((i + 1)) done "${upload_cli}" measurements merge \ --out "${workspace}/measurements.json" \ "${workspace}"/pcrs-*.json if [[ ${fake_sign} -eq 1 ]]; then echo "Skipping signing of measurements and using fake signature instead (--fake-sign is set)." >&2 echo "THOSE MEASUREMENTS BELONG TO A DEBUG IMAGE. THOSE ARE NOT SINGED BY ANY KEY." > "${workspace}/measurements.json.sig" else # shellcheck disable=SC2016 echo 'Creating real signature with keys referenced in $COSIGN_PUBLIC_KEY_PATH, $COSIGN_PRIVATE_KEY and $COSIGN_PASSWORD. Set "--fake-sign" for debugging purposes.' >&2 # Enabling experimental mode also publishes signature to Rekor COSIGN_EXPERIMENTAL=1 "${cosign}" sign-blob --yes --key env://COSIGN_PRIVATE_KEY \ "${workspace}/measurements.json" > "${workspace}/measurements.json.sig" # Verify - As documentation & check # Local Signature (input: artifact, key, signature) "${cosign}" verify-blob --key "${COSIGN_PUBLIC_KEY_PATH}" \ --signature "${workspace}/measurements.json.sig" \ "${workspace}/measurements.json" # Transparency Log Signature (input: artifact, key) uuid=$("${rekor_cli}" search --artifact "${workspace}/measurements.json" | tail -n 1) sig=$("${rekor_cli}" get --uuid="${uuid}" --format=json | jq -r .Body.HashedRekordObj.signature.content) "${cosign}" verify-blob --key "${COSIGN_PUBLIC_KEY_PATH}" --signature <(echo "${sig}") "${workspace}/measurements.json" fi "${upload_cli}" measurements upload \ --measurements "${workspace}/measurements.json" \ --signature "${workspace}/measurements.json.sig"