ここ最近、CIにおいてfirebase login:ci
で取得できるトークンを利用することが非推奨になり、Workload Identity 連携を使用することが推奨されるようになりました。今回は、それを用いてFirebase Hostingに自動デプロイするワークフローを作る方法を解説します。
Table of Contents
- Firebaseの準備
- GitHubレポジトリの作成
- Workload Identity 連携の設定
- サービスアカウントの作成
- サービスアカウントとWI連携の紐付け
- ワークフローファイルの作成
- Pushする
Firebaseの準備
まず、Firebase ConsoleからFirebaseプロジェクトを作成します。Google アナリティクスについては必要に応じて有効化します。今回は有効にしませんでした。
次に、自分のPCでディレクトリを作成し、firebase init
します。選択内容は下を参照してください。
? Which Firebase features do you want to set up for this directory?
--> Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys
? Please select an option:
--> Use an existing project
? Select a default Firebase project for this directory:
--> workload-test-xxxxx (workload-test)
? What do you want to use as your public directory?
--> public
? Configure as a single-page app (rewrite all urls to /index.html)?
--> No
? Set up automatic builds and deploys with GitHub?
--> No
GitHubレポジトリの作成
GitHubでレポジトリを作成しておきます。方法については割愛します。
Workload Identity 連携の設定
Google Cloud Platform ConsoleからWorkload Identity 連携の設定をします。こちら にアクセスしてください。
「使ってみる」をクリックします。
「名前」を「GitHub Actions」にし*1、「続行」をクリックします。
*1 名前は任意ですが、今後この名称を使用して説明するため同じにすることを推奨します。
以下のように入力して「続行」をクリックします。
名称 | 値 |
---|---|
プロバイダの選択 | OpenID Connect (OIDC) |
プロバイダ名 | GitHub |
発行元(URL) | https://token.actions.githubusercontent.com |
オーディエンス | 許可するオーディエンス |
対象1 | 自身のGitHubプロフィールURL(https://github.com/<ユーザー名> の形式) |
属性マッピングで以下のように設定します。(「マッピングを追加」をクリックすると2個目が表示されます)
OIDC | |
---|---|
google.subject | assertion.sub |
attribute.repository | assertion.repository |
次に、「属性条件」で「条件を追加」をクリックし、「条件CEL」に'<GitHubユーザー名>/<レポジトリID>' == attribute.repository
の形式で入力します。
サービスアカウントの作成
次に、デプロイ用のサービスアカウントを作成します。コンソール上ではこのアカウントでデプロイしたことになります。左のメニューから「サービスアカウント」を選択し、上部の「サービスアカウントの作成」をクリックします。
まず、サービスアカウント名に「github-actions」など適当な名前を設定し、「作成して続行」をクリックします。次に、「このサービス アカウントにプロジェクトへのアクセスを許可する」で「ロールを選択」から以下の2つを追加します。
- サービス アカウント ユーザー
- Firebase Hosting 管理者
Firebase Cloud Functionsも利用している場合、以下の3つも必要になる場合があります。
- Cloud Functions 管理者
- Cloud Scheduler 管理者
- Secret Manager 管理者
最後に「続行」「完了」をクリックします。
(※ロール設定は「IAMと管理」画面の左メニュー下「リソースの管理」→プロジェクトを選択→右側の情報パネルから編集できます。ロールを追加する場合は「プリンシパルの追加」から「新しいプリンシパル」にサービスアカウントIDを入力します。)
サービスアカウントとWI連携の紐付け
次に、この2つを紐付けます。左メニューから「Workload Identity 連携」をクリックし、先程作成したWIプール(GitHub Actions)をクリックし、上部の「アクセスを許可」をクリックします。「サービスアカウント」から先程作成したサービスアカウントを選択し、「保存」をクリックします。
ワークフローファイルの作成
ここでやっとワークフローを作成します。.github/workflows/deploy.yml
ファイルを作成してください。以下が雛形になります。
name: Deploy
on:
push:
branches:
- main
workflow_dispatch:
repository_dispatch:
env:
workload_identity_provider: <Workload Identity プロバイダー>
service_account: <サービスアカウントID>
jobs:
deploy-to-hosting:
name: "Deploy to Hosting"
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
cache: yarn
- name: Install Firebase CLI
run: yarn global add firebase-tools
- name: 'Authenticate to Google Cloud'
id: auth
uses: 'google-github-actions/auth@v0'
with:
workload_identity_provider: ${{ env.workload_identity_provider }}
service_account: ${{ env.service_account }}
audience: https://github.com/<GitHubユーザー名>
- name: Deploy to Firebase Hosting
run: firebase deploy --only hosting
「Workload Identity プロバイダー」は以下の形式に従ってください。
projects/<プロジェクトID>/locations/global/workloadIdentityPools/<WIプールのID(github-actions)>/providers/<プロバイダーID(github)>
「サービスアカウントID」は左メニュー「サービスアカウント」より先程作成したサービスアカウントをクリックすると表示されるメールアドレスです。
肝は
permissions:
contents: read
id-token: write
の部分です。これがないと認証に失敗します。
お気づきかもしれませんが、そう。トークンなどの機密情報を人の手で管理する必要が一切ありません。設定を適切にすれば Workload Identity プロバイダーやサービスアカウントIDだけ知っていても誰も悪用できないため、ハードコードしても全く問題ありません。設定はめちゃくちゃ面倒臭いですが、セキュリティは最強です。
Pushする
最後に、このディレクトリをGitHubにPushすれば、public以下がデプロイされるはずです。めでたしめでたし。