🥢

Dynamic Provider Credentials with GCP を Project 配下の任意の Workspace で利用する

2024/01/30に公開

Terraform Cloudでは、Dynamic Provider Credentialsを利用する事で、AWS、Azure、GCP、Kubernetes、Vaultのプロバイダの認証情報をジャストインタイムで生成し、利用する事が出来ます。
ここではDynamic Provider Credentials with GCPを、Terraform CloudのProject配下の任意のWorkspaceで利用出来る様にする設定を紹介します。

Dynamic Provider Credentials with GCP

Dynamic Provider Credentials(以下DPC)の設定をTerraformで行う場合のサンプルコードが提供されています。DPCのチュートリアルAuthenticate providers with dynamic credentialsで参照されているTerraformコードが参考になるかと思います。
https://github.com/hashicorp-education/learn-terraform-dynamic-credentials/tree/main/gcp/trust

上記リンクのサンプルコードもそうですが、google_iam_workload_identity_pool_providerリソースのattribute_conditionの指定方法だと、特定のProject配下の特定のWorkspaceからのみ、DPCを利用してGCPのプロバイダの認証情報をジャストインタイムで利用する事が出来ます。

ただ、ユースケースによっては、Project配下の任意のWorkspaceからDPCを利用したいというケースがあると思います。例えば、No-Code Provisioiningを利用する際に、DPCを活用し、No-Code Ready Moduleで利用しているプロバイダの認証情報をジャストインタイムで生成するといったケースや、チームやプロジェクト毎にTerraform CloudのProjectをアサインし、そのProject内で利用するプロバイダの認証情報をDPCで設定しておく等。

DPC with AWSの場合は、Workspaceの指定でワイルドカード(*)を指定する事で、Project配下の任意のWorkspaceから利用するという事が実現出来たのですが、DPC with GCPではワイルドカードは上手く機能しませんでした。

という事で、attribute_conditionstartsWith関数の中で、Workspace名に空の文字列を指定する事で任意のWorkspaceを表現する事が出来ます
具体的には、google_iam_workload_identity_pool_providerリソースに関するTerraformコードとしては、以下の様に設定して頂く事で、Project配下の任意のWorkspaceからDPC with GCPを利用する事が出来ます。

resource "google_iam_workload_identity_pool_provider" "tfc_provider" {
  workload_identity_pool_id          = google_iam_workload_identity_pool.tfc_pool.workload_identity_pool_id
  workload_identity_pool_provider_id = "my-tfc-provider-id"

  attribute_mapping = {
    "google.subject"                        = "assertion.sub",
    "attribute.aud"                         = "assertion.aud",
    "attribute.terraform_run_phase"         = "assertion.terraform_run_phase",
    "attribute.terraform_project_id"        = "assertion.terraform_project_id",
    "attribute.terraform_project_name"      = "assertion.terraform_project_name",
    "attribute.terraform_workspace_id"      = "assertion.terraform_workspace_id",
    "attribute.terraform_workspace_name"    = "assertion.terraform_workspace_name",
    "attribute.terraform_organization_id"   = "assertion.terraform_organization_id",
    "attribute.terraform_organization_name" = "assertion.terraform_organization_name",
    "attribute.terraform_run_id"            = "assertion.terraform_run_id",
    "attribute.terraform_full_workspace"    = "assertion.terraform_full_workspace",
  }
  oidc {
    issuer_uri = "https://${var.tfc_hostname}"
    # The default audience format used by TFC is of the form:
    # //iam.googleapis.com/projects/{project number}/locations/global/workloadIdentityPools/{pool ID}/providers/{provider ID}
    # which matches with the default accepted audience format on GCP.
    #
    # Uncomment the line below if you are specifying a custom value for the audience instead of using the default audience.
    # allowed_audiences = [var.tfc_gcp_audience]
  }
  attribute_condition = "assertion.sub.startsWith(\"organization:${var.tfc_organization_name}:project:${var.tfc_project_name}:workspace:\")"
}

DPCを設定する際に必要な他のリソースに関しては、上記でリンク先を記載したGitHubにあるサンプルコードと同じで問題ないです。

Dynamic Provider Credentials with variable sets

サンプルコードにはTerraform Cloudへの設定をtfeプロバイダを利用して行う事をはしていませんが、DPC with GCPで必要な環境変数をVariable setsに登録し利用する場合、以下の様なTerraformコードで設定します。

provider "tfe" {}

data "tfe_organization" "myorg" {
  name = var.tfc_organization_name
}

data "tfe_project" "gcp" {
  organization = var.tfc_organization_name
  name         = var.tfc_project_name
}

resource "tfe_variable_set" "gcp" {
  name         = "gcp-dpc-for-project"
  description  = "Google Cloud Platform Dynamic Provider Credentials for Project: gcp"
  organization = var.tfc_organization_name
}

resource "tfe_project_variable_set" "gcp" {
  project_id      = data.tfe_project.gcp.id
  variable_set_id = tfe_variable_set.gcp.id
}

resource "tfe_variable" "tfc_gcp_provider_auth" {
  key             = "TFC_GCP_PROVIDER_AUTH"
  value           = "true"
  category        = "env"
  description     = "The TFC_GCP_PROVIDER_AUTH variable configures the workspace to use dynamic credentials for the GCP provider."
  variable_set_id = tfe_variable_set.gcp.id
}

resource "tfe_variable" "tfc_gcp_workload_provider_name" {
  key             = "TFC_GCP_WORKLOAD_PROVIDER_NAME"
  value           = google_iam_workload_identity_pool_provider.tfc_provider.name
  category        = "env"
  description     = "The workload provider name to authenticate against."
  variable_set_id = tfe_variable_set.gcp.id
}

resource "tfe_variable" "tfc_gcp_run_service_account_email" {
  key             = "TFC_GCP_RUN_SERVICE_ACCOUNT_EMAIL"
  value           = google_service_account.tfc_service_account.email
  category        = "env"
  description     = "The service account email used when authenticating to GCP."
  variable_set_id = tfe_variable_set.gcp.id
  depends_on = [
    google_service_account.tfc_service_account
  ]
}

このコードが反映されるとVariable setのスコープがTerraform変数var.tfc_project_nameで指定したProjectになります。

Terraformで定義したDPC with GCPのVariable setの一部

また、Variable setのスコープとして定義したProject配下にWorkspaceを作成すると、設定したVariable setが自動でWorkspaceのVariablesとしてセットされ、DPC with GCPを利用する準備が出来た状態になります。

Variable setのスコープとして定義したProject配下のWorkspaceのVariablesの一部

Notes: 上記Terraformコードで設定した環境変数TFC_GCP_WORKLOAD_PROVIDER_NAMETFC_GCP_RUN_SERVICE_ACCOUNT_EMAILもVariable setとして定義されていますが、上記2つの画像からは削除しています。

参考になる部分があれば、ご活用下さい!

References

Discussion