GitHub ActionsからGCPにOpenID Connectでアクセスする
GitHub ActionsがOIDC (OpenID Connect)に対応したと公式から発表があったため、GCPへのアクセスを行ってみました。
GCPのWebコンソールやgcloudコマンドを使ったやり方は公式ドキュメントで紹介されているため、ここではTerraformを使ったやり方を紹介します。
上記の公式ドキュメントで紹介されているコマンドはデモ用のためセキュリティ的にはあまり良い状態ではありません。
今回は特定のリポジトリのみで使用できるように設定していきます。
Terraformで設定する
まずはGitHub Actionsで使用するサービスアカウントを作成します。
resource "google_service_account" "demo" {
account_id = "demo"
display_name = "demo"
description = "demo"
}
サービスアカウントへの権限設定は今までと変わらないため省略します。
次にWorkload Identity Poolを作成します。
GCPによると環境によって分けることを推奨するようです。
Workload Identity プールは相互に分離されていますが、1 つのプールは任意の数のサービス アカウントになり代わることができます。一般に、開発、ステージング、本番環境など、環境ごとに新しいプールを作成することをおすすめします。
resource "google_iam_workload_identity_pool" "github_actions_demo" {
provider = google-beta
workload_identity_pool_id = "github-actions-demo"
display_name = "GitHub Actions demo"
disabled = false
}
次は先程作成したPoolにWorkload Identity Providerを作成します。
ここで行う属性のマッピングがセキュリティを高めるために重要になってきます。
リポジトリで権限の制御を行うために "attribute.repository" = "assertion.repository" として属性にリポジトリ名を追加します。
リポジトリだけではなくブランチに対しても制御することができます。
例として、mainブランチのみにデプロイ用の権限を許可する、などがあるかと思います。
resource "google_iam_workload_identity_pool_provider" "demo" {
provider = google-beta
workload_identity_pool_id = google_iam_workload_identity_pool.github_actions_demo.workload_identity_pool_id
workload_identity_pool_provider_id = "demo-provider"
display_name = "demo"
attribute_mapping = {
"google.subject" = "assertion.sub"
"attribute.actor" = "assertion.actor"
"attribute.aud" = "assertion.aud"
"attribute.repository" = "assertion.repository"
}
oidc {
issuer_uri = "https://token.actions.githubusercontent.com"
}
}
属性のマッピングについての詳細は以下の公式ドキュメントが参考になります。
最後にサービスアカウントと紐付けます。
resource "google_service_account_iam_binding" "gha_demo" {
service_account_id = google_service_account.demo.name
role = "roles/iam.workloadIdentityUser"
members = [
"principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.github_actions_demo.name}/attribute.repository/[your_github_name]/[your_repository_name]",
]
}
最後の [your_github_name]/[your_repository_name] はサービスアカウントの使用を許可するリポジトリになります。
GitHub Actions
GitHub Actionsでは以下のようにProviderとサービスアカウントの指定をすればアクセスできます。
jobs:
demo:
runs-on: ubuntu-latest
permissions:
contents: 'read'
id-token: 'write'
steps:
- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@v0.3.1
with:
create_credentials_file: 'true'
workload_identity_provider: 'projects/xxxxxxxxxxx/locations/global/workloadIdentityPools/github-actions-demo/providers/demo-provider'
service_account: 'demo@xxxxxxxxxxxx.iam.gserviceaccount.com'
- name: gcloud
run: |-
gcloud auth login --brief --cred-file=${{ steps.auth.outputs.credentials_file_path }}