Carpe Diem

備忘録

Workload Identity Federationを図で理解する

概要

GCPのWorkload Identity連携はサービスアカウントで秘密鍵を作らずともGCPリソースへのアクセス権を他の環境(オンプレ、別パブリッククラウド)に付与することができます。

これにより

  • AWSからGCPリソースにアクセスする
  • GitHub ActionsからGCRにDocker imageをpushする
  • CircleCIでGKEのデプロイを行う

といった連携が鍵なしで実現できます。

ただ実装だけだとイメージしづらいので今回は図示してみました。

Workload Identity Federation

Workload Identity連携における登場人物は以下です。

左のWorkloadsがGCPリソースにアクセスしたいアプリケーションに当たります。

準備

Workload Identity Poolの作成とサービスアカウントの作成

まずはWorkload Identity Poolとサービスアカウントを用意します。
サービスアカウントにはアクセスしたいGCPリソースに対する最低限の権限を付与します。

Identity ProviderとWorkload Identity Poolの連携

Workload Identity Poolが外部IdPを信頼するように設定します。

gcloudコマンドだと

IdPによってやや変わりますが以下のように設定します。

$ gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
    --location="global" \
    --workload-identity-pool="POOL_ID" \
    --issuer-uri="ISSUER" \
    --allowed-audiences="AUDIENCE" \
    --attribute-mapping="MAPPINGS" \
    --attribute-condition="CONDITIONS"

Workload Identity 連携の構成  |  IAM Documentation  |  Google Cloud に各IdPとの連携方法が載っています。

attribute-mappingattribute-conditionを使ってIdP側のユーザグループに対するアクセス制御のための情報を渡します。

attribute-mappingは以下をマッピングできます。

属性 設定するロールバインディング ユースケース
google.subject principal:// 一意のユーザにアクセス権を付与したい
google.groups principalSet:// グループのすべてのメンバーにアクセス権を付与したい
attribute.XXX principalSet:// 特定の属性を持つすべての ID にアクセス権を付与したい

例えばGitHub Actionsであれば以下のようにattribute.repositoryを渡すことで、

--attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository"

認証を特定のリポジトリに制限することができます。

※次のWorkload Identity Poolとサービスアカウントのロールバインディングでも設定が必要です

Workload Identity Poolとサービスアカウントの連携

最後にWorkload Identity Poolがサービスアカウントの権限を借用する(impersonate=成りすます)ための設定を行います。

以下はGitHub Actionsの例です。先程attribute-mappingマッピングした情報(attribute.repository)を使うことで、リソースにアクセスできるメンバー(リポジトリ)を制限しています。

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

リソースアクセスまでの流れ

設定が完了したら以下のフローでGCPリソースにアクセスすることができます。

  1. Workload(アプリケーション)がIdPに認証
  2. IdPがクレデンシャルを発行
  3. WorkloadがクレデンシャルをGCPSTSに渡す
  4. STSはクレデンシャルの正当性をWorkload Identity Poolに登録した情報を使ってチェック
  5. 問題なければ進める
  6. サービスアカウントに成りすますことができる一時トークンを発行
  7. 一時トークンを使ってサービスアカウントになりすます
  8. GCPリソースにアクセス

その他

assertion.XXXには何が使えるか

OIDCトークン(JWT)に内包されている各claimsが使えます。

例えばGitHub Actionsだと以下です。

{
  "jti": "example-id",
  "sub": "repo:octo-org/octo-repo:environment:prod",
  "environment": "prod",
  "aud": "https://github.com/octo-org",
  "ref": "refs/heads/main",
  "sha": "example-sha",
  "repository": "octo-org/octo-repo",
  "repository_owner": "octo-org",
  "run_id": "example-run-id",
  "run_number": "10",
  "run_attempt": "2",
  "actor": "octocat",
  "workflow": "example-workflow",
  "head_ref": "",
  "base_ref": "",
  "event_name": "workflow_dispatch",
  "ref_type": "branch",
  "job_workflow_ref": "octo-org/octo-automation/.github/workflows/oidc.yml@refs/heads/main",
  "iss": "https://token.actions.githubusercontent.com",
  "nbf": 1632492967,
  "exp": 1632493867,
  "iat": 1632493567
}

ref: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#understanding-the-oidc-token

公式動画

公式にとても分かりすい動画が上がっているのでオススメです。

www.youtube.com

まとめ

Workload Identity連携はIdPによって若干設定が異なります。

今回図示することで連携に必要な手順の根本を理解できたので、異なるIdPにおいてもスムーズに設定できるようになりました。

参考