繁体   English   中英

Terraform 和 GCP:尝试在项目级别引入模拟时出现错误 403

[英]Terraform & GCP : Error 403 when attempting to introduce impersonation on project-level

在应用启用服务帐户模拟的原则时,我非常迷茫......

我的 terraform 项目结构在每个环境中都有一个根模块,用于基本基础架构的base ,用于开发环境的dev和用于生产环境的prod

terraform-infra-genesis
 ┣ base
 ┃ ┣ ...
 ┃ ┣ impersonators_x_users.tf  <- user email me@domain.com is granted iam.serviceAccounts.getAccessToken role on 'super-admin' here (On all the organization)
 ┃ ┣ ...
 ┃ ┣ providers_x_access_tokens.tf 
 ┃ ┣ service_accounts_x_roles.tf   <- 'dev-admin' service account declared here
 ┃ ┣ terraform.tfstate
 ┃ ┗ terraform.tfstate.backup
 ┣ dev <- Everything here belongs to the dev environment
 ┃ ┣ backend.tf
 ┃ ┣ data_products.tf  <- Usage of the module 'marketing-hub' here
 ┃ ┣ ...
 ┃ ┣ impersonators_x_providers_x_access_tokens.tf  <- Declaration of as_dev_admin provider to 'delegate' ressource creation (such as folders) to the dev environment "super" administrator. I also declared "as_<project>_dev_admin" that should in principle, be able to create ressources only within its own <project>
 ┣ modules
 ┃ ┣ data-products
 ┃ ┃ ┣ cmi
 ┃ ┃ ┃ ┗ feedback-hub
 ┃ ┃ ┗ ddm
 ┃ ┃ ┃ ┣ analytics-hub
 ┃ ┃ ┃ ┣ marketing-hub
 ┃ ┃ ┃ ┃ ┣ marketing_hub.tf <- Usage of module 'data-project' here to bundle all logical projects together.
 ┃ ┃ ┃ ┗ media-hub
 ┃ ┗ data-project
 ┃ ┃ ┣ data_project.tf <- Module to create a GCP project and its project-dev-admin service account here
 ┣ prod
 ┃ ┣ ...
 ┣ .gitignore
 ┗ README.md

如该结构的注释中所述,我通常在dev/根模块中使用provider = as_dev_admin 我使用它成功创建了dev_coupons (一个 GCP 项目)。

这是我的dev/impersonators_x_providers_x_access_tokens.tf的结构

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = ">=3.85.0"
    }
  }
}

locals {
  tier_1_scopes = [
    "https://www.googleapis.com/auth/cloud-platform",
    "https://www.googleapis.com/auth/userinfo.email",
  ]
  tier_2_scopes = [
    "cloud-platform",
    "userinfo-email",
  ]
}
# Dev Admin impersonation
provider "google" {
  alias  = "impersonation"
  scopes = local.tier_1_scopes
}

data "google_service_account_access_token" "dev-admin" {
  provider               = google.impersonation
  target_service_account = data.terraform_remote_state.base.outputs.service-accounts.dev-admin.email
  scopes                 = local.tier_2_scopes
  lifetime               = "1200s"
}

provider "google" {
  alias        = "as_dev_admin"
  access_token = data.google_service_account_access_token.dev-admin.access_token
  region       = var.region
  zone         = var.zone
}


################################################################################
##################### Impersonation of a service account #######################
############################ as_dev_coupons_admin ##############################
################################################################################
# Copy/paste this block in order to introduce the 
# impersonation of any service account

data "google_service_account_access_token" "dev-coupons-admin" {
  provider               = google.impersonation
  target_service_account = module.marketing-hub-products.projects.coupons.admin_service_account.email
  scopes                 = local.tier_2_scopes
  lifetime               = var.lifetime
}

provider "google" {
  alias        = "as_dev_coupons_admin"
  project      = module.marketing-hub-products.projects.coupons.project_info.project_id
  access_token = data.google_service_account_access_token.dev-coupons-admin.access_token
  region       = var.region
  zone         = var.zone
}

resource "google_service_account_iam_member" "dev-coupons-admin-impersonators" {
  provider = google.as_dev_admin  # Global dev environment admin will grant this permission
  for_each = toset([
    for account in var.user_accs_impersonators_info.as_dev_coupons_admin :
    "${account.acc_type}:${account.acc_details.email}"
  ])

  service_account_id = module.marketing-hub-products.projects.coupons.admin_service_account.name
  role               = "roles/iam.serviceAccountTokenCreator"
  member             = each.value
}


################################################################################
################################### End of #####################################
############################ as_dev_coupons_admin ##############################
################################################################################

我的项目名称是dev-coupons

当我尝试将附加provider alias as_dev_coupons_admin声明给特定项目dev-coupons管理员时,我收到此错误:

│ Error: googleapi: Error 403: The caller does not have permission, forbidden
│
│   with data.google_service_account_access_token.dev-coupons-admin,
│   on impersonators_x_providers_x_access_tokens.tf line 48, in data "google_service_account_access_token" "dev-coupons-admin":
│   48: data "google_service_account_access_token" "dev-coupons-admin" {
│

我不明白为什么创建"google_service_account_access_token" "dev_coupons_admin"返回403 ......起初,我以为是因为某些父模块的provider在干扰,但不,这里我们在基本模块dev ,具有相同的创建整个dev环境资源的凭据,具有相同的关联用户 email,但返回此拒绝访问。

然后我启用了日志export TF_VARS=DEBUG; export TF_LOG_PATH="terraform_log.txt" export TF_VARS=DEBUG; export TF_LOG_PATH="terraform_log.txt" ,我发现这一行:

---[ REQUEST ]---------------------------------------
POST /v1/projects/-/serviceAccounts/dev-coupons-admin@<redacted_project_id>.iam.gserviceaccount.com:generateAccessToken?alt=json&prettyPrint=false HTTP/1.1
Host: iamcredentials.googleapis.com
User-Agent: google-api-go-client/0.5 Terraform/1.2.9 (+https://www.terraform.io) Terraform-Plugin-SDK/2.10.1 terraform-provider-google/dev
Content-Length: 129
Content-Type: application/json
X-Goog-Api-Client: gl-go/1.18.1 gdcl/0.92.0
Accept-Encoding: gzip

{
 "lifetime": "1200s",
 "scope": [
  "https://www.googleapis.com/auth/cloud-platform",
  "https://www.googleapis.com/auth/userinfo.email"
 ]
}

-----------------------------------------------------: timestamp=2022-09-21T21:25:58.442+0200
2022-09-21T21:25:58.534+0200 [INFO]  provider.terraform-provider-google_v4.36.0_x5: 2022/09/21 21:25:58 [DEBUG] Google API Response Details:
---[ RESPONSE ]--------------------------------------
HTTP/2.0 403 Forbidden
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
Cache-Control: private
Content-Type: application/json; charset=UTF-8
Date: Wed, 21 Sep 2022 19:26:04 GMT
Server: scaffolding on HTTPServer2
Vary: Origin
Vary: X-Origin
Vary: Referer
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 0

{
  "error": {
    "code": 403,
    "message": "The caller does not have permission",
    "errors": [
      {
        "message": "The caller does not have permission",
        "domain": "global",
        "reason": "forbidden"
      }
    ],
    "status": "PERMISSION_DENIED"
  }
}

也许它正在尝试通过指定的服务帐户访问“所有”项目? 请参阅-/v1/projects/-/serviceAccounts/中?

如果您能够阐明我缺乏理解的地方,我将不胜感激。

编辑: dev-coupons-admindev-coupons的所有者

TL;DR me@domain.com有权使用dev环境超级管理员创建令牌。 这并不意味着正确的级联到同一环境中的项目,您必须将帐户重新声明为与正确的服务帐户关联的令牌创建者。

我想我弄清楚了这个问题。 关键是要了解服务帐户 token_creators 的角色token_creators

  • 在我的组织中, as_dev_admin用于创建资源作为默认提供程序。
    • 有一个服务帐户有权创建基础结构元素。
    • 具有roles/iam.serviceAccountTokenCreator的用户 email me@domain.com通过base基础结构中的项目关联到此服务帐户,在层次结构中较高,但不是直接父级。
    • -> 假设与服务帐户关联的用户在基础设施的子元素中具有相同的权限显然是错误的。

这意味着模拟者的这个角色不会在dev环境中创建的data-project中继承。 Once you try to impersonate the dev-coupons-admin@<redacted_project_id>.iam.gserviceaccount.com using me@domain.com , it will not transfer to this email account because it was present in dev-admin@<some_common_project_id>.iam.gserviceaccount.comdev超级管理员。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM