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

针对带count启用资源的aws_iam_policy_document的DRY方案咨询

最初实现方案
data "aws_iam_policy_document" "lambda_read_secrets" {
    statement {
      actions = [
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret",
        "secretsmanager:ListSecretVersionIds"
      ]

      effect = "Allow"
      resources = [
        "${var.enable_test_users == true ? aws_secretsmanager_secret.test_user[0].arn : ""}",
        "${var.enable_prod_users == true ? aws_secretsmanager_secret.prod_user[0].arn : ""}"
      ]
    }

    statement {
      effect    = "Allow"
      actions   = ["secretsmanager:ListSecrets"]
      resources = ["*"]
    }
  }

上述配置运行时报错如下:

Error: error creating IAM policy test-lambda-logging20211011172058509500000003: MalformedPolicyDocument: Resource  must be in ARN format or "*".
        status code: 400, request id: c5c62446-eba7-450d-b97d-505be530ba2d

  on ../../../../module/lambda/iam.tf line 58, in resource "aws_iam_policy" "lambda_read_secrets":
  58: resource "aws_iam_policy" "lambda_read_secrets" {

报错原因是resources数组中存在条件判断返回的空字符串,不符合IAM策略的资源格式要求。

现有解决方案

当前采用的方案是分别声明data "aws_iam_policy_document" "dev_lambda_read_secrets"和data "aws_iam_policy_document" "prod-lambda_read_secrets"两份数据源,再根据部署环境做条件判断选用对应策略。
该方案的问题是需要重复声明几乎完全一致的策略,仅资源列表存在差异,不符合DRY原则。

最优实现方案

不需要拆分多份策略声明,用Terraform内置函数处理动态资源列表即可,有两种常用实现方式:

方案1:使用compact()函数过滤空值

直接在资源列表外层包裹compact()函数,自动移除数组内的空字符串元素:

data "aws_iam_policy_document" "lambda_read_secrets" {
    statement {
      actions = [
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret",
        "secretsmanager:ListSecretVersionIds"
      ]

      effect = "Allow"
      resources = compact([
        var.enable_test_users ? aws_secretsmanager_secret.test_user[0].arn : "",
        var.enable_prod_users ? aws_secretsmanager_secret.prod_user[0].arn : ""
      ])
    }

    statement {
      effect    = "Allow"
      actions   = ["secretsmanager:ListSecrets"]
      resources = ["*"]
    }
  }

方案2:使用concat()拼接动态数组

直接根据条件返回对应元素的数组,条件不成立时返回空数组,拼接后不会生成空值:

data "aws_iam_policy_document" "lambda_read_secrets" {
    statement {
      actions = [
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret",
        "secretsmanager:ListSecretVersionIds"
      ]

      effect = "Allow"
      resources = concat(
        var.enable_test_users ? [aws_secretsmanager_secret.test_user[0].arn] : [],
        var.enable_prod_users ? [aws_secretsmanager_secret.prod_user[0].arn] : []
      )
    }

    statement {
      effect    = "Allow"
      actions   = ["secretsmanager:ListSecrets"]
      resources = ["*"]
    }
  }

两种方案都可以生成符合IAM规范的策略,不需要重复声明多份策略配置,完全符合DRY原则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 21:45:03