Fix: Isolate installer GPG inspection
This commit is contained in:
@@ -6,10 +6,16 @@
|
||||
|
||||
declare -gA INSTALLER_PROVENANCE=()
|
||||
|
||||
_primary_key_fingerprints() {
|
||||
gpg --batch --with-colons --import-options show-only --import "$1" 2>/dev/null \
|
||||
_primary_key_fingerprints() (
|
||||
local home
|
||||
home="$(mktemp -d)" || exit 1
|
||||
chmod 700 "$home"
|
||||
trap 'rm -rf -- "$home"' EXIT
|
||||
trap 'exit 130' INT
|
||||
trap 'exit 143' TERM
|
||||
GNUPGHOME="$home" gpg --batch --with-colons --import-options show-only --import "$1" 2>/dev/null \
|
||||
| awk -F: '$1 == "pub" { primary = 1; next } primary && $1 == "fpr" { print $10; primary = 0 }'
|
||||
}
|
||||
)
|
||||
|
||||
key_fingerprint_matches() {
|
||||
local file="$1" expected="$2"
|
||||
@@ -27,13 +33,15 @@ _key_has_one_primary() {
|
||||
verify_detached_signature() {
|
||||
local key="$1" signature="$2" content="$3" home
|
||||
_key_has_one_primary "$key" || return 1
|
||||
home="$(mktemp -d)" || return 1
|
||||
(
|
||||
home="$(mktemp -d)" || exit 1
|
||||
chmod 700 "$home"
|
||||
trap 'rm -rf -- "$home"' EXIT
|
||||
trap 'exit 130' INT
|
||||
trap 'exit 143' TERM
|
||||
GNUPGHOME="$home" gpg --batch --quiet --import "$key" >/dev/null 2>&1 \
|
||||
&& GNUPGHOME="$home" gpg --batch --verify "$signature" "$content" >/dev/null 2>&1
|
||||
local status=$?
|
||||
rm -rf -- "$home"
|
||||
return "$status"
|
||||
)
|
||||
}
|
||||
|
||||
download_sha256() {
|
||||
|
||||
@@ -10,6 +10,7 @@ config="$repo_dir/setup/provenance/installers.conf"
|
||||
test_tmp="$(mktemp -d)"
|
||||
host_gnupg="${GNUPGHOME:-$HOME/.gnupg}"
|
||||
host_rpmdb="/usr/lib/sysimage/rpm/rpmdb.sqlite"
|
||||
ambient_gnupg="$test_tmp/fresh-ambient-gnupg"
|
||||
|
||||
cleanup() {
|
||||
rm -rf -- "$test_tmp"
|
||||
@@ -55,6 +56,14 @@ snapshot_gpg_state() {
|
||||
done < <(find "$path" -maxdepth 1 -type f \( -name pubring.kbx -o -name trustdb.gpg \) | sort)
|
||||
}
|
||||
|
||||
export GNUPGHOME="$ambient_gnupg"
|
||||
mkdir -m 700 "$ambient_gnupg"
|
||||
ambient_before="$(snapshot "$ambient_gnupg")"
|
||||
ambient_gpg_files_before="$(snapshot_gpg_state "$ambient_gnupg")"
|
||||
before_gnupg="$(snapshot "$host_gnupg")"
|
||||
before_gpg_files="$(snapshot_gpg_state "$host_gnupg")"
|
||||
before_rpmdb="$(snapshot "$host_rpmdb")"
|
||||
|
||||
# This must be the only production file sourced by the contract.
|
||||
# shellcheck source=../../setup/lib/artifact-provenance
|
||||
source "$repo_dir/setup/lib/artifact-provenance"
|
||||
@@ -70,6 +79,10 @@ base64 --decode "$fixtures/wrong-signer-fixture.rpm.base64" > "$test_tmp/wrong-s
|
||||
|| fail 'tampered artifact does not differ by exactly one byte'
|
||||
|
||||
expect_success key_fingerprint_matches "$fixtures/fixture-key.asc" "$fixture_fingerprint"
|
||||
[[ "$ambient_before" == "$(snapshot "$ambient_gnupg")" ]] \
|
||||
|| fail 'fingerprint inspection created ambient GPG state'
|
||||
[[ "$ambient_gpg_files_before" == "$(snapshot_gpg_state "$ambient_gnupg")" ]] \
|
||||
|| fail 'fingerprint inspection created an ambient GPG keybox or trust database'
|
||||
expect_failure key_fingerprint_matches "$fixtures/fixture-key.asc" '0000000000000000000000000000000000000000'
|
||||
cat "$fixtures/fixture-key.asc" "$fixtures/wrong-signer-key.asc" > "$test_tmp/combined-key.asc"
|
||||
expect_failure key_fingerprint_matches "$test_tmp/combined-key.asc" "$fixture_fingerprint"
|
||||
@@ -78,6 +91,8 @@ expect_success verify_detached_signature \
|
||||
"$fixtures/fixture-key.asc" "$fixtures/SHASUMS256.txt.asc" "$fixtures/SHASUMS256.txt"
|
||||
expect_failure verify_detached_signature \
|
||||
"$fixtures/fixture-key.asc" "$fixtures/SHASUMS256.txt.asc" "$fixtures/tiny-artifact"
|
||||
expect_failure verify_detached_signature \
|
||||
"$fixtures/fixture-key.asc" "$fixtures/SHASUMS256.txt.asc" "$fixtures/tiny-artifact-tampered"
|
||||
cp "$fixtures/SHASUMS256.txt.asc" "$test_tmp/bad-signature.asc"
|
||||
sed -i 's/^=MJqv$/=MJqa/' "$test_tmp/bad-signature.asc"
|
||||
expect_failure verify_detached_signature \
|
||||
@@ -159,9 +174,6 @@ expect_failure download_sha256 'https://fixture.invalid/interrupted' "$tiny_sha2
|
||||
assert_file_bytes "$destination" 'known-good'
|
||||
[[ ! -e "$destination.part" ]] || fail 'interrupted download left a part file'
|
||||
|
||||
before_gnupg="$(snapshot "$host_gnupg")"
|
||||
before_gpg_files="$(snapshot_gpg_state "$host_gnupg")"
|
||||
before_rpmdb="$(snapshot "$host_rpmdb")"
|
||||
expect_success rpm_signature_matches \
|
||||
"$test_tmp/signed-fixture.rpm" "$fixtures/fixture-key.asc" "$fixture_fingerprint"
|
||||
expect_failure rpm_signature_matches \
|
||||
@@ -175,6 +187,9 @@ expect_failure rpm_signature_matches \
|
||||
[[ "$before_gnupg" == "$(snapshot "$host_gnupg")" ]] || fail 'host GPG state changed'
|
||||
[[ "$before_gpg_files" == "$(snapshot_gpg_state "$host_gnupg")" ]] || fail 'host GPG keybox or trust database changed'
|
||||
[[ "$before_rpmdb" == "$(snapshot "$host_rpmdb")" ]] || fail 'host RPM database changed'
|
||||
[[ "$ambient_before" == "$(snapshot "$ambient_gnupg")" ]] || fail 'production helper created ambient GPG state'
|
||||
[[ "$ambient_gpg_files_before" == "$(snapshot_gpg_state "$ambient_gnupg")" ]] \
|
||||
|| fail 'production helper created an ambient GPG keybox or trust database'
|
||||
|
||||
expect_success load_installer_provenance "$config"
|
||||
[[ "${INSTALLER_PROVENANCE[BUN_VERSION]:-}" == '1.4.0' ]] || fail 'valid provenance was not loaded'
|
||||
|
||||
Reference in New Issue
Block a user