Logofpack

macOS: provisioning profiles

Make apps with push, iCloud or other restricted entitlements launch after Developer ID signing, and catch problems before notarization.

macOS:描述文件

让使用推送、iCloud 等受限 entitlements 的应用在 Developer ID 签名后能够启动,并在公证前发现问题。

Most apps need none of this page. You need it if your app's entitlements include restricted keys such as push notifications (com.apple.developer.aps-environment), iCloud, associated domains or keychain access groups.

The problem#

flutter build macos embeds Xcode's development provisioning profile ("Mac Team Provisioning Profile"). Once fpack re-signs the app with Developer ID, that profile no longer authorizes the restricted entitlements, and macOS refuses to launch the app (RBSRequestErrorDomain Code=5, POSIX 163, "Launch failed"), even though signing and notarization succeeded. The fix is a Developer ID provisioning profile for your app id.

1. Create the profile#

You need to be Account Holder or Admin.

  1. developer.apple.com → Certificates, IDs & Profiles → Identifiers: open the app id (for example com.example.app, the PRODUCT_BUNDLE_IDENTIFIER in macos/Runner/Configs/AppInfo.xcconfig) and enable the capabilities your entitlements use (Push Notifications, iCloud, Associated Domains, …). Save.
  2. Profiles → + → under Distribution choose Developer ID → platform macOS → the app id → the Developer ID Application certificate you sign with. It must be that exact certificate: check its SHA-1 with security find-identity -v -p codesigning; a profile made for another certificate is rejected at launch. Name it, Generate, Download.
  3. Put the .provisionprofile in the project (for example macos/MyApp.provisionprofile). It contains no secret, but you can keep it out of git and point to it from CI with FPACK_MACOS_PROVISIONING_PROFILE.
  4. Make the release entitlements match the profile. Developer ID profiles authorize aps-environment production, so macos/Runner/Release.entitlements needs <key>com.apple.developer.aps-environment</key><string>production</string>.

2. Tell fpack#

macos:
  sign:
    identity: "Developer ID Application: Your Name (ABCDE12345)"
    provisioning_profile: macos/MyApp.provisionprofile      # or FPACK_MACOS_PROVISIONING_PROFILE / --provisioning-profile
    provisioning_profiles:                                  # extensions and login items: bundle id → profile
      com.example.app.share: macos/MyAppShare.provisionprofile
  smoke_test: true                                          # or FPACK_MACOS_SMOKE_TEST / --smoke-test

Before signing, fpack copies the profile to Contents/embedded.provisionprofile (and the mapped profiles into app extensions and login items), then signs inside-out: nested code, nested bundles with their own entitlements, then the app. Repeat the profile creation for every extension or login item that has its own bundle id.

3. What fpack checks#

Every profile is checked with security cms -D -i before signing; a problem stops the build with a message instead of producing an app that will not launch. fpack doctor reports the same findings.

  • the profile is a Developer ID profile (ProvisionsAllDevices);
  • it belongs to the same team as the signing certificate and was generated for that certificate;
  • the app id matches (TEAM.bundle.id, wildcards allowed);
  • it has not expired;
  • every restricted entitlement used for signing is authorized with a matching value (for example aps-environment must be production).

Without a profile, restricted entitlements or an embedded development profile stop the build before signing. To sign anyway, set macos.sign.profile_check: false (FPACK_MACOS_PROFILE_CHECK=false); the profile is still embedded.

MessageMeaning and fix
… uses restricted entitlements (…) that a Developer ID app may only use with a provisioning profile no profile configured: set macos.sign.provisioning_profile
the app embeds Xcode's development profile "…" Xcode embedded its development profile: configure a Developer ID profile so fpack replaces it
… is a development/ad hoc profile (N registered devices) you downloaded a Development profile: create a Developer ID one
… is not a Developer ID profile (ProvisionsAllDevices is missing) an App Store profile: create a Developer ID one
… was generated for another Developer ID Application certificate (…), not the signing certificate … the profile lists other certificates than the one fpack signs with (for example after a certificate was recreated); macOS logs Unsatisfied entitlements and refuses to launch: edit the profile, select the signing certificate, download it again
… belongs to team X, but the signing certificate is from team Y profile and certificate are from different teams
… is for app id TEAM.a, not TEAM.b the profile was made for another bundle id
… expired on YYYY-MM-DDgenerate and download the profile again
entitlement … is not authorized by … enable the capability for the app id, regenerate the profile
aps-environment is "development" in the entitlements but the profile allows "production" set production in the release entitlements

4. Smoke test: does the signed app start?#

Enable it with macos.smoke_test: true, FPACK_MACOS_SMOKE_TEST=true or --smoke-test:

fpack build macos dmg --smoke-test

fpack runs open -n on the signed app, waits macos.smoke_test_seconds (default 5, from 1 to 300), checks with pgrep that the app is still running, and quits it with pkill. If it is not running, the build fails with the app was not running … after launch (it crashed or macOS refused to start it) and prints a log show command that shows why (typically amfid or RunningBoard messages such as Unsatisfied entitlements, No matching profile found). It runs before notarization, so a broken app is never uploaded.

Inspect profiles and apps yourself#

security cms -D -i macos/MyApp.provisionprofile                          # the profile's contents
codesign -d --entitlements - --xml MyApp.app                              # entitlements of a built app
security cms -D -i MyApp.app/Contents/embedded.provisionprofile           # the embedded profile

Next#

Back to the macOS tutorial, or troubleshooting.

大多数应用用不到本页。只有当应用的 entitlements 里含有受限键时才需要,例如推送通知(com.apple.developer.aps-environment)、iCloud、关联域名或钥匙串访问组。

问题所在#

flutter build macos 会嵌入 Xcode 的开发描述文件(“Mac Team Provisioning Profile”)。fpack 用 Developer ID 重新签名后,这个描述文件不再授权受限的 entitlements,macOS 会拒绝启动应用(RBSRequestErrorDomain Code=5、POSIX 163、“Launch failed”),尽管签名和公证都成功了。解决办法是为你的应用 ID 创建一个 Developer ID 描述文件。

1. 创建描述文件#

你需要是账号持有者或管理员。

  1. developer.apple.com → Certificates, IDs & Profiles → Identifiers:打开应用 ID(例如 com.example.app,即 macos/Runner/Configs/AppInfo.xcconfig 里的 PRODUCT_BUNDLE_IDENTIFIER),启用你的 entitlements 用到的能力(Push Notifications、iCloud、Associated Domains…),保存。
  2. Profiles → + → 在 Distribution 下选择 Developer ID → 平台 macOS → 选应用 ID → 选你用来签名的 Developer ID Application 证书。必须是那张确切的证书:用 security find-identity -v -p codesigning 查看它的 SHA-1;为别的证书生成的描述文件会在启动时被拒绝。命名、Generate、Download。
  3. 把 .provisionprofile 放进项目(例如 macos/MyApp.provisionprofile)。它不含机密,但你也可以不提交到 git,在 CI 里用 FPACK_MACOS_PROVISIONING_PROFILE 指向它。
  4. 让 release entitlements 与描述文件一致。Developer ID 描述文件授权 aps-environment 为 production,所以 macos/Runner/Release.entitlements 里需要有 <key>com.apple.developer.aps-environment</key><string>production</string>。

2. 告诉 fpack#

macos:
  sign:
    identity: "Developer ID Application: Your Name (ABCDE12345)"
    provisioning_profile: macos/MyApp.provisionprofile      # 或 FPACK_MACOS_PROVISIONING_PROFILE / --provisioning-profile
    provisioning_profiles:                                  # 扩展和登录项:bundle id → 描述文件
      com.example.app.share: macos/MyAppShare.provisionprofile
  smoke_test: true                                          # 或 FPACK_MACOS_SMOKE_TEST / --smoke-test

签名之前,fpack 会把描述文件复制到 Contents/embedded.provisionprofile(并把映射的描述文件复制到 App 扩展和登录项里),然后由内向外签名:内嵌代码、带各自 entitlements 的内嵌 bundle,最后是应用本身。每个有自己 bundle id 的扩展或登录项都要重复创建描述文件。

3. fpack 检查什么#

签名前会用 security cms -D -i 检查每个描述文件;有问题就带着提示停止构建,而不是产出一个无法启动的应用。fpack doctor 会报告同样的结果。

  • 描述文件是 Developer ID 类型(ProvisionsAllDevices);
  • 它与签名证书属于同一个团队,并且是为这张证书生成的;
  • 应用 ID 匹配(TEAM.bundle.id,允许通配符);
  • 没有过期;
  • 签名使用的每个受限 entitlement 都被授权,且值匹配(例如 aps-environment 必须是 production)。

没有描述文件、使用了受限 entitlements 或嵌入了开发描述文件,会在签名前停止构建。想强行签名,设置 macos.sign.profile_check: false(FPACK_MACOS_PROFILE_CHECK=false);描述文件仍会被嵌入。

提示含义与处理
… uses restricted entitlements (…) that a Developer ID app may only use with a provisioning profile 没有配置描述文件:设置 macos.sign.provisioning_profile
the app embeds Xcode's development profile "…" Xcode 嵌入了它的开发描述文件:配置 Developer ID 描述文件,fpack 会替换它
… is a development/ad hoc profile (N registered devices) 你下载的是 Development 描述文件:创建 Developer ID 的
… is not a Developer ID profile (ProvisionsAllDevices is missing) 是 App Store 描述文件:创建 Developer ID 的
… was generated for another Developer ID Application certificate (…), not the signing certificate … 描述文件里的证书不是 fpack 签名用的那张(例如证书被重新创建过);macOS 会记录 Unsatisfied entitlements 并拒绝启动:编辑描述文件,选中签名证书,重新下载
… belongs to team X, but the signing certificate is from team Y 描述文件和证书属于不同团队
… is for app id TEAM.a, not TEAM.b描述文件是为另一个 bundle id 创建的
… expired on YYYY-MM-DD重新生成并下载描述文件
entitlement … is not authorized by …为应用 ID 启用对应能力,重新生成描述文件
aps-environment is "development" in the entitlements but the profile allows "production" 在 release entitlements 里设置 production

4. 冒烟测试:签名后的应用能启动吗?#

用 macos.smoke_test: true、FPACK_MACOS_SMOKE_TEST=true 或 --smoke-test 开启:

fpack build macos dmg --smoke-test

fpack 对签名后的应用运行 open -n,等待 macos.smoke_test_seconds(默认 5,范围 1 到 300),用 pgrep 检查应用是否仍在运行,再用 pkill 退出它。如果没有在运行,构建会失败并提示 the app was not running … after launch (it crashed or macOS refused to start it),同时打印一条能看到原因的 log show 命令(通常是 amfid 或 RunningBoard 的 Unsatisfied entitlements、No matching profile found 之类消息)。它在公证之前运行,所以有问题的应用不会被上传。

自己检查描述文件和应用#

security cms -D -i macos/MyApp.provisionprofile                          # 描述文件的内容
codesign -d --entitlements - --xml MyApp.app                              # 已构建应用的 entitlements
security cms -D -i MyApp.app/Contents/embedded.provisionprofile           # 嵌入的描述文件

下一步#

回到 macOS 教程,或看故障排查。