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

Terraform脚本运行时如何为桶策略的iam_policy_document动态添加语句?

Terraform动态生成IAM策略Statement的可行实现方法

方法1:使用aws_iam_policy_document的dynamic块实现

  • 适合条件分支多、每个statement结构差异大的场景,可读性更高
  • 示例代码:
# 定义条件标志变量
variable "enable_public_read_access" {
  type    = bool
  default = false
}

variable "enable_cross_account_write" {
  type    = bool
  default = false
}

# 预定义所有可选的statement配置
locals {
  optional_statements = [
    var.enable_public_read_access ? {
      effect    = "Allow"
      actions   = ["s3:GetObject"]
      resources = ["${aws_s3_bucket.my_buckets[*].arn}/*"]
      principals {
        type        = "AWS"
        identifiers = ["*"]
      }
    } : null,
    var.enable_cross_account_write ? {
      effect    = "Allow"
      actions   = ["s3:PutObject"]
      resources = ["${aws_s3_bucket.my_buckets[*].arn}/*"]
      principals {
        type        = "AWS"
        identifiers = ["arn:aws:iam::123456789012:root"]
      }
    } : null,
  ]
  # 过滤掉空值的无效statement
  valid_optional_statements = [for stmt in local.optional_statements : stmt if stmt != null]
}

data "aws_iam_policy_document" "bucket_policy" {
  # 先添加固定生效的通用statement
  statement {
    effect    = "Allow"
    actions   = ["s3:ListBucket"]
    resources = [aws_s3_bucket.my_buckets[*].arn]
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
    }
  }

  # 动态生成符合条件的statement
  dynamic "statement" {
    for_each = local.valid_optional_statements
    content {
      effect       = statement.value.effect
      actions      = statement.value.actions
      resources    = statement.value.resources
      principals   = statement.value.principals
    }
  }
}

# 绑定单个统一桶策略到所有存储桶
resource "aws_s3_bucket_policy" "common_policy" {
  for_each = aws_s3_bucket.my_buckets
  bucket   = each.value.id
  policy   = data.aws_iam_policy_document.bucket_policy.json
}

方法2:使用concat函数直接拼接statement列表

  • 适合简单条件判断场景,代码更简洁,不需要依赖dynamic块
  • 示例代码:
data "aws_iam_policy_document" "bucket_policy" {
  statement = concat(
    # 固定生效的statement列表
    [
      {
        effect    = "Allow"
        actions   = ["s3:ListBucket"]
        resources = [aws_s3_bucket.my_buckets[*].arn]
        principals {
          type        = "AWS"
          identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
        }
      }
    ],
    # 条件满足才添加的statement,不满足则返回空列表不占位置
    var.enable_public_read_access ? [
      {
        effect    = "Allow"
        actions   = ["s3:GetObject"]
        resources = ["${aws_s3_bucket.my_buckets[*].arn}/*"]
        principals {
          type        = "AWS"
          identifiers = ["*"]
        }
      }
    ] : [],
    var.enable_cross_account_write ? [
      {
        effect    = "Allow"
        actions   = ["s3:PutObject"]
        resources = ["${aws_s3_bucket.my_buckets[*].arn}/*"]
        principals {
          type        = "AWS"
          identifiers = ["arn:aws:iam::123456789012:root"]
        }
      }
    ] : []
  )
}

方法3:使用for表达式过滤预定义statement集合

  • 适合存在多组不同判断条件、十余个可选statement的复杂场景,便于统一维护策略规则
  • 示例代码:
locals {
  # 预先定义所有可能的statement,每个自带生效条件字段
  all_possible_statements = [
    {
      enable_condition = var.enable_public_read_access
      effect           = "Allow"
      actions          = ["s3:GetObject"]
      resources        = ["${aws_s3_bucket.my_buckets[*].arn}/*"]
      principals = {
        type        = "AWS"
        identifiers = ["*"]
      }
    },
    {
      enable_condition = var.enable_cross_account_write
      effect           = "Allow"
      actions          = ["s3:PutObject"]
      resources        = ["${aws_s3_bucket.my_buckets[*].arn}/*"]
      principals = {
        type        = "AWS"
        identifiers = ["arn:aws:iam::123456789012:root"]
      }
    },
    # 可继续添加更多带条件的statement规则
  ]
  # 仅保留满足生效条件的statement
  active_statements = [for stmt in local.all_possible_statements : {
    effect     = stmt.effect
    actions    = stmt.actions
    resources  = stmt.resources
    principals = stmt.principals
  } if stmt.enable_condition]
}

data "aws_iam_policy_document" "bucket_policy" {
  dynamic "statement" {
    for_each = local.active_statements
    content {
      effect     = statement.value.effect
      actions    = statement.value.actions
      resources  = statement.value.resources
      principals = statement.value.principals
    }
  }
}

注意:生成策略后建议先执行terraform plan查看输出的policy json内容,确认符合预期后再执行apply操作,避免权限配置错误导致存储桶访问异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 02:54:06