#!/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 jq -e ' any( .[]; ( .relation_extensions["delegate_permission/common.handle_all_urls"] .dynamic_app_link_components ) as $rules | ($rules | type == "array" and length > 0) and any($rules[]; .["/"] == "/safety" and (.exclude // false) == false) and any($rules[]; .["/"] == "/requests/*" and (.exclude // false) == false) and any($rules[]; .["/"] == "*" and .exclude == true) and all($rules[]; ((.["/"] // "") | startswith("/auth")) | not) ) ' <<<"$payload" >/dev/null fi echo "Android package, signing certificate, and App Links configuration agree."