🔑

サービスアカウントキーを利用せずに Terraform を実行する方法

2023/01/01に公開

Google Cloud のリソース構築に Terraform を利用していますが、セキュリティの観点からサービスアカウントキーを発行したくないという方も多いのではないでしょうか。今回は有効期限の短いアクセストークンを利用してサービスアカウントの権限を借用することで、サービスアカウントキーを利用せずに Terraform を実行する方法を解説します。
今回の記事は下記の Google Cloud ブログを参考にしています。ブログ投稿だと行間が分かりにくい部分があるので、行間を補足するイメージ記載しています。

https://cloud.google.com/blog/ja/topics/developers-practitioners/using-google-cloud-service-account-impersonation-your-terraform-code

また、この方法はローカル環境から Terraform を実行することを想定しています。CI/CD で Terraform を実行するような場合には、Workload Identity 連携の利用を推奨します。Workload Identity 連携を利用した方法もいずれまとめたいと思います。

概要

サービスアカウントキーを利用しないとはどんな方法か?端的に説明すると有効期限の短いアクセストークンを発行し、サービスアカウントの権限借用を行う方法です。と言われてもパッとイメージするのは難しいと思いますので、Terraform で BigQuery のデータセットを作成するケースを例にポンチ絵にするとこんな感じです。

詳細は各手順の中で解説するので、ここでは大まかなイメージを掴んでください。

  1. Google アカウントの認証情報をリクエスト
  2. Google アカウントの認証情報を取得、アプリケーションのデフォルト認証情報(ADC)として設定
  3. ADC を利用してサービスアカウントの有効期限の短いアクセストークンをリクエスト
  4. 有効期限の短いアクセストークンを取得
  5. 有効期限の短いアクセストークンを利用してサービスアカウントの権限で BigQuery データセットを作成

設定の流れ

Terraform を実行できるようになるまでの流れは以下の通りです。

  1. サービスアカウントを作成
  2. Google アカウントに必要な権限を付与
  3. サービスアカウントに必要な権限を付与
  4. アプリケーションのデフォルト認証情報 (ADC) に Google アカウントの認証情報を設定
  5. Terraform コードの作成

前半の 1 ~ 3 は Google Cloud プロジェクト上での作業、4 ~ 5 はローカル環境側の作業です。
また、以下は完了している前提としています。

  • Google Cloud プロジェクトの作成
  • Google アカウントへ 1 ~ 3 の操作を行うための権限付与
  • ローカル環境で gcloud コマンドが実行できる状態
  • ローカル環境で Terraform が実行できる状態

1. サービスアカウントを作成

まずは Terraform を実行するためのサービスアカウントを作成します。
名前は任意ですが、Terraform の実行用途と分かりやすい名前が良いかもしれません。

gcloud iam service-accounts create terraform --display-name="Terraform service account"

2. Google アカウントに必要な権限を付与

自身の Google アカウントに必要な権限を付与します。
アクセストークンを発行し、サービスアカウントの権限借用を行うために必要最小限のロールは Service Account Token Creator (roles/iam.serviceAccountTokenCreator) です。今回は簡易的に gcloud iam service-accounts add-iam-policy-binding コマンドを利用してロールを付与しますが、IAM を Terraform で管理しているケースも多いかと思いますので、権限付与の方法は適宜変更して下さい。
terraform@[myprojectid].iam.gserviceaccount.com 部分は前の手順で作成したサービスアカウントの情報に、user:[mygoogleaccount] 部分は自身の Google アカウントのアドレス、もしくは Google グループのアドレスに読み替えてください。

gcloud iam service-accounts add-iam-policy-binding terraform@[myprojectid].iam.gserviceaccount.com --member='user:[mygoogleaccount]' --role='roles/iam.serviceAccountTokenCreator'

プロジェクトレベルで Google アカウントに Service Account Token Creator ロールを付与することも可能ですが、他のサービスアカウントに対してもトークン作成の権限が付与されることになり、過剰な権限付与となってしまう可能性があるため、サービスアカウント単位で個別に権限付与することを推奨します。

3. サービスアカウントに必要な権限を付与

サービスアカウントに Terraform でリソース構築するために必要な権限を付与します。
今回は BigQuery のデータセットを作成するので、BigQuery Data Editor (roles/bigquery.dataEditor) ロールを付与します。今回は簡易的に gcloud projects add-iam-policy-binding コマンドを利用してロールを付与しますが、IAM を Terraform で管理しているケースも多いかと思いますので、権限付与の方法は適宜変更して下さい。

gcloud projects add-iam-policy-binding [myprojectid] --member='serviceAccount:terraform@[myprojectid].iam.gserviceaccount.com' --role='roles/bigquery.dataEditor'

4. アプリケーションのデフォルト認証情報 (ADC) に Google アカウントの認証情報を設定

アプリケーションのデフォルト認証情報(ADC)は、Cloud クライアントライブラリ等が Google Cloud APIs の認証に利用する認証情報のことであり、Terraform の実行においても ADC を利用した認証が推奨されています。

https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#authentication

今回のケースでは ADC をサービスアカウントのアクセストークンを取得するために利用しますので、以下のコマンドで Google アカウントの認証情報を ADC としてローカルに保存します。

gcloud auth application-default login

コマンドを実行すると Web ブラウザが自動起動し、Google アカウントのログイン画面が表示されます。画面に従いアクセスリクエストを許可することでアクセストークンが取得されます。

これで Terraform の実行に必要な準備はすべて完了です。次の手順では具体的な Terraform のコードの中身を見ていきます。

5. Terraform コードの作成

Terraform のコードを作成していきます。
まずは provider.tf ファイルです。ここではプロバイダ情報を2つ指定します。1つ目はサービスアカウントのアクセストークンを取得するために使用するプロバイダ、 2つ目はリソースを構築するために使用するプロバイダです。またアクセストークンを取得するためのデータブロックもあわせて記載します。

provider.tf
# リソースを構築するためのプロバイダ
provider "google" {
  project     = "nridev"
  access_token	= data.google_service_account_access_token.default.access_token
}

# 有効期限の短いトークンを取得するためのプロバイダ
provider "google" {
 alias = "impersonation"
 scopes = [
   "https://www.googleapis.com/auth/cloud-platform",
   "https://www.googleapis.com/auth/userinfo.email",
 ]
}

# 有効期限の短いトークンを取得するためのデータ
data "google_service_account_access_token" "default" {
 provider               	= google.impersonation
 target_service_account 	= var.terraform_service_account
 scopes                 	= ["userinfo-email", "cloud-platform"]
 lifetime               	= "300s"
}

lifetime はトークンの有効期限です。Terraform の実行に必要な時間だけ使えれば良いので、今回は5分 (300s) にしています。

次にサービスアカウントの情報を変数で定義します。今回は変数で値を渡していますが、Google Cloud ブログでは local 変数を利用しているようです。ここはお好みの方法を利用いただければ問題ありません。

variables.tf
variable "terraform_service_account" {}
terraform.tfvars
terraform_service_account = "terraform@[myprojectid].iam.gserviceaccount.com"

最後に BigQuery のデータセットを定義します。

main.tf
resource "google_bigquery_dataset" "dataset" {
  dataset_id                  = "test"
  friendly_name               = "test"
  description                 = "This is a test dataset"
  location                    = "asia-northeast1"
}

あとは Terraform を実行するだけです。


サービスアカウントキーを利用せずに Terraform を実行する方法について解説しました。
認証・認可まわりは少し地味ではありますが Google Cloud に限らずクラウドを利用するためには非常に重要なポイントです。Google Cloud では Workload Identity 連携や Workforce Identity 連携など新しい機能が登場していますので、今後も安全かつスマートな方法を追求していきたいと思います。

Discussion