Skip to content

Commit 30daf76

Browse files
committed
guix: Add guix-attest script
1 parent 0c9597c commit 30daf76

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed

contrib/guix/guix-attest

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
#!/usr/bin/env bash
2+
export LC_ALL=C
3+
set -e -o pipefail
4+
5+
# Source the common prelude, which:
6+
# 1. Checks if we're at the top directory of the Bitcoin Core repository
7+
# 2. Defines a few common functions and variables
8+
#
9+
# shellcheck source=libexec/prelude.bash
10+
source "$(dirname "${BASH_SOURCE[0]}")/libexec/prelude.bash"
11+
12+
13+
###################
14+
## Sanity Checks ##
15+
###################
16+
17+
################
18+
# Required non-builtin commands should be invokable
19+
################
20+
21+
check_tools cat env basename mkdir xargs find gpg
22+
23+
################
24+
# Required env vars should be non-empty
25+
################
26+
27+
cmd_usage() {
28+
cat <<EOF
29+
Synopsis:
30+
31+
env GUIX_SIGS_REPO=<path/to/guix.sigs> \\
32+
SIGNER=GPG_KEY_NAME[=SIGNER_NAME] \\
33+
./contrib/guix/guix-attest
34+
35+
Example w/o overriding signing name:
36+
37+
env GUIX_SIGS_REPO=/home/achow101/guix.sigs \\
38+
SIGNER=achow101 \\
39+
./contrib/guix/guix-attest
40+
41+
Example overriding signing name:
42+
43+
env GUIX_SIGS_REPO=/home/dongcarl/guix.sigs \\
44+
SIGNER=0x96AB007F1A7ED999=dongcarl \\
45+
./contrib/guix/guix-attest
46+
47+
EOF
48+
}
49+
50+
if [ -z "$GUIX_SIGS_REPO" ] || [ -z "$SIGNER" ]; then
51+
cmd_usage
52+
exit 1
53+
fi
54+
55+
################
56+
# GUIX_SIGS_REPO should exist as a directory
57+
################
58+
59+
if [ ! -d "$GUIX_SIGS_REPO" ]; then
60+
cat << EOF
61+
ERR: The specified GUIX_SIGS_REPO is not an existent directory:
62+
63+
'$GUIX_SIGS_REPO'
64+
65+
Hint: Please clone the guix.sigs repository and point to it with the
66+
GUIX_SIGS_REPO environment variable.
67+
68+
EOF
69+
cmd_usage
70+
exit 1
71+
fi
72+
73+
################
74+
# The key specified in SIGNER should be usable
75+
################
76+
77+
IFS='=' read -r gpg_key_name signer_name <<< "$SIGNER"
78+
if [ -z "${signer_name}" ]; then
79+
signer_name="$gpg_key_name"
80+
fi
81+
82+
if ! gpg --dry-run --list-secret-keys "${gpg_key_name}" >/dev/null 2>&1; then
83+
echo "ERR: GPG can't seem to find any key named '${gpg_key_name}'"
84+
exit 1
85+
fi
86+
87+
################
88+
# We should be able to find at least one output
89+
################
90+
91+
echo "Looking for build output directories in ${OUTDIR_BASE}"
92+
93+
shopt -s nullglob
94+
OUTDIRS=( "${OUTDIR_BASE}"/* ) # This expands to an array of directories...
95+
shopt -u nullglob
96+
97+
if (( ${#OUTDIRS[@]} )); then
98+
echo "Found build output directories:"
99+
for outdir in "${OUTDIRS[@]}"; do
100+
echo " '$outdir'"
101+
done
102+
echo
103+
else
104+
echo "ERR: Could not find any build output directories in ${OUTDIR_BASE}"
105+
exit 1
106+
fi
107+
108+
109+
##############
110+
## Attest ##
111+
##############
112+
113+
# Usage: out_name $outdir
114+
#
115+
# HOST: The output directory being attested
116+
#
117+
out_name() {
118+
basename "$1"
119+
}
120+
121+
# Usage: out_sig_dir $outdir
122+
#
123+
# outdir: The output directory being attested
124+
#
125+
out_sig_dir() {
126+
echo "$GUIX_SIGS_REPO/$VERSION/$(out_name "$1")/$signer_name"
127+
}
128+
129+
# Accumulate a list of signature directories that already exist...
130+
outdirs_already_attested_to=()
131+
132+
echo "Attesting to build outputs for version: '${VERSION}'"
133+
echo ""
134+
135+
# MAIN LOGIC: Loop through each output for VERSION and attest to output in
136+
# GUIX_SIGS_REPO as SIGNER, if attestation does not exist
137+
for outdir in "${OUTDIRS[@]}"; do
138+
outname="$(out_name "$outdir")"
139+
outsigdir="$(out_sig_dir "$outdir")"
140+
if [ -e "$outsigdir" ]; then
141+
echo "${outname}: SKIPPING: Signature directory already exists in the specified guix.sigs repository"
142+
outdirs_already_attested_to+=("$outdir")
143+
else
144+
mkdir -p "$outsigdir"
145+
echo "${outname}: Hashing build outputs to produce SHA256SUMS"
146+
(
147+
cd "$outdir"
148+
find . -type f -printf '%P\0' | env LC_ALL=C sort -z | xargs -r0 sha256sum >> "$outsigdir"/SHA256SUMS
149+
)
150+
echo "${outname}: Signing SHA256SUMS to produce SHA256SUMS.asc"
151+
gpg --detach-sign --local-user "$gpg_key_name" --output "$outsigdir"/SHA256SUMS.asc "$outsigdir"/SHA256SUMS
152+
echo ""
153+
fi
154+
done
155+
156+
if (( ${#outdirs_already_attested_to[@]} )); then
157+
# ...so that we can print them out nicely in a warning message
158+
cat << EOF
159+
160+
WARN: Signature directories from '$signer_name' already exist in the specified
161+
guix.sigs repository for the following output directories and were
162+
skipped:
163+
164+
EOF
165+
for outdir in "${outdirs_already_attested_to[@]}"; do
166+
echo " '${outdir}'"
167+
echo " Corresponds to: '$(out_sig_dir "$outdir")'"
168+
echo ""
169+
done
170+
fi

0 commit comments

Comments
 (0)