
macOS Catalinaから、macOSアプリはAppleによる公証(Notarization)が必須化されます。Notarizationのプロセスではアプリのバイナリを一度Appleに送って、マルウェアなどのチェックを受けます。雰囲気は以下のページがわかりやすいです。
さて、自分もTransporterPadというmacOSアプリを作っています。CIには無料でmacOSアプリのビルドができるVisual Studio App Centerを使っていますが、公式な対応はしばらくかかりそうな様子でした。
そこで、カスタムビルドスクリプトを使って対応させることにしました。
事前に必要なこと
Notarizeするには、アプリが以下の条件を満たしている必要があります。
- アプリ内のすべての実行ファイルが署名されていること。
- Developer ID の証明書で署名されていること
- セキュアタイムスタンプが署名に含まれていること
- Hardened Runtimeを使用する設定になっていること
- macOS 10.9以上のSDKでビルドされていること
- get-task-allowのEntitlementが含まれていないこと
特にHardened Runtimeについてですが、これはXcodeでここをONにするだけで対応が可能です。

App Centerのカスタムビルドスクリプト
App CenterではPost-clone、Pre-build、Post-buildの3種類のカスタムビルドスクリプトを使うことができます。
今回はビルド後に動作したいので、appcenter-post-build.shを実行権限をつけた上でリポジトリに含めました。
このスクリプトに export とか find とかを書いて何度か試したところ、成果物としては$APPCENTER_OUTPUT_DIRECTORY の場所に (プロジェクト名)_distribution.zip と (プロジェクト名)_download.zip ができており、恐らく前者が AppStore 送信用、後者がApp Centerのコンソールからダウンロードしたときに降ってくるファイルです。(プロジェクト名)_download.zipの方には関連するplistなども入っているため、Notarizeに投げるものとしては$APPCENTER_OUTPUT_DIRECTORY/(プロジェクト名)_distribution.zipが適切でしょう。
NotarizationをPost-buildで実行する
では、appcenter-post-build.shにNotarizationを実行するスクリプトを記述します。コマンドなどは以下を参考に。
BUNDLE_IDENTIFIER=net.iseteki.TransporterPad DISTRIBUTION_FILE=$APPCENTER_OUTPUT_DIRECTORY/TransporterPad_distribution.zip xcrun altool --notarize-app --primary-bundle-id $BUNDLE_IDENTIFIER --username $AC_USERNAME --password $AC_PASSWORD --file $DISTRIBUTION_FILE
$AC_USERNAMEと$AC_PASSWORDはApp Store ConnectにサインインするApple IDの認証情報です。アカウントで2ファクタ認証が有効になっている場合、パスワードはApp用パスワードをMy Apple IDで発行して使います。
Apple IDの情報はApp Centerのビルド設定の環境変数から与えます。

こんな感じになれば成功。

Error: To use this application, you must first sign in to iTunes Connect and sign the relevant contracts.というエラーでうまくいかない場合は、App Store Connectの契約情報のところを確認してみてください。すべてグリーンになっていないと失敗するみたいです。
結果を確認する
ローカルマシンでxcrun altool --notarization-history 0を実行すると、結果を確認できます。
$ xcrun altool --notarization-history 0 -u $AC_USERNAME -p $AC_PASSWORD Notarization History - page 0 Date RequestUUID Status Status Code Status Message ------------------------- ------------------------------------ ------- ----------- --------------- 2019-07-23 14:11:09 +0000 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx invalid 2 Package Invalid Next page value: 1563891069000
ちょ…invalid?????
詳細を確認してみましょう。xcrun altool --notarization-info $RequestUUIDで、詳細を確認できます。
$ xcrun altool --notarization-info fd2790db-dbc4-4e1c-a38c-bca4ffff9284 -u $AC_USERNAME -p $AC_PASSWORD
2019-07-23 23:53:01.397 altool[56209:21692262] No errors getting notarization info.
RequestUUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Date: 2019-07-23 14:11:09 +0000
Status: invalid
LogFileURL: https://osxapps-ssl.itunes.apple.com/...
Status Code: 2
Status Message: Package Invalid
LogFileURLの内容を見てみましょう。
$ curl "https://osxapps-ssl.itunes.apple.com/..." | jq '.'
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1016 100 1016 0 0 951 0 0:00:01 0:00:01 --:--:-- 975
{
"logFormatVersion": 1,
"jobId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"status": "Invalid",
"statusSummary": "Archive contains critical validation errors",
"statusCode": 4000,
"archiveFilename": "TransporterPad_distribution.zip",
"uploadDate": "2019-07-23T14:11:09Z",
"sha256": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"ticketContents": null,
"issues": [
{
"severity": "error",
"code": null,
"path": "TransporterPad_distribution.zip/TransporterPad.app/Contents/Resources/android-platform-tools/adb",
"message": "The executable does not have the hardened runtime enabled.",
"docUrl": null,
"architecture": "x86_64"
},
{
"severity": "error",
"code": null,
"path": "TransporterPad_distribution.zip/TransporterPad.app/Contents/Resources/ios-deploy/ios-deploy",
"message": "The executable does not have the hardened runtime enabled.",
"docUrl": null,
"architecture": "x86_64"
}
]
}
なんということでしょう。アプリ本体はHardened Runtimeを使用する設定になっているものの、TranspoterPadはサブコマンドとして埋め込まれているadbとios-deployがHardened Runtimeに対応していません!このアプリをNotarizeするには、まずadbとios-deployをHardened Runtimeにしてビルドしなくてはならないということです。
このあとは
もし、これがうまくいった場合、.appにAppleの公証済み情報を埋め込むstapleという処理を施す追加処理をすることでオフライン環境下でもアプリを起動させることができます。(stapleをしない場合、実行時にインターネット経由で取得することになる)
今のApp Centerでこれをするには、一度zipを展開してstaple後、再圧縮となると思われます。上記の問題が解決できたら、また書こうと思います。