前回の続き
以前、Cloud Buildをつかった自動デプロイを使ってたけど、
いつの間にか進化していて、かなり楽にデプロイできるようになってた(*´ω`*)
実際に試してみたら、すごい設定が少なくリリースできるようになってたので、
ハマったところを含めてまとめてみた備忘録(*´ω`*)
ざっくり、よくなったところとしては、
公式のドキュメントだとこの辺りを起点に読むとよいかも。
- GitHub Actions からのキーなしの認証の有効化 | Google Cloud 公式ブログ
- Google Cloud の Buildpacks でコンテナ イメージ作成が簡単に | Google Cloud 公式ブログ
- Google Cloud Platform での OpenID Connect の構成 - GitHub Docs
GitHub Actionsのworkflowファイル
yamlはこんな感じに。
actions/checkout@v3
でチェックアウトgoogle-github-actions/auth@v1
でOIDC認証gcloud run deploy
でソースからデプロイ
name: "[MAIN] Deploy" "on": push: branches: - main workflow_dispatch: env: SERVICE_ACCOUNT: "YOUR_SERVICE_ACCOUNT_EMAIL" PROVIDER: "YOUR_WORKLOAD_IDENTITY_PROVIDER" SERVICE_NAME: "YOUR_CLOUD_RUN_SERVICE_NAME" SERVICE_REGION: "asia-northeast1" jobs: build_and_deploy_dev: runs-on: ubuntu-latest # Add "id-token" with the intended permissions. permissions: id-token: write contents: read steps: # actions/checkout MUST come before auth - uses: actions/checkout@v3 # Configure Workload Identity Federation via a credentials file. - uses: google-github-actions/auth@v1 with: service_account: ${{ env.SERVICE_ACCOUNT }} workload_identity_provider: ${{ env.PROVIDER }} - run: gcloud run deploy ${SERVICE_NAME} --source . --region ${SERVICE_REGION}
uses: google-github-actions/auth@v1
で認証ができるように、
GCP側の設定をしていく。
Buildpacksでソースからデプロイについては、こちら
ローカルからはgcloud run deploy
が実行できるよう、
APIの有効化などはできている想定。
Workload Identity連携の設定
以下のSetting up Workload Identity Federationに従って設定していく。
IAM Service Account Credentials APIの有効化
「APIとサービス > ライブラリ」から
「IAM Service Account Credentials API」を検索して有効化
$ gcloud services enable iamcredentials.googleapis.com \ --project "${PROJECT_ID}"
Workload Identity Poolの作成
「IAMと管理 > Workload Identity連携」にある
「プールを作成」からWorkload Identity Poolを追加
$ gcloud iam workload-identity-pools create "github-actions-pool" \ --project="${PROJECT_ID}" \ --location="global" \ --display-name="github-actions-pool"
Workload Identity Providerの作成
「IAMと管理 > Workload Identity連携」にある
「プロバイダの追加」からWorkload Identity Providerを追加
- プロバイダの選択: OpenID Connect (OIDC)
- プロバイダー名: github-actions-provider(好きな名前)
- 発行元(URL): https://token.actions.githubusercontent.com
- オーディエンス: デフォルトのオーディエンス
- 属性のマッピング
OIDC | |
---|---|
google.subject | assertion.sub |
attribute.repository | assertion.repository |
attribute.actor | assertion.actor |
attribute.repository_owner | assertion.repository_owner |
$ gcloud iam workload-identity-pools providers create-oidc "github-actions-provider" \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="github-actions-pool" \ --display-name="github-actions-provider" \ --attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository,attribute.repository_owner=assertion.repository_owner" \ --issuer-uri="https://token.actions.githubusercontent.com"
Workload Identity PoolのIAM プリンシパルを取得
「IAMと管理 > Workload Identity連携」にある
作成したプール(github-actions-pool
)を選択し、
「IAMプリンシパル」の内容をコピー
principalSet://iam.googleapis.com/projects/<PROJECT_NO>/locations/global/workloadIdentityPools/github-actions-pool/*
$ gcloud iam workload-identity-pools describe "github-actions-pool" \ --project="${PROJECT_ID}" \ --location="global" \ --format="value(name)" # => # projects/<PROJECT_NO>/locations/global/workloadIdentityPools/github-actions-pool # 表示された内容を環境変数としてexport $ export WORKLOAD_IDENTITY_POOL_ID="..." # value from above # POOL_IDからIAMプリンシパルを準備し、環境変数としてexport $ export IAM_PRINCIPAL="principalSet://iam.googleapis.com/${WORKLOAD_IDENTITY_POOL_ID}/*"
サービスアカウントの作成
「IAMと管理 > サービスアカウント」で、GitHub Actionsで利用するサービスアカウントを作成。
github-actions@${PROJECT_ID}.iam.gserviceaccount.com
// gcloudコマンドの場合 $ gcloud iam service-accounts create "github-actions" \ --project "${PROJECT_ID}"
workflowファイルenv.SERVICE_ACCOUNT
に設定。
env: SERVICE_ACCOUNT: "github-actions@${PROJECT_ID}.iam.gserviceaccount.com"
サービスアカウントにIAMプリンシパルを追加
「IAMと管理 > サービスアカウント」で、
作成したサービスアカウントを選択し、
「権限」タブの「GRANT ACCESS」から追加
- プリンシパル: principalSet://iam.googleapis.com/projects/<PROJECT_NO>/locations/global/workloadIdentityPools/github-actions-pool/*
- ロール: Workload Identity ユーザ
$ gcloud iam service-accounts add-iam-policy-binding "github-actions@${PROJECT_ID}.iam.gserviceaccount.com" \ --project="${PROJECT_ID}" \ --role="roles/iam.workloadIdentityUser" \ --member="${IAM_PRINCIPAL}"
※このプリンシパルだと、誰でもサービスアカウントを使えてしまうので、
以下に書いているオーナー指定やリポジトリ指定などが必要
workflowファイルのenv.PROVIDER
の設定
env: PROVIDER: "projects/<PROJECT_NO>/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider"
$ gcloud iam workload-identity-pools providers describe "github-actions-provider" \ --project="${PROJECT_ID}" \ --location="global" \ --workload-identity-pool="github-actions-pool" \ --format="value(name)" # => # projects/<PROJECT_NO>/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider
サービスアカウントに必要なロールを設定
「IAMと管理 > サービスアカウント」で、
作成したサービスアカウントの編集から、
やりたいコマンドに必要なロールを割り当てる。
今回はソースからCloud Runデプロイなので、以下を設定
- Artifact Registry 書き込み
- Cloud Build サービスアカウント
- Cloud Run デベロッパー
- Cloud Run 起動元
実行してみる
これでプッシュしたりして、うまくデプロイできていればOK(´ω`)
おまけ
属性のマッピング
プロバイダで設定した「属性のマッピング」は、以下のような感じらしい。
assertion.<属性名>
をattribute.<属性名>
にマッピングする設定をすると、
Google側でattribute.<属性名>
として扱えるようになる。
Google側のattribute.<属性名>
を利用して、
認証を許可するリポジトリなどの制限をかけることができる。
{ "jti": "...", "sub": "repo:username/reponame:ref:refs/heads/main", "aud": "https://iam.googleapis.com/projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider", "ref": "refs/heads/main", "sha": "d11880f4f451ee35192135525dc974c56a3c1b28", "repository": "username/reponame", "repository_owner": "username", "repository_visibility": "private", "repository_id": "74", "repository_owner_id": "65", "run_id": "1238222155", "run_number": "18", "run_attempt": "1", "actor": "username", "actor_id": "12", "workflow": "oidc", "head_ref": "", "base_ref": "", "event_name": "push", "ref_type": "branch", "job_workflow_ref": "username/reponame/.github/workflows/token.yml@refs/heads/main", "iss": "https://token.actions.githubusercontent.com", "nbf": 1631718827, "exp": 1631719727, "iat": 1631719427 }
- GitHub Token Format | google-github-actions/auth
- About security hardening with OpenID Connect - GitHub Docs
- 属性のマッピング | Workload Identity 連携 | IAM のドキュメント | Google Cloud
属性を利用したリポジトリの制限
2つの方法がある
- サービスアカウントに追加した権限のプリンシパルで指定
- プロバイダの属性条件で指定
サービスアカウントに追加した権限のプリンシパルで指定
上記では、こんな感じでだれでもOKだったけど、
principalSet://<...略>/github-actions-pool/*
https://github.com/my-org/my-repo
のようなGitHubリポジトリの場合、
principalSet://<...略>/github-actions-pool//attribute.repository/my-org/my-repo
と指定すると、このリポジトリのみに制限できる。
指定の仕方はいろいろあり、属性マッピングをしておけば、
リポジトリ指定(attribute.repository)や
リポジトリオーナー指定(attribute.repository_owner)などもできる
ID | ID の形式 |
---|---|
プール内のすべての ID | principalSet://iam.googleapis.com/<...略>/* |
特定の属性値を持つすべての ID | principalSet://iam.googleapis.com/<...略>/attribute.ATTRIBUTE_NAME/ATTRIBUTE_VALUE |
単一の ID | principal://iam.googleapis.com/<...略>/subject/SUBJECT_ATTRIBUTE_VALUE |
グループ内のすべての ID | principalSet://iam.googleapis.com/<...略>/group/GROUP_ID |
プロバイダの属性条件で指定
プロバイダの「属性のマッピング」の下にある「属性条件」で指定してもOK
https://github.com/my-org/my-repo
のようなGitHubリポジトリの場合、
attribute.repository_owner=="my-org" && attribute.repository=="my-org/my-repo"
こんな感じで指定すると、リポジトリ指定とリポジトリオーナー指定を両方設定できる。
ハマったポイント
権限や属性周りがわからなくて、かなり時間かかった。。
だいたいこのあたり。。
- IAMプリンシパルの設定ミス
attribute.repository
のオーナーがない- 属性マッピング正しくない
- ロール割当に「Workload Identity ユーザ」がない
- サービスアカウントの権限不足
- Cloud Runのデプロイに必要な権限がない
どんな属性があるのかは、
github/actions-oidc-debuggerを使うと確認できるので、
必要なときは使ってみるといいかも(*´ω`*)
以上!! 仕組みが分かれば、かなり簡単に実行できるように(*´ω`*)!!
参考にしたサイト様
- GitHub Actions で OIDC を使用して GCP 認証を行う
- GitHub Actions から Cloud Run ジョブで Google Cloud のプライベートネットワーク内へアクセスした - バイセル Tech Blog
- 【GCP】CloudRun × GitHub Actionsを使用したデプロイ自動化を実装する - KIYONO Engineer Blog
- google-github-actions/auth: A GitHub Action for authenticating to Google Cloud.
- github/actions-oidc-debugger: An Action for printing OIDC claims in GitHub Actions.
- Workload Identity 連携 | IAM のドキュメント | Google Cloud
- Workload Identity 連携の構成 | IAM のドキュメント | Google Cloud
- Workload Identity 連携の使用に関するベスト プラクティス | IAM のドキュメント | Google Cloud
- OpenID Connect を使ったセキュリティ強化について - GitHub Docs