Xojoで作成したMac用アプリの公証を通す

　macOSはセキュリティ強化の取り組みを継続的に強化していますが、macOS 10.15 Catalina以降でついに<strong>「アプリのインストール時にアップルのサーバに登録情報を照会しに行き、登録がなければインストールさせない」</strong>という処理を<strong>「必ず」</strong>行うようになったため（それ以前からあるにはありましたが回避方法が用意されていました）、アプリを作って配布する際のハードルがかなり上がりました。Adobeアプリで言うところのプロダクトアクティベートと同種の処理ですが、それをユーザーが作成して配布するアプリにも求めるようになったわけです。私が過去に作って配布していたアプリもこれに引っかかってダウンロードしてもインストールできない状態になっていましたが、アップルのサーバにアプリの情報を申請して登録するための手続き<strong>「Notarization/公証」</strong>を行い、配布できるようになりましたので以下に覚え書きとしてやり方を書いておきます。

　なお、これは<strong>Xcode以外のビルド環境（Xojo）でビルドしたアプリを公証に対応させるための話</strong>なので、<strong>ターミナルのCUI操作で手続きをすることが前提</strong>になっています。参考にしたページは<a href="https://www.hiroakit.com/archives/20200514/" rel="noopener" target="_blank"><strong>こちら</strong></a>など。情報がほぼそのまま使えて大変有り難かったのですが、一部変更しないと処理が通らなかったり、また個人でフリーウェアを配布する程度の目的だと過剰な部分もありましたので、こちらでもメモを残しておこうと思いました。
<div style="padding-left:1em" class="clear">
<h3 style="border-bottom: medium solid gray">Developer登録を済ませる</h3>
　開発したアプリを登録するためには<strong>申請者がAppleの登録Developerである必要がある</strong>ので、まず事前にDeveloperの登録手続きを済ませておきます。二段階認証を済ませた端末から申請してDeveloperの年間登録料（2022年現在12,800円）を支払う必要があります（多分クレジットカードとの紐付け必須）。また、<strong>政府発行の身分証明書のコピーの送付が最終段階で必要</strong>でした（フォームから画像を送る）。会社としての登録の場合にはそれ以外に<strong>「D-U-N-S番号」</strong>が必要になるようです。詳しくは<a href="https://developer.apple.com/jp/support/app-account/" rel="noopener" target="_blank"><strong>こちら</strong></a>。
　自分の場合はMacのDeveloper.app内から申請して通しました。それ以前にiPhoneから申請したところずっと審査中で止まってしまっていて、あらためてMacから申請し直したらあっさり通ったような経緯です。止まっていた理由は何も表示されないのでよくわかりません。
</div>
<div style="padding-left:1em" class="clear">
<h3 style="border-bottom: medium solid gray">「App用パスワード」を作っておく</h3>
　Xcode以外の環境でビルドしたアプリの登録には<strong>「App用パスワード」</strong>が必要になるとのことなので事前に<a href="https://appleid.apple.com/account/home" rel="noopener" target="_blank"><strong>こちら</strong></a>にDeveloper登録に使ったApple IDでログインしてApp用パスワードを作っておきます。<strong>「+」</strong>ボタンをクリックして分類名（任意でよい）を入れ、<strong>表示されるパスワードをメモ</strong>しておきます。

<a href="http://densyodamasii.com/wp-content/uploads/2022/10/column89_01.png" rel=lightbox[column89]><img src="http://densyodamasii.com/wp-content/uploads/2022/10/column89_01.png" alt="App用パスワード" width="300" height="201" class="size-full wp-image-4093 thinborder" /></a>
</div>
<div style="padding-left:1em" class="clear">
<h3 style="border-bottom: medium solid gray">キーチェーンアクセスで証明書（CSR）を発行しておく</h3>
　Macの<strong>「キーチェーンアクセス」</strong>アプリを開き、ドロップダウンメニューから<strong>「証明書アシスタント」</strong>→<strong>「認証局に証明書を要求」</strong>を選択します。

<a href="http://densyodamasii.com/wp-content/uploads/2022/10/column89_02.png" rel=lightbox[column89]><img src="http://densyodamasii.com/wp-content/uploads/2022/10/column89_02.png" alt="認証局に証明書を要求･･･" width="600" height="179" class="size-full wp-image-4094 thinborder" style="float:left" /></a>


　Apple IDの登録メールアドレス、通称（登録しようとしているアプリの略称など）を入れ、<strong>「ディスクに保存」</strong><strong>「鍵ペア情報を指定」</strong>を選んで<strong>「続ける」</strong>をクリック。証明書ファイル<strong>（以下Apple Developer Programで作る証明書と紛らわしいので「CSRファイル」と呼称する）</strong>の保存先を指定し、次の画面で秘密鍵、公開鍵に<strong>「2048ビット」</strong>、<strong>「RSA」</strong>の設定を選んで保存を実行します。これで指定した場所にCSRファイルが保存されたはずです。

<a href="http://densyodamasii.com/wp-content/uploads/2022/10/column89_03.png" rel=lightbox[column89]><img src="http://densyodamasii.com/wp-content/uploads/2022/10/column89_03.png" alt="証明書をディスクに保存" width="600" height="432" class="size-full wp-image-4095 thinborder" style="float:left" /></a>

　なお、この作業中何度かアカウントのログインパスワードの入力を求められましたが、これは環境によって変わるかもしれません。
</div>
<div style="padding-left:1em" class="clear">
<h3 style="border-bottom: medium solid gray">アプリとインストーラーの証明書を発行する</h3>
　まずアプリ本体の証明書を発行します。<a href="https://developer.apple.com/jp/" rel="noopener" target="_blank"><strong>Apple Developer Programのサイト</strong></a>にログインし、<strong>「アカウント」</strong>タブから<strong>「証明書、ID、プロファイル」</strong>の<strong>「証明書（英語）」</strong>を選択し、次画面で<strong>「Certificates」</strong>の横の<strong>「+」</strong>ボタンを押して証明書の種類を選びます。

<a href="http://densyodamasii.com/wp-content/uploads/2022/10/column89_04.png" rel=lightbox[column89]><img src="http://densyodamasii.com/wp-content/uploads/2022/10/column89_04.png" alt="Apple Developer Programサイト" width="600" height="474" class="size-full wp-image-4096 thinborder" style="float:left" /></a>

　Xcode以外で作成したアプリを自分のサイト等から配布したい場合は<strong>「Developer ID Application」</strong>を選んで<strong>「Continue」</strong>ボタンを押します。App Store経由での配布の場合はここで選ぶ証明書の種類が変わるようです。

<a href="http://densyodamasii.com/wp-content/uploads/2022/10/column89_05.png" rel=lightbox[column89]><img src="http://densyodamasii.com/wp-content/uploads/2022/10/column89_05.png" alt="発行する証明書の種類を選択" width="600" height="520" class="size-full wp-image-4097 thinborder" style="float:left" /></a>

　次に<strong>「Certificates, Identifiers & Profiles」</strong>の画面が出るので、画面下の<strong>「Choose File」</strong>ボタンをクリックし、さきほど作成して保存したCSRファイルを選択してアップロードします。<strong>「Profile Type」</strong>はよくわからなかったので<strong>「Previous Sub-CA」</strong>を選びましたが、特に問題なかったようです。<strong>「Continue」</strong>を押し、次の画面で<strong>「Download」</strong>をクリックして証明書をダウンロードします。

<a href="http://densyodamasii.com/wp-content/uploads/2022/10/column89_06.png" rel=lightbox[column89]><img src="http://densyodamasii.com/wp-content/uploads/2022/10/column89_06.png" alt="CSRファイルをアップロードする" width="600" height="429" class="size-full wp-image-4098 thinborder" style="float:left" /></a>

　同じくインストーラの証明書も必要になるので、<strong>「証明書、ID、プロファイル」</strong>の<strong>「証明書（英語）」</strong>から<strong>「Developer ID Installer」</strong>を選んで証明書を作ります。CSRファイルは同じもので良いようです。

　ダウンロードした証明書のファイルをダブルクリックするとキーチェーンアクセスに取り込まれますので、その状態にしておきます。
</div>
<div style="padding-left:1em" class="clear">
<h3 style="border-bottom: medium solid gray">Xojoでデベロッパ署名をいれた状態でアプリをビルドする</h3>
　Xojoで配布対象のアプリのビルド元ファイルを開き、発行されたDeveloper IDを<strong>「Build Settings」</strong>の<strong>「macOS」</strong>内にある<strong>「Sign」</strong>に記入してアプリをビルドします。

<a href="http://densyodamasii.com/wp-content/uploads/2022/10/column89_07.png" rel=lightbox[column89]><img src="http://densyodamasii.com/wp-content/uploads/2022/10/column89_07.png" alt="Xojo内で署名を入れてアプリをビルド" width="600" height="422" class="size-full wp-image-4099 thinborder" style="float:left" /></a>

　Developer IDはキーチェーンアクセスで対象の証明書の項目を見れば確認できるはずです。

<a href="http://densyodamasii.com/wp-content/uploads/2022/10/column89_09.png" rel=lightbox[column89]><img src="http://densyodamasii.com/wp-content/uploads/2022/10/column89_09.png" alt="Developer IDはキーチェーンアクセスで確認できる" width="600" height="365" class="size-full wp-image-4101 thinborder" style="float:left" /></a>

　テスト時にはこのあとアプリ本体へのコード署名処理でエラーが出てしまって困ったのですが、この形で事前に署名を済ませておいて<strong>ターミナルでのコード署名処理では署名部分を指定しない</strong>ことで回避できたようです。
　　また、同一の署名がキーチェーンアクセス内に複数あるとエラーになるようです。各アプリごとにアプリとインストーラーの証明書を取得してキーチェーンアクセスに登録する必要は無く、使い回して大丈夫な模様。あるいは公証が終わったらキーチェーンアクセス内の証明書は消す形でしょうか。

　なお余談ですが、パッケージ内に含めたい外部ファイル／フォルダはビルドする前にパーミッションを適切に設定しておかないとインストール後にそれが原因で一部の機能が動かなくなったりします（なった）。ターミナルで
 
<pre class="lang:sh decode:true " >chmod 755 ファイルパス</pre> 

などとやってパーミッションを設定しておきましょう。

</div>
<div style="padding-left:1em" class="clear">
<h3 style="border-bottom: medium solid gray">配布用ファイル作成作業用のフォルダを作る</h3>
　配布用ファイル作成作業用のフォルダを作ります。今回は参照サイトに従ってMacのApplicationsフォルダにインストーラ（.pkg）でインストールする形を取りますので、<strong>pkg/Applications/“アプリ名フォルダ”/“アプリ名.App”</strong> の構成としました。

<a href="http://densyodamasii.com/wp-content/uploads/2022/10/column89_08.png" rel=lightbox[column89]><img src="http://densyodamasii.com/wp-content/uploads/2022/10/column89_08.png" alt="パッケージ作成用フォルダ構成例" width="593" height="265" class="size-full wp-image-4100 thinborder" style="float:left" /></a>

　署名の処理に必要になるentitlements.plistは参照先サイトのものをそのままコピーして保存（文字コードUTF-8指定に注意）。一応以下に同じものを置いておきます。

 
<pre class="lang:xhtml decode:true " >&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
    &lt;dict&gt;
        &lt;key&gt;com.apple.security.network.client&lt;/key&gt;
        &lt;true/&gt;
        &lt;key&gt;com.apple.security.cs.disable-library-validation&lt;/key&gt;
        &lt;true/&gt;
    &lt;/dict&gt;
&lt;/plist&gt;</pre> 

</div>
<div style="padding-left:1em" class="clear">
<h3 style="border-bottom: medium solid gray">アプリ本体へのコード署名を行う</h3>
　以下のコマンドで署名処理を実行します。
 
<pre class="lang:sh decode:true " >cd 作成作業フォルダへのパス</pre> 

　で作成作業フォルダに移動してから

 
<pre class="lang:sh decode:true " >codesign -s "Developer ID Application" --options runtime --timestamp --force --deep --entitlements "entitlements.plist" "./pkg/Applications/アプリ名フォルダ/アプリ.app"</pre> 

　のコマンドを実行。<strong>「replacing existing signature」</strong>のメッセージが出ればOK。

　なお、参考にしたページの情報だと-sの後で指定するのが<strong>「"Developer ID Application: ${DEVELOPER_ID}”」</strong>となっていたのですが、なぜかこの指定だと<strong>「&#45;&#45;options runtime」</strong>で<strong>「&#45;&#45;options というコマンドが見当たらない」</strong>という旨のエラーが出てしまっていました。その状態だと<strong>Hardened Runtime対応</strong>がされないので、この後のAppleのサーバへの登録で蹴られます（ました）。理由はわからないのですが<strong>「“Developer ID Application”」</strong>とだけ入れておけば処理が通る模様。なんでしょうねえ。つまりここではアプリへのDeveloper IDの署名自体は行っていない（ビルド時にXojo内で済ませている）のですが、上記のコマンドの実行は必要です。

　署名ができているかの確認は以下のコマンドで行います。
 
<pre class="lang:sh decode:true " >pkgutil --check-signature "./pkg/Applications/アプリ名フォルダ/アプリ.app"</pre> 

　署名が確認できればOK。

<a href="http://densyodamasii.com/wp-content/uploads/2022/10/column89_10.png" rel=lightbox[column89]><img src="http://densyodamasii.com/wp-content/uploads/2022/10/column89_10.png" alt="署名が入っていることを確認" width="578" height="371" class="size-full wp-image-4102 thinborder" style="float:left" /></a>
</div>
<div style="padding-left:1em" class="clear">
<h3 style="border-bottom: medium solid gray">インストーラパッケージ（.pkg）の作成</h3>
　次はインストーラパッケージの作成です。Dmg形式やZIP形式での配布もできるようなのですが、とりあえず参照先サイトに従って<strong>pkg形式のインストーラ</strong>を作成することとします。

　まずpkgファイルに含めるファイルを指定するための.plistファイルのひな形を出力します。
 
<pre class="lang:sh decode:true " >cd pkg</pre> 

　で作成作業用フォルダ内のpkgフォルダに移動後、
 
<pre class="lang:sh decode:true " >pkgbuild --analyze --root Applications packages.plist</pre> 

　を入れると、packages.plistの名前でひな形が出てきます。

　それを開いて編集するとのことなのですが、参照先サイトに従ってとりあえず<strong>「BundleIsRelocatable」</strong>の指定を<strong>「false」</strong>にすることだけしました。以下に一応置いておきます。
 
<pre class="lang:xhtml decode:true " >&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;array&gt;
	&lt;dict&gt;
		&lt;key&gt;BundleHasStrictIdentifier&lt;/key&gt;
		&lt;true/&gt;
		&lt;key&gt;BundleIsRelocatable&lt;/key&gt;
		&lt;false/&gt;
		&lt;key&gt;BundleIsVersionChecked&lt;/key&gt;
		&lt;true/&gt;
		&lt;key&gt;BundleOverwriteAction&lt;/key&gt;
		&lt;string&gt;upgrade&lt;/string&gt;
		&lt;key&gt;ChildBundles&lt;/key&gt;
		&lt;array&gt;
			&lt;dict&gt;
				&lt;key&gt;BundleOverwriteAction&lt;/key&gt;
				&lt;string&gt;&lt;/string&gt;
				&lt;key&gt;RootRelativeBundlePath&lt;/key&gt;
				&lt;string&gt;アプリ名フォルダ/アプリ.app/Contents/Frameworks/XojoFramework.framework&lt;/string&gt;
			&lt;/dict&gt;
		&lt;/array&gt;
		&lt;key&gt;RootRelativeBundlePath&lt;/key&gt;
		&lt;string&gt;アプリ名フォルダ/アプリ.app&lt;/string&gt;
	&lt;/dict&gt;
&lt;/array&gt;
&lt;/plist&gt;</pre> 

　編集が済んだら、以下のコマンドを実行して「インストーラパッケージ」を作成します。
 
<pre class="lang:sh decode:true " >pkgbuild 作成するパッケージ名.pkg --root Applications --component-plist packages.plist --identifier xxx.xxxxxx.xxxxxxxxxxxxxxxxxx（Xojoのプロダクトを作成する際に生成されるリバースドメイン） --version X.X.X --install-location "/Applications"</pre> 

　<strong>「&#45;&#45;identifier」</strong>で指定するリバースドメインはXojoのビルド元ファイルを開いて<strong>「Build Settings」</strong>の<strong>「macOS」</strong>から<strong>「Bundle Identifer」</strong>を見れば確認できます。
　<strong>「&#45;&#45;version」</strong>はインストーラのバージョンとのことなので何でもよさげですが、一応アプリのバージョンをそのまま入れました。
　実行すると「.pkg」ファイルが生成されます。

　なお、.pkgファイルを一旦XMLとして出力することで<strong>インストーラの内容を編集</strong>できるようなのですが、参照したサイトで記述があったタイトルの抜けもこちらの環境では見られなかったので省略しました。pkgutil側でアップデートがあったのかもしれません。
　また、インストーラ実行時の追加処理を指定することもできます。情報は<a href="https://engineer-milione.com/tips/mac-script.html" rel="noopener" target="_blank"><strong>こちら</strong></a>などを参照。--scriptオプションで指定したフォルダ内の「preinstall」「postinstall」の名称のファイル内にシェルスクリプトを記述することで処理が実行されます。「preinstall」「postinstall」には拡張子が付かないことに注意です。
</div>
<div style="padding-left:1em" class="clear">
<h3 style="border-bottom: medium solid gray">インストーラパッケージに署名を行う</h3>
　次にパッケージに署名を行います。以下のコマンドで<strong>「署名済のインストーラパッケージ」</strong>が作成できます。
 
<pre class="lang:sh decode:true " >productsign --sign "Developer ID Installer: 支給されたDeveloper ID" 元のパッケージ.pkg 署名後のパッケージ.pkg</pre> 

　Developer IDは<strong>「キーチェーンアクセス」</strong>で対象の証明書の項目を見れば確認できます。

　署名できたかの確認は先ほどのアプリの時と同じく <strong>pkgutil &#45;&#45;check-signature</strong> コマンドで
 
<pre class="lang:sh decode:true " >pkgutil --check-signature パッケージのパス</pre> 

　で実行できます。
</div>
<div style="padding-left:1em" class="clear">
<h3 style="border-bottom: medium solid gray">アップルの公証サーバにアップロードして登録</h3>
　いよいよ最終段階です。以下のコマンドを実行してアップルの公証サーバに登録を行います。
 
<pre class="lang:sh decode:true " >xcrun altool --notarize-app --primary-bundle-id "xxx.xxxxxx.xxxxxxxxxxxxxxxxxx（id識別用リバースドメイン）" --username "AppleIDの登録名（メールアドレス）" --password 発行されたApp用パスワード --file "署名後のパッケージ.pkg"</pre> 

　しばらく経って
 
<pre class="lang:sh decode:true " >No errors uploading '署名後のパッケージ.pkg'.
RequestUUID = xxxxxxx--xxxx-xxxx-xxxx-xxxxxxxxxxxx（ステータス照合用UUID）</pre> 

　のメッセージが出ればアップロードは完了です。

　このあと公証サーバで処理が行われ、終了後に登録メールアドレスに結果の通知が来ます。

　<strong>「Your Mac software was successfully notarized.」</strong>の通知が来れば公証は完了。あとは配布するだけです。

<a href="http://densyodamasii.com/wp-content/uploads/2022/10/column89_11.png" rel=lightbox[column89]><img src="http://densyodamasii.com/wp-content/uploads/2022/10/column89_11.png" alt="公証処理完了の通知メール" width="600" height="494" class="size-full wp-image-4103 thinborder" style="float:left" /></a>

　一応ターミナルでの確認方法も書いておきます。
 
<pre class="lang:sh decode:true " >xcrun altool --notarization-info xxxxxxx--xxxx-xxxx-xxxx-xxxxxxxxxxxx（ステータス照合用UUID） --username "AppleIDの登録名（メールアドレス）" --password 発行されたApp用パスワード</pre> 

　で確認できます。<strong>「Status: success」</strong>と出ていればOK。

　なお、参照先サイトにはログに残さないためにApp用パスワードをキーチェーンアクセスに入れておいて指定する方法の記述もありましたが、個人作成フリーウェア程度では必要ないと思われたので割愛しました。
</div>