グローバルナビゲーションへ

本文へ

フッターへ

お役立ち情報Blog



Google Workload identity federationでGitHub Actionsを設定してみた

現在開発中のプロジェクトでReactで構築したSPAのアプリケーションを開発しています。

提供方法はビルドしたReactのアプリケーションをGoogle Cloud Storage(GCS)に配置する方式でしたので、継続的なデプロイを円滑に進めるためにGitHub ActionsによるCI/CDを使うことにしました。

GitHub ActionsのworkflowでGCSにデプロイするためには、GCSにアクセス可能な権限(role)を持ったGoogle Cloud Platform(GCP)のIAMサービスアカウントとの紐づけが必要になります。

従来はサービスアカウントの credentials.json を使用して連携する形式が一般的なようですが、この場合クレデンシャル情報の管理が必要になってきます。

代替案はないかを検討したところ、社内のエンジニアから本題のWorkload identity federationを教えていただきました。

Workload identity federationを使用することで更にセキュアな連携が可能になり、クレデンシャル情報の管理も不要になるのでWorkload identity federationを採用することにしました。

今回はWorkload identity federationを使用した連携方法や作業中にハマった事についての共有です。

GCPの設定

環境変数の設定

export PROJECT_ID=<GCPのプロジェクトID>
export POOL_NAME=<Workload Identity プール名>
export POOL_DISPLAY_NAME=<Workload Identity プールの表示名>
export PROVIDER_NAME=<Workload Identity プロバイダ名>
export PROVIDER_DISPLAY_NAME=<Workload Identity プロバイダの表示名>
export SERVICE_ACCOUNT_NAME=<IAMのサービスアカウント名>
export SERVICE_ACCOUNT_DISPLAY_NAME=<IAMのサービスアカウントの表示名>
export GITHUB_REPO=<GitHubのリポジトリ名 e.g. organization/repo>

シェル変数を使用しているので同じセッション内で以下のコマンドを実行してください

IAM Service Accountを作成する

$ gcloud iam service-accounts create ${SERVICE_ACCOUNT_NAME} \
  --project="${PROJECT_ID}" \
  --display-name="${SERVICE_ACCOUNT_DISPLAY_NAME}"

IAM Service Account Credentials API を有効にする

IAM Service Account Credentials API は既に有効設定済

$ gcloud services list --enabled | grep iamcredentials.googleapis.com
iamcredentials.googleapis.com           IAM Service Account Credentials API

今回のプロジェクトでは既に有効に設定済みなので不要でしたが、新規のプロジェクト等で有効にする場合は以下のコマンドを実行します。

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

GCSのrole(権限)設定

$ gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --role="roles/storage.objectAdmin" \
  --member="serviceAccount:${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"

Workload IdentityにPoolを作成する

$ gcloud iam workload-identity-pools create "${POOL_NAME}" \
  --project="${PROJECT_ID}" \
  --location="global" \
  --display-name="${POOL_DISPLAY_NAME}"
export WORKLOAD_IDENTITY_POOL_ID=$( \
  gcloud iam workload-identity-pools describe "${POOL_NAME}" \
    --project="${PROJECT_ID}" \
    --location="global" \
    --format="value(name)" \
)
echo $WORKLOAD_IDENTITY_POOL_ID

作成したPoolにProvierを作成する

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

Workload Identityでサービス アカウントの権限借用の設定

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

Workload Indentity Providerのリソース名の確認用

$ gcloud iam workload-identity-pools providers describe "${PROVIDER_NAME}" \
  --project="${PROJECT_ID}" \
  --location="global" \
  --workload-identity-pool="${POOL_NAME}" \
  --format='value(name)'

上記コマンドを実行後下記のような結果が返ってきたら成功です。

projects/<PROJECT_ID>/locations/global/workloadIdentityPools/<POOL_NAME>/providers/<PROVIDER_NAME>

GCPの設定は以上です。

GitHub Actionsの設定

環境変数の設定

GitHubリポジトリのSecretsに環境変数を追加します。

Name Value
GCP_IDENTITY_PROVIDER Workload Indentity Providerのリソース名の確認用の結果
GCP_SERVICE_ACCOUNT サービスアカウント名
GCP_BUCKET GCSのバケット名

GitHub Actionsのworkflowファイルを作成

GitHub Actionsにはgoogle謹製の setup-gcloud を使用します。

 /.github/workflows/xxx.yaml に追加

name: Deploy

on:
  push:
    branches:
      - main

  workflow_dispatch:

jobs:
  deploy:
    strategy:
      matrix:
        node-version: [16.13.1]
        os: [ubuntu-20.04]

    runs-on: ${{ matrix.os }}
    timeout-minutes: 10

    # For google could SDK needs permissions.
    # Add "id-token" with the intended permissions.
    # ref. https://github.com/google-github-actions/setup-gcloud
    permissions:
      contents: read
      id-token: write

    steps:

      - name: Checkout
        uses: actions/checkout@v2
        with:
          persist-credentials: false

      - name: Setup node
        uses: actions/setup-node@v2
        with:
          node-version: ${{ matrix.node-version }}

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: |
          npm run build

      - name: Setup google cloud SDK
        uses: google-github-actions/setup-gcloud@v0.3.0

      - id: auth
        name: Authenticate to google cloud platform
        uses: google-github-actions/auth@v0
        with:
          workload_identity_provider: ${{ secrets.GCP_IDENTITY_PROVIDER }}
          service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
          create_credentials_file: 'true'
          access_token_lifetime: 1200s

      - name: Deploy
        run: |
          gcloud --quiet alpha storage cp -r ./dist/* "gs://${GCP_BUCKET}"
        env:
          GCP_BUCKET: ${{ secrets.GCP_BUCKET }}

この設定でmainブランチにpush(merge)されると都度デプロイされるようになります。

ハマり箇所

gsutil Workload Identity Federation対応してないってよ

元々は  gsutil rsync  を使用する予定だったんですが、対応していないようで gcloud alha storage cp に変更。

gcloudコマンドのalphaなので、正式に使用する場合には upload-cloud-storage に変更した方がよさそうです。

最後に

Google Workload identity federationの設定とGitHub Actionsの設定方法をお送りしました。

 gsutil がWorkload identity federationに対応していないことに気づくのにえらい時間が掛かりましたが、それ以外の設定は比較的スムーズで、結果クレデンシャル情報を管理しなくてよくなったのは気持ちとしてすごく楽です。

今回のプロジェクトでは結果としてデプロイ先がGCSから別のプラットフォームに変更になったので、このGitHub Actionsの設定もあと少しだけの期間ですが、これからGCSにGitHub ActionsでCI/CDを検討される方のお役に立つと嬉しく思います。

この記事を書いた人

美髭公
美髭公事業開発部 web application engineer
2013年にアーティスに入社。システムエンジニアとしてアーティスCMSを使用したWebサイトや受託システムの構築・保守に携わる。環境構築が好き。
この記事のカテゴリ

FOLLOW US

最新の情報をお届けします