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

如何在Terraform模块间共享资源?多IAM角色复用同一IAM策略

解决Terraform模块复用资源避免重复创建的问题

核心问题分析

你当前的写法中,每个角色模块都独立调用了policy模块,而Terraform的模块实例是完全独立的,因此会触发两次IAM策略的创建操作。Terraform的模块结构确实是树形的,兄弟模块默认无法直接共享子模块的资源,必须通过向上声明、向下传递的方式实现资源复用。

基础解决方案:单策略多角色场景

将共享的策略模块提升到父模块中声明,再把策略的ARN作为变量传递给各个角色模块,这样就能保证策略只创建一次,所有角色共享同一资源。

1. 修改角色模块,添加变量接收策略ARN

以test-role-1模块为例,移除内部的policy模块调用,新增变量接收外部传入的策略ARN:

# test-role-1/main.tf
variable "secrets_manager_policy_arn" {
  type        = string
  description = "ARN of the SecretsManager read-only policy"
}

resource "aws_iam_role" "test_role_1" {
  name = "test-role-1"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Sid    = ""
        Principal = {
          Service = "ecs-tasks.amazonaws.com"
        }
      },
    ]
  })
}

resource "aws_iam_role_policy_attachment" "attach_secrets_manager_read_to_role" {
  role       = aws_iam_role.test_role_1.name
  policy_arn = var.secrets_manager_policy_arn
}

test-role-2模块做完全相同的修改即可。

2. 在父模块中声明策略并传递引用

在create-roles父模块中,只声明一次policy模块,然后将其输出的ARN传递给两个角色模块:

# create-roles/main.tf
module "secrets_policy" {
  source = "../../../modules/resources/test-policy"
}

module "role-1" {
  source = "../../../modules/resources/test-role-1"
  secrets_manager_policy_arn = module.secrets_policy.policy.arn
}

module "role-2" {
  source = "../../../modules/resources/test-role-2"
  secrets_manager_policy_arn = module.secrets_policy.policy.arn
}

进阶方案:多对多关系(多角色共享多策略)

如果需要实现多个角色绑定多个不同策略的场景,可以通过列表类型变量配合for_each元参数来实现,让角色模块支持接收多个策略ARN并批量创建附件。

1. 修改角色模块支持多策略传入

# test-role-1/main.tf
variable "policy_arns" {
  type        = list(string)
  description = "List of policy ARNs to attach to this IAM role"
}

resource "aws_iam_role" "test_role_1" {
  name = "test-role-1"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Sid    = ""
        Principal = {
          Service = "ecs-tasks.amazonaws.com"
        }
      },
    ]
  })
}

# 使用for_each批量创建策略附件
resource "aws_iam_role_policy_attachment" "attach_policies" {
  for_each = toset(var.policy_arns)
  role       = aws_iam_role.test_role_1.name
  policy_arn = each.value
}

2. 父模块中组合多策略并分配给角色

在父模块中声明所有需要的策略模块,然后将对应的ARN组合成列表,按需传递给不同角色:

# create-roles/main.tf
# 声明多个共享策略
module "secrets_policy" {
  source = "../../../modules/resources/test-policy"
}

module "s3_read_policy" {
  source = "../../../modules/resources/s3-read-policy"
}

# 角色1绑定两个策略
module "role-1" {
  source = "../../../modules/resources/test-role-1"
  policy_arns = [
    module.secrets_policy.policy.arn,
    module.s3_read_policy.policy.arn
  ]
}

# 角色2仅绑定SecretsManager策略
module "role-2" {
  source = "../../../modules/resources/test-role-2"
  policy_arns = [module.secrets_policy.policy.arn]
}

总结

Terraform的模块设计遵循树形结构,兄弟模块无法直接共享子资源,必须通过父模块作为中间层传递资源引用。这种方式既能保持代码的模块化拆分(角色、策略各自独立为模块),又能避免重复创建资源。对于多对多的绑定需求,通过列表变量+for_each就能灵活实现不同角色与策略的组合。

内容的提问来源于stack exchange,提问作者Gergő Horváth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 02:57:32