Xojoで作成したMac用アプリの公証を通す
macOSはセキュリティ強化の取り組みを継続的に強化していますが、macOS 10.15 Catalina以降でついに「アプリのインストール時にアップルのサーバに登録情報を照会しに行き、登録がなければインストールさせない」という処理を「必ず」行うようになったため(それ以前からあるにはありましたが回避方法が用意されていました)、アプリを作って配布する際のハードルがかなり上がりました。Adobeアプリで言うところのプロダクトアクティベートと同種の処理ですが、それをユーザーが作成して配布するアプリにも求めるようになったわけです。私が過去に作って配布していたアプリもこれに引っかかってダウンロードしてもインストールできない状態になっていましたが、アップルのサーバにアプリの情報を申請して登録するための手続き「Notarization/公証」を行い、配布できるようになりましたので以下に覚え書きとしてやり方を書いておきます。
なお、これはXcode以外のビルド環境(Xojo)でビルドしたアプリを公証に対応させるための話なので、ターミナルのCUI操作で手続きをすることが前提になっています。参考にしたページはこちらなど。情報がほぼそのまま使えて大変有り難かったのですが、一部変更しないと処理が通らなかったり、また個人でフリーウェアを配布する程度の目的だと過剰な部分もありましたので、こちらでもメモを残しておこうと思いました。
Developer登録を済ませる
開発したアプリを登録するためには申請者がAppleの登録Developerである必要があるので、まず事前にDeveloperの登録手続きを済ませておきます。二段階認証を済ませた端末から申請してDeveloperの年間登録料(2022年現在12,800円)を支払う必要があります(多分クレジットカードとの紐付け必須)。また、政府発行の身分証明書のコピーの送付が最終段階で必要でした(フォームから画像を送る)。会社としての登録の場合にはそれ以外に「D-U-N-S番号」が必要になるようです。詳しくはこちら。
自分の場合はMacのDeveloper.app内から申請して通しました。それ以前にiPhoneから申請したところずっと審査中で止まってしまっていて、あらためてMacから申請し直したらあっさり通ったような経緯です。止まっていた理由は何も表示されないのでよくわかりません。
「App用パスワード」を作っておく
Xcode以外の環境でビルドしたアプリの登録には「App用パスワード」が必要になるとのことなので事前にこちらにDeveloper登録に使ったApple IDでログインしてApp用パスワードを作っておきます。「+」ボタンをクリックして分類名(任意でよい)を入れ、表示されるパスワードをメモしておきます。
キーチェーンアクセスで証明書(CSR)を発行しておく
Macの「キーチェーンアクセス」アプリを開き、ドロップダウンメニューから「証明書アシスタント」→「認証局に証明書を要求」を選択します。
Apple IDの登録メールアドレス、通称(登録しようとしているアプリの略称など)を入れ、「ディスクに保存」「鍵ペア情報を指定」を選んで「続ける」をクリック。証明書ファイル(以下Apple Developer Programで作る証明書と紛らわしいので「CSRファイル」と呼称する)の保存先を指定し、次の画面で秘密鍵、公開鍵に「2048ビット」、「RSA」の設定を選んで保存を実行します。これで指定した場所にCSRファイルが保存されたはずです。
なお、この作業中何度かアカウントのログインパスワードの入力を求められましたが、これは環境によって変わるかもしれません。
アプリとインストーラーの証明書を発行する
まずアプリ本体の証明書を発行します。Apple Developer Programのサイトにログインし、「アカウント」タブから「証明書、ID、プロファイル」の「証明書(英語)」を選択し、次画面で「Certificates」の横の「+」ボタンを押して証明書の種類を選びます。
Xcode以外で作成したアプリを自分のサイト等から配布したい場合は「Developer ID Application」を選んで「Continue」ボタンを押します。App Store経由での配布の場合はここで選ぶ証明書の種類が変わるようです。
次に「Certificates, Identifiers & Profiles」の画面が出るので、画面下の「Choose File」ボタンをクリックし、さきほど作成して保存したCSRファイルを選択してアップロードします。「Profile Type」はよくわからなかったので「Previous Sub-CA」を選びましたが、特に問題なかったようです。「Continue」を押し、次の画面で「Download」をクリックして証明書をダウンロードします。
同じくインストーラの証明書も必要になるので、「証明書、ID、プロファイル」の「証明書(英語)」から「Developer ID Installer」を選んで証明書を作ります。CSRファイルは同じもので良いようです。
ダウンロードした証明書のファイルをダブルクリックするとキーチェーンアクセスに取り込まれますので、その状態にしておきます。
Xojoでデベロッパ署名をいれた状態でアプリをビルドする
Xojoで配布対象のアプリのビルド元ファイルを開き、発行されたDeveloper IDを「Build Settings」の「macOS」内にある「Sign」に記入してアプリをビルドします。
Developer IDはキーチェーンアクセスで対象の証明書の項目を見れば確認できるはずです。
テスト時にはこのあとアプリ本体へのコード署名処理でエラーが出てしまって困ったのですが、この形で事前に署名を済ませておいてターミナルでのコード署名処理では署名部分を指定しないことで回避できたようです。
また、同一の署名がキーチェーンアクセス内に複数あるとエラーになるようです。各アプリごとにアプリとインストーラーの証明書を取得してキーチェーンアクセスに登録する必要は無く、使い回して大丈夫な模様。あるいは公証が終わったらキーチェーンアクセス内の証明書は消す形でしょうか。
なお余談ですが、パッケージ内に含めたい外部ファイル/フォルダはビルドする前にパーミッションを適切に設定しておかないとインストール後にそれが原因で一部の機能が動かなくなったりします(なった)。ターミナルで
1 |
chmod 755 ファイルパス |
などとやってパーミッションを設定しておきましょう。
配布用ファイル作成作業用のフォルダを作る
配布用ファイル作成作業用のフォルダを作ります。今回は参照サイトに従ってMacのApplicationsフォルダにインストーラ(.pkg)でインストールする形を取りますので、pkg/Applications/“アプリ名フォルダ”/“アプリ名.App” の構成としました。
署名の処理に必要になるentitlements.plistは参照先サイトのものをそのままコピーして保存(文字コードUTF-8指定に注意)。一応以下に同じものを置いておきます。
1 2 3 4 5 6 7 8 9 10 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.security.network.client</key> <true/> <key>com.apple.security.cs.disable-library-validation</key> <true/> </dict> </plist> |
アプリ本体へのコード署名を行う
以下のコマンドで署名処理を実行します。
1 |
cd 作成作業フォルダへのパス |
で作成作業フォルダに移動してから
1 |
codesign -s "Developer ID Application" --options runtime --timestamp --force --deep --entitlements "entitlements.plist" "./pkg/Applications/アプリ名フォルダ/アプリ.app" |
のコマンドを実行。「replacing existing signature」のメッセージが出ればOK。
なお、参考にしたページの情報だと-sの後で指定するのが「”Developer ID Application: ${DEVELOPER_ID}”」となっていたのですが、なぜかこの指定だと「--options runtime」で「--options というコマンドが見当たらない」という旨のエラーが出てしまっていました。その状態だとHardened Runtime対応がされないので、この後のAppleのサーバへの登録で蹴られます(ました)。理由はわからないのですが「“Developer ID Application”」とだけ入れておけば処理が通る模様。なんでしょうねえ。つまりここではアプリへのDeveloper IDの署名自体は行っていない(ビルド時にXojo内で済ませている)のですが、上記のコマンドの実行は必要です。
署名ができているかの確認は以下のコマンドで行います。
1 |
pkgutil --check-signature "./pkg/Applications/アプリ名フォルダ/アプリ.app" |
署名が確認できればOK。
インストーラパッケージ(.pkg)の作成
次はインストーラパッケージの作成です。Dmg形式やZIP形式での配布もできるようなのですが、とりあえず参照先サイトに従ってpkg形式のインストーラを作成することとします。
まずpkgファイルに含めるファイルを指定するための.plistファイルのひな形を出力します。
1 |
cd pkg |
で作成作業用フォルダ内のpkgフォルダに移動後、
1 |
pkgbuild --analyze --root Applications packages.plist |
を入れると、packages.plistの名前でひな形が出てきます。
それを開いて編集するとのことなのですが、参照先サイトに従ってとりあえず「BundleIsRelocatable」の指定を「false」にすることだけしました。以下に一応置いておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <array> <dict> <key>BundleHasStrictIdentifier</key> <true/> <key>BundleIsRelocatable</key> <false/> <key>BundleIsVersionChecked</key> <true/> <key>BundleOverwriteAction</key> <string>upgrade</string> <key>ChildBundles</key> <array> <dict> <key>BundleOverwriteAction</key> <string></string> <key>RootRelativeBundlePath</key> <string>アプリ名フォルダ/アプリ.app/Contents/Frameworks/XojoFramework.framework</string> </dict> </array> <key>RootRelativeBundlePath</key> <string>アプリ名フォルダ/アプリ.app</string> </dict> </array> </plist> |
編集が済んだら、以下のコマンドを実行して「インストーラパッケージ」を作成します。
1 |
pkgbuild 作成するパッケージ名.pkg --root Applications --component-plist packages.plist --identifier xxx.xxxxxx.xxxxxxxxxxxxxxxxxx(Xojoのプロダクトを作成する際に生成されるリバースドメイン) --version X.X.X --install-location "/Applications" |
「--identifier」で指定するリバースドメインはXojoのビルド元ファイルを開いて「Build Settings」の「macOS」から「Bundle Identifer」を見れば確認できます。
「--version」はインストーラのバージョンとのことなので何でもよさげですが、一応アプリのバージョンをそのまま入れました。
実行すると「.pkg」ファイルが生成されます。
なお、.pkgファイルを一旦XMLとして出力することでインストーラの内容を編集できるようなのですが、参照したサイトで記述があったタイトルの抜けもこちらの環境では見られなかったので省略しました。pkgutil側でアップデートがあったのかもしれません。
インストーラパッケージに署名を行う
次にパッケージに署名を行います。以下のコマンドで「署名済のインストーラパッケージ」が作成できます。
1 |
productsign --sign "Developer ID Installer: 支給されたDeveloper ID" 元のパッケージ.pkg 署名後のパッケージ.pkg |
Developer IDは「キーチェーンアクセス」で対象の証明書の項目を見れば確認できます。
署名できたかの確認は先ほどのアプリの時と同じく pkgutil --check-signature コマンドで
1 |
pkgutil --check-signature パッケージのパス |
で実行できます。
アップルの公証サーバにアップロードして登録
いよいよ最終段階です。以下のコマンドを実行してアップルの公証サーバに登録を行います。
1 |
xcrun altool --notarize-app --primary-bundle-id "xxx.xxxxxx.xxxxxxxxxxxxxxxxxx(id識別用リバースドメイン)" --username "AppleIDの登録名(メールアドレス)" --password 発行されたApp用パスワード --file "署名後のパッケージ.pkg" |
しばらく経って
1 2 |
No errors uploading '署名後のパッケージ.pkg'. RequestUUID = xxxxxxx--xxxx-xxxx-xxxx-xxxxxxxxxxxx(ステータス照合用UUID) |
のメッセージが出ればアップロードは完了です。
このあと公証サーバで処理が行われ、終了後に登録メールアドレスに結果の通知が来ます。
「Your Mac software was successfully notarized.」の通知が来れば公証は完了。あとは配布するだけです。
一応ターミナルでの確認方法も書いておきます。
1 |
xcrun altool --notarization-info xxxxxxx--xxxx-xxxx-xxxx-xxxxxxxxxxxx(ステータス照合用UUID) --username "AppleIDの登録名(メールアドレス)" --password 発行されたApp用パスワード |
で確認できます。「Status: success」と出ていればOK。
なお、参照先サイトにはログに残さないためにApp用パスワードをキーチェーンアクセスに入れておいて指定する方法の記述もありましたが、個人作成フリーウェア程度では必要ないと思われたので割愛しました。
(2022.10.11)
アプリ内同梱ファイルのパーミッションについて追記
(2022.11.10)
タグ: mac, Notarization, Xojo, 公証