Workload Identity連携とは
何が嬉しいのか
Workload Identity連携 (Workflow Identity Federation)とは、GCPと外部のワークロード(Workload)
とのID連携のことです。
従来はサービスアカウントキーを用いて認証認可を行うことが一般的でしたが、Workflow Identity連携を用いるとサービスアカウントキーを使わずに、GCP外のワークロードからGCPのリソースへアクセス出来るようになります。
サービスアカウントキーを管理する手間が減ることは流出などセキュリティリスクを減らすことに繋がります。
どういう仕組みか
GitHub ActionsからCloud FunctionsにDeployする事例で解説してみます。
- WorkloadがIdP(Identity Provider)に認証
- IdPがクレデンシャルをWorkloadを経由してGCPのSTS(Security Token Services)に渡す
- STSがクレデンシャルを事前登録内容と照合
- STSがWorkloadに一時トークンを発行
- Workloadが一時トークンを用いてgcloudコマンドを実行
こちらのブログの「リソースアクセスまでの流れ」の解説が参考になりました。
christina04.hatenablog.com
設定の仕方
事前準備
- GitHub Actionsを動かすためのリポジトリ(hoge)とworkflowファイルを作成
- Cloud Functionsのコード(main.py)を作成
- Cloud Functionsを動かすためのサービスアカウントを作成
Workload Identity Poolの設定
「IAM」→「Workload Identity 連携」→「プールを作成」
名前の欄に「test-pool」と入力
IdP (Identity Provider)の登録とWorkload Identity Poolの追加
本説明では、GitHub ActionsからGCPリソースへのアクセスを事例にしているため、GitHubのプロバイダを用います。
下記の値を入力します。*1
プロバイダの選択 | Open ID Connect | |
プロバイダ名 | GitHub | |
プロバイダID | github | |
発行元 | https://token.actions.githubusercontent.com | 公式ドキュメント参照の値 |
オーディエンス | デフォルトのオーディエンス |
プロバイダの属性設定では、下記の値を入力します。
属性マッピング | google.subject = assertion.repository |
属性条件 | assertion.repository == "GitHub組織名/リポジトリ名" (gesogse0/hoge) |
外部IDがサービスアカウントを使えるようにする
作成したWorkload Identittyプールの画面を開き「アクセスを許可」を開きます。
「サービスアカウント」には利用したいサービスアカウントを、
「プリンシパル」には「フィルタに一致するIDのみ」を選択し、「subject」を選択し、入力欄には「リポジトリ所有者/リポジトリ名(gesoges0/hoge)」を入力します。
ここまで登録すると、下記コマンドで外部IDに権限が付与されていることが伺えます。
gcloud iam service-accounts get-iam-policy <サービスアカウント>
workflowにdeploy jobを記述する
まず下記のコマンドでprovider_idを取得します。
gcloud iam workload-identity-pools providers describe "github" --project=$PROJECT_ID --location="global" --workload-identity-pool="test-pool" --format='value(name)'
provider_idが取得できたら下記のworkflowを記述します。
これで、mainリポジトリにpushしたらmain.pyのhello_http()関数をCloud FunctionsにDeployできるようになります。
name: Deploy Cloud Functions on: # 手動ormainブランチにpush時に実行 workflow_dispatch: push: branches: - main jobs: deploy-job: runs-on: 'ubuntu-latest' permissions: contents: 'read' id-token: 'write' steps: # ソースコードのチェックアウトをする - uses: 'actions/checkout@v3' - id: 'auth' name: 'Authenticate to Google Cloud' # Workload Identity連携を利用してGitHub ActionsからGoogle Cloudへ認証を行う uses: 'google-github-actions/auth@v1' with: workload_identity_provider: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER_ID }} service_account: ${{ vars.SERVICE_ACCOUNT }} - name: 'Set up Cloud SDK' # gcloudコマンドを実行するためにCloud SDKを準備する uses: 'google-github-actions/setup-gcloud@v1' - name: 'Deploy Cloud Functions gen2 Using gcloud command' # gcloudコマンドを利用してCloud Functionsをデプロイする run: >- gcloud functions deploy ${{ vars.CLOUD_FUNCTIONS_ID }} --gen2 --runtime=python310 --region=asia-northeast1 --source=./functions --entry-point=hello_http --trigger-http --no-allow-unauthenticated --set-env-vars GCP_PROJECT=${{ vars.PROJECT_ID }} --run-service-account ${{ vars.SERVICE_ACCOUNT }}
追記
なお、Cloud Buildでも同じようなことを実現可能です。
下記の手順で実行します。
- Cloud Buildコンソールにリポジトリを登録
- Cloud Buildでトリガーを作成し、「mainブランチにpushされた場合にトリガーする」ように設定
- リポジトリにcloudbuild.yamlを入れ、Cloud FunctionsにDeployするよう記述