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版本会直接报参数冲突错误。
修复方案
- 修正策略中Resource字段的引用,去掉splat表达式,直接引用同索引的桶资源ARN即可——两个资源的
count判断条件完全一致,当aws_s3_bucket_policy存在时,aws_s3_bucket.bucket[0]必然存在,不会出现引用错误。 - 移除
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
相关产品推荐
相关产品推荐

