Mobile Factory Tech Blog

技術好きな方へ!モバイルファクトリーのエンジニアたちが楽しい技術話をお届けします!

google-github-actions/auth を使った GitHub Actions で Firebase へのセキュアデプロイ

こんにちは、エンジニアの夕凪です。

最近、 GitHub Actions が OIDC を正式サポートし、 AWS や GCP へのセキュアなデプロイが可能になりました。
そのうちの GCP の公式実装である google-github-actions/auth を使って、 Firebase へデプロイを行ってみたので、この記事ではそのやり方を解説します。

前提条件

この記事は以下の環境を前提としています。

GCP 側でやること

まずは GCP 側でサービスアカウントの準備などが必要なので、それらを作成していきましょう。
以下ちょっと特殊ですが、 fish shell からコマンドラインでの操作例を記載しておきます。

$ set -x PROJECT_ID <対象のGCPのプロジェクトID (Firebase のプロジェクトID)>
$ set -x SERVICE_ACCOUNT_NAME <発行するサービスアカウント名>

# まずは、 Service Account を発行します
$ gcloud iam service-accounts create $SERVICE_ACCOUNT_NAME --project $PROJECT_ID
Created service account [hogehoge]

$ set -x SERVICE_ACCOUNT "$SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com"

# ここでは最低限のロールを割り当てていきます
# 今回は Firebase Hosting と Firebase Functions を使用します
# GCP/Firebase 側より細かく設定したい場合は、代わりにそれらを設定してください
$ gcloud projects add-iam-policy-binding $PROJECT_ID --role="roles/iam.serviceAccountUser" --member "serviceAccount:$SERVICE_ACCOUNT"
$ gcloud projects add-iam-policy-binding $PROJECT_ID --role="roles/serviceusage.apiKeysViewer" --member "serviceAccount:$SERVICE_ACCOUNT"
$ gcloud projects add-iam-policy-binding $PROJECT_ID --role="roles/firebaserules.systen" --member "serviceAccount:$SERVICE_ACCOUNT"
$ gcloud projects add-iam-policy-binding $PROJECT_ID --role="roles/firebasehosting.admin" --member "serviceAccount:$SERVICE_ACCOUNT"
$ gcloud projects add-iam-policy-binding $PROJECT_ID --role="roles/cloudfunctions.developer" --member "serviceAccount:$SERVICE_ACCOUNT"

# IAM Service Account Credentials API を有効にします
$ gcloud services enable iamcredentials.googleapis.com --project $PROJECT_ID

# Workload Identity Pool の作成をし、その ID を取得します
$ set -x POOL_NAME <Workload Identity Pool の名前; なんでも OK>

$ gcloud iam workload-identity-pools create $POOL_NAME --project=$PROJECT_ID --location="global" --display-name=$POOL_NAME
$ gcloud iam workload-identity-pools describe "github-actions-pool"  --project=$PROJECT_ID --location="global" --format="value(name)"

$ set -x WORKLOAD_IDENTITY_POOL_ID (上の出力結果)

# OIDC Provider を作成し、その ID を取得します
# attribute-mapping の値は必要に応じて変更してください
# 今回はプライベートな対象リポジトリに存在するユーザーなら誰でも OK としています
$ set -x OIDC_PROVIDER_NAME <OIDC Provider の名前; なんでも OK>
$ set -x GITHUB_REPOSITORY "github/actions"

$ gcloud iam workload-identity-pools providers create-oidc $OIDC_PROVIDER_NAME \
    --project=$PROJECT_ID \
    --location="global" \
    --workload-identity-pool=$POOL_NAME \
    --display-name=$OIDC_PROVIDER_NAME \
    --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository" \
    --issuer-uri="https://token.actions.githubusercontent.com"
    
$ gcloud iam service-accounts add-iam-policy-binding $SERVICE_ACCOUNT \
    --project=$PROJECT_ID \
    --role="roles/iam.workloadIdentityUser" \
    --member="principalSet://iam.googleapis.com/$WORKLOAD_IDENTITY_POOL_ID/attribute.repository/$GITHUB_REPOSITORY"
    
$ gcloud iam workload-identity-pools providers describe $OIDC_PROVIDER_NAME \
    --project=$PROJECT \
    --location="global" \
    --workload-identity-pool=$POOL_NAME \
    --format="value(name)"

出力結果を控えておく

GitHub Actions 側の設定

シークレットに入れても直接書いても環境変数として渡してもなんでも良いんですが、以下のような GitHub Actions を用意します。
このとき、 access_token_scopes を追加設定していること、 actions/checkout@v2 の後に実行していることについて注意してください。

name: Firebase へデプロイ
on:
  # ここは好きにすると良い
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v2
      
      - uses: google-github-actions/auth@v0.4.3
        with:
          access_token_scopes: 'email, openid, https://www.googleapis.com/auth/cloud-platform, https://www.googleapis.com/auth/firebase'
          workload_identity_provider: "控えておいた出力結果を貼る, projects/ACCOUNT_ID/locations/global... の形式"
          service_account: "発行したサービスアカウントの ID を貼る, name@PROJECT_ID.iam.gserviceaccount.com の形式"
          create_credentials_file: true
          
      - run: |
          yarn firebase deploy --only functions,hosting --project PROJECT_ID

最後に、上記の GitHub Actions をデフォルトブランチに追加して、 on に記述した方法で実行すれば、無事デプロイされます。
ということで、 OIDC を使った Firebase へのデプロイ方法の紹介でした。