概要
- ターミナルでコマンドを打ち込み各アプリにそれぞれ公証を行う…というのが面倒なので、以下の通り一括で処理できるようなシェルスクリプトを作成しました。
背景
- macOS10.15よりAppleの公証(Apple Notarization Service)を受けていないアプリケーションは、起動に制限がかかるようになりました。
- Xcode内ビルドが完結する場合には
Archive
をOrganizer
でAppleへ公証することができるので、特に考えることも少なくて済みます。 - しかし既にビルドしてしまったアプリや、ビルドした後に
Resource
内のファイルを操作する場合、別途Appleの公証を行う必要があります。
参考
-
新しいLinuxの教科書
- シェルスクリプトの作成の際に参考にしました。
- ほぼ知識ゼロの状態から数日で、下記のようなシェルスクリプトが書けるようになる良本です!
-
リリース済みのアプリのApple Notarization Service (Notary Service) 対応
- 使用したコマンドの詳細はこちらを参照下さい。
作成したシェルスクリプト
# !/bin/bash
# 指定したフォルダ内のファイルを公証するためのスクリプト
# 定義
primary_bundle_id="jp.co.xxx.xxx" # 適当な文字列で良い?
developer_email="xxx@gmail.com" # 開発者メールアドレス
# Appleの公証
notary_applications ()
{
xcrun altool --notarize-app \
--primary-bundle-id "${1}" \
--username "${2}" \
--password "@keychain:AC_PASSWORD" \
--file "${3}"
if [ $? -ne 0 ]; then
echo "[Error]apple notarization service error" 1>&2
exit 4
fi
}
# 公証情報をファイルに紐付ける
staple_notaryinfo ()
{
local application_path=$1
# 公証完了までwaitする(zipのアップロードから公証完了まで時間がかかるため)
# 5s * 120 = 10m
echo "waiting for completing notarization(${application_path})..."
local number_of_try=120
for try_count in $(seq 0 $number_of_try)
do
# 規定の回数を終えて尚エラーならば終了する
if [ $try_count -eq $number_of_try ]; then
echo "[Error]staple notarization information error" 1>&2
exit 4
fi
xcrun stapler staple "${application_path}" > /dev/null # stapleの試行
if [ $? -eq 0 ]; then # 成功した時点で終了する
echo ""
break
else
sleep 5s
fi
done
}
#############
# Entry Point
#############
# 引数の例
# $1:公証対象を入れたフォルダへの相対パス。
folder_path=$1
# フォルダの存在確認
if [ ! -d "${folder_path}" ]; then
echo "${0}: ${1}: No such folder" 1>&2
exit 1
fi
# 公証のためのzip化
zip_name="${folder_path%%/}.zip"
zip -r "${zip_name}" "${folder_path}" > /dev/null
if [ $? -ne 0 ]; then
echo "[Error]zip error" 1>&2
exit 3
fi
# 公証を行う
notary_applications "${primary_bundle_id}" "${developer_email}" "${zip_name}"
# オフラインの公証のため、ファイル毎にStapleを行う
if [ -d "${folder_path}" ]; then
# 内部フィールド区切り文字を改行のみに指定
_IFS=$IFS
IFS=$'\n'
for file_name in $(ls ${folder_path})
do
# 公証情報をファイルに紐付ける(オフライン用)
staple_notaryinfo "${folder_path}${file_name}"
done
IFS=$_IFS
fi
実行例
必要な準備
- 公証可能な条件でプログラムをビルドする
- (私の環境で作業が必要なのは以下でした。その他の条件は自動で設定されるものと思います。)
- Hardened Runtimeが有効になっている
- 開発者IDで署名していること
- ビルド後に
Resource
内を操作した場合はメタデータのリセットと再署名をしておく
- ビルド後に
- アプリパスワードを発行しキーチェーンに登録しておく
- シェルスクリプトと公証対象(
sample.app``sample2.app
)を含んだフォルダを下記の位置関係で配置します
- 呼び出しは
cd
でシェルスクリプトの存在するフォルダに移動してから、以下のように行います。 - 絶対パスの指定すると例えば
zip
の際に深い階層になってしまうので、正常に動作するか怪しいです。 - 正常に動作しているかどうか気になる場合は適宜
1>&2
を外して出力を確認すると良いです。
スクリプトの実行
cd /Users/.../sample/
./notarization.sh FilesForNotarization/
(実行結果)
No errors uploading 'FilesForNotarization.zip'.
RequestUUID = xxx-xxx-xxx-xxx-xxxxxxxxxx
waiting for completing notarization(FilesForNotarization/sample.app)...
waiting for completing notarization(FilesForNotarization/sample2.app)...
備考
- Stapleを成功するまで繰り返すよりも、RequestUUIDを記憶しておいて、Successとなるまで確認するのが本筋かもしれません。
xcrun altool --notarization-info xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -u xxxxx@xxx.co.jp -p "@keychain:AC_PASSWORD"
(実行結果)
No errors getting notarization info.
RequestUUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Date: 2020-01-10 00:09:50 +0000
Status: success
LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets/Enigma113/v4/...
Status Code: 0
Status Message: Package Approved