-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #207 from puppetlabs/iterate-on-download-verify
Improve download task gpg verification
- Loading branch information
Showing
2 changed files
with
91 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,90 @@ | ||
#!/bin/bash | ||
|
||
urisize=$(curl -s -L --head "$PT_source" | sed -n 's/Content-Length: \([0-9]\+\)/\1/p' | tr -d '\012\015') | ||
filesize=$(stat -c%s "$PT_path" 2>/dev/null) | ||
# Exit code indicating "a service is unavailable", from | ||
# /usr/include/sysexits.h. The verify-file function will return this code if | ||
# prerequisites for verification are unavailable. | ||
EX_UNAVAILABLE=69 | ||
|
||
# Assume that if the file exists and is the same size, we don't have to | ||
# re-download. | ||
if [[ ! -z "$urisize" && ! -z "$filesize" && "$filesize" -eq "$urisize" ]]; then | ||
exit 0 | ||
else | ||
printf '%s\n' "Downloading: ${PT_source}" >&2 | ||
curl -f -L -o "$PT_path" "$PT_source" | ||
fi | ||
verify-file() { | ||
local sig="$1" | ||
local doc="$2" | ||
|
||
if [[ "$PT_check_download" == "false" ]]; then | ||
exit 0 | ||
fi | ||
# The GPG binary is required to be present in order to perform file download | ||
# verification. If it is not present, return EX_UNAVAILABLE. | ||
if ! command -v gpg >/dev/null; then | ||
echo "gpg binary not found; required in path for checking download" | ||
return "$EX_UNAVAILABLE" | ||
fi | ||
|
||
if ! which -s gpg ; then | ||
echo "gpg binary required in path for checking download. Skipping check." | ||
exit 0 | ||
fi | ||
# The verification key must be present, or it must be possible to download it | ||
# from the keyserver to perform file verification. If it is not present, | ||
# return EX_UNAVAILABLE. | ||
if ! { gpg --list-keys "$PT_key_id" || gpg --keyserver "$PT_key_server" --recv-key "$PT_key_id"; } then | ||
echo "Unable to download verification key ${PT_key_id}" | ||
return "$EX_UNAVAILABLE" | ||
fi | ||
|
||
echo "Importing Puppet gpg public key" | ||
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --recv-key 4528B6CD9E61EF26 | ||
if gpg --list-key --fingerprint 4528B6CD9E61EF26 | grep -q -E "D681 +1ED3 +ADEE +B844 +1AF5 +AA8F +4528 +B6CD +9E61 +EF26" ; then | ||
echo "gpg public key imported successfully." | ||
else | ||
echo "Could not import gpg public key - wrong fingerprint." | ||
exit 1 | ||
fi | ||
# Perform the verification and return success or failure. | ||
if gpg --verify "$sig" "$doc"; then | ||
echo "Signature verification succeeded" | ||
return 0 | ||
else | ||
echo "Signature verification failed" | ||
return 1 | ||
fi | ||
} | ||
|
||
download() { | ||
printf '%s\n' "Downloading: ${1}" | ||
curl -s -f -L -o "$2" "$1" | ||
} | ||
|
||
download-size-verify() { | ||
local source="$1" | ||
local path="$2" | ||
|
||
urisize=$(curl -s -L --head "$source" | sed -rn 's/Content-Length: ([0-9]+)/\1/p' | tr -d '\012\015') | ||
filesize=$(stat -c%s "$path" 2>/dev/null || stat -f%z "$path" 2>/dev/null) | ||
|
||
echo "Filesize: ${filesize}" | ||
echo "Content-Length header: ${urisize}" | ||
|
||
# Assume that if the file exists and is the same size, we don't have to | ||
# re-download. | ||
if [[ ! -z "$urisize" && ! -z "$filesize" && "$filesize" -eq "$urisize" ]]; then | ||
echo "File size matches HTTP Content-Length header. Using file as-is." | ||
exit 0 | ||
else | ||
download "$source" "$path" | ||
fi | ||
} | ||
|
||
download-signature-verify() { | ||
local source="$1" | ||
local path="$2" | ||
|
||
if ! download "${source}.asc" "${path}.asc" ; then | ||
echo "Unable to download ${source}.asc. Skipping verification." | ||
download-size-verify "$source" "$path" | ||
return "$?" | ||
fi | ||
|
||
sigpath=${PT_path}.asc | ||
sigsource=${PT_source}.asc | ||
echo "Verifying ${path}..." | ||
verify_output=$(verify-file "${path}.asc" "$path"); | ||
verify_exit="$?" | ||
if [[ "$verify_exit" -eq "$EX_UNAVAILABLE" ]]; then | ||
echo "Verification unavailable. ${verify_output}. Skipping verification." | ||
download-size-verify "$source" "$path" | ||
elif [[ "$verify_exit" -eq "1" ]]; then | ||
echo "$verify_output" | ||
download "$source" "$path" | ||
echo "Verifying ${path}..." | ||
verify-file "${path}.asc" "$path" | ||
fi | ||
} | ||
|
||
echo "Downloading tarball signature from ${sigsource}..." | ||
curl -f -L -o "${sigpath}" "${sigsource}" | ||
echo "Downloaded tarball signature to ${sigpath}." | ||
echo "Checking tarball signature at ${sigpath}..." | ||
if gpg --verify "${sigpath}" "${PT_path}" ; then | ||
echo "Signature verification succeeded." | ||
if [[ "$PT_verify_download" == "true" ]]; then | ||
download-signature-verify "$PT_source" "$PT_path" | ||
else | ||
echo "Signature verification failed, please re-run the installation." | ||
exit 1 | ||
download-size-verify "$PT_source" "$PT_path" | ||
fi |