Terraform如何为不同项目生成仅含对应资源的独立IAM策略
解决方案
你当前的问题核心是template_file数据源只全局渲染了一次,传入了所有项目的资源,所有policy复用了同一份渲染结果,按以下方式修改即可实现需求:
1. 调整数据源配置,增加循环和资源筛选
给template_file也加上count循环,每次仅传入当前项目对应的资源列表:
data "template_file" "project_policy" { count = length(var.projects) template = file("${path.module}/project_policy.tpl") vars = { # 筛选当前项目对应的资源 current_project_resources = join(",", [for res in var.projects_resources : res if startswith(res, "${var.projects[count.index]}/")]) } }
2. 调整模板文件
现在每次传入的都是单项目的资源,替换模板里的变量名即可,同时注意删掉原模板中多余的右大括号:
... "Resource": [ %{ for res in slice(split(",", current_project_resources), 0, length(split(",", current_project_resources))-1) } "arn:aws:...${res}", %{ endfor } %{ for res in slice(split(",", current_project_resources), length(split(",", current_project_resources))-1, length(split(",", current_project_resources))) } "arn:aws:...${res}" %{ endfor } ]
3. 修改policy资源引用逻辑
每个policy对应同索引的模板渲染结果即可:
resource "aws_iam_policy" "iam_policies_projects" { count = length(var.projects) name = "policy_${var.projects[count.index]}" policy = data.template_file.project_policy[count.index].rendered }
可选优化(Terraform版本≥0.12适用)
更推荐用templatefile内置函数代替template_file数据源,写法更简洁,不需要单独定义数据源:
resource "aws_iam_policy" "iam_policies_projects" { count = length(var.projects) name = "policy_${var.projects[count.index]}" policy = templatefile("${path.module}/project_policy.tpl", { current_project_resources = [for res in var.projects_resources : res if startswith(res, "${var.projects[count.index]}/")] }) }
对应的模板可以直接用列表遍历,不需要再做split/join处理:
... "Resource": [ %{ for idx, res in current_project_resources ~} "arn:aws:...${res}"%{ if idx != length(current_project_resources)-1 },%{ endif } %{ endfor ~} ]
内容的提问来源于stack exchange,提问作者naeroy
相关产品推荐
相关产品推荐

