2023年11月1日以降、Appleの公証サービスを利用して公証を受ける場合、notarytoolまたはXcode 14以降の使用が必要になることが発表されました。
Appleからの発表内容については、以下のページをご覧ください。
この記事の執筆時(2023年8月20日)から11月1日まで2か月余りとなりますが、先行して移行することをお勧めします。
この記事では少し掘り下げて、公証について解説します。
そもそも公証とは何か?
公証は公式のApp Store以外で配布されているプログラムに対しても、安全性をある程度担保するための仕組みです。
公証はApp Store外で配布されているプログラムについて、マルウェアなど不正なプログラムではないことをチェックします。ユーザーは任意のWebサイトからダウンロードしたプログラムであっても、起動しようとすると、公証されているプログラムかどうかがチェックされ、公証されていないプログラムや改ざんされたプログラムと判断されると、OSは起動を中止し、ユーザーに危険なプログラムである可能性があることを通知します。
ユーザーは信頼されたところから入手した、安全なプログラムであると確証があれば、自己責任の下に起動することも可能です。
公証済みのプログラムで、かつ、改ざんも行われていないと判断されると、OSはプログラムの起動処理を続けます。ダウンロード直後の初回起動時のみは、どこからダウンロードされたプログラムかということと、公証済みでマルウェアではないということを表示するメッセージが表示されます。
公証などの仕組みがないい頃は、公式のApp Store以外で配布されているプログラムは、配布元を信頼するしかないという状況でした。公証という仕組みが導入されたことで、公式のApp Store以外で配布されているプログラムであっても、ある程度、信頼性を担保できるようになりました。
プログラムの中には不正行為を行うものがあります。不正行為が発覚すると、Appleは該当のプログラムの公証、開発元のデベロッパーID、および使用されたコードサイニング証明書を無効化します。その結果、ダウンロード済みのプログラムも含めて起動できなくなります。
kext (Kernel Extensions) は公証が必須
アプリについては公証されていない場合でも自己責任で起動できます。しかし、kext(Kernel Extension)については公証されていないものは読み込まれません。ただし、開発目的でSystem Integrity Protectionが無効化されている場合は、kext対応のDeveloper ID Application証明書で署名されているものは読み込むことができます。
公証の流れ
公証を受けるには、開発したプログラムを配布前にApple社に登録する必要があります。次のような流れで行います。
- 通常通り開発する。
- Developer ID Application証明書でコードサイニングする。
- インストーラが必要な場合はインストーラを作成し、Developer ID Installer証明書でインストーラをコードサイニングする。
- 配布用ファイルをdmg、または、zipで1ファイル化する。
- Apple Notary Serviceに4のアーカイブを登録する。
- Apple Notary Serviceで公証に成功したら、Stapleする。
- Stapleしたアーカイブを配布する。
notarytoolとXcodeはどちらを使用するのか?
notarytoolはコマンドラインユーティリティです。CI/CDから実行するときや独自のビルドスクリプトがあるとき、インストーラが必要なときなどはnotarytoolが必要です。アプリケーションパッケージをZipで固めて単純に配布するだけであれば、XcodeのGUI操作で公証を受けられます。
公証時のチェック内容
Apple Notary Serviceにアップロードすると、次のような項目がチェックされます。
- 適切なコードサイニングが行われているか。
- 悪意のあるコンテンツが含まれていないか。
公証は人力による審査ではありません。自動的にアップロードされたファイルをスキャンし、zipやpkg, dmgはアーカイブを展開して、中のファイルを再帰的にスキャンします。問題が検出されない場合、チケットが発行されます。
アップロード可能なファイル
Apple Notary Serviceが対応しているファイル形式は以下の通りです。
- アプリケーションパッケージ(埋め込みフレームワークなどのバイナリも再帰的にスキャンされる)
- Kext(Kernel Extension)
- ディスクイメージ(dmg, UDIF形式)
- フラットインストーラパッケージ(pkg, mpkgは非対応)
アプリケーションパッケージやKextなどのバンドルは、zipやディスクイメージ化してアップロードする。インストーラ形式で配布する場合は、インストーラをzipやdmgでアーカイブ化する。簡易インストールなど、複数のpkgを内包するインストーラは最も外側、つまり、実際に配布するインストーラをアーカイブ化してアップロードします。
適切なコードサイニング
「適切なコードサイニング」という表現を使用したのは、GateKeeperのコードサイニングにはいくつかのバージョンが存在し、それぞれ異なる要件が必要とされるためです。基本的には新しいバージョンに対応する必要があります。この記事執筆時点では、次の要件を満たす必要があります。
- バンドル内の実行ファイルは全てApp Sandbox、もしくは、Hardened Runtimeに対応している。
- バンドル内の実行ファイル、フレームワーク、ライブラリなどのオブジェクトファイルは全て適切なコードサイニングが行われている。
- アプリケーションパッケージはDeveloper ID Application証明書で署名されている。
- インストーラパッケージはDeveloper ID Installer証明書で署名されている。
App SandboxやHardened Runtimeに対応するには、以下の要件を満たす必要があります。
- コードサイニングにセキュアタイムスタンプを含む。
com.apple.security.get-task-allow
をtrue
にしたEntitlementを含まない。- macOS 10.9 SDK以降のSDKとリンクする。
オフライン用の情報埋め込み
macOSではプログラムを実行するときにGateKeeperによって公証の確認が行われます。GateKeeperはインターネットに接続されている場合は、Appleのサーバーに問い合わせを行い、プログラムが公証済みであるかを確認します。
オフライン時は問い合わせができないため、プログラム内の情報が利用されます。公証に成功し、Stapleという作業を行うと、公証成功時に発行されたチケットがプログラム内に埋め込まれます。オフラインの場合はこの情報を使って公証済みかどうかを判断します。
まとめ
公証はmacOSのセキュリティ対策の一部です。安全な環境を提供できる仕組みなので、適切に対応しましょう。