はじめに
最近、GCP(Google Cloud Platform)を少し触ろうと思い、せっかくならTerraformでリソース管理しようとしたのだが、Terraform CloudとGCPを接続する方法の記事が日本語だとあまり見つからなかった。
そもそも、「Terraform Cloud GCP」みたいな検索クエリだと検索意図を「Terraform Google Cloud Platform」とも解釈されてしまうため"非Terraform Cloud"の記事も多くヒットしてしまって目的の記事を探すのが難しいという課題もある。
そこで、一つでもTerraform CloudとGCPに関する記事を増やそうと、設定手順のログを記事として残しておく。
Terraform CloudとGCPを利用(認証)する2つの方法
Terraform Cloudの環境からrunしたときGCPの認証を行う方法は2種類ある
- サービスアカウントのキーで認証を行う
- Workload Identity連携を利用して動的クレデンシャル認証を行う
- OIDCを利用してTerraform CloudとGCP間の認証を行う
この記事ではTerraform Cloud側にGOOGLE_CREDENTIALSのようなセンシティブな情報を保存する必要がないWorkload Identity連携を利用して動的認証を行う方法を紹介していく
手っ取り早く使いたい人向けの情報
Workload Identity連携を利用した認証ができれば何でも良いという人はこちらの記事を見て、Terraform CloudとGCPの設定をlocal等のTerraformで行う方法を見ていただくのが良いだろう。
操作手順
ここから具体的な操作手順に入っていく。
目標
この記事では下記のことができる環境を用意することをゴールとする。
事前準備
これらのリソースは既に存在している前提で手順は書いていく。
- 管理する「Terraform Cloud」のワークスペース
- 管理対象の「Google Cloud Platformのプロジェクト」
- IAM Service Account Credentials APIが有効になっている必要がある
[GCP] Workload IdentityのIDプールとプロバイダを作成する
まず、Terraform CloudからGCPへOIDCで認証するためにGCPで「IAMと管理」内のWorkload Identity連携でIDプールとプロバイダを作成する。
1. IDプールの作成
- プール名
- 説明
- 空欄でも問題ないが、Terraform CloudのOrganization名/Workspace名を入れておくと分かりやすいと思う
2. プールにプロバイダを追加
- プロバイダの選択:
OpenID Connect (OIDC)
を選択 - プロバイダ名:
tfc-oidc-provider
など任意の名前を付ける- ベストプラクティスに沿うのであれば、IDプールにプロバイダは1つしか作られないので、プロバイダ名/IDはユニーク性を考慮する必要はない
- 発行元 (URL):
https://app.terraform.io
- Terraform Cloudを利用するなら、この欄は
https://app.terraform.io
で固定になる
- Terraform Cloudを利用するなら、この欄は
- オーディエンス:
デフォルトのオーディエンス
を選択
Terraform Cloudの場合は下記のURLのjwks_uri
がJWKファイルとして取り込まれる。
https://app.terraform.io/.well-known/openid-configuration
参考: Workload Identity 連携 | IAM のドキュメント | Google Cloud
3. プロバイダの属性を構成
属性マッピング
属性マッピングはこの後の手順があるサービスアカウントとプロバイダを関連付ける際のロールバインディングで使用するようだが、今回は使わないので最低限必要なマッピングだけを設定していく。
OIDC | |
---|---|
google.subject | assertion.sub |
属性条件
assertion.terraform_full_workspace=='organization:${TFC_ORGANIZATION}:project:${TFC_PROJECT}:workspace:${TFC_WORKSPACE}'
※${TFC_ORGANIZATION}
, ${TFC_PROJECT}
, ${TFC_WORKSPACE}
は各自の環境で異なる値
Terraform Cloudの公式の例ではassertion.sub.startsWith(\”organization:my-org:project:my-project:workspace:my-workspace”\)
という記述が用いられているがsub.startsWithだとmy-workspace2
のように複数のワークスペースでOIDCトークンが認証されてしまうので、assertion.terraform_full_workspace
の完全一致で条件を指定したほうがより安心なはずである。
これで保存すれば、IDプールとプロバイダを作成することができる。
[GCP] Workload Identityプールにサービス アカウントへのアクセスを許可する
次にTerraform CloudからGoogle Cloudのリソースを操作を操作するためのサービスアカウントでWorkload Identityを利用できるようにする。
1. サービスアカウントを作成
まず、適切な権限を持ったサービスアカウントを作成しておく。 既にGOOGLE_CREDENTIALS認証で利用しているサービスアカウントがあればそれでも問題は無い。
2. プールにサービスアカウントのアクセス権を追加する
先ほど作成したプールの詳細画面を見に行くと「アクセス権を追加」という項目からアクセス権を追加する。
- サービスアカウント: Terraform Cloudで使用するサービスアカウントを選択
- プリンシパル(サービス アカウントにアクセスできる ID)の選択:
プール内のすべてのID
追加の際に「アプリケーションの構成」というモーダルが表示されるが、これは不要なので「非表示」を押して閉じてしまって問題ない。
ここまで行えばGCP側の設定は完了となる。
[TFC] 認証用の環境変数を設定する
最後にTerraform CloudからGoogle Cloudへの接続時に作成したWorkload Identity経由で認証するようワークスペースに環境変数を追加する。
Key | Value |
---|---|
TFC_GCP_PROVIDER_AUTH | true |
TFC_GCP_RUN_SERVICE_ACCOUNT_EMAIL | Workload Identityと連携させたサービスアカウントのメールアドレス |
TFC_GCP_PROJECT_NUMBER | GCPのダッシュボードに表示されているプロジェクト番号 |
TFC_GCP_WORKLOAD_POOL_ID | 作成したプールのID |
TFC_GCP_WORKLOAD_PROVIDER_ID | 作成したプロバイダのID |
変数の種類はすべてEnvironment variable
を選択する。
TFC_GCP_WORKLOAD_PROVIDER_NAME
は下記のフォーマットになるが、変数一覧を見たときに各値が分かりやすいよう個別の変数を設定する方法で設定をおこなった。
projects/${TFC_GCP_PROJECT_NUMBER}/locations/global/workloadIdentityPools/${TFC_GCP_WORKLOAD_POOL_ID}/providers/${TFC_GCP_WORKLOAD_PROVIDER_ID}
ここまで設定すればWorkload Identity連携を用いた動的認証が使えるようになっているはず。
トラブルシューティング
実際にTerraform Cloudでrunしてみたところ下記のようなエラーに遭遇したので、対処方法を書いておく。
アクセストークンの生成失敗系のエラー (status code: 400)
Invalid resource name supplied as 'audience': parent resource 'projects/***' does not exist or has been disabled/deleted.
TFC_GCP_PROJECT_NUMBER
の環境変数の値が間違っているときに表示されるエラー
対処方法: GCPのプロジェクト番号をダッシュボードで確認して、TFC_GCP_PROJECT_NUMBER
の値を変更する
The given credential is rejected by the attribute condition.
プロバイダ作成時の属性条件と実行したTerraform Cloudの環境が一致していないときに表示されるエラー 対処方法: Workload Identityプロバイダの属性条件を確認して、組織名/プロジェクト名/ワークスペース名などに間違いがないか確認する
Permission系のエラー (status code: 403)
IAM Service Account Credentials API has not been used in project *** before or it is disabled
OIDCトークンでの認証に必要なAPIが有効になっていないときに表示されるエラー
対処方法: APIとサービスの画面からIAM Service Account Credentials APIを有効にする
Permission '*******' denied on resource
サービスアカウントにリソースの作成・変更に必要な権限が付いていないときに表示されるエラー 対処方法: プロバイダと関連付けたサービスアカウントのプリンシパルに割り当てられているロールを変更する
参考ページ
- Workload Identity 連携の構成 | IAM のドキュメント | Google Cloud
- Dynamic Credentials with the GCP Provider - Workspaces - Terraform Cloud | Terraform | HashiCorp Developer
- 動的クレデンシャルで Terraform Cloud から Google Cloud を楽に&安全に 利用しよう
- GitHub Actions と Terraform Cloud に対応した Workload Identity 連携の構成 | Google Cloud 公式ブログ