From 30daf76a97c57a5f74c8dad1da282dcc0ff8b3fb Mon Sep 17 00:00:00 2001 From: Carl Dong Date: Wed, 17 Mar 2021 13:49:04 -0400 Subject: guix: Add guix-attest script --- contrib/guix/guix-attest | 170 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100755 contrib/guix/guix-attest (limited to 'contrib/guix/guix-attest') diff --git a/contrib/guix/guix-attest b/contrib/guix/guix-attest new file mode 100755 index 0000000000..d7604dd75f --- /dev/null +++ b/contrib/guix/guix-attest @@ -0,0 +1,170 @@ +#!/usr/bin/env bash +export LC_ALL=C +set -e -o pipefail + +# Source the common prelude, which: +# 1. Checks if we're at the top directory of the Bitcoin Core repository +# 2. Defines a few common functions and variables +# +# shellcheck source=libexec/prelude.bash +source "$(dirname "${BASH_SOURCE[0]}")/libexec/prelude.bash" + + +################### +## Sanity Checks ## +################### + +################ +# Required non-builtin commands should be invokable +################ + +check_tools cat env basename mkdir xargs find gpg + +################ +# Required env vars should be non-empty +################ + +cmd_usage() { +cat < \\ + SIGNER=GPG_KEY_NAME[=SIGNER_NAME] \\ + ./contrib/guix/guix-attest + +Example w/o overriding signing name: + + env GUIX_SIGS_REPO=/home/achow101/guix.sigs \\ + SIGNER=achow101 \\ + ./contrib/guix/guix-attest + +Example overriding signing name: + + env GUIX_SIGS_REPO=/home/dongcarl/guix.sigs \\ + SIGNER=0x96AB007F1A7ED999=dongcarl \\ + ./contrib/guix/guix-attest + +EOF +} + +if [ -z "$GUIX_SIGS_REPO" ] || [ -z "$SIGNER" ]; then + cmd_usage + exit 1 +fi + +################ +# GUIX_SIGS_REPO should exist as a directory +################ + +if [ ! -d "$GUIX_SIGS_REPO" ]; then +cat << EOF +ERR: The specified GUIX_SIGS_REPO is not an existent directory: + + '$GUIX_SIGS_REPO' + +Hint: Please clone the guix.sigs repository and point to it with the + GUIX_SIGS_REPO environment variable. + +EOF +cmd_usage +exit 1 +fi + +################ +# The key specified in SIGNER should be usable +################ + +IFS='=' read -r gpg_key_name signer_name <<< "$SIGNER" +if [ -z "${signer_name}" ]; then + signer_name="$gpg_key_name" +fi + +if ! gpg --dry-run --list-secret-keys "${gpg_key_name}" >/dev/null 2>&1; then + echo "ERR: GPG can't seem to find any key named '${gpg_key_name}'" + exit 1 +fi + +################ +# We should be able to find at least one output +################ + +echo "Looking for build output directories in ${OUTDIR_BASE}" + +shopt -s nullglob +OUTDIRS=( "${OUTDIR_BASE}"/* ) # This expands to an array of directories... +shopt -u nullglob + +if (( ${#OUTDIRS[@]} )); then + echo "Found build output directories:" + for outdir in "${OUTDIRS[@]}"; do + echo " '$outdir'" + done + echo +else + echo "ERR: Could not find any build output directories in ${OUTDIR_BASE}" + exit 1 +fi + + +############## +## Attest ## +############## + +# Usage: out_name $outdir +# +# HOST: The output directory being attested +# +out_name() { + basename "$1" +} + +# Usage: out_sig_dir $outdir +# +# outdir: The output directory being attested +# +out_sig_dir() { + echo "$GUIX_SIGS_REPO/$VERSION/$(out_name "$1")/$signer_name" +} + +# Accumulate a list of signature directories that already exist... +outdirs_already_attested_to=() + +echo "Attesting to build outputs for version: '${VERSION}'" +echo "" + +# MAIN LOGIC: Loop through each output for VERSION and attest to output in +# GUIX_SIGS_REPO as SIGNER, if attestation does not exist +for outdir in "${OUTDIRS[@]}"; do + outname="$(out_name "$outdir")" + outsigdir="$(out_sig_dir "$outdir")" + if [ -e "$outsigdir" ]; then + echo "${outname}: SKIPPING: Signature directory already exists in the specified guix.sigs repository" + outdirs_already_attested_to+=("$outdir") + else + mkdir -p "$outsigdir" + echo "${outname}: Hashing build outputs to produce SHA256SUMS" + ( + cd "$outdir" + find . -type f -printf '%P\0' | env LC_ALL=C sort -z | xargs -r0 sha256sum >> "$outsigdir"/SHA256SUMS + ) + echo "${outname}: Signing SHA256SUMS to produce SHA256SUMS.asc" + gpg --detach-sign --local-user "$gpg_key_name" --output "$outsigdir"/SHA256SUMS.asc "$outsigdir"/SHA256SUMS + echo "" + fi +done + +if (( ${#outdirs_already_attested_to[@]} )); then +# ...so that we can print them out nicely in a warning message +cat << EOF + +WARN: Signature directories from '$signer_name' already exist in the specified + guix.sigs repository for the following output directories and were + skipped: + +EOF +for outdir in "${outdirs_already_attested_to[@]}"; do + echo " '${outdir}'" + echo " Corresponds to: '$(out_sig_dir "$outdir")'" + echo "" +done +fi -- cgit v1.2.3