新しいApple公証用ツールのnotarytoolを使ってみた

# 公証について

AppleのOS(iOS, macOS...)用のソフトウェアを作成する時、ソフトウェアの署名（sign)の他に公証(notarize)をする必要がある。
署名は開発者が開発元の情報をソフトウェアに付与して、開発元を明らかにする。
公証はAppleがソフトウェアを自動でスキャンし、セキュリティチェックを実施して悪質なソフトウェアでないか確認する。
セキュリティチェックで問題が検出されなかった場合ソフトウェアは公証される。
https://developer.apple.com/jp/developer-id/

また、AppStore上にアプリを公開するにも公証が必要で、macOSのドライバでも必須となる。
AppStore以外で配布するMacOS用のアプリについても、公証されていない場合ユーザーが起動した時警告が表示される。
そのため、基本的にどんな形態のアプリでも公証をするのが望ましい。

# 新しい公証ツール

WWDC2021で公証用の新しいツール`notarytool`が発表された。
https://developer.apple.com/videos/play/wwdc2021/10261/

アプリバンドル(.app形式)はXCodeのアーカイブ機能を使って公証を行えるが、コマンドラインツールや単一実行ファイルは直接XCodeでは公証できない。
これまではXCodeのツールとして配布されていた`altool`というコマンドラインツールを使って単一実行ファイルを公証していた。

新しい公証ツールはXcode13のツールとして配布されている。
XCode13がリリースされたのでこの新しいツールを使ったみた。

`altool`と使い方に大きな違いはないが利便性が大幅に上がっている。
使いやすくなっ理由が4つあると感じた。

* ファイルのアップロード速度の改善
* --waitオプションで公証完了まで待てる
* store-credential サブコマンドで公証認証情報が保存できる
* log サブコマンドで公証失敗理由がすぐに確認できる

それぞれの点について解説していこう。

# ファイルのアップロード速度の改善

使ってみて一番最初に気づいたのはファイルのアップロードの速さだ。
`notarytool`は`altool`と同様、公証する実行ファイルを圧縮して、appleIDとApp用パスワードを指定して使用する。

```
# zip化
> zip testTool.zip testTool
# 公証
> xcrun notarytool submit testTool.zip --apple-id "デベロッパーID" --password xxxx-xxxx-xxxx-xxxx --team-ID チームID
Submission ID received
  id: aaaaaaaa-bbbb-cccc-dddd-eeeeeeffffff
Successfully uploaded file
  id: aaaaaaaa-bbbb-cccc-dddd-eeeeeeffffff
  path: testTool.zip
```

パスワードはAppleのApp用パスワードを入力する。App用パスワードの作成方法はAppleのサポートページを参照[リンク](https://support.apple.com/ja-jp/HT204397)。

ステータスメッセージに`Successfully uploaded file`と書いてあるとおり、このコマンドはAppleのサーバーに圧縮ファイルをアップロードしている。
そのアップロードスピードが`altool`とは全く違った。
`time`コマンドで計ってみたところ、altoolは35~40秒弱アップロードにかかったのに対して`notartytool`では3~5秒でアップロードが完了していた。
WWDCのプレゼンのタイトルが"Faster and simpler notarization for Mac apps"だったので速くはなっているだろうと思っていたが、これほど違うとは驚いた。

# --wait オプション

`altool`では公証のためにAppleのサーバーに圧縮ファイルを送信したあと、`--notarization-info`サブコマンドを使って公証ステータスを定期的に取得して公証が完了したか確認する必要があった。
`notarytool`ではその必要がなく、送信する時点で以下の用に`--wait`オプションを追加することで公証の完了が確認できる。

```
> xcrun notarytool submit testTool.zip --apple-id "デベロッパーID" --password xxxx-xxxx-xxxx-xxxx --team-ID チームID --wait
Submission ID received
  id: aaaaaaaa-bbbb-cccc-dddd-eeeeeeffffff
Successfully uploaded file
  id: aaaaaaaa-bbbb-cccc-dddd-eeeeeeffffff
  path: testTool.zip

# 数秒後
Waiting for processing to complete.
Current status: In Progress....

# 数十秒後
Processing complete
  id: aaaaaaaa-bbbb-cccc-dddd-eeeeeeffffff
  status: Accepted

```
このように`submit`コマンドが圧縮ファイルを送信したらすぐに終了せず、Appleのサーバーでスキャンが完了するまで待ち、スキャンの結果を返してくれる。
これは本当にありがたい。

## store-credential　サブコマンド

`store-credential`サブコマンドを使って公証に必要な認証情報（AppleID、パスワード、チームID)を纏めてキーチェインに保存できる。
`altool`でもパスワードをキーチェインに登録できるが、キーチェインアプリから行う必要があり、少し手間だったのと、同時にAppleIDとチームIDを保存できなかった。

このように`notarytool`から直接キーチェインに認証情報を保存できる。

```
> xcrun notarytool store-credentials                    
This process stores your credentials securely in the Keychain. You reference these credentials later using a profile name.

Profile name:
(任意のプロファイル名を入力）

We recommend using App Store Connect API keys for authentication. If you'd like to authenticate with an Apple ID and app-specific password instead, leave this unspecified.

Path to App Store Connect API private key:
(AppleIDを使用するので何も記入せずにEnter)

Switching prompts to app-specific password credentials.
Developer Apple ID:
(AppleIDを入力)

Password for (AppleID): 
(App用パスワードを入力)

Developer Team ID:
(チームIDを入力)

Validating your credentials...
Success. Credentials validated.
Credentials saved to Keychain.
To use them, specify `--keychain-profile "任意のプロファイル名"`
```

また、AppleIDとチームIDをコマンドラインで指定できる。

```
> xcrun notarytool store-credentials --apple-id "AppleID" --team-id チームID
```

登録が完了すると以下のコマンドで公証を行えるようになる。

```
> xcrun notarytool submit testTool.zip --keychain-profile "設定したプロファイル名" --wait
```

コマンドが簡略化できて公証を通すのが少し楽になった。

## log サブコマンド

Appleの公証はちゃんと準備していれば通らないことが滅多にない。
しかし、時々なにかしらのステップを忘れてしまい失敗することがある。
その場合、`altool`では`--notarization-info`オプションで公証チケットのUUIDを使って理由を確認していた。
`--notarization-info`は公証チケットのステータスとチェックが終了している場合、詳細を確認できるurlを返してくれる。
そのurlにアクセスして初めて失敗した理由が確認できた。
`notarytool`の`log`サブコマンドを使えばUUIDを指定するだけで失敗理由を返してくる。

```
> xcrun notarytool log 公証チケットのUUID --keychain-profile "プロファイル名" 
```
コマンドを実行して、返ってきたurlをコピーしてAppleのログサーバーにアクセスしてエラー理由を確認するという2段階の工程を１つのコマンドでできるようになったのですごく楽になった。


# おわりに
`notarytool`は公証にかかる時間の短縮だけでも使うメリットがあるが、それに加えて色々と使いやすくなったのでXCode13へのアップグレード後には使ってみるのをおすすめする。