Notarization (公証化)

2023 年 11 月から、Apple は altool を使った notarization を受け付けなくなって、RubyMotion の rake notarize がまだそれに対応していないので、notarytool を使った方法を追記しておきます。

Apple から公証を受けるには、Developer 登録をして、RubyMotion App に、Developer ID (email address: DEV@ID) を登録する必要があります。Rake file に codesign certificate を追加します。rake notarize  で  notarization  を行わない場合は必要ありませんが、近いうちに対応すれば (すでに対応しているかもしれませんが) 使えるので、追加しておいた方がいいでしょう。

Motion::Project::App.setup do |app|
  app.codesign_certificate = "Developer ID Application: NAME (DEV@ID)"
end

次に、公証を受けるために必要な App-Specific Password を生成します。

Apple の Web サイト (https://appleid.apple.com/account/home ) Developer ID (email address) でログインします。 

ログインしたら、セキュリティにある App 用パスワードのパスワードを生成... をクリックします。

パスワードのラベルを入力するように求められるので、適当な名前をつけます (App Notarization としました)。

ここで表示される xxxx-xxxx-xxxx-xxxx という形式の password を記録しておきます。ターミナル.app  で、次のコマンドを実行して、App  Password をキーチェーンアクセスに登録します。DEV@ID は、ADC の Developer Account の Email アドレスです。APP_PASSWORD は、Apple のサイトで作成した App 用パスワード (xxxx-xxxx-xxxx-xxxx) です。AC_PASSWORD は参照用のキーチェーンのラベルなので、任意でいいのだと思いますが、Apple の例でも AC_PASSWORD になっているので、そうしています。DEV_TEAM_ID は、Apple Developer のサイトで、アカウントにあるメンバーシップの詳細チームIDとして記載されているものを使います。


xcrun notarytool store-credentials "AC_PASSWORD" --apple-id "DEV@ID" --team-id "DEV_TEAM_ID" --password "APP_PASSWORD"


これで、キーチェーンアクセスに登録したら、Rake file の App.setup に、次の 3 行を追加します。この部分も rake notarize を使わなければ必要ありません。

app.codesign_certificate = "Developer ID Application: YOUR NAME (DEV_TEAM_ID)"

app.developer_userid = "DEV@ID"

app.developer_app_password = "@keychain:AC_PASSWORD"


この DEV@ID は、上のものと同じ Developer ID の Email アドレスを入れます。上でキーチェーンアクセスに AC_PASSWORD で App Password を登録したので developer_app_password は、それを使います。

また、最新のテンプレートで App を作成している場合は問題ないかもしれませんが、古いテンプレートの場合は、テンプレートへのパスを追加する処理を Rake file の最初に入れます (1 行目のものは入っていると思います)。

$:.unshift("/Library/RubyMotion/lib")

$:.unshift("~/.rubymotion/rubymotion-templates")


ここまで準備ができたら、配布用のビルドを作成します。

rake build:release

現在は、Rubymotion の template が対応したので、code sign を手動で行う必要はなくなっていますが、記録として残しておきます。

Terminal.app 上で code sign を実行します。notarytool に対応したバージョンがリリースされれば必要なくなるはずです。

まずは、アプリケーションパッケージが作成された directory に移動して entitlements ファイルを作成します。移動しない場合は、current directory  からの相対パスを入力してください。MyApp.app  は、build  で作成されたアプリケーションパッケージになります。

codesign -d --xml --entitlements - 'MyApp.app' > 'entitlements.xml'

次に、作成した entitlements ファイルを利用して、code sign を追加します。この --sign の部分の文字列は、上の、app.codesign_certificate の部分の文字列と同じです。

codesign -dvv MyApp.app --timestamp --sign 'Developer ID Application: YOUR NAME (DEV@ID)' -f --verbose=9 --entitlements 'entitlements.xml' --deep --options runtime


App がビルドできたら、ちゃんとコード書名ができていることを確認してください。プロセスの一番最後に次のような表示があるはずです。(この部分は、RubyMotion  が  notarytool  に対応するまでは意味がないでしょう)

Codesign ./build/<YOUR APP SPECIFIC DIRECTORY>/XXXXX.app

これで、公証のために App を提出する処理をします。これ以降は、RubyMotion  が notarytool に対応した場合、ということになりますが、code sign の処理が面倒な場合は、rake notarize で  code certificate が追加されたアプリケーションパッケージを .zip ファイルにしたものが生成されるので、上の code sign と次の zip 化のプロセスを飛ばすことができます。

rake notarize


自前で zip 化するには、次のコマンドを実行します。MyApp の部分は、自分のアプリケーションパッケージの名前になります。ファイルのある directory で処理しない場合は、そこまでの相対パスを入れます。

/usr/bin/ditto -c -k --keepParent MyApp.app MyApp.zip


notarytool に対応していない現時点では、rake notarize で zip ファイルを作成し、ファイル自体はアップロードされるようですが、notarization が実行されません。ただ、作成された zip ファイルは code sign が追加されているので、そのまま利用できます。

zip ファイルができたら、Terminal.app で次のようなコマンドで notarization のためにファイルをアップロードします。

xcrun notarytool submit MyApp.zip --keychain-profile "AC_PASSWORD" --wait

最後の --wait があると、処理の status が表示されます。

アップロードに成功すると、RequestUUID が表示されます。

RequestUUID = xxxx-xxxx.....


この時点では、提出に成功しただけで、公証を受けられているかは分かりません。しばらく待つと、Developer の登録アドレスにメールが届きます。Your Mac software was successfully notarized. という件名のメールが届けば公証を受けられたということです。また、以下のコマンドでも状況を確認できます。

rake notarize:history


RubyMotion が対応するまでは、status: Invalid と表示されて、公証を受けられなかった場合に status と一緒に表示される id を使って、なぜ公証を受けられなかったのかの確認がある程度できます。次の ID は、status と一緒に表示される id の長い文字列です。これで、developer_log.json というファイルが生成され、その中の issue の message の部分に問題の原因が表示されているかもしれません。


xcrun notarytool log STATUS_ID --keychain-profile "AC_PASSWORD" developer_log.json


これで、build/...Release にある XXXX.app を配布すればいいことになりますが、オフラインでは Gatekeeper を通らないようなので、次のコマンドでチケットを結合する必要があります。

rake notarize:staple


RubyMotion が対応するまでは、自前で staple 処理をします。

xcrun stapler staple MyApp.app


これで、XXXXX.app を配布すると、オフラインでも Gatekeeper が安全なアプリであると判断して実行できます。