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
相关产品推荐
相关产品推荐

