who_need_help/scripts/android-app-links-verify.sh

112 lines
3.1 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
env_file=${1:-"$ROOT/.env"}
artifact_dir=${2:-"$ROOT/android/dist-staging"}
online_mode=${3:-}
if [[ "$env_file" != /* ]]; then
env_file="$ROOT/$env_file"
fi
if [[ "$artifact_dir" != /* ]]; then
artifact_dir="$ROOT/$artifact_dir"
fi
[[ -f "$env_file" ]] || {
echo "Android App Links environment does not exist: $env_file" >&2
exit 1
}
[[ -f "$artifact_dir/package-name.txt" ]] || {
echo "Android package report does not exist: $artifact_dir/package-name.txt" >&2
exit 1
}
[[ -f "$artifact_dir/signing-certificate.txt" ]] || {
echo "Android signing report does not exist: $artifact_dir/signing-certificate.txt" >&2
exit 1
}
read_env_value() {
local key=$1
awk -v key="$key" '
index($0, key "=") == 1 {
print substr($0, length(key) + 2)
found = 1
exit
}
END { if (!found) exit 1 }
' "$env_file"
}
expected_package=$(read_env_value ANDROID_APP_LINKS_PACKAGE_NAME 2>/dev/null || true)
expected_fingerprints=$(
read_env_value ANDROID_APP_LINKS_SHA256_CERT_FINGERPRINTS 2>/dev/null || true
)
base_url=$(read_env_value WNH_BASE_URL 2>/dev/null || true)
observed_package=$(tr -d '\r\n' <"$artifact_dir/package-name.txt")
observed_fingerprint=$(
awk -F': ' '
/certificate SHA-256 digest:/ {
print $NF
found = 1
exit
}
END { if (!found) exit 1 }
' "$artifact_dir/signing-certificate.txt" |
tr '[:lower:]' '[:upper:]'
)
observed_fingerprint=$(
printf '%s' "$observed_fingerprint" |
sed 's/../&:/g; s/:$//'
)
[[ -n "$expected_package" && -n "$expected_fingerprints" ]] || {
echo "Android App Links package and fingerprints are not configured in $env_file." >&2
exit 1
}
[[ "$observed_package" == "$expected_package" ]] || {
echo "The signed APK package does not match ANDROID_APP_LINKS_PACKAGE_NAME." >&2
exit 1
}
fingerprint_found=false
IFS=',' read -r -a fingerprints <<<"$expected_fingerprints"
for fingerprint in "${fingerprints[@]}"; do
compact=${fingerprint//:/}
compact=${compact//[[:space:]]/}
normalized=$(printf '%s' "$compact" | tr '[:lower:]' '[:upper:]' | sed 's/../&:/g; s/:$//')
if [[ "$normalized" == "$observed_fingerprint" ]]; then
fingerprint_found=true
break
fi
done
[[ "$fingerprint_found" == true ]] || {
echo "The signed APK certificate is absent from the configured App Links fingerprints." >&2
exit 1
}
if [[ "$online_mode" == --online ]]; then
[[ "$base_url" == https://* ]] || {
echo "Online Android App Links verification requires an HTTPS WNH_BASE_URL." >&2
exit 1
}
payload=$(curl --fail --silent --show-error \
"$base_url/.well-known/assetlinks.json")
jq -e \
--arg package "$observed_package" \
--arg fingerprint "$observed_fingerprint" \
'
any(
.[];
.target.namespace == "android_app" and
.target.package_name == $package and
(.relation | index("delegate_permission/common.handle_all_urls")) != null and
(.target.sha256_cert_fingerprints | index($fingerprint)) != null
)
' <<<"$payload" >/dev/null
fi
echo "Android package, signing certificate, and App Links configuration agree."