XcodeでiOS向けのアプリケーションを作っていると検証のためなどに過去に作ったアプリケーション(.ipa)のプロビジョニングプロファイルだけを入れ替えたくなることがままあるのでスクリプトを作ってみた。
replace_mobileprovision
#!/bin/bash
# .ipaファイルを作業ディレクトリに展開する
# リリース用のipaは../Release-iphoneos/MyApplication.ipaと仮定
if [ $# -ne 2 ]; then
echo "指定された引数は$#個です。" 1>&2
echo "実行するには<ipaパッケージ> <プロビジョニング>の2個の引数が必要です。" 1>&2
exit 1
fi
# 引数に渡されたファイル名を絶対パスに変換
ABS_BASE_PATH=$(cd "$(dirname "$1")" && pwd)
IPA_FILE_PATH=${ABS_BASE_PATH%/}/$(basename $1)
prov_base_path=$(cd "$(dirname $2)" && pwd)
PROV_FILE_PATH=${prov_base_path%/}/$(basename $2)
echo "${PROV_FILE_PATH}" 1>&2
# 作業ディレクトリを作成
TMPDIR=`mktemp -d build_temp.XXXXXX`
trap "rm -rfv ${TMPDIR}" EXIT
mkdir -p ${TMPDIR}/AdHoc-iphoneos
cd ${TMPDIR}/AdHoc-iphoneos
# 作業ディレクトリに1番目の引数に渡された.ipaファイルを展開
unzip "${IPA_FILE_PATH}"
PACKAGE_NAME=`ls Payload/`
# パッケージのファイル名に使えそうな値を取得しておく
BUILD_DATE=`date '+%Y%m%d'`
BUNDLE_VERSION=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "Payload/${PACKAGE_NAME}/Info.plist"`
BUNDLE_SHORT_VERSION_STRING=`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "Payload/${PACKAGE_NAME}/Info.plist"`
BUILD_VERSION=${BUNDLE_SHORT_VERSION_STRING}-${BUNDLE_VERSION}
# 2番目の引数に渡されたプロビジョニングを検証するとともにプレーンテキストに
/usr/bin/openssl smime -in "${PROV_FILE_PATH}" -inform der -verify > $(basename $2)
TERM_NAME=`/usr/libexec/PlistBuddy -c "Print TeamName" $(basename $2)`
# KeychaneにインストールされているCodeSign用証明書からユニークIDを取り出す
CODE_SIGN_UID=`/usr/bin/security find-identity -p codesigning -v | grep "iPhone Distribution: ${TERM_NAME}" | sed -e 's/^[ ]*//g' | cut -d " " -f 2 | sort | uniq`
# 2番目の引数に渡されたプロビジョニングに入れ替えたパッケージを生成
# Entitlements.plistを取り出す
xcrun codesign -d --entitlements :- "Payload/${PACKAGE_NAME}" 2> /dev/null > "../../${PACKAGE_NAME}.xcent"
# AdHocやDebugではEntitlements.plistのget-task-allowがfalseでないとアプリが実行できない
/usr/libexec/PlistBuddy -c "Set get-task-allow NO" "../../${PACKAGE_NAME}.xcent"
# AdHocやDebugではEntitlements.plistにbeta-reports-activeエントリーがあるとアプリが実行できない
/usr/libexec/PlistBuddy -c "Delete beta-reports-active" "../../${PACKAGE_NAME}.xcent"
# 2番目の引数に渡されたプロビジョニングに入れ替え
cp "${PROV_FILE_PATH}" "Payload/${PACKAGE_NAME}/embedded.mobileprovision"
rm -rf "Payload/${PACKAGE_NAME}/_CodeSignature"
rm -f "Payload/${PACKAGE_NAME}/CodeResources"
# 新しいプロビジョニングに入れ替えたパッケージに署名する
xcrun codesign -f -s ${CODE_SIGN_UID} --entitlements "../../${PACKAGE_NAME}.xcent" "Payload/${PACKAGE_NAME}"
# 出来上がったパッケージの署名を検証する
xcrun codesign --no-strict -vvvv --verify "Payload/${PACKAGE_NAME}"
# パッケージを<パッケージ名>_<BUILD_VERSION>_fix.ipaにアーカイブ
zip -qr "${ABS_BASE_PATH%/}/${PACKAGE_NAME}-${BUILD_VERSION}_fix.ipa" Payload Symbols
rm -rfv ${TMPDIR}
2017/02/21 KeyChaneに同じデベロッパーの証明書が2つ以上インストールされているとエラーになるのを(なるべく)回避