Go to list of users who liked
Share on X(Twitter)
Share on Facebook
More than 5 years have passed since last update.
iOS受託開発における署名付け替えの技術
受託開発におけるiOSアプリの納品方法は様々です。
iTunes Connectにアップロードしてくれと頼まれる場合があったり、証明書とProvisioning File渡すからipaをビルドして納品してくれと言われる場合があったり。
お客様のDeveloperIDとパスワードを受領できるケースは、なんでもできると思いますが、そうでない場合は色々と方法を考えなければなりません。
普段関わっているアプリは証明書すらもらえないため、App.xcodeprojを丸ごと納品するスタイルをとっているのですが、下記のような問題があります。
- そのままだとソースコードが丸見えで、悪意がある人間が簡単に流用できてしまう。
- ので、ソースコードだけは一旦static libraryに固めています。これのせいで納品手順が煩雑になっている上に、Swiftも使えません。
- 納品用にプロジェクトを構成し直すので、みんなで一生懸命テストするものと、Apple審査に出すものが別物になってしまう
もっといい方法があるはず、と思い調べてみました。お楽しみください。
アウトライン(App.xcarchive案)
まずはxcarchiveを納品するスタイルを考えてみました。結論から言うと、最終的にiTunesConnectで利用するのと同じTeamを使えないとダメでした。つまりお客さんのDeveloperIDとパスワードが分からない場合は採用できないと思います。一応情報としてやろうとしたことを残しておきます。
- App.xcarchive を作る
- App.xcarchiveから開発用の署名をして、ipaを作って配布、テストする
- App.xcarchive を納品する
- iTunesConnectへアップする
App.xcarchive を作る
Archiveして、codesignを確認します。
$ cd /path/to/archive/ $ codesign -d CodeSignSample\ 11-28-15\,\ 10.44.xcarchive/CodeSignSample 11-28-15, 10.44.xcarchive/: code object is not signed at allArchiveした時点ではcodesignはされていないことがわかります。
App.xcarchiveから開発用の署名をして、ipaを作って配布、テストする
$xcodebuild-exportArchive-archivePath /path/to/App.xcarchive/-exportPath /path/to/hello.ipa ~ ~(省略) ~ Results at'/var/folders/tr/3lftss053tqdh731cgt0w1p00000gn/T/713B1E1E-9F4D-4F8D-98DD-826D6428F82A-23330-000024AF65316D33/App' Moving exported product to'/Users/toshi0383/Library/Developer/Xcode/Archives/2015-11-28/hello.ipa'** EXPORT SUCCEEDED**ipaができました。
App.xcarchive を納品する
ソースコード丸見えになっていたりしないか、念のため確認します。
$ cd /path/to/App.xcarchive/ $ tree ~ ~ ~省略しますが、ソースコードは (多分Products/Applications/App.app/App に)コンパイルされて実行形態になっているようです。
これで安心して納品できそうです。
iTunesConnectへアップする
App.xcarchiveをダブルクリックするとXcodeのOrganizerが開きます。ここからいつも通り(本番用のProvisioningで署名をして)ipaを作ってiTunesConnectへアップします。

ここでコケます。ビルドに使ったチームと違うアカウントでipa作ろうとしてるでしょ?って言われています。ズバリその通り!!むしろそれがやりたいことなんだけど。。
というわけで、Teamが異なってしまう場合はxcarchiveを納品する案は使えないようです。
アウトライン(ipa案)
そのような場合でも、fastlane sign を使えばイケるという情報を入手しました。
If you generated your ipa file but want to apply a different code signing onto the ipa file, you can use sigh resign
説明を読む限りはズバリこれっぽいです。
まとめるとこのような流れになります。
- App.ipaを開発用の署名で作る、配布する、テストする(ご自由に)
- App.ipaを納品する
- お客さん側でAppStore用の署名+BundleIDに付け替えてそのままiTunesConnectへ
まずは納品まで
開発で使用するTeamとProvisioningでArchiveします。
Archive成功しました。sigh resignはipaを求めているので、開発で使用するTeamを指定して、ipaを作成します。
ビルドとipa exportのTeamが同じなのでエラーになりませんでした。
念のため、codesignを確認します。
$ unzip CodeSignSample_InHouseSigned.ipa $ codesign -d --entitlements - Payload/CodeSignSample.app/Executable=/Users/toshi0383/Desktop/inhouse/Payload/CodeSignSample.app/CodeSignSample??qq?<?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"><dict><key>application-identifier</key><string>P945A6YU32.net.nextscape.hello.world</string><key>aps-environment</key><string>production</string><key>com.apple.developer.default-data-protection</key><string>NSFileProtectionComplete</string><key>com.apple.developer.team-identifier</key><string>P945A6YU32</string><key>com.apple.external-accessory.wireless-configuration</key><true/><key>get-task-allow</key><false/><key>keychain-access-groups</key><array><string>P945A6YU32.net.nextscape.hello.world</string></array></dict></plist>$ grep -A1 CFBundleIdentifier ./Payload/CodeSignSample.app/Info.plist <key>CFBundleIdentifier</key> <string>net.nextscape.hello.world</string>P945A6YU32が開発で使用する証明書のIDです。BundleIDも開発用のものになっています。問題なさそうです。これが、我々が動作確認に使用するipaになります。
次はいよいよこのipaを納品して、お客様側で署名とバンドルIDを付け替えることになりますね。
sighの使い方を調べたところ、
- Provisioning Profileをダウンロードする
- Provisioning Profileを指定してresignする
という2段階になりそうです。
$sigh-a jp.toshi0383.JamNavi-u${AppleDeveloperID}-q jamnavi-prod.mobileprovision# 初回はパスワード聞かれます# カレントにjamnavi-prod.mobileprovisionが展開されます[20:50:54]: Successfully loggedin[20:50:54]: Fetching profiles...[20:50:58]: Found 1 matching profile(s)[20:50:58]: Downloading provisioning profile...[20:50:58]: Successfully downloaded provisioning profile...[20:50:58]: Installing provisioning profile.../Users/toshi0383/Desktop/codesign/jamnavi-prod.mobileprovision$sigh resign ./CodeSignSample_InHouseSigned.ipa--signing_identity'iPhone Distribution: Toshihiro Suzuki (T47KPZ35V7)'-n"jamnavi-prod.mobileprovision"# パラメータが間違っていた場合はプロンプトで聞いてきますので答えてあげてください。~~(省略)~Resigning application using certificate:'iPhone Distribution: Toshihiro Suzuki (T47KPZ35V7)'and entitlements from provisioning profile: /Users/toshi0383/Desktop/codesign/jamnavi-prod.mobileprovision_floatsignTemp/Payload/CodeSignSample.app: replacing existing signatureRepackaging as ../CodeSignSample_InHouseSigned.ipaProcesscomplete[20:51:14]: Successfully signed ./CodeSignSample_InHouseSigned.ipa!成功したと言っています。確認しましょう。
$ unzip CodeSignSample_InHouseSigned.ipa $ codesign -d --entitlements - Payload/CodeSignSample.app/Executable=/Users/toshi0383/Desktop/codesign/Payload/CodeSignSample.app/CodeSignSample??qq?<?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"><dict><key>application-identifier</key><string>T47KPZ35V7.jp.toshi0383.JamNavi</string><key>aps-environment</key><string>production</string><key>beta-reports-active</key><true/><key>com.apple.developer.team-identifier</key><string>T47KPZ35V7</string><key>com.apple.security.application-groups</key><array><string>group.jp.toshi0383.jamnavi</string></array><key>get-task-allow</key><false/><key>keychain-access-groups</key><array><string>T47KPZ35V7.*</string></array></dict></plist>$ grep -A1 CFBundleIdentifier ./Payload/CodeSignSample.app/Info.plist<key>CFBundleIdentifier</key><string>jp.toshi0383.JamNavi</string>署名がつけ変わり、BundleIDも書き換えられました。
iTunesConnectへアップする
準備が整いましたので、iTunesConnectにアップしましょう。Application Loaderを使いました。
成功した画面をキャプチャし忘れましたが、無事iTunesConnectの画面上に表示されました。
せっかくなのでfastlane deliverも使ってみました。が、アプリのページでエラーが出ているとコケるみたいです。コマンドはこう。
$deliver--ipa App.ipa-u${itc_user}アップロードだけをする方法を教えて欲しい旨issueにコメントしました。回答あったら更新します。
deliverはメタデータのチェックとか余計なことまでしてしまうので、お客さんにやってもらうにはaltoolの方が安全かもしれません。ただこちらも初回にちゃんと設定しないとまともに動かないという。。私だけ?
$ PATH=$PATH:$(dirname"$(find$(dirname$(xcode-select-p))-name altool |head-1)")$ln-s"/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/itms" /usr/local/$altool--upload-app--file'${ipa_filename}'--username${ITC_USER}--password${ITC_PASSWORD}最初2行は初回エラーになるときのワークアラウンドです。
おまけ sigh resignは何をやっているのか
sighのresignは、resign.sh というのが実態のようです。
中を覗くと、/usr/libexec/PlistBuddy を使ってアプリのInfo.plistを編集していることがわかります。
ipaをunzipして直接いじっちゃってます。なんて荒技!
PlistBuddyで値を更新しているのは下記の4つでした。
`PlistBuddy -c "Set :CFBundleDisplayName $DISPLAY_NAME" "$APP_PATH/Info.plist"``PlistBuddy -c "Set :CFBundleIdentifier $BUNDLE_IDENTIFIER" "$APP_PATH/Info.plist"``PlistBuddy -c "Set :CFBundleVersion $VERSION_NUMBER" "$APP_PATH/Info.plist"``PlistBuddy -c "Set :CFBundleShortVersionString $VERSION_NUMBER" "$APP_PATH/Info.plist"`署名情報も基本的にはplistの形で抜き出せるので、これを編集した上でcodesignし直しているようです。これはXcodeもやっていることだとかソースコードのコメントに書いてありました。
/usr/bin/codesign-f-s"$CERTIFICATE"--entitlements="$TEMP_DIR/newEntitlements""$APP_PATH"スクリプト冒頭のライセンス表記を見ると、このスクリプト自体は2011年頃からメンテナンスが継続されているようで、向こうでは結構実績ありそうな感じします。
さらに
- now re-signs embedded iOS frameworks, if present, prior to re-signing the application itself
とある通り、embedded frameworkの署名もつけかえてくれるようです。
まとめ
以上、iOS受託開発における署名付け替えの技術について解説してきました。
半年以上メンバー全員の悩みの種だった問題が、数日で一気に解決に近づいた気がします。
結論としては、
- sigh resignを使うと、ipaの署名付け替えが簡単にできる。BundleIDも、Provisioning Profileにひもづくものに書き換えてくれる。ということは、ipa納品にできる。
- ipa納品にすることで、ついに納品が自動化できる。
- ipa納品にすることで、static library作成の必要がなくなり、Swiftが使える!!
- sigh resignは、内部的にはPlistBuddyを使用してかなり泥臭いことをしている。
ということになります。
なお今回の検証はiTunesConnectへアップロードするところまでにとどまっており、実際に審査が通るかどうかまでは検証できていません。参考にする際は自己責任でお願いします。一応今、半年以上放置していたアプリのアップデートを兼ねて、署名付け替えた版で審査まで確認しようと思っています。
最後に、再署名からアップロードを自動化する処理をまとめておきます。
# !/bin/bash## description:# ipaに再署名してiTunesConnectにアップロードする# 冒頭のパラメータを適切な値に設定してください## dependency:# sigh: `sudo gem install sigh` to install####### パラメータ#### BundleIDBUNDLE_ID=its.your.app# Apple Developer IDAPPLE_DEVELOPER_ID=# 証明書の名称です# Keychain Accessの一覧に表示されるものを設定してくださいCERT_NAME='iPhone Distribution: Hoge Huga (T47KPZ35V7)'#########IPA_NAME=App.ipaPROVISIONING_FILE_NAME=App.mobileprovisionfunctioncheckStatus{if[$?-ne 0];thenecho"Encountered an error, aborting!">&2exit1fi}which sigh> /dev/nullif[$?-ne 0];thenecho"`sigh`がないようです。こちらのコマンドでインストールしてください。">&2echo"sudo gem install sigh">&2exit1fi# sudo gem update sigh# sudo gem update altoolsigh-a$BUNDLE_ID-u$APPLE_DEVELOPER_ID-q$PROVISIONING_FILE_NAMEcheckStatussigh resign$IPA_NAME--signing_identity$CERT_NAME-n$PROVISIONING_FILE_NAMEcheckStatuswhich altool> /dev/nullif[$?-ne 0];thenPATH=$PATH:$(dirname"$(find$(dirname$(xcode-select-p))-name altool |head-1)")ln-s"`xcode-select-p`/../Applications/Application Loader.app/Contents/itms" /usr/local/ checkStatusfialtool--upload-app--file$IPA_NAME--username$APPLE_DEVELOPER_ID#--password $PASSWORDcheckStatus(altoolの解決がモヤッとします。)
以上になります。
全体的に不明点やここおかしいなどあればコメント、編集リクエスト、もしくはTwitterでご連絡いただければと思います。お気軽にどうぞ。
参考
http://blog.kishikawakatsumi.com/entry/20141022/1413963656
こちらは岸川先生が一つのxcarchiveから複数の異なるコード署名(AdHoc用とAppStore用)をして配布と申請をしている記事です。xcodebuildだけでうまくいっているのは、Teamが同じだったからだと推測しています。
http://qiita.com/naotokui/items/9cd44475c37d0c3e722f
岸川先生と同じことをやろうとしてTeamが違ったためハマった事例かと思われます。結局AppleIDとかもらえたみたいなので、それだったらiTunesConnectに直接アップする、でも良さそうです。
http://stackoverflow.com/questions/18447064/xcodebuild-code-sign-error-provisioning-profile-even-though-all-profiles-are-in
こちらは xxx.mobileprovision からIDを取得する方法が書いてあったので助かりました。
http://blogs.zealot.co.jp/archives/1003
altoolが$PATHにないときの対処法。助かりました。
http://blog.ch3cooh.jp/entry/20150210/1423573065
altoolがiTMSTransporterを見つけられないでエラーになる時の対処法。助かりました。
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme



