まずは結論から
- プロビジョニングプロファイル内のentitlementsとXcode内のentitlementsファイルのkey名が一致することは必ず確認すること
- Xcodeのビルドログをちゃんと読むこと
何が起きたのか
NetworkExtensionを利用したmacOS向けアプリを作成しようとしたときに下記の謎の事象が起きました。
- リリースビルドしたアプリを実行すると、
EXC_CRASH (Code Signature Invalid)
というエラーが発生し、落ちる - 署名自体は問題なく、Notarizationの取得も成功しているにも関わらず、エラーが発生し、落ちる
- 一方でデバッグビルドだと問題なく起動ができる
別の投稿に詳細は書いてありますが、Xcode11で適切に設定を行えば、署名とNotarizationの取得を行うことができます。
尚、アプリに署名が付いているかとNotarizationが取得できているかは下記のコマンドで確認することができます。
署名の確認
$ codesign -dv xxx.app
Notarizationの確認
$ spctl -a -vv xxx.app
原因
Xcode上のビルドログをよく読むと、そこにヒントが書かれていました。
尚、???はプロビジョニングプロファイル名が、XXXはアプリのターゲット名が入ります。
warning: Provisioning profile "???" for "XXX" contains entitlements that aren't in the entitlements file: com.apple.developer.system-extension.install. To use these entitlements, add them to your entitlements file. Otherwise, remove unused entitlements from your provisioning profile. (in target 'XXX')
つまりはプロビジョニングプロファイル内のentitlementsにXcode内にあるentitlementsファイルに無い値が入っていますよとのワーニングが出ています。
そんなばかな、Apple Developerの正規の手順で作ったプロビジョニングプロファイルとXcodeのCapabilityから作ったentitlementsファイルだぞ!おかしいはずはない!と思って確認したところ見事に一致していませんでした。
プロビジョニングプロファイル内のentitlementsは下記のコマンドで確認ができます。
確認コマンド
$ security cms -D -i プロビジョニングプロファイル
確認したところ、プロビジョニングプロファイル内では NetworkExtensionのentitle名として packet-tunnel-provider-systemextension という値を確認できましたが、Xcode内のentitlementsファイルでは packet-tunnel-provider という値になっていました。
Xcode内のentitlementsファイル内の値をpacket-tunnel-provider-systemextensionに修正してビルドしたところ、起動時に落ちることはなくなりました。
また、デバッグビルドで落ちなかった理由は、デバッグビルド用のプロビジョニングプロファイルではentitle名がpacket-tunnel-providerになっているためでした。
最後に
公式のドキュメントを改めて確認すると次の説明がありました。
packet-tunnel-provider-systemextension
The APIs you use to tunnel IP packets to a remote network using any custom tunneling protocol, when signed with a Developer ID profile.
確かに、今回のアプリはMac App Store外で配布するため、Developer IDの証明書で署名を行なっていました。
更によく読むとMac App Store外でアプリ配布するときにはプロジェクト内のentitlements.plistの値をプロビジョニングプロファイルインポート後にこうしんするようにとの注意点も書かれてありました。
また、Appleのフォーラムにも次の注意事項が書かれていました。
#8 — On the Mac, can Developer ID apps host NetworkExtension providers?
Yes, but there are some caveats:
This only works on macOS 10.15 or later.
Your NetworkExtension provider must be packaged as a system extension, not an app extension.
You must use the xxx-systemextension values for the NetworkExtension entitlement >(com.apple.developer.networking.networkextension).
See my 14 Jan 2020 post on this thread for more details.
NetworkExtensionを使ったアプリをビルドする際にはご注意ください。