S3静态网站存储桶Bucket Policy配置403错误排查求助
问题描述
创建用于静态网站托管的S3存储桶成功,但配置Bucket Policy时返回403 AccessDenied错误:
Error: putting S3 Bucket (serengatti01bhg) Policy: operation error S3: PutBucketPolicy, https response error StatusCode: 403, RequestID: 5TA4MQJ2Y0FNJ5FA, HostID: E+qj6u+HWZthQlkvOuQQRqE+pfdFOfPoceulLyDxy/70UCW7dVQU+X2GSdNs1a65LuLq9yWErOU=, api error AccessDenied: Access Denied
Terraform计划执行结果为Plan: 2 to add, 0 to change, 0 to destroy,Bucket Policy包含四条语句,需保留现有策略(因需禁用公共访问),现需排查错误原因。
Terraform配置代码
resource "aws_s3_bucket" "test01" { bucket = "serengatti01bhg" tags = { Name = "serengatti01bhg" } } resource "aws_s3_bucket_policy" "test01_policy" { bucket = aws_s3_bucket.test01.id policy = jsonencode( { Version = "2012-10-17" Statement = [ { Sid = "pc_access" Effect = "Allow" Action = "s3:*" Principal = "*" Resource = [ aws_s3_bucket.test01.arn, "${aws_s3_bucket.test01.arn}/*" ] Condition = { "IpAddress" = { "aws:SourceIp" = "my public ip" } } }, { Sid = "admins_access" Effect = "Allow" Action = "s3:*" Principal = { AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/ak" } Resource = [ aws_s3_bucket.test01.arn, "${aws_s3_bucket.test01.arn}/*" ] }, { Sid = "ssl_policy" Effect = "Deny" Principal = "*" Action = "s3:*" Resource = [ aws_s3_bucket.test01.arn, ] Condition = { Bool = { "aws:SecureTransport" = "false" } } }, { Sid = "PublicReadGetObject" Effect = "Allow" Principal = "*" Action = "s3:GetObject" Resource = [ "${aws_s3_bucket.test01.arn}/*", ] } ] } ) }
错误原因排查方向
1. 执行Terraform的IAM身份权限不足
当前执行Terraform的IAM实体(用户/角色)必须拥有s3:PutBucketPolicy权限,且没有被任何Deny策略限制。即使是管理员权限,也需确认是否存在基于资源或身份的Deny规则阻止该操作。
2. 桶的公共访问设置冲突
你的策略中包含PublicReadGetObject语句(允许所有用户执行s3:GetObject),但如果存储桶的桶级公共访问控制中开启了以下任一选项,会直接阻止添加包含公共访问的Bucket Policy,触发403错误:
Block public access to buckets and objects granted through bucket policiesBlock public access to buckets and objects granted through any access control lists (ACLs)
注意:你提到“需禁用公共访问”,但当前策略中的PublicReadGetObject本质是允许公共访问,这本身存在需求冲突,需明确实际需求。
3. Deny语句限制了PutBucketPolicy操作
第三个语句ssl_policy会Deny所有非HTTPS的s3:*操作到存储桶本身。如果Terraform执行PutBucketPolicy时使用的是HTTP请求(尽管现在大部分场景是HTTPS),会被该策略拦截,返回403。可临时注释该语句测试是否能成功添加策略,验证是否为此原因。
4. IAM用户ARN配置错误
第二个语句admins_access中引用了data.aws_caller_identity.current.account_id,若Terraform配置中未定义该数据源:
data "aws_caller_identity" "current" {}
会导致账号ID为空,生成无效的IAM用户ARN,可能引发策略验证失败,间接导致403错误。
验证步骤
- 切换到拥有完整S3权限的IAM实体执行Terraform,排除权限不足问题。
- 检查存储桶的公共访问设置,若开启了阻止公共策略的选项,需临时关闭后添加策略,再根据实际需求调整策略或公共访问设置。
- 临时注释
ssl_policy语句,重新执行terraform apply,确认是否能成功添加策略。 - 确认
data.aws_caller_identity.current已在Terraform配置中定义,且生成的IAM用户ARN正确。
内容的提问来源于stack exchange,提问作者user23350878

