Terraform创建含公开可访问对象的S3存储桶最佳实践问询
问题根因
当前AWS新创建S3桶默认启用 Bucket Owner Enforced 对象所有权模式,该模式下所有桶级、对象级ACL会被完全忽略,权限统一由IAM策略、桶策略管控。你之前配置的桶级public-readACL不会实际生效,上传的对象默认保持私有权限,自然会出现访问被拒绝的问题。
推荐实现方案(弃用ACL,符合AWS最新最佳实践)
AWS目前已经不推荐使用ACL做S3权限管控,公开静态资源桶的标准实现是通过桶策略统一开放公开读权限,对应Terraform配置如下:
resource "aws_s3_bucket" "foo_icons" { bucket = join("-", [local.prefix, "foo", "icons"]) tags = { Name = join("-", [local.prefix, "foo", "icons"]) Environment = var.environment } } # 配置公共访问拦截规则,仅放开策略管控的公开访问 resource "aws_s3_bucket_public_access_block" "foo_icons_pab" { bucket = aws_s3_bucket.foo_icons.id block_public_acls = true block_public_policy = false ignore_public_acls = true restrict_public_buckets = false } # 配置桶级公开读策略,仅开放对象获取权限 resource "aws_s3_bucket_policy" "foo_icons_public_read" { bucket = aws_s3_bucket.foo_icons.id policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Principal = "*" Action = "s3:GetObject" Resource = "${aws_s3_bucket.foo_icons.arn}/*" } ] }) }
你之前写的批量上传对象的配置不需要做任何修改,直接保留即可:
resource "aws_s3_object" "icon_repository_files" { for_each = fileset("../files/icon-repository/", "**") bucket = aws_s3_bucket.foo_icons.id key = each.value source = "../files/icon-repository/${each.value}" etag = filemd5("../files/icon-repository/${each.value}") }
配置说明
- 整套配置完全弃用老旧的ACL权限机制,不会出现桶权限和对象权限不一致的问题,所有权限统一在桶层面管控,维护成本更低
- 公共访问块配置保留了ACL相关的拦截规则,从根源上避免后续误配置对象/桶ACL导致的非预期数据公开
- 桶策略严格遵循最小权限原则:仅授予匿名用户
s3:GetObject单一权限,匿名用户可以正常访问单个图片对象,但无法列出桶内全量文件、无法修改/删除任何桶内资源 - 所有上传到桶内的对象会自动继承桶策略的公开读权限,不需要为每个对象单独配置权限,批量上传场景下不会出现漏配的问题
如果你一定要兼容旧的ACL逻辑(极不推荐),需要先将桶的对象所有权配置修改为
BucketOwnerPreferred模式,同时为每个aws_s3_object资源显式设置acl = "public-read"参数。这种方式权限管控分散,很容易出现个别对象漏配权限的问题,新架构不建议使用。
内容的提问来源于stack exchange,提问作者Johan Kuylenstierna
相关产品推荐
相关产品推荐

