つばくろぐ @takamii228

知は力なり

macOSにインストール済みのプロビジョニングプロファイルの情報を確認する

Apple Developer Programで発行したプロビジョニングプロファイル(*.mobileprovisionのファイル)はXcode経由だったりファイル自体のダブルクリックでmacOS端末へインストールされ、ipaファイル作成のときに利用されます。

今回、複数のプロビジョニングプロファイルを複数のmacOS端末にインストールして管理する必要があったので、すべてのプロファイルがすべてのマシンにきちんとインストール済みか否かを確認したくなりました。そのときに調べた結果をまとめます。

プロビジョニングプロファイルのインストール先

プロビジョニングプロファイルはインストールすると以下のフォルダに${UUID}.mobileprovisionというファイル名で保存されます。

$ ls $HOME/Library/MobileDevice/Provisioning\ Profiles/*                                                  
/Users/takami228/Library/MobileDevice/Provisioning Profiles/1018cb3f-51c0-4ac2-9f70-81af1e7a52c1.mobileprovision
/Users/takami228/Library/MobileDevice/Provisioning Profiles/2f3a3f52-13af-4a6c-937d-10028146d5ae.mobileprovision
/Users/takami228/Library/MobileDevice/Provisioning Profiles/3d943dc2-ce76-4fb1-a70e-aba05ad9fbc6.mobileprovision
/Users/takami228/Library/MobileDevice/Provisioning Profiles/40acedbd-366c-405d-9a58-ff1b5bd7645e.mobileprovision
/Users/takami228/Library/MobileDevice/Provisioning Profiles/4a898d9e-bae1-448f-b4d0-02fc90cb9bb5.mobileprovision
/Users/takami228/Library/MobileDevice/Provisioning Profiles/701406dd-b5eb-45eb-8096-45bea60f8020.mobileprovision
/Users/takami228/Library/MobileDevice/Provisioning Profiles/737b93bf-b562-4cc3-b8db-126b2e52016d.mobileprovision
/Users/takami228/Library/MobileDevice/Provisioning Profiles/8eedc147-de04-437c-a0dc-00ce0c863764.mobileprovision
/Users/takami228/Library/MobileDevice/Provisioning Profiles/900f557d-6536-46fb-8e17-9fe1b3b08a51.mobileprovision
/Users/takami228/Library/MobileDevice/Provisioning Profiles/bcd30cf8-8386-4f88-9fca-d1128e144eac.mobileprovision
/Users/takami228/Library/MobileDevice/Provisioning Profiles/c1d35546-c60e-40a7-9736-918613eecede.mobileprovision
/Users/takami228/Library/MobileDevice/Provisioning Profiles/c5e116cc-2584-473e-ac67-75a723893266.mobileprovision
/Users/takami228/Library/MobileDevice/Provisioning Profiles/daacc73a-41ce-4367-b2b2-5b97bef776de.mobileprovision

プロビジョニングプロファイルの中身を確認する

プロビジョニングプロファイルの中身はそのままだと表示できません。securityコマンドを使うことでplistファイル形式のテキストに変換ができます。

$ security cms -D -i /Users/takami228/Library/MobileDevice/"Provisioning Profiles"/1018cb3f-51c0-4ac2-9f70-81af1e7a52c1.mobileprovision
<?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>AppIDName</key>
    <string>flutteripatest</string>
    <key>ApplicationIdentifierPrefix</key>
    <array>
    <string>xxxxxxxx</string>
    </array>
    <key>CreationDate</key>
    <date>2021-07-02T04:56:27Z</date>
    <key>Platform</key>
    <array>
        <string>iOS</string>
    </array>
    <key>IsXcodeManaged</key>
    <false/>
         ...
</dict>
</plist>%  

plistファイルをJSON形式に変換してほしい情報を出力する

plistファイルはxmlチックなデータ形式になっているのでそのままだと扱いにくいです。PlistBuddyをコマンドを使っても良いのですが、securityコマンドとパイプでつないで利用したい場合は一度テキスト出力しないといけないので面倒です。

そこでplutilコマンドで無理やりJSON形式に変換してjqコマンドで必要な情報を出力することにします。

こちらのstackoverflowの記事が参考になりました。

stackoverflow.com

$ security cms -D -i "/Users/takami228/Library/MobileDevice/Provisioning Profiles/1018cb3f-51c0-4ac2-9f70-81af1e7a52c1.mobileprovision" | \
    sed -Ee 's#<(\/)?dat[ae]>#<\1string>#g' | plutil  -convert json -r -o - -- -
{
  "AppIDName" : "flutteripatest",
  "ApplicationIdentifierPrefix" : [
    "xxxxx"
  ],
  "CreationDate" : "2021-07-02T04:56:27Z",
  "DER-Encoded-Profile" : 
   ....
}%                                                                                                                                            

しかし出力されたjson形式のうちBundleIDを表すキーとして"application-identifier"があるのですが、こちらはハイフンを含むのでjqコマンドを通すとエラーになっています。そこで"application_identifier"というアンダースコアに置換することでjqコマンドをパイプすることにします。

$ security cms -D -i "/Users/takami228/Library/MobileDevice/Provisioning Profiles/1018cb3f-51c0-4ac2-9f70-81af1e7a52c1.mobileprovision" | \
    sed -Ee 's#<(\/)?dat[ae]>#<\1string>#g' | plutil  -convert json -r -o - -- - | \
    sed -Ee s/"application-identifier"/"application_identifer"/g | \
    jq -r
{
  "AppIDName": "flutteripatest",
  "ApplicationIdentifierPrefix": [
    "xxxxxxx"
  ],
  "CreationDate": "2021-07-02T04:56:27Z",
  "DER-Encoded-Profile": 
  ....
  "Entitlements": {
    "application_identifer": "xxxxxxxxxx.com.takamiii.flutter.ipa",
    "com.apple.developer.team-identifier": "xxxxx",
    "get-task-allow": true,
    "keychain-access-groups": [
      "xxxxx.*",
      "com.apple.token"
    ]
  },
  "ExpirationDate": "2022-07-02T04:56:27Z",
  "IsXcodeManaged": false,
  "Name": "flutteripa",
  "Platform": [
    "iOS"
  ],
  "ProvisionedDevices": [
    "xxx",
    "xxx",
    "xxx"
  ],
  "TeamIdentifier": [
    "xxxx"
  ],
  "TeamName": "Masanori Takami",
  "TimeToLive": 365,
  "UUID": "1018cb3f-51c0-4ac2-9f70-81af1e7a52c1",
  "Version": 1
}

あとはmobileprovisioningファイルが置かれているフォルダでforループを回せばインストール済みのプロファイル情報一覧が取得できます。 例えばBundleID(application-identifier)とprovisining profileのUUIDと有効期限を一括出力する場合は以下のようにかけます。

#!/bin/sh

for filepath in $HOME/Library/MobileDevice/"Provisioning Profiles"/*; do
  security cms -D -i "${filepath}" | sed -Ee 's#<(\/)?dat[ae]>#<\1string>#g' | \
    plutil  -convert json -r -o - -- - | \
    sed -Ee s/"application-identifier"/"application_identifer"/g | \
    jq -r '. | .Entitlements.application_identifer + " " + .UUID + " " + .ExpirationDate'
done

出力は以下のようになります。

$ ./run.sh 
xxxxxxxxxx.com.takamiii.flutter.ipa 1018cb3f-51c0-4ac2-9f70-81af1e7a52c1 2022-07-02T04:56:27Z
xxxxxxxxxx.com.takamiii.appcentersample 2f3a3f52-13af-4a6c-937d-10028146d5ae 2021-04-05T06:11:07Z
xxxxxxxxxx.takamii228.GeoLocationTracking 3d943dc2-ce76-4fb1-a70e-aba05ad9fbc6 2019-03-08T12:29:30Z
xxxxxxxxxx.com.takamiii.xcodevalidate 40acedbd-366c-405d-9a58-ff1b5bd7645e 2021-12-05T05:52:12Z
xxxxxxxxxx.* 4a898d9e-bae1-448f-b4d0-02fc90cb9bb5 2021-12-05T06:44:01Z
xxxxxxxxxx.com.takamiii.firebaseAppDistribution 701406dd-b5eb-45eb-8096-45bea60f8020 2022-01-10T06:12:26Z
xxxxxxxxxx.com.takamiii.flutter.ipa 737b93bf-b562-4cc3-b8db-126b2e52016d 2021-12-05T05:52:12Z
xxxxxxxxxx.com.takamiii.appcentersample 8eedc147-de04-437c-a0dc-00ce0c863764 2022-10-18T11:46:36Z
xxxxxxxxxx.com.takamiii.firebaseAppDistribution 900f557d-6536-46fb-8e17-9fe1b3b08a51 2022-01-10T06:11:03Z
xxxxxxxxxx.com.takamiii.appcentersample bcd30cf8-8386-4f88-9fca-d1128e144eac 2022-10-18T11:45:27Z
xxxxxxxxxx.com.takamiii.xcodevalidate c1d35546-c60e-40a7-9736-918613eecede 2021-12-05T06:05:12Z
xxxxxxxxxx.com.takamiii.xcodevalidate c5e116cc-2584-473e-ac67-75a723893266 2021-12-05T06:43:38Z
xxxxxxxxxx.com.takamiii.push-test daacc73a-41ce-4367-b2b2-5b97bef776de 2021-07-13T04:32:53Z

あとは出力結果を比較すればプロファイルがインストールされているかのチェックコマンドとして活用できそうですね。

ネイティブアプリをCLIでVisual Studio App Centerにアップロードする

以前Visual Studio App Centerを使って継続的にアプリ配信を行う記事を公開していました。

takamii.hatenablog.com

こちらの記事で紹介していたアップロード方法に変更があったようなので修正記事を公開します。

アップロードに失敗する

以前紹介したcurlでのAPIリクエストではファイルアップロードのAPIリクエストが443エラーになるようになりました。

...
*   Trying 52.177.49.80...
* TCP_NODELAY set
* Connection failed
* connect to 52.177.49.80 port 443 failed: Operation timed out
* Failed to connect to upload.appcenter.ms port 443: Operation timed out
* Closing connection 0
curl: (7) Failed to connect to upload.appcenter.ms port 443: Operation timed out

どうやらアップロード方法が変わった模様です。

確認したらファイルアップロードのエンドポイントが先日のメンテナンスでクローズされていました。

status.appcenter.ms

公式サイトの手順もアップロードで利用するAPIrelease_uploads から /uploads/releases に変わっていました。

docs.microsoft.com

APIリファレンスでも /releases_uploads はDeprecatedになっています。

openapi.appcenter.ms

公式リンクに沿ってAPIリクエストを組み直そうと思ったのですが、思った以上に処理が複雑になっていたので素直にappcenter cliを使うことにします。

appcenter cliの設定

公式リンクに従ってインストールします。npm経由でのインストールになるのでNode.jsの環境が必要です。anyenvなどで環境構築しておくとよいでしょう。

docs.microsoft.com

インストールした環境は以下の通りです。

$ node -v
v14.18.1

$ appcenter --version
appcenter version 2.10.3

認証情報の設定はAPI Tokenを利用することにします。--tokenで引数指定するか APPCENTER_ACCESS_TOKEN環境変数を利用すればよいようです。

最初のアクセス時には以下の利用状況の把握の確認が出ます。

App Center CLI would like to collect data about how users use CLI commands and some problems they encounter. Participation is
voluntary and when you choose to participate your device automatically sends information to Microsoft about how you use App
Center CLI.
For more information, please see our privacy policy at https://aka.ms/mobilecenterprivacy

? Enable telemetry?  (Y/n)

CDパイプラインでの実行では邪魔なので --disable-telemetry オプションをつけます。

アップロードのコマンドは以下の様になります。-aでオーナ名/プロジェクト名、-fでファイルパス、-rでリリースノート、-gで配信グループ名を指定します。

appcenter distribute release -a ${OWNER_NAME}'/'${ANDROID_PROJECT_NAME} \
   -f ${ANDROID_APK_FILE_PATH} -r ${RELEASE_TAG_NAME} -g ${ANDROID_TESTER_GROUP_NAME} \
   --disable-telemetry --token ${APPCENTER_ACCESS_TOKEN}

以前まとめたシェルスクリプトは以下のように修正できます。

#!/bin/sh

set -x
set -e

# タグ名
RELEASE_TAG_NAME=${1}

# APK ファイルパス
ANDROID_APK_FILE_PATH=${2}

# ipa ファイルパス
IOS_IPA_FILE_PATH=${3}

# Visual Studio App Centerのパラメータ
APPCENTER_ACCESS_TOKEN='xxxxxxxx'
OWNER_NAME='takamii228'
ANDROID_PROJECT_NAME='AndroidSample'
IOS_PROJECT_NAME='iOSSample'
ANDROID_TESTER_GROUP_NAME='Collaborators'
IOS_TESTER_GROUP_NAME='Collaborators'

# upload android file
appcenter distribute release -a ${OWNER_NAME}'/'${ANDROID_PROJECT_NAME} \
   -f ${ANDROID_APK_FILE_PATH} -r ${RELEASE_TAG_NAME} -g ${ANDROID_TESTER_GROUP_NAME} \
   --disable-telemetry --token ${APPCENTER_ACCESS_TOKEN}

echo "App file ${ANDROID_APK_FILE_PATH} was released in Visual Studio App Center in Project: ${ANDROID_PROJECT_NAME} for TAG: ${RELEASE_TAG_NAME} to Group: ${ANDROID_TESTER_GROUP_NAME}"

# upload ios file
appcenter distribute release -a ${OWNER_NAME}'/'${IOS_PROJECT_NAME} \
   -f ${IOS_IPA_FILE_PATH} -r ${RELEASE_TAG_NAME} -g ${IOS_TESTER_GROUP_NAME} \
   --disable-telemetry --token ${APPCENTER_ACCESS_TOKEN}

echo "App file ${IOS_PROJECT_NAME} was released in Visual Studio App Center in Project: ${IOS_PROJECT_NAME} for TAG: ${RELEASE_TAG_NAME} to Group: ${IOS_TESTER_GROUP_NAME}"

実行方法は以下になります。

./upload-appcenter.sh 1.1.0-dev ./app-release.apk ./appcentersample.ipa

無事AndroidiOSともにアップロードできました。

appcenter cliを使ったほうが断然シンプルですね。Node.jsへ依存してしまいますが自前でcurlでやるほうが大変なのでこちらに置き換えるとよいでしょう。

LinuxからApp Store Connectへipaファイルをアップロードする

以前Windowsからipaファイルをアップロードする方法を検証したので、Linuxでもやってみることにします。

takamii.hatenablog.com

検証環境

今回もTransporterのCLIを使います。

help.apple.com

必要となる環境の要件は以下の通りです。

System and network requirements
Apple supports Transporter on the following operating systems:

macOS 10.6 or later (64-bit system)

Microsoft Windows 7, 8, 10 or later (64-bit system)

Red Hat Enterprise Linux (64-bit system)

To install and run Transporter, you should have:

150 megabytes (MB) of available disk space and 2GB of RAM

A 2048MB maximum heap size, by default

また Transporter is Apple’s Java-based command-line tool for large catalog deliveries. とあるのでJavaも必要そうです。

OSはRed Hat Enterprise Linuxとありますが、今回はAWSのEC2で動くか試してみたいと思います。

環境構築

AWSのEC2をAmazon Linux2で立ち上げて接続し、Javaをインストールします。

$ yum install java

AWSなのでCorrettoが降ってきますね。

$ java -version
openjdk version "11.0.12" 2021-07-20 LTS
OpenJDK Runtime Environment Corretto-11.0.12.7.1 (build 11.0.12+7-LTS)
OpenJDK 64-Bit Server VM Corretto-11.0.12.7.1 (build 11.0.12+7-LTS, mixed mode)

Transporterのインストール手順を順番に実行していきます。

インストールのシェルスクリプトをダウンロードする必要があるのですが、これはApple Developer Programの認証が必要なので、macOSでダウンロードしたものをLinuxにアップロードすることにします。

$ sudo sh iTMSTransporter_installer_linux_2.2.0.10.sh 

を実行すると利用許諾のプロンプトがでるので許可します。するとコマンドが実行できるようになりました。

$ /usr/local/itms/bin/iTMSTransporter -version
[2021-09-04 11:53:59 UTC] <main> DEBUG: DataCenters already set by: defaultProperties
[2021-09-04 11:54:01 UTC] <main>  INFO: Configuring logging...
[2021-09-04 11:54:01 UTC] <main>  INFO: Logging level set to off
 
iTMSTransporter, version 2.2.0
 
[2021-09-04 11:54:05 UTC] <main> DBG-X: Returning 0

ipaファイルをアップロードする

macOSで作成したipaファイルを構築したEC2へアップロードしてTransporterコマンドを実行してみます。 AppStoreInfo.plist が必要な点とパスワードはApple IDのApp用パスワードな点に要注意です。

$ /usr/local/itms/bin/iTMSTransporter -m upload -assetFile ./sample.ipa -u "xxxxx" \
   -p "xxxxx" -assetDescription ./AppStoreInfo.plist -v eXtreme

実行すると以下のようなログがでて、数秒後に無事アップロードが成功していることが確認できました。

[2021-09-04 12:14:18 UTC] <main> DEBUG: DataCenters already set by: defaultProperties
[2021-09-04 12:14:20 UTC] <main>  INFO: Configuring logging...
[2021-09-04 12:14:20 UTC] <main>  INFO: Logging level set to eXtreme
[2021-09-04 12:14:25 UTC] <main> DEBUG: SMART-CLIENT: initializing data center locking ops: [authenticateForSession, validateAssets]
[2021-09-04 12:14:25 UTC] <main> DEBUG: SMART-CLIENT: initializing data centers with: [contentdelivery01.itunes.apple.com]
[2021-09-04 12:14:25 UTC] <main>  INFO: iTMSTransporter : iTunes Store Transporter [2.2.0]
[2021-09-04 12:14:25 UTC] <main>  INFO: OS identifier: Linux 4.14.243-185.433.amzn2.x86_64 (amd64); jvm=14.0.2+12-46; jre=14.0.2+12-46
[2021-09-04 12:14:25 UTC] <main>  INFO: Memory: [JVM] 958M free, 989M total, 1979M max [System] (Physical) 69M free, 983M total (Swap) 0 free, 0 total
[2021-09-04 12:14:25 UTC] <main> DBG-X: Memory: [JVM] 958M free, 989M total, 1979M max [System] (Physical) 69M free, 983M total (Swap) 0 free, 0 total
[2021-09-04 12:14:25 UTC] <main> DBG-X: Using operation named: authenticateForSession
[2021-09-04 12:14:25 UTC] <main> DBG-X: Apple's web service operation input parameters:
...
[2021-09-04 12:14:50 UTC] <main>  INFO: Done performing uploadDone notification to Apple.
[2021-09-04 12:14:50 UTC] <main>  INFO: Transporter's command line arguments are: -m upload -assetFile ./sample.ipa -u xxxxx -p **hidden value** -assetDescription ./AppStoreInfo.plist -v eXtreme
[2021-09-04 12:14:50 UTC] <main>  INFO: The package: /tmp/DeveloperAPIUpload587828657019442221/1574836491.itmsp has been successfully uploaded.



Package Summary:
 
1 package was uploaded successfully:
    /tmp/DeveloperAPIUpload587828657019442221/1574836491.itmsp

App Store Connectにもアップロードされていることを確認しました。

f:id:takamii228:20210904212911p:plain

以上の検証から、Amazon Linux上でもApp Store Connectにipaファイルがアップロードできることがわかりました。アップロード用にTransporterを構築済みのコンテナを作っておけばAWS CodeBuildで利用できそうですね。

まとめ

何らかの闇の力によってXcodeからのipaファイルのアップロードがブロックされている環境では、ipaファイルをS3などを経由してAWS CodeBuildからアップロードするCDパイプラインを作ればよさそうです。macOS on EC2は高いですしね。

わざわざそんなことしなくてもと思われた方が大半だと思うので、素直に自由なインターネットにつながっているmacOSからアップロードしましょう。

え?S3にはアップロードできるんだって?いいツッコミですn(ry