【Google Cloud】Terraform実行時の認証について整理した

## 概要

Terraform で Google Cloud のリソース管理をする際に必要となる認証方法について整理しました。


## 1. ADCによるGoogle認証

[Application Default Credentials (ADC) ](https://cloud.google.com/docs/authentication/provide-credentials-adc?hl=ja) による認証を利用した方法です。

認証には gcloud コマンドを実行します。

```
gcloud auth application-default login
```

実行すると、Webブラウザを経由してログインしているGoogleアカウントで認証をしてくれます。
認証後はLinux や macOSでは、`$HOME/.config/gcloud/application_default_credentials.json` のパスに認証情報が配置されます。


## 2. Google Cloud上のデフォルトの認証情報を利用

（2つ目にして例外的になってしまいますが）以下の場合はデフォルトで認証情報が設定されるため、認証のための操作は特に不要になります。

- Cloud Shell ・ Cloud Code などクラウドベースの開発環境：ログインしたGoogleアカウントのユーザの認証情報が使われる
- Compute Engine、App Engine、Cloud Run functions などのワークロードでは任意のサービスアカウントを紐づけるため、そのサービスアカウントの認証情報が使われる

## 3. サービスアカウントの鍵を利用

サービスアカウントの鍵（JSONファイル）を任意のパスに配置し、そのパスを環境変数`GOOGLE_APPLICATION_CREDENTIALS` に設定することで、Terraform実行時の認証として利用されます。
鍵の内容を環境変数に代入するのではなく、ファイルのパスとなるため注意です。

```
export GOOGLE_APPLICATION_CREDENTIALS='/path/to/credential.json'
```

## 4. サービスアカウントのアクセストークンを利用

ADCの認証コマンドにオプションをつけ、サービスアカウントとして振る舞うためのアクセストークンを発行する方法です。
権限を借用するためには、対象のサービスアカウントに対する「サービスアカウントトークン作成者 `（roles/iam.serviceAccountTokenCreator）`」の IAM ロールが必要となります。

認証方法１と似ていますが、鍵を発行せずにサービスアカウントとして認証することができる方法です。


### 4.1 コマンドでの設定

```
gcloud auth application-default login --impersonate-service-account SERVICE_ACCT_EMAIL
```

詳細は以下を参照ください。

https://cloud.google.com/docs/authentication/provide-credentials-adc?hl=ja#sa-impersonation

### 4.2 provider ブロックでの設定

Terraform で実行する際には、Provider の設定として記載することができます。

```
provider "google" {
  # Terraform実行にアクセストークンを利用するように書き換える
  access_token = data.google_service_account_access_token.sa.access_token
}

# Terraform実行用サービスアカウントの権限を借用するアクセストークンを生成する
provider "google" {
  alias = "impersonated"
}
data "google_client_config" "default" {
  provider = google.tokengen
}
data "google_service_account_access_token" "sa" {
  provider               = google.tokengen
  target_service_account = "terraform-service-account@project-id.iam.gserviceaccount.com"
  lifetime               = "300s"
  scopes                 = ["userinfo-email", "cloud-platform"]
}
```

詳細な設定については、Terraformのリファレンスをご参照ください。

https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/service_account_access_token

## 5. Workload Identity Federation

Workload Identity Federation はOpenID Connect（OIDC）やSAMLを使って外部のIDプロバイダを認証することで、サービスアカウントの権限を借用することができる機能です。

この機能を使うと、外部のIDプロバイダ（GitHubやTerraform Cloudなど）の認証で、サービスアカウントの鍵を発行することなく、認証したIDでサービスアカウントの権限を利用できるようになります。

機能や手順についは以下を参照ください。

https://cloud.google.com/iam/docs/workload-identity-federation?hl=ja

https://cloud.google.com/blog/ja/products/identity-security/secure-your-use-of-third-party-tools-with-identity-federation

拙著ですが、以前GitHub ActionsとTerraformを例に設定方法を書いた記事もありますので、そちらも載せておきます。

https://qiita.com/bosq/items/afdf3e3ccf20b5c01ec5


## 6. Direct Workload Identity Federation (GitHub Actions)

GitHub Actions で認証をする際に、よく使われるアクション[google-github-actions/auth](https://github.com/google-github-actions/auth)の機能として、Direct Workload Identity Federationというものがあります。
こちらは、[v2.0.0](https://github.com/google-github-actions/auth/releases/tag/v2.0.0)から追加された機能で、サービスアカウントを経由せず、GitHub Actions OIDC トークンを使って直接 Google Cloud に認証することができるようになります。

[google-github-actions/auth](https://github.com/google-github-actions/auth)のREADMEにはPreferredと記載されており、推奨の方法となっています。

設定などについては以下の記事が大変参考になりましたので、詳細はそちらをご参照ください。

https://paper2.hatenablog.com/entry/2024/06/29/143947

## まとめ

以上、把握している範囲のTerraform実行時のGoogle Cloudの認証方法をまとめてみました。

個人的な検討フローとしては以下のように考えています。

1. まず、Terraformの実行環境をGoolge Cloudにまとめられる（方法2）場合は、認証について考えなくてよくなります
2. 次に推奨される設定として、Workload Identity Federationによる鍵を使わない方法（方法5,6）を検討すべきかと思われます
3. もしOIDCやSAMLなどでIdPが利用できない環境の場合、鍵による認証(方法3)を使うことになるかと思われます
4. 最後に、ローカル環境などから実行する場合や特行頻度が少ない運用であれば、ADCによる認証（方法1）やアクセストークンを利用した認証（方法4）を検討してもいいかもしれません

以上、この記事が誰かの役に立ってくれれば幸いです。