Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

fastlane match を使用して iOS の証明書管理を行う

前書き

iOS 開発において「証明書」という単語を聞くだけでアレルギー反応を起こす人も少なくないかもしれません。
iOS 開発チームにメンバーが追加された際は、少なくとも以下のような作業を行ってもらう(もしくは、行う)必要があります。

  • Apple Developer アカウントの作成
  • Apple Develper Portal(以下、Dev Portal)にメンバーを招待
  • コード署名証明書(以下、証明書)の作成
  • プロビジョニングプロファイル(以下、プロファイル)の更新

これらの作業を手動で行うのには非常に手間がかかります。
Xcode 8 から Automatic Signing が導入されましたが、証明書管理が iOS 開発チームの各メンバーに依存することにより発生する証明書周りのトラブルは後を絶ちません。個人開発では発生しなかったトラブルがチーム開発では付いて回ります。
また、CI 上で証明書とプロファイルをどのように扱うかといった課題も残ります。

そこで fastlane match(以下、match) です。
match のアプローチについてはこちらに記載されています。

match とは

match は、iOS 開発チームで共通の証明書とプロファイルの作成や維持を行い、プライベートリポジトリに格納、そして全ての開発者間で共有できるようにします。
つまり、メンバーが増える度に Apple Developer アカウントや証明書を作成する必要がなくなります。

構成は以下をご覧下さい。

fastlane match
ざっくり説明すると、以下の2点が運用される状態を作ろうと思いました。
- adminに任命された人は、matchを使って証明書& Provisioning Profile の作成&commitを行う
- memberは、matchを使って証明書& Provisioning Profile をダウンロードして使う

引用元:fastlane match でiOSアプリ開発者を「証明書管理の苦しみ」から解放せよ! - BizReach Tech Blog

match の導入

インストール

match は fastlane の action のため、fastlane をインストールすることで match を使用することができます。
fastlane は RubyGems や Homebrew を利用してインストールすることができます。
Gemfile を使用するにはこちらを参照して下さい。

# Using RubyGems
sudo gem install fastlane -NV

# Alternatively using Homebrew
brew cask install fastlane

事前準備

プライベートリポジトリの作成

証明書やプロファイルを保存するためのプライベートな Git リポジトリを作成します。
リポジトリ名は certificates などにします。

Apple Developer アカウントの用意

チーム全体で共有する Apple Developer アカウントを用意します。(例:office@company.com
権限を App Manager にして下さい。

App Manager 以上の権限でないと、match を実行した際に以下のようなエラーが発生する場合があります。

[App Store Connect unification] Spaceship::UnexpectedResponse: [!] Apple provided the following error info: Access Unavailable - You currently don't have access to this membership resource

詳しくは、こちらをご覧下さい。

Xcode プロジェクト設定

Xcodeプロジェクトのプロファイルを自動に設定しないでください。常に正しいプロファイルが選択されるわけではありません。
Xcode プロジェクト設定「 General > Automatically manage signing 」を無効にしておきましょう。

詳しくは、こちらをご覧下さい。

App ID の用意

iOS アプリのための App ID を用意します。

produce を使用することで、Dev Portal と App Store Connect の両方に新しい iOS アプリを作成することが可能です。また、アプリケーションサービスの変更やアプリケーショングループの変更も可能です。

-a もしくは --app_identifier オプションを使用して、アプリの Bundle Identifier を指定できます。

fastlane produce -a <app_identifier>

-i もしくは --skip_itc オプションを使用して、App Store Connect でのアプリ作成をスキップできます。

fastlane produce -a <app_identifier> -i

メンバーの権限設定

App Store Connect の「ユーザーとアクセス」でメンバーの権限を設定できます。
「デベロッパーリソース」の項目から証明書やプロファイルのアクセス権限を設定することが可能です。

スクリーンショット 2020-04-10 15.58.36.png

こちらにチェックが付いているメンバーは Xcode 上から証明書の更新が可能となってしまいます。
誤って更新されることを防ぐために、管理者ではないメンバーにはアクセス権限を与えないことをお勧めします。

「Certificates, Identifiers & Profile (証明書、ID & プロファイル)」へのアクセスは、組織のチームのメンバーである、App Manager または Developer の役割を持つユーザに追加で割り当てることができる特権です。この権限が追加されたユーザは、すべての App に関連付けられた証明書、ID、およびプロファイルを表示できます。

引用元:役割の権限 - App Store Connect ヘルプ

初期設定

match を使用するための初期設定を行います。

fastlane match init

Git リポジトリの URL や、パスフレーズが要求されるため入力して下さい。

証明書やプロビジョニングプロファイルは openssl を使用してパスフレーズによって暗号化され、Git リポジトリに保存されます。
そのため、パスフレーズはチームに共有する必要があります。
環境変数を使用して復号化するようにパスフレーズを設定するには、MATCH_PASSWORD を使用します。

また、上記コマンドを実行すると、カレントディレクトリに Matchfile が作成されます。
fastlane init を実行したプロジェクト(以下、fastlane プロジェクト)のプロジェクトルートで上記コマンドを実行した場合は ./fastlane/ に作成されます。

match の実行

fastlane プロジェクトのプロジェクトルート外で match を実行した場合、チーム全体で共有する Apple Developer アカウントの Apple ID や、アプリの Bundle Identifier が要求されるため入力して下さい。
入力を省略したい場合は、カレントディレクトリの Matchfile を修正して下さい。

Matchfile
app_identifier("<app_identifier>")
username("<username>")

作成

証明書とプロビジョニングプロファイルを作成します。
基本的に管理者が行う作業です。

$ fastlane match development
$ fastlane match adhoc
$ fastlane match appstore
Fastfile
match(type: "development")
match(type: "adhoc")
match(type: "appstore")

既存の証明書とプロファイルを残したまま、match で作成した証明書とプロファイルを混在させ、徐々に移行することも可能です。

match を実行した例は以下をご覧下さい。

match appstore small

引用元:match - fastlane docs

具体的な処理の流れ

上記コマンドの具体的な処理の流れは以下をご覧下さい。

  1. Dev Portal に証明書とプロファイルを作成
  2. Git リポジトリに証明書(とその秘密鍵)とプロファイルを格納
  3. プロビジョニングプロファイルが ~/Library/MobileDevice/Provisioning Profiles にインストール
  4. 証明書と秘密鍵が、キーチェーンにインストール

※ 既に証明書とプロビジョニングプロファイルが作成されている場合は更新されます。

リポジトリの構造

上記コマンド実行後、Git リポジトリには2つのディレクトリが含まれます。

  • 証明書とその秘密鍵を含む certs ディレクトリ
  • プロビジョニングプロファイルを含む profiles ディレクトリ

具体的にどのような構造になるか確認したい場合は、こちらのサンプルを参照して下さい。

取得

Git リポジトリから証明書とプロビジョニングプロファイルのインストールを行います。
基本的にメンバーが行う作業です。
新規メンバーのマシンに証明書とプロビジョニングプロファイルをインストールしたい場合など、Dev Portal にアクセスする必要がない場合は --readonly オプションを使用します。

$ fastlane match development --readonly
Fastfile
match(type: "development", readonly: true)

削除

無効や期限切れ、Xcode によって管理された証明書やプロビジョニングプロファイルを Dev Portal から削除します。

$ fastlane match nuke
$ fastlane match nuke development
$ fastlane match nuke distribution

削除される予定の証明書とプロファイルのリストが表示され、削除するかどうかの確認が要求されるため、yn を入力して下さい。
y を入力し削除しても、App Store と TestFlight で既に利用可能なアプリは引き続き機能します。

※ 初めて match を実行する前に、上記コマンドを使用して既存の証明書とプロファイルの消去を考慮することが推奨されています。match の検証や、既存の証明書とプロファイルを残したい場合は上記コマンドの使用はお勧めしません。

nuke を実行した例は以下をご覧下さい。

match nuke

引用元:match - fastlane docs

パスフレーズの変更

パスフレーズを変更します。

$ fastlane match change_password

実行後、全てのマシンで新しいパスフレーズが要求されます。

新しいデバイスの登録

register_device を使用することで、Dev Portal に新しいデバイスを登録することが可能です。

$ fastlane run register_device name:"<name>" udid:"<udid>"
Fastfile
register_device(
  name: "<name>",
  udid: "<udid>"
)

--force_for_new_devices オプションを使用して、Dev Portal のデバイス数が変更されたかどうかを確認し、必要に応じてプロビジョニングプロファイルを自動的に更新します。

$ fastlane match development --force_for_new_devices
$ fastlane match adhoc --force_for_new_devices
Fastfile
match(type: "development", force_for_new_devices: true)
match(type: "adhoc", force_for_new_devices: true)

証明書の更新

証明書の有効期限は1年です。
証明書の期限が切れた状態で match を実行すると、以下のようなエラーが発生します。

[!] Your certificate 'XXXXXXXXXX.cer' is not valid, please check end date and renew it if necessary

以下の二つのソリューションどちらかの実施後に match を再度実行すると、新しい証明書とプロファイルが再作成されます。
基本的に管理者が行う作業です。
証明書の更新が完了したらメンバーに fastlane match development --readonly を実行して最新の証明書を取得するよう促してください。

1. 証明書とプロビジョニングプロファイルを fastlane match nuke で削除

前述した nuke を使用して証明書とプロビジョニングプロファイルを全て削除します。
※ nuke は特定の証明書または App ID を選択して削除することはできません。

$ fastlane match nuke development
$ fastlane match nuke distribution

※ 破壊的なため、実施する際は自己責任でお願いします。

2. 証明書とプロビジョニングプロファイルをプライベートリポジトリから手動で削除

特定の証明書やプロビジョニングプロファイル、アプリケーションのみを削除したい場合は、リポジトリ内のファイルを削除するだけです。

  • /certs/development/XXXXXXXXXX.cer
  • /certs/development/XXXXXXXXXX.p12
  • /profiles/development/Development_xxxxxxxxxx.mobileprovision

削除が完了したらリポジトリへプッシュします。

また、リポジトリ内の削除したファイルに対応する Dev Portal 上からプロビジョニングプロファイルを削除する必要があります。
※ Dev Portal 上からプロビジョニングプロファイルを削除しない場合、 ランダムな数字がサフィックスとして追加されたプロファイル名になります(fastlane が名前衝突を避けるため)。

CI で使用

取得

CI 上で match を実行するときは、常に --readonly オプションを使用することが推奨されています。

Fastfile
lane :beta do
  match(type: "appstore", readonly: is_ci)

  gym(scheme: "Release")
end

キーチェーンの作成

CI 上で match を実行するときは、キーチェーンを名前とパスワード付きで作成する必要があります。

詳しくは以下をご覧下さい。

具体的には、キーチェーンのパスワードを入力して許可する必要がありました。自分のマシンの場合はログインパスワードを入力すれば良いのですが、CIマシン上での場合は新しくキーチェーンを名前・パスワード付きで作成して、match実行時にそれを用いる、という手順が必要でした。

コードとしては、MATCH_KEYCHAIN_NAME・MATCH_KEYCHAIN_PASSWORDに適当な値を環境変数としてセットした上で、以下をmatchコマンド前に実行すれば解決しました。

引用元:Bitrise Xcode 8.1などのSierra製CIマシンとfastlaneの組み合わせでビルドが固まる問題が解決🎉

Fastfile
before_all do
  if is_ci?
    create_keychain(
      name: ENV['MATCH_KEYCHAIN_NAME'],
      password: ENV['MATCH_KEYCHAIN_PASSWORD'],
      timeout: 1800
    )
  end
end

※ AppStore のプロビジョニングプロファイルにはデバイス情報が含まれていないため、プロファイルタイプが appstore の場合無視されます。

参考文献

readyfor
想いをつなぎ、叶える未来を、つくる READYFORのOrganizationです
https://tech.readyfor.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away