Loading...
Loading...
### Terraform Version ```shell Terraform v1.14.4 on linux_arm64 + provider registry.terraform.io/hashicorp/google v7.24.0 + provider registry.terraform.io/hashicorp/google-beta v7.24.0 ``` ### Terraform Configuration Files ```terraform locals { env = basename(path.cwd) # e.g. "develop", "production" impersonated_service_account = "${terraform.applying ? "terraform-apply" : "terraform-plan"}@example-project.iam.gserviceaccount.com" } provider "google" { alias = "example" region = "us-central1" impersonate_service_account = local.impersonated_service_account } resource "google_secret_manager_secret" "example" { provider = google.example secret_id = "example-secret" project = "example-project" replication { auto {} } } resource "google_secret_manager_secret_version" "debug" { provider = google.example secret = google_secret_manager_secret.example.id # write-only attribute to verify terraform.applying value secret_data_wo = local.impersonated_service_account secret_data_wo_version = 1 } ``` ### Debug Output Key excerpt from TF_LOG=DEBUG terraform apply output. During the plan phase of terraform apply, the provider is initialized with the false branch value: ``` 2026-03-24T05:52:47.589Z [DEBUG] provider.terraform-provider-google_v7.24.0_x5: 2026/03/24 05:52:47 [INFO] Terraform is configured with service account impersonation, original identity: user@example.com, impersonated identity: terraform-plan@example-project.iam.gserviceaccount.com ``` This shows that at provider initialization time during terraform apply, terraform.applying evaluated to false, causing the provider to use the plan-phase service account instead of the apply-phase one. The subsequent API call then fails because the calling identity only has permission to impersonate terraform-apply@...: ``` 2026-03-24T05:52:47.838Z [DEBUG] provider.terraform-provider-google_v7.24.0_x5: Retry Transport: Stopping retries, last request failed with non-retryable error: impersonate: status code 403: { "error": { "code": 403, "message": "Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist).", "status": "PERMISSION_DENIED" } ``` Additionally, this can be confirmed from the Google Cloud audit log. The GenerateAccessToken request targets the plan-phase service account: ``` { "request": { "name": "projects/-/serviceAccounts/terraform-plan@example-project.iam.gserviceaccount.com", "@type": "type.googleapis.com/google.iam.credentials.v1.GenerateAccessTokenRequest" } } ``` ### Expected Behavior When running terraform apply directly (not a saved plan), terraform.applying should evaluate to true in all ephemeral contexts, including local values referenced from a provider block. The provider should be configured with terraform-apply@example-project.iam.gserviceaccount.com. The [documentation](https://developer.hashicorp.com/terraform/language/functions/terraform-applying) states that terraform.applying can be used in local values and in provider block configuration, and shows an example of exactly this pattern (switching AWS assume role ARN based on terraform.applying). ### Actual Behavior During terraform apply, the provider block receives terraform-plan@example-project.iam.gserviceaccount.com, indicating that terraform.applying evaluates to false at provider initialization time. However, terraform.applying correctly evaluates to true when referenced from a write-only attribute (secret_data_wo) in the same local value and same terraform apply invocation. This confirms the value itself is correct during the apply phase — just not at the time the provider configuration is evaluated. ### Steps to Reproduce 1. Create a configuration that uses terraform.applying in a local value referenced by a provider block's impersonate_service_account (as shown above). 1. Set up IAM so the calling identity can only impersonate terraform-apply@... (the apply-phase SA), not terraform-plan@... (the plan-phase SA). This makes it easy to detect which SA the provider attempts to use. 1. Run terraform apply directly (not terraform plan -out=plan && terraform apply plan). 1. Observe the debug log showing the provider initialized with terraform-plan@... (the false branch). 1. Observe the 403 error confirming the wrong service account was used. 1. To verify terraform.applying itself works correctly: remove the provider alias from the resource (so it uses default credentials without impersonation), add a write-only attribute referencing the same local value, and run terraform apply again. 1. Observe that the write-only attribute correctly receives terraform-apply@... (the true branch). ### Additional Context - This also reproduces when terraform.applying is used directly in the provider block instead of via a local value. - The -target flag was used during testing, but the issue is about provider initialization timing, not targeting. - Using terraform.applying in the provider block to switch credentials between plan and apply is the primary documented use case shown in the [official documentation](https://developer.hashicorp.com/terraform/language/functions/terraform-applying), which demonstrates switching an AWS IAM assume role ARN with the same pattern. ### References https://developer.hashicorp.com/terraform/language/functions/terraform-applying ### Generative AI / LLM assisted development? _No response_
Click on a version to see all relevant bugs
Terraform Integration
Learn more about where this data comes from
Bug Scrub Advisor
Streamline upgrades with automated vendor bug scrubs
BugZero Enterprise
Wish you caught this bug sooner? Get proactive today.