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

Terraform配置S3存储桶策略报Invalid policy syntax错误

问题描述

我正在尝试通过Terraform配置S3存储桶策略,目标是实现按条件创建S3存储桶及其关联策略。当前aws_s3_bucket资源可正常创建,但部署aws_s3_bucket_policy资源时抛出策略语法无效错误。
原始Terraform配置如下:

resource "aws_s3_bucket" "bucket" {
  bucket        = var.bucket
  bucket_prefix = var.bucket_prefix
  acl           = "log-delivery-write"
  count    = var.account != "" ? 1 : 0

  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }

  tags = {
    account = var.account
  }
}

resource "aws_s3_bucket_policy" "bucket" {
  bucket = aws_s3_bucket.bucket[0].id
  count    = var.account != "" ? 1 : 0
  
  policy = jsonencode(
    {
      "Id" : "SSLPolicy",
      "Version" : "2012-10-17",
      "Statement" : [
        {
          "Sid" : "AllowSSLRequestsOnly",
          "Action" : "s3:*",
          "Effect" : "Deny",
          "Resource" : [
            "${aws_s3_bucket.bucket[*].arn}",
            "${aws_s3_bucket.bucket[0].arn}/*",
          ],
          "Condition" : {
            "Bool" : {
              "aws:SecureTransport" : "false"
            }
          },
          "Principal" : "*"
        }
      ]
    }
  )
}

部署时抛出的错误信息:

Error: Error putting S3 policy: MalformedPolicy: Invalid policy syntax.
│   status code: 400, request id: BN6FRWX8A6723GAP, host id: t3yhr16yMu7VOjLIdXup1O0SlDW062VLiYJXyZ5bR6+OwrP86wjzBe7iGNzIDzCqcB1H1WUn8Pk=
│ 
│   with module.test.aws_s3_bucket_policy.bucket[0],
│   on .terraform/modules/test/main.tf line 20, in resource "aws_s3_bucket_policy" "bucket":
│   20: resource "aws_s3_bucket_policy" "bucket" {
错误原因
  • 核心问题出在策略的Resource字段:配置中使用了splat表达式aws_s3_bucket.bucket[*].arn,该表达式返回值是列表类型,直接放在Resource数组中会让jsonencode生成嵌套数组结构。而S3存储桶策略要求Resource下的所有元素必须是字符串类型的ARN,不支持嵌套数组,因此AWS会返回策略语法无效的错误。
  • 额外配置隐患:aws_s3_bucket资源中bucket和bucket_prefix是互斥参数,不能同时配置,当前能创建成功是旧版provider兼容逻辑,后续升级provider版本会直接报参数冲突错误。
修复方案
  1. 修正策略中Resource字段的引用,去掉splat表达式,直接引用同索引的桶资源ARN即可——两个资源的count判断条件完全一致,当aws_s3_bucket_policy存在时,aws_s3_bucket.bucket[0]必然存在,不会出现引用错误。
  2. 移除aws_s3_bucket中互斥的参数,根据需求二选一:需要自定义完整桶名就保留bucket,需要Terraform自动生成带随机后缀的桶名就保留bucket_prefix。

修复后的aws_s3_bucket_policy资源配置如下:

resource "aws_s3_bucket_policy" "bucket" {
  bucket = aws_s3_bucket.bucket[0].id
  count  = var.account != "" ? 1 : 0
  
  policy = jsonencode(
    {
      Id      = "SSLPolicy"
      Version = "2012-10-17"
      Statement = [
        {
          Sid    = "AllowSSLRequestsOnly"
          Action = "s3:*"
          Effect = "Deny"
          Resource = [
            aws_s3_bucket.bucket[0].arn,
            "${aws_s3_bucket.bucket[0].arn}/*",
          ]
          Condition = {
            Bool = {
              "aws:SecureTransport" = "false"
            }
          }
          Principal = "*"
        }
      ]
    }
  )
}

修正后重新执行terraform plan和terraform apply即可正常部署策略。

内容的提问来源于stack exchange,提问作者Mary-Ann

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:54:29