Access Google Cloud from HCP Terraform with workload identity
Securely access Google Cloud from HCP Terraform using workload identity federation, eliminating the need to store service account keys.
Storing long-lived service account keys in HCP Terraform poses a significant security risk. If compromised, these account keys could give an attacker access to your Google Cloud environment. Not only is leaking the key a risk, but many organizations have a policy to block creation of such keys. Fortunately, in many cases, you can authenticate with more secure alternatives to service account keys. One such alternative is workload identity federation, which uses identity and access management (IAM) to grant external identities (such as HCP Terraform) the ability to impersonate service accounts.
HCP Terraform’s dynamic provider credentials allow Terraform runs to impersonate a service account through native OpenID Connect (OIDC) integration and obtain a short-lived OAuth 2.0 access token for each run. This short-lived access token lets you call any Google Cloud APIs that the service account has access to at runtime, making your HCP Terraform runs much more secure.
Using HashiCorp Terraform, you have the ability to create a Google Cloud workload identity pool and provider, which HCP Terraform uses to request a federated token. This token is then passed to the Google Terraform provider, which impersonates a service account to obtain temporary credentials to plan or apply Terraform.
The above diagram illustrates the authentication sequence for accessing Google Cloud using dynamic provider credentials and workload identity federation.
Below is an example to configure workload identity federation in Google Cloud. This approach assumes you have a pre-existing method to authenticate with your Google Cloud project. If you don’t, you can create the temporary service account outlined below.
» Set up the workload identity pool and provider
To get started, create a temporary service account along with a JSON key. Safely store this key within your HCP Terraform workspace variables to grant temporary access to your Google Cloud project. This less-secure access method will only be used for initial setup. Remember to delete the temporary service account key once you’ve transitioned to workload identity federation using the steps below.
To set up the HCP Terraform pool and provider for workload identity federation, update the local google_project_id
and organization_name
values in the locals{}
block:
locals {
google_project_id = "example-project"
organization_name = "example-org"
}
# create a workload identity pool for HCP Terraform
resource "google_iam_workload_identity_pool" "hcp_tf" {
project = local.google_project_id
workload_identity_pool_id = "hcp-tf-pool"
display_name = "HCP Terraform Pool"
description = "Used to authenticate to Google Cloud"
}
# create a workload identity pool provider for HCP Terraform
resource "google_iam_workload_identity_pool_provider" "hcp_tf" {
project = local.google_project_id
workload_identity_pool_id = google_iam_workload_identity_pool.hcp_tf.workload_identity_pool_id
workload_identity_pool_provider_id = "hcp-tf-provider"
display_name = "HCP Terraform Provider"
description = "Used to authenticate to Google Cloud"
attribute_condition = "assertion.terraform_organization_name==\"${local.organization_name}\""
attribute_mapping = {
"google.subject" = "assertion.sub"
"attribute.terraform_workspace_id" = "assertion.terraform_workspace_id"
"attribute.terraform_full_workspace" = "assertion.terraform_full_workspace"
}
oidc {
issuer_uri = "https://app.terraform.io"
}
}
Once the HCP Terraform pool and provider are created, create a service account that HCP Terraform will impersonate at runtime:
# example service account that HCP Terraform will impersonate
resource "google_service_account" "example" {
account_id = "example"
display_name = "Service Account for HCP Terraform"
project = local.google_project_id
}
# IAM verifies the HCP Terraform Workspace ID before authorizing access to impersonate the 'example' service account
resource "google_service_account_iam_member" "example_workload_identity_user" {
service_account_id = google_service_account.example.name
role = "roles/iam.workloadIdentityUser"
member = "principalSet://iam.googleapis.com/${google_iam_workload_identity_pool.hcp_tf.name}/attribute.terraform_workspace_id/ws-ZZZZZZZZZZZZZZZ"
}
# grant 'example' service account permissions to create a bucket
resource "google_project_iam_member" "example_storage_admin" {
member = "serviceAccount:${google_service_account.example.email}"
role = "roles/storage.admin"
project = local.google_project_id
}
» Delegating access to another workspace
For improved security and scalability, consider using a separate HCP Terraform workspace to set up and configure your workload identity federation. From this workspace, using HCP Terraform variable sets, you can share the service account and identity federation configuration, allowing you to securely delegate access to Google Cloud from one workspace to another.
Below is an example configuration that creates a variable set and shares it with another HCP Terraform workspace.
# create a variable set to store the workload identity federation config for the 'example' service account
resource "tfe_variable_set" "example" {
name = google_service_account.example.account_id
description = "Workload identity federation configuration for ${google_service_account.example.name}"
organization = local.organization_name
}
# share the variable set with another HCP Terraform Workspace
resource "tfe_workspace_variable_set" "example" {
variable_set_id = tfe_variable_set.example.id
workspace_id = "ws-XXXXXXXXXXXXXXX"
}
Create the required environment variables below and associate them with the variable set. HCP Terraform uses these to obtain the short-lived OAuth 2.0 access token, which it uses to impersonate a service account at runtime that can call any Google Cloud APIs that the service account has access to:
resource "tfe_variable" "example_provider_auth" {
key = "TFC_GCP_PROVIDER_AUTH"
value = "true"
category = "env"
variable_set_id = tfe_variable_set.example.id
}
resource "tfe_variable" "example_service_account_email" {
sensitive = true
key = "TFC_GCP_RUN_SERVICE_ACCOUNT_EMAIL"
value = google_service_account.example.email
category = "env"
variable_set_id = tfe_variable_set.example.id
}
resource "tfe_variable" "example_provider_name" {
sensitive = true
key = "TFC_GCP_WORKLOAD_PROVIDER_NAME"
value = google_iam_workload_identity_pool_provider.hcp_tf.name
category = "env"
variable_set_id = tfe_variable_set.example.id
}
» Using workload identity federation
When using workload identity federation, you don't need to define anything within the provider itself. By sharing the variable set — which includes the service account and identity federation configuration — with another HCP Terraform workspace, you automatically gain access to Google Cloud within the shared workspace.
HCP Terraform does this by impersonating the service account at runtime, using the environment variables from the shared variable set. This approach allows you to securely scale access management within HCP Terraform by delegating access from one workspace to another while precisely restricting Google Cloud access to only what the service account needs.
Using the service account created earlier, which has been assigned only the cloud storage admin role, you can immediately create a bucket within the shared workspace without having to configure anything else:
resource "google_storage_bucket" "example" {
name = "example"
location = "EU"
project = “example-project”
}
» Learn more about workload identity federation
If you want to learn more about keyless Google Cloud access from HCP Terraform, check out the dynamic provider credentials and workload identity federation documentation. You can find all the code used in this post on GitHub in the keyless-auth-gcp-hcp-terraform repository.
Sign up for the latest HashiCorp news
More blog posts like this one
Fix the developers vs. security conflict by shifting further left
Resolve the friction between dev and security teams with platform-led workflows that make cloud security seamless and scalable.
HashiCorp at AWS re:Invent: Your blueprint to cloud success
If you’re attending AWS re:Invent in Las Vegas, Dec. 2 - Dec. 6th, visit us for breakout sessions, expert talks, and product demos to learn how to take a unified approach to Infrastructure and Security Lifecycle Management.
Speed up app delivery with automated cancellation of plan-only Terraform runs
Automatic cancellation of plan-only runs allows customers to easily cancel any unfinished runs for outdated commits to speed up application delivery.