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

Terraform中如何迭代长度不同的Map元素生成IAM策略资源

Terraform配置报错解决:多列表迭代生成S3资源ARN

报错信息

Invalid value for "args" parameter: argument 3 has length 1, which is inconsistent with argument 2 of length 3

中文翻译:参数"args"值无效:参数3长度为1,与长度为3的参数2不匹配

原Terraform配置

locals {
  environment_map = {
    prd    = ["prd"]
    nonprd = ["dev", "qa", "stg"]
  }
  bucket_name = "test-bucket"
  account     =  "Prod" 

  consumers_config =  {
        client1 = {
          provider_url      = "www.google.com/abc/"
          source_id =         ["1001"]
        }
      }
  
  client_map = merge([
    for consumer, consumer_details in local.consumers_config : {
      for env, env_details in local.environment_map :
      "${consumer}_${env}" => {
        env               = env_details
        source_id_list = consumer_details["source_id"]
        provider_url      = consumer_details["provider_url"]
        audience_id       = "URN://${consumer}_${local.account_type}_AWS_${local.account}"
  } }]...)
}

data "aws_iam_policy_document" "read_policy" {

  for_each = var.client_specific_iam_roles ? local.client_map : {}
  statement {
    effect = "Allow"
    actions = [
      "s3:GetObject",
      "s3:GetObjectAttributes",
      "s3:GetObjectVersion",
      "s3:GetObjectVersionAttributes"
    ]
    resources = concat(formatlist("arn:aws:s3:::%s/%s/test/test_json/*/source_id=%s/*",
      local.bucket_name,lookup(each.value, "env"), lookup(each.value, "source_id")))
  }
}

问题说明

当前配置中,env字段是多元素列表(比如nonprd对应["dev","qa","stg"]),source_id_list也是多元素列表,需要同时迭代这两个列表生成所有组合的S3资源ARN。但直接使用formatlist会因为两个列表长度不匹配报错,目前将source_id_list改为单个字符串能临时解决,但需求要求支持多个source_id,如何实现?

解决方案

方案一:提前拆分所有组合到client_map

核心思路是在生成client_map时,直接遍历env和source_id的所有笛卡尔积组合,将每个组合作为单独的条目,避免后续处理时的列表长度不匹配问题。

修改后的client_map代码:

client_map = merge([
  for consumer, consumer_details in local.consumers_config : {
    for env, env_details in local.environment_map : {
      for source_id in consumer_details["source_id"] :
      "${consumer}_${env}_${source_id}" => {
        env           = env_details
        source_id     = source_id
        provider_url  = consumer_details["provider_url"]
        audience_id   = "URN://${consumer}_${local.account_type}_AWS_${local.account}"
      }
    }
  }]...)

对应的aws_iam_policy_document调整为:

data "aws_iam_policy_document" "read_policy" {
  for_each = var.client_specific_iam_roles ? local.client_map : {}

  statement {
    effect = "Allow"
    actions = [
      "s3:GetObject",
      "s3:GetObjectAttributes",
      "s3:GetObjectVersion",
      "s3:GetObjectVersionAttributes"
    ]
    resources = [
      format("arn:aws:s3:::%s/%s/test/test_json/*/source_id=%s/*",
        local.bucket_name, each.value.env, each.value.source_id)
    ]
  }
}

此方案适合需要为每个env+source_id组合单独配置额外属性的场景。

方案二:在生成Policy时动态生成组合

如果不想修改原有client_map结构,可以在生成resources时,通过嵌套for表达式生成env和source_id的所有组合,再用flatten将嵌套列表转为一维列表。

修改后的resources字段代码:

resources = flatten([
  for env in each.value.env : [
    for source_id in each.value.source_id_list :
    format("arn:aws:s3:::%s/%s/test/test_json/*/source_id=%s/*",
      local.bucket_name, env, source_id)
  ]
])

此方案无需调整client_map,直接在Policy生成阶段处理组合逻辑,适合原有结构需要保留的场景。


内容的提问来源于stack exchange,提问作者bharath

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 07:07:03