mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-25 23:49:37 -05:00
145 lines
4.2 KiB
Bash
145 lines
4.2 KiB
Bash
|
#!/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"
|