如何在 terraform 中创建 "impersonation" 模块?
How do I create an "impersonation" module in terraform?
我正在尝试使用以下项目结构编写具有角色分离功能的干净 Terraform 配置:
terraform-infra-genesis
┣ modules
┃ ┗ impersonation
┃ ┃ ┣ generic_sa_impersonation.tf
┃ ┃ ┣ inputs.tf
┃ ┃ ┗ test_i1.tfvars
┣ org
┃ ┣ main.tf
┃ ┣ outputs.tf
┃ ┣ terraform.tfvars
┃ ┗ variables.tf
┣ .gitignore
┗ README.md
我的目标(目前)是 运行 通过 org
目录定义我的基础设施。
第一步 - 不使用模块:我能够使用 Service account impersonation
guide found here 创建上述基础设施。执行 terraform apply
后,我在 GCP 上的基础设施状态已更新。这里没问题。
第二步 - 我创建了我将使用的 modules/impersionation,因为它可能对其他几个实例有用,例如创建 VPC、子网等...这里的目标是该模块将在设定的秒数内生成访问令牌。所以没有输出预期
在我的modules/impersonation中我写了下面的代码:
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "3.85.0"
}
}
}
# For a list of all scopes visit : https://developers.google.com/identity/protocols/oauth2/scopes
provider "google" {
alias = "service_account_impersonation"
scopes = var.p_info.scopes
}
data "google_service_account_access_token" "service_account_to_impersonate" {
provider = google.service_account_impersonation
target_service_account = var.sa_to_impersonate_info.email
scopes = var.sa_to_impersonate_info.token_scopes
lifetime = var.sa_to_impersonate_info.token_lifetime
}
provider "google" {
access_token = data.google_service_account_access_token.service_account_to_impersonate.access_token
region = var.p_info.region
zone = var.p_info.zone
}
# Add users as a token creators and impersonators for this service account
resource "google_service_account_iam_binding" "impersonators" {
for_each = toset([
for user in var.user_accs_impersonators_info : "${user.acc_type}:${user.acc_details.email}"
])
service_account_id = "projects/${var.sa_to_impersonate_info.belonging_project_id}/serviceAccounts/${var.sa_to_impersonate_info.email}"
role = "roles/iam.serviceAccountTokenCreator"
members = [each.key]
}
我 test/debug 通过创建 test_i1.tfvars 这个模块将包含以下(已编辑)值:
p_info = {
scopes = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email",
]
region = <redacted>
zone = <redacted>
}
sa_to_impersonate_info = {
email = <redacted>
belonging_org_id = <redacted>
belonging_project_id = <redacted>
token_lifetime = "1200s"
token_scopes = ["cloud-platform", "userinfo-email"]
}
user_accs_impersonators_info = [{
acc_type = "user",
acc_details = {
email = <redacted>
},
}]
当我执行 terraform plan
时有效,显示以下输出:
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
... <redacted> ...
Plan: 1 to add, 0 to change, 0 to destroy.
第三步——我在org/main.tf
:
中使用了之前写好的模块
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "3.85.0"
}
}
}
module "terraform_super_admin_service_account_impersonation" {
source = "../modules/impersonation"
p_info = {
region = <redacted>
zone = <redacted>
scopes = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email",
]
}
sa_to_impersonate_info = {
email = <redacted>
belonging_org_id = <redacted>
belonging_project_id = <redacted>
token_lifetime = "1200s"
token_scopes = [
"cloud-platform", "userinfo-email"
]
}
user_accs_impersonators_info = [{
acc_type = "user"
acc_details = {
email = <redacted>
}
}]
}
这里我得到错误:
Error: Error when reading or editing Resource "service account '<redacted>'" with IAM Binding (Role "roles/iam.serviceAccountTokenCreator"): Error retrieving IAM policy for service account '<redacted>': googleapi: Error 403: Permission iam.serviceAccounts.getIamPolicy is required to perform this operation on service account '<redacted>'., forbidden
但这没有意义,因为我只是在第 1 步和第 2 步中使用了这些相同的凭据...我在想,也许我使用的 provider 块错误模块,但我看不出我有其他选择来进行模拟。
这是怎么回事?
当您从 top-level Terraform 代码中使用该模块时,您的“模拟”模块中的提供程序块将被忽略。根据 the documentation:
Provider configurations, unlike most other concepts in Terraform, are global to an entire Terraform configuration and can be shared across module boundaries. Provider configurations can be defined only in a root Terraform module.
和:
A module intended to be called by one or more other modules must not contain any provider blocks.
因此,您模块中的 provider
配置仅在您从同一文件夹中执行 运行 terraform
命令时才有效。在您的顶级文件夹中启动 运行 terraform
命令后,该配置将被忽略。
根据我的经验,您在“模拟”模块中尝试做的事情只属于 top-level .tf 文件,而不是模块。
我正在尝试使用以下项目结构编写具有角色分离功能的干净 Terraform 配置:
terraform-infra-genesis
┣ modules
┃ ┗ impersonation
┃ ┃ ┣ generic_sa_impersonation.tf
┃ ┃ ┣ inputs.tf
┃ ┃ ┗ test_i1.tfvars
┣ org
┃ ┣ main.tf
┃ ┣ outputs.tf
┃ ┣ terraform.tfvars
┃ ┗ variables.tf
┣ .gitignore
┗ README.md
我的目标(目前)是 运行 通过 org
目录定义我的基础设施。
第一步 - 不使用模块:我能够使用 Service account impersonation
guide found here 创建上述基础设施。执行 terraform apply
后,我在 GCP 上的基础设施状态已更新。这里没问题。
第二步 - 我创建了我将使用的 modules/impersionation,因为它可能对其他几个实例有用,例如创建 VPC、子网等...这里的目标是该模块将在设定的秒数内生成访问令牌。所以没有输出预期
在我的modules/impersonation中我写了下面的代码:
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "3.85.0"
}
}
}
# For a list of all scopes visit : https://developers.google.com/identity/protocols/oauth2/scopes
provider "google" {
alias = "service_account_impersonation"
scopes = var.p_info.scopes
}
data "google_service_account_access_token" "service_account_to_impersonate" {
provider = google.service_account_impersonation
target_service_account = var.sa_to_impersonate_info.email
scopes = var.sa_to_impersonate_info.token_scopes
lifetime = var.sa_to_impersonate_info.token_lifetime
}
provider "google" {
access_token = data.google_service_account_access_token.service_account_to_impersonate.access_token
region = var.p_info.region
zone = var.p_info.zone
}
# Add users as a token creators and impersonators for this service account
resource "google_service_account_iam_binding" "impersonators" {
for_each = toset([
for user in var.user_accs_impersonators_info : "${user.acc_type}:${user.acc_details.email}"
])
service_account_id = "projects/${var.sa_to_impersonate_info.belonging_project_id}/serviceAccounts/${var.sa_to_impersonate_info.email}"
role = "roles/iam.serviceAccountTokenCreator"
members = [each.key]
}
我 test/debug 通过创建 test_i1.tfvars 这个模块将包含以下(已编辑)值:
p_info = {
scopes = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email",
]
region = <redacted>
zone = <redacted>
}
sa_to_impersonate_info = {
email = <redacted>
belonging_org_id = <redacted>
belonging_project_id = <redacted>
token_lifetime = "1200s"
token_scopes = ["cloud-platform", "userinfo-email"]
}
user_accs_impersonators_info = [{
acc_type = "user",
acc_details = {
email = <redacted>
},
}]
当我执行 terraform plan
时有效,显示以下输出:
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
... <redacted> ...
Plan: 1 to add, 0 to change, 0 to destroy.
第三步——我在org/main.tf
:
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "3.85.0"
}
}
}
module "terraform_super_admin_service_account_impersonation" {
source = "../modules/impersonation"
p_info = {
region = <redacted>
zone = <redacted>
scopes = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email",
]
}
sa_to_impersonate_info = {
email = <redacted>
belonging_org_id = <redacted>
belonging_project_id = <redacted>
token_lifetime = "1200s"
token_scopes = [
"cloud-platform", "userinfo-email"
]
}
user_accs_impersonators_info = [{
acc_type = "user"
acc_details = {
email = <redacted>
}
}]
}
这里我得到错误:
Error: Error when reading or editing Resource "service account '<redacted>'" with IAM Binding (Role "roles/iam.serviceAccountTokenCreator"): Error retrieving IAM policy for service account '<redacted>': googleapi: Error 403: Permission iam.serviceAccounts.getIamPolicy is required to perform this operation on service account '<redacted>'., forbidden
但这没有意义,因为我只是在第 1 步和第 2 步中使用了这些相同的凭据...我在想,也许我使用的 provider 块错误模块,但我看不出我有其他选择来进行模拟。
这是怎么回事?
当您从 top-level Terraform 代码中使用该模块时,您的“模拟”模块中的提供程序块将被忽略。根据 the documentation:
Provider configurations, unlike most other concepts in Terraform, are global to an entire Terraform configuration and can be shared across module boundaries. Provider configurations can be defined only in a root Terraform module.
和:
A module intended to be called by one or more other modules must not contain any provider blocks.
因此,您模块中的 provider
配置仅在您从同一文件夹中执行 运行 terraform
命令时才有效。在您的顶级文件夹中启动 运行 terraform
命令后,该配置将被忽略。
根据我的经验,您在“模拟”模块中尝试做的事情只属于 top-level .tf 文件,而不是模块。