diff --git a/build_tools/macos/README_MAS.md b/build_tools/macos/README_MAS.md index 3a6aa255b..66a16727c 100644 --- a/build_tools/macos/README_MAS.md +++ b/build_tools/macos/README_MAS.md @@ -89,6 +89,16 @@ If you see errors like: This is almost always a **keychain search list / trust chain** issue. +#### Important: do NOT “Always Trust” your Apple Distribution / Installer certs + +Setting your leaf signing certificates (e.g. **Apple Distribution** / **3rd Party Mac Developer Installer**) to **Always Trust** can make things worse by overriding the normal trust chain and causing codesign to fail chain building. + +If you changed trust settings: + +- In **Keychain Access → login → My Certificates** + - open the cert → **Trust** + - set **“When using this certificate” = “Use System Defaults”** + Fix (safe, common): ensure the System keychains are included in the user search list: ```bash @@ -98,6 +108,36 @@ security list-keychains -d user -s "$HOME/Library/Keychains/login.keychain-db" Then re-run the build/sign script. +#### Install the correct Apple intermediate certificates (WWDR) + +If the System keychains are already in the search list and you still get chain errors, you’re likely missing an Apple intermediate (commonly **WWDR**). + +Download the current Apple WWDR intermediate certificate(s) from Apple’s official Certificate Authority page: + +- `https://www.apple.com/certificateauthority/` + +Then import into the **System** keychain (recommended): + +- Keychain Access → **System** keychain → File → **Import Items…** → select the downloaded `.cer` + +Or via CLI (requires admin): + +```bash +sudo security add-certificates -k /Library/Keychains/System.keychain "/path/to/WWDR.cer" +``` + +Verify it’s visible: + +```bash +security find-certificate -a -c "Apple Worldwide Developer Relations" /Library/Keychains/System.keychain | head -n 10 +``` + +If needed, you can also verify the chain for your distribution cert: + +```bash +security verify-cert -c "Apple Distribution: Dry Ark LLC (7628766FL2)" 2>&1 | head -n 80 +``` + ```bash security find-identity -p codesigning -v security find-identity -p basic -v @@ -172,6 +212,52 @@ Outputs: --- +## Troubleshooting — `productbuild` fails with CSSM `-60008` (authorization) + +If you see something like: + +- `SignData failed ... CSSM Exception: -60008 Unable to obtain authorization for this operation` + +That means the **Installer** certificate is present, but macOS is not allowing `productbuild` to use the **private key** without additional authorization. + +### Fix option A (recommended): set key partition list (CLI) + +This is the standard “allow Apple tools to sign without GUI prompts” fix: + +```bash +security unlock-keychain "$HOME/Library/Keychains/login.keychain-db" +security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "" "$HOME/Library/Keychains/login.keychain-db" +``` + +Note: if your password contains characters like `!` or `$` and you paste it into a command in `zsh`, +the shell can modify it (history/variable expansion) and `security ... -k` may claim it’s “incorrect”. +Use **single quotes** (or the env var path shown below) to avoid this, e.g.: + +```bash +security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k 'p@ssw0rd!$' "$HOME/Library/Keychains/login.keychain-db" +``` + +Then rerun: + +```bash +./build_tools/macos/build_mas_pkg.sh --run ... +``` + +This repo’s script also supports: + +- `--keychain-password ` (or env var `STRAWBERRY_KEYCHAIN_PASSWORD`) + +### Fix option B: Keychain Access UI (one-time) + +1. Open **Keychain Access** +2. Select **login** keychain → **My Certificates** +3. Find your installer cert (e.g. `3rd Party Mac Developer Installer: ...`) and **expand it** +4. Select the **private key** under it +5. **Get Info → Access Control** + - Add `/usr/bin/productbuild` (and optionally `/usr/bin/pkgbuild`) to the allowed apps + +--- + ## Step 7 — Upload + submit for review - Upload the `.pkg` using Apple’s **Transporter** app (App Store Connect). diff --git a/build_tools/macos/build_mas_pkg.sh b/build_tools/macos/build_mas_pkg.sh index 47657ab81..1bc9e44db 100755 --- a/build_tools/macos/build_mas_pkg.sh +++ b/build_tools/macos/build_mas_pkg.sh @@ -1,12 +1,46 @@ #!/usr/bin/env bash set -euo pipefail +# Guard: this script must be executed with bash (not sourced into zsh, not run via sh). +if [[ -z "${BASH_VERSION:-}" ]]; then + echo "Error: this script must be run with bash (it uses bash arrays)." >&2 + echo "Run:" >&2 + echo " bash ./build_tools/macos/build_mas_pkg.sh --run ..." >&2 + exit 2 +fi + ts() { date +"%H:%M:%S"; } lower() { echo "$1" | tr '[:upper:]' '[:lower:]'; } script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" repo_root="$(cd -- "${script_dir}/../.." && pwd)" +prepare_login_keychain_for_signing() { + # Some setups require explicitly granting Apple tooling access to the private key(s) + # (otherwise productbuild/codesign can fail with authorization errors like: + # CSSM Exception: -60008 Unable to obtain authorization for this operation + # or "User interaction is not allowed"). + # + # This function is optional and only runs if a keychain password is provided. + local keychain_path="$HOME/Library/Keychains/login.keychain-db" + local pw="${1:-}" + + if [[ -z "$pw" ]]; then + echo "==> [$(ts)] Note: no keychain password provided; skipping keychain access-control preparation." + echo " If productbuild later fails with -60008 authorization errors, fix it with either:" + echo " - Keychain Access → login → My Certificates → select the *private key* under the Installer cert → Get Info → Access Control → allow productbuild" + echo " - OR (CLI): security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k \"$keychain_path\"" + return 0 + fi + + echo "==> [$(ts)] Preparing login keychain for signing (unlock + key partition list)" + # Unlock so Security/Authorization can use keys without prompting. + security unlock-keychain -p "$pw" "$keychain_path" >/dev/null 2>&1 || true + # Allow Apple tools (codesign/productbuild) to access the private key without GUI prompts. + # This is the standard fix used for non-interactive signing. + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$pw" "$keychain_path" >/dev/null 2>&1 || true +} + ensure_keychain_search_list() { # codesign builds the cert chain using the user keychain search list. # If the list is missing the System keychain, you can get: @@ -27,6 +61,22 @@ ensure_keychain_search_list() { security list-keychains -d user -s "$login_kc" "$system_kc" "$roots_kc" >/dev/null 2>&1 || true } +diagnose_chain_failure() { + echo "==> [$(ts)] Codesign failed. Common causes on macOS:" + echo " - System keychains not in the user keychain search list" + echo " - Missing/invalid WWDR intermediate certificate" + echo " - Keychain/key access issues" + echo + echo "==> [$(ts)] Keychain search list:" + security list-keychains -d user || true + echo + echo "==> [$(ts)] Checking for Apple WWDR intermediate in System keychain:" + security find-certificate -a -c "Apple Worldwide Developer Relations" /Library/Keychains/System.keychain 2>/dev/null | head -n 5 || true + echo + echo "==> [$(ts)] If WWDR is missing, install the current Apple WWDR intermediate certificate (via Xcode or Apple Developer portal)." + echo "==> [$(ts)] Then re-run this script." +} + preflight_identity() { local what="$1" @@ -67,8 +117,17 @@ Optional: --entitlements Codesign entitlements (default: dist/macos/entitlements.mas.plist) --bundle-id Override CFBundleIdentifier (default: com.dryark.strawberry) --pkg-out Output .pkg path (default: /strawberry-mas.pkg) + --keychain-password OPTIONAL: unlock/login keychain + set key partition list for Apple tools + (alternative: set env var STRAWBERRY_KEYCHAIN_PASSWORD) Examples: + # Tip: if your keychain password contains characters like ! or $, prefer the env var or single quotes. + STRAWBERRY_KEYCHAIN_PASSWORD='your-login-keychain-password' \ + ./build_tools/macos/build_mas_pkg.sh --run --release --clean \ + --codesign-identity "Apple Distribution: Your Name (TEAMID)" \ + --installer-identity "3rd Party Mac Developer Installer: Your Name (TEAMID)" \ + --provisionprofile "$HOME/Library/MobileDevice/Provisioning Profiles/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.provisionprofile" + ./build_tools/macos/build_mas_pkg.sh --run --release --clean \ --codesign-identity "Apple Distribution: Your Name (TEAMID)" \ --installer-identity "3rd Party Mac Developer Installer: Your Name (TEAMID)" \ @@ -95,6 +154,7 @@ provisionprofile="" entitlements="" bundle_id="com.dryark.strawberry" pkg_out="" +keychain_password="${STRAWBERRY_KEYCHAIN_PASSWORD:-}" while [[ $# -gt 0 ]]; do case "$1" in @@ -109,6 +169,7 @@ while [[ $# -gt 0 ]]; do --entitlements) entitlements="${2:-}"; shift 2 ;; --bundle-id) bundle_id="${2:-}"; shift 2 ;; --pkg-out) pkg_out="${2:-}"; shift 2 ;; + --keychain-password) keychain_password="${2:-}"; shift 2 ;; -h|--help) usage; exit 0 ;; *) echo "Unknown arg: $1" >&2; usage; exit 2 ;; esac @@ -182,6 +243,7 @@ echo "==> [$(ts)] Embedding provisioning profile" cp -f "$provisionprofile" "${app_path}/Contents/embedded.provisionprofile" ensure_keychain_search_list +prepare_login_keychain_for_signing "$keychain_password" preflight_identity "codesign" "codesigning" "$codesign_identity" preflight_identity "installer" "basic" "$installer_identity" @@ -231,10 +293,26 @@ codesign --verify --deep --strict --verbose=2 "$app_path" echo "==> [$(ts)] Building signed .pkg for App Store upload" rm -f "$pkg_out" >/dev/null 2>&1 || true -productbuild \ - --component "$app_path" /Applications \ - --sign "$installer_identity" \ - "$pkg_out" +if ! productbuild \ + --component "$app_path" /Applications \ + --sign "$installer_identity" \ + "$pkg_out"; then + echo "Error: productbuild failed while signing the .pkg." >&2 + echo "Common cause: keychain/private-key authorization (e.g. CSSM -60008)." >&2 + echo >&2 + echo "Fix options:" >&2 + echo "1) Keychain Access UI:" >&2 + echo " - Keychain Access → login → My Certificates" >&2 + echo " - Find: $installer_identity" >&2 + echo " - Expand it and select the *private key* under it" >&2 + echo " - Get Info → Access Control → allow /usr/bin/productbuild (optionally also allow /usr/bin/pkgbuild)" >&2 + echo "2) CLI (recommended for repeatable builds):" >&2 + echo " security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k \"$HOME/Library/Keychains/login.keychain-db\"" >&2 + echo >&2 + echo "Tip: you can also rerun this script with:" >&2 + echo " --keychain-password " >&2 + exit 1 +fi echo "==> [$(ts)] Verifying pkg signature" pkgutil --check-signature "$pkg_out" || true