iOS code signing is notoriously complex, especially when running builds on headless, remote CI/CD systems where you cannot open Xcode's graphic manager. Let's break down the exact components, security requirements, and automated scripting to sign your production applications securely.
The Components of iOS App Signing
To sign an iOS application, you need three elements:
- P12 Certificate: A certificate containing your private key and Apple Developer credentials. This is downloaded from the Apple Developer Portal and must be exported as a
.p12file. - Provisioning Profile: A file associating your App ID, development/test devices, and signing certificate.
- App Store Connect Key: An API key used to download matching provisioning profiles on the fly from Apple's servers.
[Apple Developer Portal] -> Certificate + Provisioning Profile
|
v
[CI Environment] -> Import Certificate to Keychain -> Sign App (.ipa)
Automated Keyring Management in Headless Runners
When building on a remote Mac runner, you must create a temporary keychain, unlock it, and import your .p12 certificate. You must also configure the keychain search list so Xcode can locate the credentials. Here is the bash sequence:
#!/bin/bash
set -e
KEYCHAIN_PATH="$HOME/Library/Keychains/build.keychain-db"
KEYCHAIN_PASSWORD="temp-pass-signing"
CERT_FILE="./certs/dist.p12"
P12_PASSWORD="vault-cert-password"
# 1. Create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
# 2. Set keychain settings (prevent dynamic dialogs)
security set-keychain-settings -lut 7200 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
# 3. Import Apple Worldwide Developer Relations Certificate (WWDR)
curl -o apple-wwdr.cer https://developer.apple.com/certificationauthority/AppleWWDRCA.cer
security import apple-wwdr.cer -k "$KEYCHAIN_PATH" -T /usr/bin/codesign
# 4. Import certificate
security import "$CERT_FILE" -k "$KEYCHAIN_PATH" -P "$P12_PASSWORD" -T /usr/bin/codesign -T /usr/bin/productsign
# 5. Set partition list to avoid dialog prompts
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
# 6. Add keychain to lookup path
security list-keychains -d user -s "$KEYCHAIN_PATH"
Verifying Code Signing
After building your IPA, you should always verify that it has been signed correctly. Run the following check in your post-build pipeline script:
# Verify the code signature on the generated app bundle
codesign --verify --verbose /path/to/App.app
# Display detailed signature details and entitlements
codesign -d --entitlements - /path/to/App.app
If the signature is invalid or missing, it will exit with a non-zero status code, letting you abort the deployment process immediately.
Security Best Practices
- Short-lived Keys: Always use ephemeral build sandboxes where the imported keychain is completely wiped immediately when the compile job finishes.
- Secrets Encryption: Encrypt certificates with AES-256 before uploading to your environment variable vault. For tips on managing fastlane certificates, check Securing Fastlane in Ephemeral Sandboxes.
References & Citations
- Apple Developer Code Signing: Apple Developer Support
- Fastlane Match Documentation: Fastlane Match
- Headless Xcode Compilation: LLVM Developers Guide