Xcode13で新しくシンプルになったmacOSアプリの公証(Notarization)を行う

Apple における公証(Notarization)とは、何かということについては割愛します。App Store を通さずにアプリに公証を行って配布したい場合、必要になってくる手段です。

## Xcode13から公証が簡単に

私は今まで公証をしたことがなかったので、どう簡単になったかは分かりませんが、前よりもシンプルに行えるツールが提供されたようです。

***Apple、App Store外で公開するMacアプリのマルウェアチェックを行う公証サービスをより速くシンプルに行える「notarytool」コマンドを提供。***
<https://applech2.com/archives/20210611-apple-provide-notarytool-command.html>

とはいえ、けっこうつまずくことが多かったので、ここにシェアしたいと思います。

## xcrun notarytool を使うには

```notarytool```を使うには、大前提として Apple Developer Program に入っている Apple アカウントによるキーチェーンアクセスが必要です。

ヘルプを見てみましょう。

```sh
% xcrun notarytool --help
OVERVIEW: Manage submissions to the Apple notary service

USAGE: notarytool <subcommand>

OPTIONS:
  --version               Show the version.
  -h, --help              Show help information.

SUBCOMMANDS:
  store-credentials       Save Notary service credentials to the Keychain.
                          Leave credential options not specified for
                          interactive prompts.
  submit                  Submit an archive to the Notary service
  info                    Get status information for a submission
  wait                    Wait for completion of a previous submission
  history                 Get a list of previous submissions for your team
  log                     Retrieve notarization log for a single completed
                          submission
```
　
```store-credentials```を使ってキーチェインアクセスをするようだ、ということは分かりました。

さっそくアクセスしてみましょう。以下の ```"m@hibara.org"```は、Apple ID で、```"XXXXXXXXXX"```はチームID、キーチェーンアクセスでいうところの「部署」記号です。

```sh
% xcrun notarytool store-credentials --apple-id "m@hibara.org" --team-id "XXXXXXXXXX"

This process stores your credentials securely in the Keychain. You reference these credentials later using a profile name.

Profile name:

```

いきなり、```Profile name``` は何？と聞かれます。これは、

Apple ID - Appleアカウントの管理
<https://appleid.apple.com/>

にアクセスすることで作成することができます。

「App用パスワード」から、Apple Developer Program に入っている Apple ID でアクセスします。

![signin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30945/c158206f-0450-db77-eee2-1fd92750e971.png)

表示されたアカウントの、「セキュリティ」欄にある「パスワードを生成...」をクリックします。

![App用パスワード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30945/d643dc21-3f24-b5b7-8d4c-5bb1b6f7b9ab.png)

プロファイル名の入力を促されますので、あとでターミナルから入力するとき、判別できる適当な名前を入力します。ここでは、仮に「notaryprofile」とします。

![プロファイル名.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30945/5797c625-8ea4-b904-da49-07546489daf3.png)

「作成」ボタンを押すと、いまサインイン中の Apple IDアカウントのパスワードを聞かれますので、入力します。

![AppleIDアカウントのパスワード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30945/145e1e74-ae0d-cbd1-1d00-c13bb4e43d4c.png)

すると、「App用パスワード」が表示されますので、これをメモしておきます。

![App用パスワード表示.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30945/68483345-cd20-3a6d-ee90-3d2496c4c45d.png)

ここでは、「zkf-edpz-kioz-mvnf」が、パスワードになります。

## ターミナルへ戻ってキーチェーンアクセスに保存します

再び、以下のコマンドをターミナルから入力します。```Profile name```を聞かれるので、先ほど Apple ID アカウントで作った「App用パスワード」名を入力します。

ここの例では、「notaryprofile」を入力します。

```sh
% xcrun notarytool store-credentials --apple-id "m@hibara.org" --team-id "XXXXXXXXXX"

This process stores your credentials securely in the Keychain. You reference these credentials later using a profile name.

Profile name:
notaryprofile
```

すると、「App用パスワード」名を入力したときのパスワードを求められます。

```sh
App-specific password for m@hibara.org: 

```

ここの例では、「zkf-edpz-kioz-mvnf」を後から入力します。

```sh
Validating your credentials...
Success. Credentials validated.
Credentials saved to Keychain.
To use them, specify `--keychain-profile "notaryprofile"`
```

と表示され、ローカルのキーチェーンアクセスに保存されます。

## 準備が整ったので公証を行ってみる

公証を行うには、Apple へ「*.app」をアップロードしてチェックを受けなければなりませんが、そのままでは、アップロードは行えずエラーになります。

```sh
Error: AttacheCase.app must be a zip archive (.zip), flat installer package (.pkg), or UDIF disk image (.dmg)
```

アップロードできるファイル形式は、「.zip」「.pkg」「.dmg」に限ります。

ここの例では、「.zip」へ圧縮を行ってからアップロードを行いましょう。

```sh
% /usr/bin/ditto -c -k --keepParent "AttacheCase.app" "AttacheCase.zip"          
```

Zip圧縮を行ったら、いよいよそのアーカイブの公証を行います。

```sh
% xcrun notarytool submit /Users/hibara/Desktop/AttacheCase.zip --keychain-profile "notaryprofile" --wait
```

アップロードされ、チェックにしばらく待たされたあと、以下のメッセージが出れば、公証は成功です。

```sh
Conducting pre-submission checks for AttacheCase.zip and initiating connection to the Apple notary service...
Submission ID received
  id: d78c6198-b368-4c9a-9847-9a011ccffbde
Successfully uploaded file15.4 MB of 15.5 MB)    
  id: d78c6198-b368-4c9a-9847-9a011ccffbde
  path: /Users/hibara/Desktop/AttacheCase.zip
Waiting for processing to complete.
Current status: Accepted........
Processing complete
  id: d78c6198-b368-4c9a-9847-9a011ccffbde
  status: Accepted
```

## 公証が失敗する場合

アップロードされ、公証のチェックが行われたあと、失敗することがあります。

```sh
Conducting pre-submission checks for AttacheCase.zip and initiating connection to the Apple notary service...
Submission ID received
  id: c3a641ea-716b-4c56-9efa-63835ef73450
Successfully uploaded file15.4 MB of 15.5 MB)    
  id: c3a641ea-716b-4c56-9efa-63835ef73450
  path: /Users/hibara/Desktop/AttacheCase.zip
Waiting for processing to complete.
Current status: Invalid.............
Processing complete
  id: c3a641ea-716b-4c56-9efa-63835ef73450
  status: Invalid
```

その場合は、同時に出力された UUID（ここでは```c3a641ea-716b-4c56-9efa-63835ef73450```）から、エラーログを参照することができます。コマンドは以下の通りです。

```sh
% xcrun notarytool log c3a641ea-716b-4c56-9efa-63835ef73450 --keychain-profile "notaryprofile" developer_log.json
```

この例では、「developer_log.json」というファイルにログを出力させます。成功すれば、以下のメッセージが表示され、ログファイル（JSONファイル）が生成されると思います。

```sh
Successfully downloaded submission log
  id: c3a641ea-716b-4c56-9efa-63835ef73450
  location: /Users/hibara/Desktop/developer_log.json
```

ログファイルを見れば、公証に失敗した理由は書かれていますが、主に失敗する例は、

* コードサインが「Developer ID Application」で行われていない
* Hardened Runtimeを有効になっていない
* Secure Timestampが付いていない

などでしょうか。順を追って説明します。

### コードサインが「Developer ID Application」で行われていない

意外と「Distribution」などの証明書をコードサインしそうですが、ここでは「Developer ID Application」で行います。

参考：
<https://developer.apple.com/forums/thread/128772>

まだ作成していない場合は、

<https://developer.apple.com/account/resources/certificates/list>

で作成し、ダウンロードしてください。

![DeveloperIDApplication.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30945/9fb4f47c-d84c-0f0c-89d9-c1f987aca972.png)

### Hardened Runtimeを有効になっていない

ランタイムのセキュリティを強化することで、コードを容易に変更されないようにし、アプリケーションを防御します。プロセスで実行できるものを詳細に制御します。ようは公証を行うには、アプリケーション内部のセキュリティ強化が必須ということです。

Xcodeから設定するときは、以下の記事が役立つでしょう。
参考：<https://qiita.com/IKEH/items/5d093644922991079ee2>

また、Visual Studio for Mac で設定を行っている場合は、「プロジェクト オプション」の「コード署名」で「セキュリティが強化されたランタイムを有効化」をチェックします。

![セキュリティ強化ランタイム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30945/cb04b7a6-ece5-69d3-923c-c416f8b1a528.png)

また、「Entitlements.plist」の編集も必要です。

![Entitlements.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30945/5b656b5e-383c-f19c-36da-e2229d3bc245.png)

### Secure Timestampが付いていない

これも、Xcodeのプロジェクト設定で指定できます。「--timestamp」を追加します。
先ほどの記事が同様に参考になります。
参考：<https://qiita.com/IKEH/items/5d093644922991079ee2>

Visual Studio for Mac で設定を行っている場合は、「プロジェクト オプション」の「コード署名」で「追加引数」の欄に、「--timestamp」を追加することで対応できます。

![timestamp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30945/29a85032-133a-7d88-9722-0f834fded4e7.png)

以上です。