This commit improves the `find_mas_provisioning_profile.sh` script by expanding the search for provisioning profiles to include both `.provisionprofile` and `.mobileprovision` files. It also introduces a new function to print SHA-1 values for identities, helping to avoid ambiguity when multiple identities share the same display name. Additionally, the `check_signing_identities.sh` script is updated to provide clearer recommendations for using SHA-1 hashes with codesigning and installer identities, enhancing the overall usability and clarity for developers working with macOS builds.
208 lines
6.2 KiB
Bash
Executable File
208 lines
6.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# macOS signing identity sanity check for:
|
|
# - Developer ID (outside Mac App Store)
|
|
# - Mac App Store (Apple Distribution + 3rd Party Mac Developer Installer)
|
|
|
|
ts() { date +"%H:%M:%S"; }
|
|
|
|
if [[ "$(uname -s)" != "Darwin" ]]; then
|
|
echo "Error: This script is for macOS only." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "==> [$(ts)] Strawberry macOS signing identity check"
|
|
echo "==> [$(ts)] Host: $(sw_vers -productName 2>/dev/null || true) $(sw_vers -productVersion 2>/dev/null || true)"
|
|
echo
|
|
|
|
echo "==> [$(ts)] Keychains searched by 'security' (user)"
|
|
security list-keychains -d user || true
|
|
echo
|
|
|
|
echo "==> [$(ts)] Valid code signing identities (must include private key)"
|
|
codesigning_out="$(security find-identity -p codesigning -v 2>&1 || true)"
|
|
echo "$codesigning_out"
|
|
echo
|
|
|
|
echo "==> [$(ts)] Valid installer/pkg identities (must include private key)"
|
|
basic_out="$(security find-identity -p basic -v 2>&1 || true)"
|
|
echo "$basic_out"
|
|
echo
|
|
|
|
echo "==> [$(ts)] Note"
|
|
cat <<'EOF'
|
|
- Apple uses multiple certificate types. The "basic" identity list can include certificates that are not usable
|
|
for signing a Mac App Store upload package.
|
|
- For App Store Connect uploads via .pkg, you typically need an *Installer* identity (e.g. "3rd Party Mac Developer Installer"
|
|
or "Mac Installer Distribution") and it must have a private key on this Mac.
|
|
EOF
|
|
echo
|
|
|
|
list_cert_labels() {
|
|
local query="$1"
|
|
# Extract "labl" lines like: "labl"<blob>="Apple Distribution: ..."
|
|
security find-certificate -a -c "$query" 2>/dev/null \
|
|
| sed -n 's/.*"labl"<blob>="\(.*\)".*/\1/p' \
|
|
| sort -u
|
|
}
|
|
|
|
check_label_in_identities() {
|
|
local label="$1"
|
|
local out="$2"
|
|
if echo "$out" | grep -Fq "$label"; then
|
|
echo "YES"
|
|
else
|
|
echo "NO"
|
|
fi
|
|
}
|
|
|
|
check_label_in_installer_identities() {
|
|
local label="$1"
|
|
local out="$2"
|
|
# Only treat as installer-capable if the cert label itself is an installer cert.
|
|
case "$label" in
|
|
*Installer*|*installer*) ;;
|
|
*) echo "NO"; return 0 ;;
|
|
esac
|
|
if echo "$out" | grep -Fq "$label"; then
|
|
echo "YES"
|
|
else
|
|
echo "NO"
|
|
fi
|
|
}
|
|
|
|
print_section() {
|
|
local title="$1"
|
|
shift
|
|
local queries=("$@")
|
|
|
|
echo "==> [$(ts)] ${title}"
|
|
local any=0
|
|
|
|
local q
|
|
for q in "${queries[@]}"; do
|
|
local labels
|
|
labels="$(list_cert_labels "$q" || true)"
|
|
if [[ -z "$labels" ]]; then
|
|
continue
|
|
fi
|
|
any=1
|
|
while IFS= read -r label; do
|
|
[[ -z "$label" ]] && continue
|
|
local in_codesign in_basic
|
|
in_codesign="$(check_label_in_identities "$label" "$codesigning_out")"
|
|
in_basic="$(check_label_in_installer_identities "$label" "$basic_out")"
|
|
printf -- "- %s\n" "$label"
|
|
printf -- " - codesigning identity: %s\n" "$in_codesign"
|
|
printf -- " - installer identity: %s\n" "$in_basic"
|
|
if [[ "$in_codesign" == "NO" && "$in_basic" == "NO" ]]; then
|
|
printf -- " - note: certificate exists, but it is NOT a usable identity on this Mac (almost always missing private key)\n"
|
|
fi
|
|
done <<<"$labels"
|
|
done
|
|
|
|
if [[ "$any" -eq 0 ]]; then
|
|
echo "(no matching certificates found)"
|
|
fi
|
|
echo
|
|
}
|
|
|
|
print_section "Expected for Developer ID (outside Mac App Store)" \
|
|
"Developer ID Application" \
|
|
"Developer ID Installer"
|
|
|
|
print_section "Expected for Mac App Store submissions" \
|
|
"Apple Distribution" \
|
|
"Mac App Distribution" \
|
|
"3rd Party Mac Developer Application" \
|
|
"3rd Party Mac Developer Installer" \
|
|
"Mac Installer Distribution"
|
|
|
|
echo "==> [$(ts)] Quick interpretation"
|
|
cat <<'EOF'
|
|
- If a certificate label appears above, but both:
|
|
- codesigning identity: NO
|
|
- installer identity: NO
|
|
then the certificate is present but NOT usable for signing on this Mac.
|
|
The most common cause is: the private key is missing.
|
|
|
|
Fix:
|
|
- Open Keychain Access → login → "My Certificates"
|
|
- Expand the certificate. You must see a private key underneath it.
|
|
- If there is no private key:
|
|
- Recreate the certificate on this Mac via Xcode (Accounts → Manage Certificates), OR
|
|
- Import a .p12 that includes the private key from the machine where it was created.
|
|
EOF
|
|
echo
|
|
|
|
echo "==> [$(ts)] Provisioning profiles (Mac App Store builds require one)"
|
|
prof_dirs=(
|
|
"${HOME}/Library/Developer/Xcode/UserData/Provisioning Profiles"
|
|
"${HOME}/Library/MobileDevice/Provisioning Profiles"
|
|
)
|
|
any_prof=0
|
|
for prof_dir in "${prof_dirs[@]}"; do
|
|
if [[ -d "${prof_dir}" ]]; then
|
|
any_prof=1
|
|
echo " ${prof_dir}"
|
|
ls -la "${prof_dir}" | head -n 20
|
|
echo
|
|
fi
|
|
done
|
|
if [[ "$any_prof" -eq 0 ]]; then
|
|
echo "(no provisioning profile directories found in common locations)"
|
|
fi
|
|
|
|
echo "Tip: to pick the right MAS profile for a bundle id, run:"
|
|
echo " ./build_tools/macos/find_mas_provisioning_profile.sh --bundle-id com.dryark.strawberry"
|
|
\n\necho\n
|
|
echo "==> [$(ts)] Recommended SHA-1 values to use (avoids ambiguity when names are duplicated)"
|
|
cat <<'EOF'
|
|
When you have multiple identities with the same display name, prefer using the SHA-1 hash in scripts:
|
|
|
|
--codesign-identity "<SHA1>"
|
|
--installer-identity "<SHA1>"
|
|
|
|
This prevents codesign/productbuild from picking an unexpected identity.
|
|
EOF
|
|
echo
|
|
|
|
extract_identities() {
|
|
local policy="$1" # codesigning | basic
|
|
# Output: SHA1|LABEL
|
|
security find-identity -p "$policy" -v 2>/dev/null \
|
|
| sed -n 's/^[[:space:]]*[0-9][0-9]*[)] \([0-9A-F]\{40\}\) "\(.*\)"$/\1|\2/p'
|
|
}
|
|
|
|
print_sha_list() {
|
|
local title="$1"
|
|
local policy="$2"
|
|
local label_match="$3"
|
|
|
|
echo "$title"
|
|
local matches
|
|
matches="$(extract_identities "$policy" | grep -F "$label_match" || true)"
|
|
if [[ -z "$matches" ]]; then
|
|
echo " (none found)"
|
|
return 0
|
|
fi
|
|
|
|
local first=1
|
|
while IFS='|' read -r sha label; do
|
|
[[ -z "$sha" || -z "$label" ]] && continue
|
|
if [[ $first -eq 1 ]]; then
|
|
echo " recommended: $sha ($label)"
|
|
first=0
|
|
else
|
|
echo " alternative: $sha ($label)"
|
|
fi
|
|
done <<<"$matches"
|
|
}
|
|
|
|
print_sha_list "Mac App Store (app signing) [use with --codesign-identity]:" "codesigning" "Apple Distribution:"
|
|
print_sha_list "Mac App Store (pkg signing) [use with --installer-identity]:" "basic" "3rd Party Mac Developer Installer:"
|
|
print_sha_list "Developer ID (app signing) [outside App Store]:" "codesigning" "Developer ID Application:"
|
|
print_sha_list "Developer ID (pkg signing) [outside App Store]:" "basic" "Developer ID Installer:"
|
|
|