mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-03 17:26:57 +01:00
scripts: extract functions
As a preparation to make the script easier to understand, we extract some of the sub tasks into functions.
This commit is contained in:
parent
23d7065655
commit
4c8bf9c28d
1 changed files with 109 additions and 108 deletions
|
@ -9,6 +9,7 @@ MANIFEST_SELECTOR=". | select(.name | test(\"manifest-v.*(\\\\.txt)$\")) | .name
|
|||
SIGNATURE_SELECTOR=". | select(.name | test(\"manifest-.*(\\\\.sig)$\")) | .name"
|
||||
HEADER_JSON="Accept: application/json"
|
||||
HEADER_GH_JSON="Accept: application/vnd.github.v3+json"
|
||||
MIN_REQUIRED_SIGNATURES=5
|
||||
|
||||
# All keys that can sign lnd releases. The key must be downloadable/importable
|
||||
# from the URL given after the space.
|
||||
|
@ -22,6 +23,8 @@ KEYS+=("7E81EF6B9989A9CC93884803118759E83439A9B1 https://keybase.io/eugene_/pgp_
|
|||
KEYS+=("7AB3D7F5911708842796513415BAADA29DA20D26 https://keybase.io/halseth/pgp_keys.asc")
|
||||
KEYS+=("E97A1AB6C77A1D2B72F50A6F90E00CCB1C74C611 https://keybase.io/arshbot/pgp_keys.asc")
|
||||
|
||||
TEMP_DIR=$(mktemp -d /tmp/lnd-sig-verification-XXXXXX)
|
||||
|
||||
function check_command() {
|
||||
echo -n "Checking if $1 is installed... "
|
||||
if ! command -v "$1"; then
|
||||
|
@ -30,6 +33,107 @@ function check_command() {
|
|||
fi
|
||||
}
|
||||
|
||||
function import_keys() {
|
||||
for key in "${KEYS[@]}"; do
|
||||
KEY_ID=$(echo $key | cut -d' ' -f1)
|
||||
IMPORT_URL=$(echo $key | cut -d' ' -f2)
|
||||
echo "Downloading and importing key $KEY_ID from $IMPORT_URL"
|
||||
curl -L -s $IMPORT_URL | gpg --import
|
||||
|
||||
# Make sure we actually imported the correct key.
|
||||
if ! gpg --list-key "$KEY_ID"; then
|
||||
echo "ERROR: Imported key from $IMPORT_URL doesn't match ID $KEY_ID."
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function verify_signatures() {
|
||||
# Download the JSON of the release itself. That'll contain the release ID we
|
||||
# need for the next call.
|
||||
RELEASE_JSON=$(curl -L -s -H "$HEADER_JSON" "$RELEASE_URL/$LND_VERSION")
|
||||
|
||||
TAG_NAME=$(echo $RELEASE_JSON | jq -r '.tag_name')
|
||||
RELEASE_ID=$(echo $RELEASE_JSON | jq -r '.id')
|
||||
echo "Release $TAG_NAME found with ID $RELEASE_ID"
|
||||
|
||||
# Now download the asset list and filter by the manifest and the signatures.
|
||||
ASSETS=$(curl -L -s -H "$HEADER_GH_JSON" "$API_URL/$RELEASE_ID" | jq -c '.assets[]')
|
||||
MANIFEST=$(echo $ASSETS | jq -r "$MANIFEST_SELECTOR")
|
||||
SIGNATURES=$(echo $ASSETS | jq -r "$SIGNATURE_SELECTOR")
|
||||
|
||||
# Download the main "manifest-*.txt" and all "manifest-*.sig" files containing
|
||||
# the detached signatures.
|
||||
echo "Downloading $MANIFEST"
|
||||
curl -L -s -o "$TEMP_DIR/$MANIFEST" "$RELEASE_URL/download/$LND_VERSION/$MANIFEST"
|
||||
|
||||
for signature in $SIGNATURES; do
|
||||
echo "Downloading $signature"
|
||||
curl -L -s -o "$TEMP_DIR/$signature" "$RELEASE_URL/download/$LND_VERSION/$signature"
|
||||
done
|
||||
|
||||
echo ""
|
||||
|
||||
# Before we even look at the content of the manifest, we first want to make
|
||||
# sure the signatures actually sign that exact manifest.
|
||||
NUM_CHECKS=0
|
||||
for signature in $SIGNATURES; do
|
||||
echo "Verifying $signature"
|
||||
if gpg --verify "$TEMP_DIR/$signature" "$TEMP_DIR/$MANIFEST" 2>&1 | grep -q "Good signature"; then
|
||||
echo "Signature for $signature appears valid: "
|
||||
gpg --verify "$TEMP_DIR/$signature" "$TEMP_DIR/$MANIFEST" 2>&1 | grep "using"
|
||||
elif gpg --verify "$TEMP_DIR/$signature" 2>&1 | grep -q "No public key"; then
|
||||
echo "Unable to verify signature $signature, no key available, skipping"
|
||||
continue
|
||||
else
|
||||
echo "ERROR: Did not get valid signature for $MANIFEST in $signature!"
|
||||
echo " The developer signature $signature disagrees on the expected"
|
||||
echo " release binaries in $MANIFEST. The release may have been faulty or"
|
||||
echo " was backdoored."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Verified $signature against $MANIFEST"
|
||||
((NUM_CHECKS=NUM_CHECKS+1))
|
||||
done
|
||||
|
||||
# We want at least five signatures (out of seven public keys) that sign the
|
||||
# hashes of the binaries we have installed. If we arrive here without exiting,
|
||||
# it means no signature manifests were uploaded (yet) with the correct naming
|
||||
# pattern.
|
||||
if [[ $NUM_CHECKS -lt $MIN_REQUIRED_SIGNATURES ]]; then
|
||||
echo "ERROR: Not enough valid signatures found!"
|
||||
echo " Valid signatures found: $NUM_CHECKS"
|
||||
echo " Valid signatures required: $MIN_REQUIRED_SIGNATURES"
|
||||
echo
|
||||
echo " Make sure the release $LND_VERSION contains the required "
|
||||
echo " number of signatures on the manifest, or wait until more "
|
||||
echo " signatures have been added to the release."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function check_hash() {
|
||||
# If we're inside the docker image, there should be a shasums.txt file in the
|
||||
# root directory. If that's the case, we first want to make sure we still have
|
||||
# the same hash as we did when building the image.
|
||||
if [[ -f /shasums.txt ]]; then
|
||||
if ! grep -q "$1" /shasums.txt; then
|
||||
echo "ERROR: Hash $1 for $2 not found in /shasums.txt: "
|
||||
cat /shasums.txt
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! grep -q "^$1" "$TEMP_DIR/$MANIFEST"; then
|
||||
echo "ERROR: Hash $1 for $2 not found in $MANIFEST: "
|
||||
cat "$TEMP_DIR/$MANIFEST"
|
||||
echo " The expected release binaries have been verified with the developer "
|
||||
echo " signatures. Your binary's hash does not match the expected release "
|
||||
echo " binary hashes. Make sure you're using an official binary."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# By default we're picking up lnd and lncli from the system $PATH.
|
||||
LND_BIN=$(which lnd)
|
||||
LNCLI_BIN=$(which lncli)
|
||||
|
@ -104,121 +208,18 @@ if [[ ${#LNCLI_SUM} -ne 64 ]]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# If we're inside the docker image, there should be a shasums.txt file in the
|
||||
# root directory. If that's the case, we first want to make sure we still have
|
||||
# the same hash as we did when building the image.
|
||||
if [[ -f /shasums.txt ]]; then
|
||||
if ! grep -q "$LND_SUM" /shasums.txt; then
|
||||
echo "ERROR: Hash $LND_SUM for lnd not found in /shasums.txt: "
|
||||
cat /shasums.txt
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -q "$LNCLI_SUM" /shasums.txt; then
|
||||
echo "ERROR: Hash $LNCLI_SUM for lnd not found in /shasums.txt: "
|
||||
cat /shasums.txt
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Import all the signing keys.
|
||||
for key in "${KEYS[@]}"; do
|
||||
KEY_ID=$(echo $key | cut -d' ' -f1)
|
||||
IMPORT_URL=$(echo $key | cut -d' ' -f2)
|
||||
echo "Downloading and importing key $KEY_ID from $IMPORT_URL"
|
||||
curl -L -s $IMPORT_URL | gpg --import
|
||||
|
||||
# Make sure we actually imported the correct key.
|
||||
if ! gpg --list-key "$KEY_ID"; then
|
||||
echo "ERROR: Imported key from $IMPORT_URL doesn't match ID $KEY_ID."
|
||||
fi
|
||||
done
|
||||
import_keys
|
||||
|
||||
echo ""
|
||||
|
||||
# Download the JSON of the release itself. That'll contain the release ID we need for the next call.
|
||||
RELEASE_JSON=$(curl -L -s -H "$HEADER_JSON" "$RELEASE_URL/$LND_VERSION")
|
||||
|
||||
TAG_NAME=$(echo $RELEASE_JSON | jq -r '.tag_name')
|
||||
RELEASE_ID=$(echo $RELEASE_JSON | jq -r '.id')
|
||||
echo "Release $TAG_NAME found with ID $RELEASE_ID"
|
||||
|
||||
# Now download the asset list and filter by the manifest and the signatures.
|
||||
ASSETS=$(curl -L -s -H "$HEADER_GH_JSON" "$API_URL/$RELEASE_ID" | jq -c '.assets[]')
|
||||
MANIFEST=$(echo $ASSETS | jq -r "$MANIFEST_SELECTOR")
|
||||
SIGNATURES=$(echo $ASSETS | jq -r "$SIGNATURE_SELECTOR")
|
||||
|
||||
# Download the main "manifest-*.txt" and all "manifest-*.sig" files containing
|
||||
# the detached signatures.
|
||||
TEMP_DIR=$(mktemp -d /tmp/lnd-sig-verification-XXXXXX)
|
||||
echo "Downloading $MANIFEST"
|
||||
curl -L -s -o "$TEMP_DIR/$MANIFEST" "$RELEASE_URL/download/$LND_VERSION/$MANIFEST"
|
||||
|
||||
for signature in $SIGNATURES; do
|
||||
echo "Downloading $signature"
|
||||
curl -L -s -o "$TEMP_DIR/$signature" "$RELEASE_URL/download/$LND_VERSION/$signature"
|
||||
done
|
||||
|
||||
echo ""
|
||||
cd $TEMP_DIR || exit 1
|
||||
|
||||
# Before we even look at the content of the manifest, we first want to make sure
|
||||
# the signatures actually sign that exact manifest.
|
||||
NUM_CHECKS=0
|
||||
for signature in $SIGNATURES; do
|
||||
echo "Verifying $signature"
|
||||
if gpg --verify "$signature" "$MANIFEST" 2>&1 | grep -q "Good signature"; then
|
||||
echo "Signature for $signature appears valid: "
|
||||
gpg --verify "$signature" "$MANIFEST" 2>&1 | grep "using"
|
||||
elif gpg --verify "$signature" 2>&1 | grep -q "No public key"; then
|
||||
echo "Unable to verify signature $signature, no key available, skipping"
|
||||
continue
|
||||
else
|
||||
echo "ERROR: Did not get valid signature for $MANIFEST in $signature!"
|
||||
echo " The developer signature $signature disagrees on the expected"
|
||||
echo " release binaries in $MANIFEST. The release may have been faulty or"
|
||||
echo " was backdoored."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Verified $signature against $MANIFEST"
|
||||
((NUM_CHECKS=NUM_CHECKS+1))
|
||||
done
|
||||
|
||||
# We want at least five signatures (out of seven public keys) that sign the
|
||||
# hashes of the binaries we have installed. If we arrive here without exiting,
|
||||
# it means no signature manifests were uploaded (yet) with the correct naming
|
||||
# pattern.
|
||||
MIN_REQUIRED_SIGNATURES=5
|
||||
if [[ $NUM_CHECKS -lt $MIN_REQUIRED_SIGNATURES ]]; then
|
||||
echo "ERROR: Not enough valid signatures found!"
|
||||
echo " Valid signatures found: $NUM_CHECKS"
|
||||
echo " Valid signatures required: $MIN_REQUIRED_SIGNATURES"
|
||||
echo
|
||||
echo " Make sure the release $LND_VERSION contains the required "
|
||||
echo " number of signatures on the manifest, or wait until more "
|
||||
echo " signatures have been added to the release."
|
||||
exit 1
|
||||
fi
|
||||
# Verify and count the signatures.
|
||||
verify_signatures
|
||||
|
||||
# Then make sure that the hash of the installed binaries can be found in the
|
||||
# manifest that we now have verified the signatures for.
|
||||
if ! grep -q "^$LND_SUM" "$MANIFEST"; then
|
||||
echo "ERROR: Hash $LND_SUM for lnd not found in $MANIFEST: "
|
||||
cat "$MANIFEST"
|
||||
echo " The expected release binaries have been verified with the developer "
|
||||
echo " signatures. Your binary's hash does not match the expected release "
|
||||
echo " binary hashes. Make sure you're using an official binary."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep -q "^$LNCLI_SUM" "$MANIFEST"; then
|
||||
echo "ERROR: Hash $LNCLI_SUM for lncli not found in $MANIFEST: "
|
||||
cat "$MANIFEST"
|
||||
echo " The expected release binaries have been verified with the developer "
|
||||
echo " signatures. Your binary's hash does not match the expected release "
|
||||
echo " binary hashes. Make sure you're using an official binary."
|
||||
exit 1
|
||||
fi
|
||||
check_hash "$LND_SUM" "lnd"
|
||||
check_hash "$LNCLI_SUM" "lncli"
|
||||
|
||||
echo ""
|
||||
echo "SUCCESS! Verified lnd and lncli against $MANIFEST signed by $NUM_CHECKS developers."
|
||||
|
|
Loading…
Add table
Reference in a new issue