You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform初始化GCP远程状态遇403:如何指定及查看操作账号

核心问题
  • 如何为terraform init等Terraform操作指定用户账号/邮箱?
  • 如何查看Terraform默认使用的邮箱?
问题背景

我的Terraform远程状态存储在GCP Bucket中,目前无法通过Terraform操作访问该状态(组织权限正常)。我通过服务账号模拟(impersonation),使用gcloud和gsutil测试访问,能够读写状态存储桶,命令如下:

gsutil -i "terraform-admin@<project-id>.iam.gserviceaccount.com" cp test-file.txt gs://<state-bucket-id>/terraform.tfstate/test-file.txt

我已验证,用于模拟高权限服务账号的用户账号已被赋予iam.serviceAccountTokenCreator角色。但执行terraform init时,出现如下错误:

│ Error: Failed to get existing workspaces: querying Cloud Storage failed: Get "https://storage.googleapis.com/storage/v1/b/<project-bucket-state-for-workspace>/o?alt=json&delimiter=%2F&pageToken=&prefix=terraform.tfstate%2F&prettyPrint=false&projection=full&versions=false": impersonate: status code 403: {
│   "error": {
│     "code": 403,
│     "message": "The caller does not have permission",
│     "status": "PERMISSION_DENIED"
│   }
│ }

我尝试通过gcloud auth login登录管理员用户账号,仍出现相同错误,说明Terraform未使用正确的账号/邮箱执行init操作。

补充日志信息

启用TF_LOG=TRACE后的客户端日志如下:

2022-11-21T01:40:23.350+0100 [INFO]  Terraform version: 1.3.4
2022-11-21T01:40:23.351+0100 [DEBUG] using github.com/hashicorp/go-tfe v1.9.0
2022-11-21T01:40:23.351+0100 [DEBUG] using github.com/hashicorp/hcl/v2 v2.14.1
2022-11-21T01:40:23.351+0100 [DEBUG] using github.com/hashicorp/terraform-config-inspect v0.0.0-20210209133302-4fd17a0faac2
2022-11-21T01:40:23.351+0100 [DEBUG] using github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734
2022-11-21T01:40:23.351+0100 [DEBUG] using github.com/zclconf/go-cty v1.12.0
2022-11-21T01:40:23.351+0100 [INFO]  Go runtime version: go1.19.3
2022-11-21T01:40:23.351+0100 [INFO]  CLI args: []string{"terraform", "init"}
2022-11-21T01:40:23.351+0100 [TRACE] Stdout is a terminal of width 156
2022-11-21T01:40:23.351+0100 [TRACE] Stderr is a terminal of width 156
2022-11-21T01:40:23.351+0100 [TRACE] Stdin is a terminal
2022-11-21T01:40:23.351+0100 [DEBUG] Attempting to open CLI config file: /home/<user>/.terraformrc
2022-11-21T01:40:23.351+0100 [DEBUG] File doesn't exist, but doesn't need to. Ignoring.
2022-11-21T01:40:23.351+0100 [DEBUG] ignoring non-existing provider search directory terraform.d/plugins
2022-11-21T01:40:23.351+0100 [DEBUG] ignoring non-existing provider search directory /home/<user>/.terraform.d/plugins
2022-11-21T01:40:23.351+0100 [DEBUG] ignoring non-existing provider search directory /home/<user>/.local/share/terraform/plugins
2022-11-21T01:40:23.351+0100 [DEBUG] ignoring non-existing provider search directory /usr/local/share/terraform/plugins
2022-11-21T01:40:23.351+0100 [DEBUG] ignoring non-existing provider search directory /usr/share/terraform/plugins
2022-11-21T01:40:23.351+0100 [DEBUG] ignoring non-existing provider search directory /var/lib/snapd/desktop/terraform/plugins
2022-11-21T01:40:23.351+0100 [INFO]  CLI command args: []string{"init"}
Initializing modules...
2022-11-21T01:40:23.358+0100 [TRACE] ModuleInstaller: installing child modules for . into .terraform/modules
2022-11-21T01:40:23.363+0100 [DEBUG] Module installer: begin dev-omni-orchestrator-instance
2022-11-21T01:40:23.367+0100 [TRACE] ModuleInstaller: Module installer: dev-omni-orchestrator-instance <nil> already installed in ../modules/omni-orchestrator
2022-11-21T01:40:23.367+0100 [DEBUG] Module installer: begin gcs-infra-genesis-state-buckets
2022-11-21T01:40:23.370+0100 [TRACE] ModuleInstaller: Module installer: gcs-<terraform-project>-state-buckets 3.4.0 already installed in .terraform/modules/gcs-<terraform-project>-state-buckets
2022-11-21T01:40:23.370+0100 [TRACE] modsdir: writing modules manifest to .terraform/modules/modules.json

Initializing the backend...
2022-11-21T01:40:23.382+0100 [TRACE] Meta.Backend: built configuration for "gcs" backend with hash value <V1>
2022-11-21T01:40:23.382+0100 [TRACE] Meta.Backend: backend has not previously been initialized in this working directory
2022-11-21T01:40:23.382+0100 [DEBUG] New state was assigned lineage "<V2>"
2022-11-21T01:40:23.382+0100 [TRACE] Meta.Backend: moving from default local state only to "gcs" backend
2022-11-21T01:40:23.382+0100 [DEBUG] checking for provisioner in "."
2022-11-21T01:40:23.384+0100 [DEBUG] checking for provisioner in "/usr/bin"
2022-11-21T01:40:23.384+0100 [TRACE] backend/local: state manager for workspace "default" will:
 - read initial snapshot from terraform.tfstate
 - write new snapshots to terraform.tfstate
 - create any backup at terraform.tfstate.backup
2022-11-21T01:40:23.384+0100 [TRACE] statemgr.Filesystem: reading initial snapshot from terraform.tfstate
2022-11-21T01:40:23.384+0100 [TRACE] statemgr.Filesystem: snapshot file has nil snapshot, but that's okay
2022-11-21T01:40:23.384+0100 [TRACE] statemgr.Filesystem: read nil snapshot
2022-11-21T01:40:23.384+0100 [TRACE] Meta.Backend: ignoring local "default" workspace because its state is empty
2022-11-21T01:40:23.385+0100 [DEBUG] New state was assigned lineage "<V3>"
╷
│ Error: Failed to get existing workspaces: querying Cloud Storage failed: Get "https://storage.googleapis.com/storage/v1/b/<terraform-project>-terraform-state/o?alt=json&delimiter=%2F&pageToken=&prefix=terraform.tfstate%2F&prettyPrint=false&projection=full&versions=false": impersonate: status code 403: {
│   "error": {
│     "code": 403,
│     "message": "The caller does not have permission",
│     "status": "PERMISSION_DENIED"
│   }
│ }
│
解决方案

一、查看Terraform默认使用的账号/邮箱

Terraform依赖GCP的认证凭据,默认读取gcloud的活跃账号或环境变量中的凭据,可通过以下方式查看:

  1. 查看gcloud所有已登录账号及当前活跃账号:
gcloud auth list

输出中带*标记的就是当前活跃账号,Terraform默认会使用这个账号。
2. 直接查看当前gcloud配置的账号:

gcloud config get-value account

二、为Terraform操作指定账号/邮箱

方法1:切换gcloud活跃账号

直接切换到目标账号,Terraform会自动继承该账号身份:

gcloud config set account "your-target-account@example.com"

如果需要使用服务账号模拟,先配置模拟身份(需当前用户有iam.serviceAccountTokenCreator权限):

gcloud config set auth/impersonate_service_account terraform-admin@<project-id>.iam.gserviceaccount.com

配置完成后运行terraform init即可。

方法2:通过环境变量临时指定

设置环境变量让Terraforce使用指定凭据,仅在当前终端会话生效:

# 使用服务账号密钥文件
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"

# 或者使用服务账号模拟
export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT="terraform-admin@<project-id>.iam.gserviceaccount.com"

设置后直接运行terraform init。

方法3:在Terraform后端配置中指定

在backend "gcs"块中直接添加服务账号模拟配置:

terraform {
  backend "gcs" {
    bucket = "<state-bucket-id>"
    prefix = "terraform.tfstate"
    impersonate_service_account = "terraform-admin@<project-id>.iam.gserviceaccount.com"
  }
}

修改配置后运行terraform init -reconfigure生效。

三、当前问题额外排查建议

从错误日志看,Terraform在模拟服务账号时触发403,建议:

  • 确认当前用户的iam.serviceAccountTokenCreator角色绑定在目标服务账号层级(而非仅项目层级);
  • 检查GCP Bucket的权限策略,确保目标服务账号拥有storage.objects.list、storage.objects.get、storage.objects.create等必要权限;
  • 运行gcloud auth print-access-token验证当前凭据的有效性,以及是否包含服务账号模拟权限。

内容的提问来源于Stack Exchange,提问作者Imad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 05:10:29