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

使用Terraform创建S3 Bucket ACL及Policy时遇Access Denied错误求助

S3 Bucket创建时Terraform报Access Denied错误排查

问题场景

尝试使用Terraform创建S3 Bucket,执行terraform apply时持续出现Access Denied错误,涉及ACL和Bucket Policy的资源操作。

Terraform代码

resource "aws_s3_bucket" "prod_media" {
  bucket = var.prod_media_bucket
  acl = "public-read"
}

resource "aws_s3_bucket_cors_configuration" "prod_media" {
  bucket = aws_s3_bucket.prod_media.id  

  cors_rule {
    allowed_headers = ["*"]
    allowed_methods = ["GET", "HEAD"]
    allowed_origins = ["*"]
    expose_headers  = ["ETag"]
    max_age_seconds = 3000
  }  
}

resource "aws_s3_bucket_acl" "prod_media" {
    bucket = aws_s3_bucket.prod_media.id
    acl    = "public-read"
}


resource "aws_iam_user" "prod_media_bucket" {
  name = "prod-media-bucket"
}

resource "aws_s3_bucket_policy" "prod_media_bucket" {
    bucket = aws_s3_bucket.prod_media.id
    policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Principal = "*"
        Action = [
          "s3:*",
        ]
        Effect = "Allow"
        Resource = [
          "arn:aws:s3:::${var.prod_media_bucket}",
          "arn:aws:s3:::${var.prod_media_bucket}/*"
        ]
      },
      {
        Sid = "PublicReadGetObject"
        Principal = "*"
        Action = [
          "s3:GetObject",
        ]
        Effect   = "Allow"
        Resource = [
          "arn:aws:s3:::${var.prod_media_bucket}",
          "arn:aws:s3:::${var.prod_media_bucket}/*"
        ]
      },
    ]
  })
}

resource "aws_iam_user_policy" "prod_media_bucket" {
  user = aws_iam_user.prod_media_bucket.name
  policy = aws_s3_bucket_policy.prod_media_bucket.id
}

resource "aws_iam_access_key" "prod_media_bucket" {
  user = aws_iam_user.prod_media_bucket.name
}

错误信息

╷
│ Error: error creating S3 bucket ACL for prod-media-8675309: AccessDenied: Access Denied
│       status code: 403, request id: XNW2R0KWFYB3KB9R, host id: CuBMdZSaJJgu+0Rprzlptt7oRsjMxBNNHJPhFq98ROGC9l9BUmfmv5YxYZuxf/V3GJBoiGJKJkg=
│
│   with aws_s3_bucket_acl.prod_media,
│   on s3.tf line 18, in resource "aws_s3_bucket_acl" "prod_media":
│   18: resource "aws_s3_bucket_acl" "prod_media" {
│
╵
╷
│ Error: Error putting S3 policy: AccessDenied: Access Denied
│       status code: 403, request id: XNW60T7SQXW1Y4SV, host id: AyGS46L37yIcI4JwddrjHo4GRF7T9JrnfD8TGNdUhpO5uLOWBbgY3+c4opoQTFc2jRdHtXwkqO8=
│
│   with aws_s3_bucket_policy.prod_media_bucket,
│   on s3.tf line 28, in resource "aws_s3_bucket_policy" "prod_media_bucket":
│   28: resource "aws_s3_bucket_policy" "prod_media_bucket" {
│

运行Terraform的账号权限

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
        }
    ]
}

错误原因及修复方案

1. 重复设置ACL引发冲突

在aws_s3_bucket资源中已经指定了acl = "public-read",又单独创建aws_s3_bucket_acl资源重复设置相同ACL,这会导致Terraform执行时对同一资源的权限进行重复操作,触发S3的权限校验异常。

修复:删除单独的aws_s3_bucket_acl资源块,保留aws_s3_bucket内的ACL设置即可。

2. IAM用户策略配置错误

aws_iam_user_policy资源的policy字段需要传入JSON格式的策略内容,但代码中直接引用了aws_s3_bucket_policy.prod_media_bucket.id(Bucket Policy的ID),这是完全错误的配置,会导致IAM资源配置失败,同时干扰Terraform整体执行流程。

修复:为IAM用户单独定义合法的JSON策略,示例如下:

resource "aws_iam_user_policy" "prod_media_bucket" {
  user = aws_iam_user.prod_media_bucket.name
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = "s3:*"
        Resource = [
          "arn:aws:s3:::${var.prod_media_bucket}",
          "arn:aws:s3:::${var.prod_media_bucket}/*"
        ]
      }
    ]
  })
}

3. S3公共访问阻止限制

即使账号拥有管理员权限,如果AWS账号级别或桶级别开启了S3公共访问阻止(Block Public Access),设置public-read ACL和允许Principal = "*"的Bucket Policy会被直接拒绝,返回403错误。

修复:

  • 登录AWS控制台,检查账号或目标桶的公共访问阻止设置,根据业务需求关闭对应选项;
  • 或在Terraform中显式配置公共访问阻止规则(仅当确认需要公开访问时使用):
resource "aws_s3_bucket_public_access_block" "prod_media" {
  bucket = aws_s3_bucket.prod_media.id

  block_public_acls       = false
  block_public_policy     = false
  ignore_public_acls      = false
  restrict_public_buckets = false
}

4. Bucket Policy冗余且资源范围错误

现有Bucket Policy包含两条冗余语句,第一条允许所有S3操作给所有用户,权限过宽且完全覆盖第二条的GetObject权限;同时GetObject操作的Resource包含了桶本身的ARN,这是不必要的(GetObject仅作用于桶内对象)。

修复:精简Policy,保留必要权限并修正资源范围:

resource "aws_s3_bucket_policy" "prod_media_bucket" {
  bucket = aws_s3_bucket.prod_media.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid = "PublicReadGetObject"
        Principal = "*"
        Action = ["s3:GetObject"]
        Effect = "Allow"
        Resource = "arn:aws:s3:::${var.prod_media_bucket}/*"
      }
    ]
  })
}

总结修复步骤

  1. 删除重复的aws_s3_bucket_acl资源;
  2. 修正aws_iam_user_policy的配置,使用合法的JSON策略内容;
  3. 检查并调整S3公共访问阻止设置(按需关闭);
  4. 精简Bucket Policy,修正资源范围。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 18:54:59