📝

Workload Identity 連携を利用して GitHub Actions から Cloud Run にデプロイ

2023/10/31に公開

概要

Workload Identity 連携を利用した GitHub Actions からのGCP認証を行ったので、参考にしたサイトと手順を備忘録として残します。

Workload Identity 連携について

https://cloud.google.com/blog/ja/products/identity-security/enable-keyless-access-to-gcp-with-workload-identity-federation

Workload Identity 連携は、キーなしの新しいアプリケーション認証メカニズムであり、オンプレミス、AWS、Azure で実行するワークロードは、外部 ID プロバイダ(IdP)と連携し、サービス アカウント キーを使用せずに Google Cloud リソースを呼び出すことができます。ワークロードはセキュリティ トークン サービス(STS)エンドポイントを呼び出して、IdP から取得した認証トークンを有効期間が短い GCP アクセス トークンと交換します。そして、このアクセス トークンを使用してサービス アカウントになりすまして、GCP リソースにアクセスするサービス アカウントの権限を継承します。

従来のサービスアカウントキーによる認証は以下の欠点があり、現在は最終手段になっているようです。

  • キーを保持しているアプリケーションにそのキーを使用する権限があるかどうかを確認する方法がない
  • 有効期限が長い

Workload Identity 連携を使うことで、外部の ID に対して サービスアカウントになりすます機能を含むIAMロールを付与できるので、アカウントキーを発行する必要がなくなり、キーのメンテナンスとセキュリティの負担がなくなります。

動画での説明が分かりやすかったのでオススメです。
https://www.youtube.com/watch?v=4vajaXzHN08

GCP設定

1. サービスアカウントの作成

プロジェクトの確認

$ gcloud projects list

プロジェクトの切り替え

$ gcloud config set project $PROJECT_ID

サービスアカウントの作成

$ gcloud iam service-accounts create $SA_NAME

サービスアカウントの確認

$ gcloud iam service-accounts list

2. サービスアカウントに権限付与

Artifact Registry と Cloud Run を利用することを踏まえ、以下の権限を付与

  • roles/iam.serviceAccountUser
  • roles/artifactregistry.writer
  • roles/run.admin

roles/iam.serviceAccountUser を付与する例

$ gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:$SA_EMAIL" \
    --role="roles/iam.serviceAccountUser"

3. Workload Identity 連携

https://github.com/marketplace/actions/authenticate-to-google-cloud#setting-up-workload-identity-federation

IAM Credentials API の有効化

$ gcloud services enable iamcredentials.googleapis.com \
 --project $PROJECT_ID

Workload Identity プールの作成

$ gcloud iam workload-identity-pools create $POOL_NAME \
    --project="$PROJECT_ID" \
    --location="global"

Workload Identity プロバイダの作成

$ gcloud iam workload-identity-pools providers create-oidc $PROVIDER_NAME \
    --project="$PROJECT_ID" \
    --location="global" \
    --workload-identity-pool="$POOL_NAME" \
    --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
    --issuer-uri="https://token.actions.githubusercontent.com"

プールとサービスアカウントの紐付け

$ export WORKLOAD_IDENTITY_POOL_ID=$(gcloud iam workload-identity-pools describe $POOL_NAME --project="$PROJECT_ID" --location="global" --format="value(name)")

# GitHub Actions を利用したいリポジトリ名
$ export REPO="username/name" # e.g. "Teasegasugoi/sample-app"

$ gcloud iam service-accounts add-iam-policy-binding $SA_EMAIL \
   --project="$PROJECT_ID" \
   --role="roles/iam.workloadIdentityUser" \
   --member="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/attribute.repository/${REPO}"

GitHub Actions から Cloud Run にデプロイ

https://cloud.google.com/blog/ja/products/devops-sre/deploy-to-cloud-run-with-github-actions
https://github.com/google-github-actions/example-workflows/blob/main/workflows/deploy-cloudrun/cloudrun-docker.yml

認証

GitHub Actions の permissionsとstepsに以下を追加します。

    permissions:
      contents: 'read'
      id-token: 'write'

    steps:
      - name: 'Checkout'
        uses: 'actions/checkout@v4'

      - name: 'Authenticate to Google Cloud'
        id: 'auth'
        uses: 'google-github-actions/auth@v1'
        with:
          token_format: 'access_token'
          workload_identity_provider: '${{ secrets.WIF_PROVIDER }}'
          service_account: '${{ secrets.WIF_SERVICE_ACCOUNT }}'

      - name: 'Docker Auth'
        id: docker-auth
        uses: 'docker/login-action@v1'
        with:
          username: 'oauth2accesstoken'
          password: '${{ steps.auth.outputs.access_token }}'
          registry: '${{ vars.LOCATION }}-docker.pkg.dev'

これ以降のstepではサービスアカウントが認証されている状態となり、dockerコマンドやgcloudコマンドを実行できます。

コンテナの Build と Push

- name: Build, tag and push container
        id: build-image
        uses: docker/build-push-action@v3
        with:
          context: ${{ vars.code_directory }}
          push: true 
          tags: |
            ${{ vars.REGION }}-docker.pkg.dev/${{ vars.GCP_PROJECT_ID }}/${{ vars.ARTIFACT_REPO }}/${{ vars.SERVICE_NAME }}:${{ inputs.ref }}

Cloud Run にデプロイ

- name: 'Deploy to Cloud Run'
        id: deploy
        uses: google-github-actions/deploy-cloudrun@v0
        with:
          service: ${{ vars.service_name }}
          region: ${{ vars.region }}
          metadata: container-${{ inputs.environment }}.yaml

その他参考

https://zenn.dev/t_hayashi/articles/bb800299388c1c#継続的インテグレーション:github-actions
https://zenn.dev/kou_pg_0131/articles/gh-actions-oidc-gcp

Discussion