🚀

Fastlaneを使ったiOSの証明書/プロファイル管理

2023/07/08に公開

前置き

iOS アプリの複数人開発で一番厄介なのが「証明書」周りですよね。
新しい開発メンバーが Join してくると、最小限でも以下の作業が発生してきます。

  • AppleDeveloper アカウントの新規作成
  • 新メンバーを DeveloperPortal へ招待
  • 証明書・プロビジョニングファイルの作成・更新

基本的には、AutomaticSigning によって自動的に証明書・プロビジョニングファイル周りが設定されますが、厳密なプロジェクトだと証明書を新規作成してはならない。などの制約がある場合があります。

また、CI/CD を運用している場合、どうやって CI 上で証明書・プロビジョニングファイルを扱うかといった問題も発生してきます。

そこで、今回は fastlanematch を使って証明書を管理するようにして、簡単に証明書・プロビジョニングファイルの共有・更新を行えるようにします。

Fastlane

Fastlane とは iOS/Android で必要な様々な作業を自動化してくれる便利ツールです。

https://fastlane.tools/

  • ipa/apk ファイルの作成
  • AppStoreConnect/GooglePlay へアプリのアップロード
  • AppStoreConnect/GooglePlay へのメタデータ登録・更新
  • テスト実行
  • iOS の証明書・プロビジョニングファイル管理
  • AppDistribution/TestFlight などへのアップロード

Fastlane match

Fastlane の match とは、開発チームで共有の証明書・プロビジョニングファイル作成や更新を行い、プライベートリポジトリに格納して、全メンバーで共有できるようにするものです。

メンバーが追加されたら、fastlane match を使って、管理されている証明書・プロビジョニングファイルを自動で登録・更新してくれるようになるため、AppleDeveloper アカウントを作成したりなどの、面倒な作業をする必要がなくなります。

ざっとしたフローは以下のような感じになります。

導入手順

fastlane 導入には、homebrew や rubyGem を使う方法など、いくつかありますが、今回は rubyGem を利用する方法とします。

また、各バージョン管理には asdf を利用していますので、各環境に合わせて読み替えください 🙇‍♀

https://asdf-vm.com/

証明書管理用のリポジトリ作成

fastlane では証明書をリポジトリで管理するため、Private の専用リポジトリを先に準備しておく必要があります。

Ruby, Bundler の設定・インストール

ruby は 2.7.2 を使用します。

システムで利用する ruby のバージョンを変更する必要はないので、local(ワーキングディレクトリ直下のみ適用)で 2.7.2 を動かすようにします。

$ asdf install ruby 2.7.2
$ asdf local ruby 2.7.2

ruby の設定が終わったら、bundler をインストールします。

$ gem install bundler

fastlane のインストール

fastlane を rubyGem 経由でインストールするため、Gemfile を作成します。以下の内容をコピペしてもらえば大丈夫です。

Gemfile は、<project_name>.xcodeproj があるディレクトリに作成してください。

source "https://rubygems.org"

gem "fastlane"

plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)

Gemfile を作成したら、以下のコマンドを実行して、fastlane をインストールします。

$ asdf exec bundle update

fastlane の初期設定

以下のコマンドで fastlane を使用するための初期設定を行います。

コマンドを実行すると、どのように fastlane を初期設定するかの選択肢が表示されますので、「4」の手動設定を選択しておきます。

$ asdf exec bundle exec fastlane init
[✔] 🚀
[✔] Looking for iOS and Android projects in current directory...
[02:25:58]: Created new folder './fastlane'.
[02:25:58]: Detected an iOS/macOS project in the current directory: '<project_name>.xcodeproj'
[02:25:58]: -----------------------------
[02:25:58]: --- Welcome to fastlane 🚀 ---
[02:25:58]: -----------------------------
[02:25:58]: fastlane can help you with all kinds of automation for your mobile app
[02:25:58]: We recommend automating one task first, and then gradually automating more over time
[02:25:58]: What would you like to use fastlane for?
1. 📸  Automate screenshots
2. 👩‍✈️  Automate beta distribution to TestFlight
3. 🚀  Automate App Store distribution
4. 🛠  Manual setup - manually setup your project to automate your tasks
? 4

fastlane match の初期設定

証明書管理は fastlane の match を使って行うため、fastlane の設定が終わったら、match の初期設定を行います。

どの環境で証明書を管理するか聞かれるため、「1」の Git を選択します。

$ asdf exec bundle exec fastlane match init
[✔] 🚀
[02:31:47]: fastlane match supports multiple storage modes, please select the one you want to use:
1. git
2. google_cloud
3. s3
4. gitlab_secure_files
?  1

選択すると、リポジトリの URL を聞かれるので、https or ssh のコピペします。

[02:32:05]: Please create a new, private git repository to store the certificates and profiles there
[02:32:05]: URL of the Git Repo: <https or sshのリポジトリURL>

[02:36:51]: Successfully created './fastlane/Matchfile'. You can open the file using a code editor.
[02:36:51]: You can now run `fastlane match development`, `fastlane match adhoc`, `fastlane match enterprise` and `fastlane match appstore`
[02:36:51]: On the first run for each environment it will create the provisioning profiles and
[02:36:51]: certificates for you. From then on, it will automatically import the existing profiles.
[02:36:51]: For more information visit https://docs.fastlane.tools/actions/match/

AppStoreConnect API の設定

fastlane のみで証明書・プロビジョニングファイルを作成・削除・更新ができるわけではありません。

AppStoreConnect の API を利用することで、TestFlight 配信・ユーザーの追加などを行うことができます。

App Store Connect にアクセスし、「ユーザとアクセス」から「キー」タブをクリックします。

新しい API キーを生成する場合には、確認画面が表示されるので、内容を確認して「提出」ボタンをクリックすると、上記画面に遷移します。

image.png

「API キーを生成」をクリックすると、以下の API キー登録画面が表示されます。

image.png

「名前」にはどこで利用されている API キーなのかなど、識別しやすい名前を入力します。

「アクセス」では、API キーに付与する権限を設定します。fastlane では「App Manager」の権限を付与します。

image.png

API キーが生成されると、API へ接続するために必要な情報が表示されます。API キーをダウンロードをクリックして、キーをダウンロードします。

また、

  • Issuer ID
  • キー ID

は、fastlane の処理を記述する際に必要になるため、メモしておきます。

env ファイル作成の前準備

fastlane では、API に接続するために必要な情報を変数に渡す必要があります。

各接続情報をハードコードしてしまうと、Github に掲載されてしまうため、万が一のときにインシデントになってしまう場合があります。

そのため、接続情報などは全て env ファイルで管理するようにします。

先程ダウンロードした、キー情報も env ファイルに記述する必要がありますが、そのままの内容を記述するわけではなく、base64 化したものを env ファイルへ記述します。

以下のコマンドを実行して、API キー情報を base64 化します。出力された結果をメモしておきます。

$ cat AuthKey_KEYID.p8 | base64

env ファイルの作成

作成するファイルは 2 つです。

  • .env
  • .env.skel

.env は実際に値が入っているもの、.env.skel はどのようなキーを設定する必要があるのかの Skeleton ファイルとなります。

ひとまず .env.skel を作成します。

### 以下を .env.skel にコピー
ASC_KEY_ID=
ASC_ISSUER_ID=
ASC_KEY_CONTENT=
MATCH_PASSWORD=
FASTLANE_USER=

そして .env ファイルも作成して、AppStoreConnect API の情報(ASC_KEY_ID, ASC_ISSUER_ID, ASC_KEY_CONTENT)を含む設定値を設定します。

MATCH_PASSWORD は証明書に設定する Password になりますので、各自任意で設定してもらって大丈夫です。

FASTLANE_USER は AppleId になります。

また .env は Github で管理しませんが、.env.skel は管理したいため、以下の内容を .gitignore ファイルに追記します。

.env*
!.env.skel

Fastfile の修正

fastlane フォルダにある、Fastfile に fastlane で実行したい lane を記述します。

今回の Fastfile では、以下のことが実行できるようになっています。

できること 実行コマンド
Development 証明書・プロビジョニングファイルの作成・更新 make match_force_development
Development 証明書・プロビジョニングファイルの取得 make fetch_development_profiles
Development 証明書・プロビジョニングファイルの削除 make delete_development_profiles
Distribution 証明書・プロビジョニングファイルの作成・更新 make match_force_appstore
Distribution 証明書・プロビジョニングファイルの取得 make fetch_appstore_profiles
Distribution 証明書・プロビジョニングファイルの削除 make delete_appstore_profiles

以下を Fastfile へコピペします。初期化後の既存で書かれている内容は削除して問題ありません。

  • appstore_identifier(本番環境用 AppID)
  • dev_identifier(検証環境用 AppID)

の 2 項目については、各自プロジェクトに合わせてください。

# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
#     https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
#     https://docs.fastlane.tools/plugins/available-plugins
#

# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane

default_platform(:ios)

platform :ios do
  def asc_api_key
    app_store_connect_api_key(
      key_id: ENV['ASC_KEY_ID'],
      issuer_id: ENV['ASC_ISSUER_ID'],
      key_content: ENV['ASC_KEY_CONTENT'],
      is_key_content_base64: true
    )
  end

  def appstore_identifier
    "your.appstore.identifier"
  end

  def dev_identifier
    "your.development.identifier"
  end

  def dev_identifiers
    [appstore_identifier, dev_identifier]
  end

  def appstore_identifiers
    [appstore_identifier]
  end

  desc "create development cert and profiles"
  lane :match_force_development do
    api_key = asc_api_key
    match(
      api_key: api_key,
      type: "development",
      app_identifier: dev_identifiers,
      force: true
    )
  end

  desc "create appstore cert and profiles"
  lane :match_force_appstore do
    api_key = asc_api_key
    match(
      api_key: api_key,
      type: "appstore",
      app_identifier: appstore_identifiers,
      force: true
    )
  end

  desc "fetch development profiles and cert"
  lane :fetch_development_profiles do
    api_key = asc_api_key
    match(
      api_key: api_key,
      type: "development",
      app_identifier: dev_identifiers,
      readonly: true
    )
  end

  desc "fetch appstore profiles and cert"
  lane :fetch_appstore_profiles do
    api_key = asc_api_key
    match(
      api_key: api_key,
      type: "appstore",
      app_identifier: appstore_identifiers,
      readonly: true
    )
  end

  desc "delete development profiles and cert"
  lane :delete_development_profiles do
    api_key = asc_api_key
    match_nuke(
      api_key: api_key,
      type: "development",
      app_identifier: dev_identifiers
    )
  end

  desc "delete appstore profiles and cert"
  lane :delete_appstore_profiles do
    api_key = asc_api_key
    match_nuke(
      api_key: api_key,
      type: "appstore",
      app_identifier: appstore_identifiers
    )
  end
end

Makefile の作成

毎回 fastlane コマンドを打つのは面倒。かつ、様々な処理を実行した後に fastlane を実行したい。という場合を想定して、Makefile を作成します。

Makefile は Xcode プロジェクトファイルと同じ階層に配置します。(Gemfile とかと同じ階層)

基本的には、make コマンドを実行してもらうこととなります。

FASTLANE := bundle exec fastlane

match_force_development:
	$(FASTLANE) ios match_force_development

match_force_appstore:
	$(FASTLANE) ios match_force_appstore

fetch_development_profiles:
	$(FASTLANE) ios fetch_development_profiles

fetch_appstore_profiles:
	$(FASTLANE) ios fetch_appstore_profiles

delete_development_profiles:
	$(FASTLANE) ios delete_development_profiles

delete_appstore_profiles:
	$(FASTLANE) ios delete_appstore_profiles

おわりに

以上で、iOS プロジェクトでの Fastlane 組み込みが終わりました。

全てのプロジェクトで Fastlane を導入して、ストレスフリーな開発環境を作りましょう!

GitHubで編集を提案

Discussion