#!/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 monero 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 diff sort xargs tee if [ -z "$NO_SIGN" ]; then # make it possible to override the gpg binary GPG=${GPG:-gpg} # $GPG can contain extra arguments passed to the binary # so let's check only the existence of arg[0] # shellcheck disable=SC2206 GPG_ARRAY=($GPG) check_tools "${GPG_ARRAY[0]}" fi ################ # Required env vars should be non-empty ################ cmd_usage() { cat <<EOF Synopsis: env GUIX_SIGS_REPO=<path/to/guix.sigs> \\ SIGNER=GPG_KEY_NAME[=SIGNER_NAME] \\ [ NO_SIGN=1 ] ./contrib/guix/guix-attest Example w/o overriding signing name: env GUIX_SIGS_REPO=/home/user/guix.sigs \\ SIGNER=achow101 \\ ./contrib/guix/guix-attest Example overriding signing name: env GUIX_SIGS_REPO=/home/user/guix.sigs \\ SIGNER=0x96AB007F1A7ED999=dongcarl \\ ./contrib/guix/guix-attest Example w/o signing, just creating SHA256SUMS: env GUIX_SIGS_REPO=/home/user/guix.sigs \\ SIGNER=achow101 \\ NO_SIGN=1 \\ ./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 [ -z "$NO_SIGN" ] && ! ${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 ############## ## Attest ## ############## # Usage: out_name $logdir # # HOST: The output directory being attested # out_name() { basename "$(dirname "$1")" } shasum_already_exists() { cat <<EOF -- ERR: An ${1} file already exists for '${VERSION}' and attests differently. You likely previously attested to a partial build (e.g. one where you specified the HOST environment variable). See the diff above for more context. Hint: You may wish to remove the existing attestations and their signatures by invoking: rm '${PWD}/${1}'{,.asc} Then try running this script again. EOF } echo "Attesting to build outputs for version: '${VERSION}'" # Given a SHA256SUMS file as stdin that has lines like: # 0ba536819b221a91d3d42e978be016aac918f40984754d74058aa0c921cd3ea6 a/b/d/c/d/s/monero-aarch64-apple-darwin-v0.18.3.2.tar.bz2 # ... # # Replace each line's file name with its basename: # 0ba536819b221a91d3d42e978be016aac918f40984754d74058aa0c921cd3ea6 monero-aarch64-apple-darwin-v0.18.3.2.tar.bz2 # ... # basenameify_SHA256SUMS() { sed -E 's@(^[[:xdigit:]]{64}[[:space:]]+).+/([^/]+$)@\1\2@' } outsigdir="$GUIX_SIGS_REPO/$VERSION/$signer_name" mkdir -p "$outsigdir" ( cd "$outsigdir" temp_all="$(mktemp)" trap 'rm -rf -- "$temp_all"' EXIT echo "Looking for build output SHA256SUMS fragments in ${LOGDIR_BASE}" all_fragments=$(find "$LOGDIR_BASE" -name "SHA256SUMS.part" -print0 | xargs -0 sort -u /dev/null | basenameify_SHA256SUMS | sort -k2 | tee "$temp_all") if [ -z "${all_fragments}" ]; then echo "ERR: Could not find any build output SHA256SUMS fragments in ${LOGDIR_BASE}" exit 1 fi all_file="all.SHA256SUMS" if [ -e "$all_file" ]; then # The SHA256SUMS already exists, make sure it's exactly what we # expect, error out if not if diff -u ${all_file} "$temp_all"; then echo "A ${all_file} file already exists for '${VERSION}' and is up-to-date." else shasum_already_exists "$all_file" exit 1 fi else mv "$temp_all" "$all_file" fi if [ -z "$NO_SIGN" ]; then echo "Signing ${all_file} to produce ${all_file}.asc" if [ ! -e "$all_file".asc ]; then ${GPG} --detach-sign \ --digest-algo sha256 \ --local-user "$gpg_key_name" \ --armor \ --output "$all_file".asc "$all_file" else echo "Signature already there" fi else echo "Not signing ${all_file} as \$NO_SIGN is not empty" fi )