デプロイメント パイプラインとの Workload Identity 連携を構成する

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

このガイドでは、Workload Identity 連携を使用して、デプロイ パイプラインで Google Cloud に対する認証を行えるようにする方法について説明します。

使用している CI / CD システムによっては、デプロイ パイプラインからアンビエントな環境固有の認証情報にアクセスできる場合があります。次に例を示します。

  • GitHub Actions ワークフローでは、GitHub OIDC トークンを取得して、ワークフローとそのリポジトリを一意に識別できます。
  • Terraform Cloud では、ワークスペースと環境を一意に識別する OIDC トークンを Terraform 構成に指定できます。

Workload Identity 連携を使用することで、サービス アカウント キーを保存して管理する必要がなくなります。また、デプロイ パイプラインで環境固有の認証情報を使用して Google Cloud APIs にアクセスする必要がなくなります。

外部 IdP を準備する

GitHub Actions

GitHub アカウントで構成を変更する必要はありません。

GitHub リポジトリを信頼するように Workload Identity プールを構成すると、そのリポジトリのワークフローで GitHub OIDC トークンを使用して、有効期間の短い Google Cloud 認証情報を取得できます。

Terraform Cloud

Terraform Cloud アカウントで構成を変更する必要はありません。

Terraform Cloud を信頼するように Workload Identity プールを構成すると、個々のワークスペースで Workload Identity 連携を有効にできます。

Workload Identity 連携を構成する

この手順は、GitHub または Terraform Cloud 組織ごとに行う必要があります。

Workload Identity 連携の構成を開始するには、次の操作を行います。

  1. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  2. Workload Identity プールとプロバイダの管理に専用のプロジェクトを使用することをおすすめします。
  3. Cloud プロジェクトに対して課金が有効になっていることを確認します。詳しくは、プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。

  4. IAM, Resource Manager, Service Account Credentials, and Security Token Service API を有効にします。

    API を有効にする

属性のマッピングと条件を定義する

デプロイ パイプラインの環境固有の認証情報には複数の属性が含まれているため、Google Cloud でサブジェクト識別子(google.subject)として使用する属性を決定する必要があります。

必要に応じて、追加の属性をマッピングできます。これにより、リソースへのアクセス権を付与する際にこれらの追加属性を参照できます。

GitHub Actions

属性マッピングでは、次のような OIDC トークンに埋め込まれたクレームをソース属性として使用できます。

  • sub: リポジトリ名と Git リファレンスが含まれます(例: repo:username/reponame:ref:refs/heads/master)。
  • repository: オーナーとリポジトリ名が含まれます(例: username/reponame)。
  • repository_owner: オーナー(ユーザー名または GitHub 組織の名前)が含まれます。
  • ref: Git リファレンスが含まれます(refs/heads/main など)。

次の属性マッピングでは、google.subject を GitHub Actions OIDC トークンの sub クレームに設定します。sub クレームにはリポジトリ名と Git リファレンスの両方が含まれるため、このマッピングによりリポジトリとブランチによるアクセスを制御できます。

google.subject=assertion.sub

リポジトリとブランチによるアクセスの制御は、特定のブランチ(main など)が他のブランチ(機能ブランチなど)以外のリソースに対する異なるアクセスが必要な場合に役立ちます。

ブランチごとにアクセスを区別しない場合は、次の属性マッピングを使用します。これにより、google.subjectrepository クレームに設定されます。

google.subject=assertion.repository

Terraform Cloud

属性マッピングでは、次のような Terraform Cloud OIDC トークンに埋め込まれたクレームを使用できます。

  • terraform_organization_id: 組織の一意の ID が含まれます(例: org-xxxxxxxxxxxxxxxx)。
  • terraform_workspace_id: ワークスペースの一意の ID が含まれます(例: ws-xxxxxxxxxxxxxxxx)。
  • terraform_workspace_name: ワークスペースの表示名が含まれます。
  • sub: 組織、ワークスペース、フェーズの表示名が含まれます(例: organization:example-org:workspace:example-workspace:run_phase:apply)。

次の属性マッピングは、google.subject を Terraform Cloud OIDC トークンの terraform_workspace_id クレームに設定します。

google.subject=assertion.terraform_workspace_id

このマッピングにより、ワークスペースごとに Google Cloud リソースへのアクセスを制御できます。

属性条件は、アサーション属性とターゲット属性をチェックする CEL 式です。特定の認証情報の属性条件が true と評価されると、認証情報が受け入れられます。それ以外の場合、認証情報は拒否されます。

GitHub Actions

GitHub 組織によって発行されたトークンへのアクセスを制限するには、次の条件を使用します。

assertion.repository_owner=='ORGANIZATION'

ORGANIZATION は、GitHub 組織の名前に置き換えます。

必要に応じて属性条件を拡張して、ワークフローまたはブランチのサブセットへのアクセスを制限します。たとえば、次の条件は、Git ブランチ main を使用するワークフローへのアクセスを制限します。

assertion.repository_owner=='ORGANIZATION' && assertion.ref=='refs/heads/main'

Terraform Cloud

Terraform Cloud 組織によって発行されたトークンへのアクセスを制限するには、次の条件を使用します。

assertion.terraform_organization_id=='ORGANIZATION_ID'

ORGANIZATION_ID は、組織の一意の ID に置き換えます(例: org-xxxxxxxxxxxxxxxx)。必要に応じて属性条件を拡張して、ワークフローまたはブランチのサブセットへのアクセスを制限します。たとえば、次の条件により、特定のワークスペースへのアクセスが制限されます。

assertion.terraform_organization_id=='ORGANIZATION_ID' && terraform_workspace_id=='WORKSPACE_ID'

Workload Identity のプールとプロバイダを作成する

必要なロール

Workload Identity 連携の構成に必要な権限を取得するには、プロジェクトに対して次の IAM ロールを付与するよう管理者に依頼してください。

  • Workload Identity プール管理者(roles/iam.workloadIdentityPoolAdmin
  • サービス アカウント管理者(roles/iam.serviceAccountAdmin

ロールの付与の詳細については、アクセスの管理をご覧ください。

また、IAM オーナー(roles/owner)の基本ロールには ID 連携を構成する権限も含まれています。本番環境では基本ロールを付与すべきではありません。基本ロールは、開発環境またはテスト環境で付与してください。

これで、Workload Identity プールとプロバイダの作成に必要な情報がすべて収集されました。

コンソール

  1. Google Cloud コンソールで、[新しいワークロード プロバイダとプール] ページに移動します。

    [新しいワークロード プロバイダとプール] に移動

  2. [ID プールを作成] に、次のように入力します。

    • 名前: プールの名前。この名前はプール ID としても使用されます。プール ID を後で変更することはできません。
    • 説明: プールの目的を説明するテキスト。
  3. [続行] をクリックします。

  4. プロバイダを構成します。

    GitHub Actions

    • プロバイダを選択: OpenID Connect(OIDC)
    • プロバイダ名: プロバイダの名前。この名前はプロバイダ ID としても使用されます。プロバイダ ID は後から変更できません。
    • 発行元 URL: https://token.actions.githubusercontent.com/
    • オーディエンス: デフォルトのオーディエンス

    Terraform Cloud

    • プロバイダを選択: OpenID Connect(OIDC)
    • プロバイダ名: プロバイダの名前。この名前はプロバイダ ID としても使用されます。プロバイダ ID は後から変更できません。
    • 発行元 URL: https://app.terraform.io
    • オーディエンス: デフォルトのオーディエンス
  5. [続行] をクリックします。

  6. [プロバイダの属性を構成する] で、前に確認した属性マッピングを追加します。

  7. [属性条件] で、前に確認した属性条件を入力します。属性条件がない場合は、空白のままにします。

  8. [保存] をクリックして、Workload Identity のプールとプロバイダを作成します。

gcloud

  1. 新しい Workload Identity プールを作成します。

    gcloud iam workload-identity-pools create POOL_ID \
        --location="global" \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
    

    次の値を置き換えます。

    • POOL_ID: プールの一意の ID。
    • DISPLAY_NAME: プールの名前。
    • DESCRIPTION: プールの説明。この説明は、プール ID へのアクセス権を付与するときに表示されます。
  2. Workload Identity プールのプロバイダを追加します。

    GitHub Actions

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="https://token.actions.githubusercontent.com/" \
        --attribute-mapping="MAPPINGS" \
        --attribute-condition="CONDITIONS"
    

    次の値を置き換えます。

    Terraform Cloud

    gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="https://app.terraform.io" \
        --attribute-mapping="MAPPINGS" \
        --attribute-condition="CONDITIONS"
    

    次の値を置き換えます。

デプロイ パイプラインを認証する

この手順は、GitHub Actions ワークフローまたは Terraform Cloud ワークスペースごとに行う必要があります。

デプロイ パイプライン用のサービス アカウントを作成する

  1. IAM, Security Token Service, and Service Account Credentials API を有効にします。

    API を有効にする

  2. ワークロードを表すサービス アカウントを作成します。デプロイ パイプラインごとに専用のサービス アカウントを使用することをおすすめします。

    サービス アカウントは、Workload Identity プールと同じプロジェクトにある必要はありません。

  3. 外部 ID にアクセスを許可するリソースに対するアクセス権をサービス アカウントに付与します。

デプロイ パイプラインによるサービス アカウントの権限借用を許可する

外部 ID にサービス アカウントの権限借用を許可するには、サービス アカウントに Workload Identity ユーザーロール(roles/iam.workloadIdentityUser)を付与します。このロールは、特定の外部 ID または複数の外部 ID に付与できます。

  • 特定の外部 ID の場合は、google.subject 属性をチェックする属性条件を記述します。
  • 外部 ID のグループの場合は、google.groups 属性またはカスタム属性 attribute.NAME をチェックする属性条件を記述します。
  • Workload Identity プールの外部 ID には属性条件を使用しません。

コンソール

Google Cloud コンソールを使用して外部 ID にサービス アカウントの権限借用を許可するには、次の操作を行います。

  1. Google Cloud コンソールで、[Workload Identity プール] ページに移動します。

    [Workload Identity プール] に移動

  2. 更新する Workload Identity プールを見つけて選択します。

  3. 選択した Workload Identity プールへのアクセス権を付与するには、[ アクセスを許可] をクリックします。

  4. [サービス アカウント] リストで、権限を借用する外部 ID のサービス アカウントを選択します。

  5. プール内のどの ID がサービス アカウントの権限を借用できるかを選択するには、次のいずれかを行います。

    • Workload Identity プールの特定の ID のみにサービス アカウントの権限借用を許可するには、[フィルタに一致する ID のみ] を選択します。

      [属性名] リストで、フィルタリングする属性を選択します。

      [属性値] フィールドに、属性の想定値を入力します。たとえば、属性マッピング google.subject=assertion.sub を使用する場合は、属性名を subject に設定します。属性値には、外部 ID プロバイダによって発行されたトークンの sub クレームの値を設定します。

    • Workload Identity プールのすべての外部 ID がサービス アカウントの権限借用を許可するには、[プール内のすべての ID] を選択します。

  6. 構成を保存するには、[保存]、[閉じる] の順にクリックします。

gcloud

gcloud CLI を使用して、外部 ID にサービス アカウントの権限借用を許可するには、次の操作を行います。

  1. 現在のプロジェクトのプロジェクト番号を取得するには、次のコマンドを実行します。

    gcloud projects describe $(gcloud config get-value core/project) --format=value\(projectNumber\)
    
  2. 特定の条件を満たす外部 ID に Workload Identity ユーザー ロール(roles/iam.workloadIdentityUser)を付与するには:

    サブジェクト

    gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT_EMAIL \
        --role=roles/iam.workloadIdentityUser \
        --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/SUBJECT"
    

    グループ

    gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT_EMAIL \
        --role=roles/iam.workloadIdentityUser \
        --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/group/GROUP"
    

    属性

    gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT_EMAIL \
        --role=roles/iam.workloadIdentityUser \
        --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.ATTRIBUTE_NAME/ATTRIBUTE_VALUE"
    

    すべての外部 ID

    gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT_EMAIL \
        --role=roles/iam.workloadIdentityUser \
        --member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/*"
    

    次のように置き換えます。

    • SERVICE_ACCOUNT_EMAIL: サービス アカウントのメールアドレス
    • PROJECT_NUMBER: Workload Identity プールを含むプロジェクトのプロジェクト番号
    • POOL_ID: Workload Identity プールのプール ID
    • SUBJECT: google.subjectマッピングされている属性の想定値
    • GROUP: google.groupsマッピングされている属性の想定値
    • ATTRIBUTE_NAME: 属性マッピングのカスタム属性の名前

デプロイ パイプラインを構成する

この時点で、デプロイ パイプラインで Workload Identity 連携を使用する準備ができています。

GitHub Actions

google-github-actions/auth アクションを使用すると、ワークフローの実行中に認証情報構成ファイルを自動的に生成できます。terraform などのクライアント ライブラリとツールでは、この認証情報構成ファイルを使用して Google 認証情報を自動的に取得できます。

GitHub Actions YAML ファイルを編集して、次の内容を追加します。

  • ジョブが GitHub ID トークンを取得できるようにするには、次の構成を追加します。

    permissions:
      id-token: write
      contents: read
    
  • 認証情報構成ファイルを作成するステップを追加します。

    - id: 'auth'
      name: 'Authenticate to Google Cloud'
      uses: 'google-github-actions/auth@v0'
      with:
        create_credentials_file: true
        workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID'
        service_account: 'SERVICE_ACCOUNT_EMAIL'
    

次の値を置き換えます。

  • PROJECT_NUMBER: Workload Identity プールを含むプロジェクトのプロジェクト番号
  • POOL_ID: Workload Identity プールの ID
  • PROVIDER_ID: Workload Identity プール プロバイダの ID
  • SERVICE_ACCOUNT_EMAIL: サービス アカウントのメールアドレス

例:

jobs:
  build:
    # Allow the job to fetch a GitHub ID token
    permissions:
      id-token: write
      contents: read

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - id: 'auth'
        name: 'Authenticate to Google Cloud'
        uses: 'google-github-actions/auth@v0'
        with:
          create_credentials_file: true
          workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID'
          service_account: 'SERVICE_ACCOUNT_EMAIL'

google-github-actions/auth アクションの使用方法については、Workload Identity 連携の設定をご覧ください。

Terraform Cloud

ワークスペースが Terraform Cloud OIDC トークンを取得できるようにワークスペースを構成します。

  1. Terraform Cloud でワークスペースを開き、[Variables] に移動します。

  2. [Add variable] をクリックし、次の変数を追加します。

    • 変数カテゴリ: 環境変数
    • キー: TFC_WORKLOAD_IDENTITY_AUDIENCE
    • :
      https://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID

    次の値を置き換えます。

    • PROJECT_NUMBER: Workload Identity プールを含むプロジェクトのプロジェクト番号
    • POOL_ID: Workload Identity プールの ID
    • PROVIDER_ID: Workload Identity プール プロバイダの ID
  3. [Save variable] をクリックします。

Terraform の構成を更新して、実行可能ファイル提供の認証情報とシェル スクリプトを使用して TFC_WORKLOAD_IDENTITY_AUDIENCE 環境変数から OIDC トークンを読み取り、Workload Identity 連携に使用します。

  1. Terraform Cloud のワークスペース構成に、2 つの変数を追加します。

    変数のカテゴリ キー
    環境変数 GOOGLE_APPLICATION_CREDENTIALS .google-cloud/workload-identity.json
    環境変数 GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES 1

    これらの変数は、実行可能ファイル提供の認証情報とファイル .google-cloud/workload-identity.json に保存された構成を使用するように、terraform とクライアント ライブラリに指示します。

  2. ソースコード リポジトリで .google-cloud/workload-identity.json ファイルを作成し、次の構成をコピーします。

    {
      "type": "external_account",
      "audience": "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID",
      "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
      "token_url": "https://sts.googleapis.com/v1/token",
      "credential_source": {
        "executable": {
          "command": "/bin/bash .google-cloud/workload-token.sh",
          "timeout_millis": 5000
        }
      },
      "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT_EMAIL:generateAccessToken"
    }
    

    次の値を置き換えます。

    • PROJECT_NUMBER: Workload Identity プールを含むプロジェクトのプロジェクト番号
    • POOL_ID: Workload Identity プールの ID
    • PROVIDER_ID: Workload Identity プール プロバイダの ID
    • SERVICE_ACCOUNT_EMAIL: サービス アカウントのメールアドレス

    この構成では、スクリプト .google-cloud/workload-token.sh を実行して Terraform Cloud OIDC トークンを取得するようにクライアント ライブラリに指示します。

  3. ソースコード リポジトリで、別のファイル .google-cloud/workload-token.sh を作成し、次のスクリプトをコピーします。

    #!/bin/sh
    if [ -z $TFC_WORKLOAD_IDENTITY_TOKEN ]
    then
        echo '{"version": 1, "success": false, "code": "missing-variable", "message": "TFC_WORKLOAD_IDENTITY_TOKEN not defined in workspace."}'
    else
        echo '{"version": 1, "success": true, "token_type": "urn:ietf:params:oauth:token-type:id_token", "id_token": "'"$TFC_WORKLOAD_IDENTITY_TOKEN"'"}'
    fi
    

    このスクリプトは、環境変数 TFC_WORKLOAD_IDENTITY_TOKEN から Terraform Cloud OIDC トークンを読み取り、クライアント ライブラリで期待される形式でトークンを返します。

  4. Terraform 構成で、バージョン 4.48.0 以降の Google Cloud プロバイダが使用されていることを確認し、必要に応じて次のように更新します。

    terraform {
      required_providers {
        google = {
          source  = "hashicorp/google"
          version = "~> 4.48.0"
        }
      }
    }
    
  5. ソースコード リポジトリに変更を送信します。

次のステップ