Terraform配置Django静态文件S3桶遇权限策略错误求助
解决Terraform配置AWS S3静态文件桶的策略错误
看起来你踩了两个典型的Terraform S3配置坑,我来帮你理清问题并修正代码:
问题根源分析
- 桶策略引用错误:你在
aws_s3_bucket_policy资源里错误引用了IAM用户的策略文档(data.aws_iam_policy_document.integrations_lite_staticfiles_s3_user_policy.json),但这个文档是给IAM用户授权用的,没有包含S3桶策略必需的Principal字段,导致AWS返回Missing required field Principal错误。 - 对
aws_s3_bucket_policy资源的误解:这个资源本身不需要principals参数,所有策略逻辑都应该通过policy字段传入的JSON文档来定义,直接加principals会被Terraform判定为无效参数。
修正后的完整代码
# 创建托管静态文件的S3桶 resource "aws_s3_bucket" "integrations_lite_staticfiles_s3_bucket" { region = var.region bucket = "integrations-lite-staticfiles" acl = "public-read" cors_rule { allowed_headers = ["*"] allowed_methods = ["PUT", "POST"] allowed_origins = ["*"] expose_headers = ["ETag"] max_age_seconds = 3000 } website { index_document = "index.html" } } # 创建用于Django上传静态文件的IAM用户 resource "aws_iam_user" "integrations_lite_staticfiles_s3_bucket_user" { name = "Integrations-Lite-staticfiles-user" } # 生成IAM用户的访问密钥(用于Django配置) resource "aws_iam_access_key" "integrations_lite_staticfiles_s3_bucket_user_key" { user = aws_iam_user.integrations_lite_staticfiles_s3_bucket_user.name } # IAM用户的权限策略:遵循最小权限原则,仅授予上传/管理静态文件的必要权限 data "aws_iam_policy_document" "integrations_lite_staticfiles_s3_user_policy" { statement { effect = "Allow" actions = [ "s3:PutObject", "s3:DeleteObject", "s3:ListBucket" ] resources = [ aws_s3_bucket.integrations_lite_staticfiles_s3_bucket.arn, "${aws_s3_bucket.integrations_lite_staticfiles_s3_bucket.arn}/*" ] } } # 将权限策略绑定到IAM用户 resource "aws_iam_user_policy" "integrations_lite_staticfiles_s3_user_policy" { name = "Integrations-Lite-staticfiles-user-policy" user = aws_iam_user.integrations_lite_staticfiles_s3_bucket_user.name policy = data.aws_iam_policy_document.integrations_lite_staticfiles_s3_user_policy.json } # S3桶的公开访问策略:允许所有用户GET静态文件 data "aws_iam_policy_document" "integrations_lite_staticfiles_s3_bucket_policy" { statement { sid = "PublicReadForGetBucketObjects" effect = "Allow" actions = ["s3:GetObject"] resources = ["${aws_s3_bucket.integrations_lite_staticfiles_s3_bucket.arn}/*"] principals { type = "AWS" identifiers = ["*"] } } } # 将公开访问策略绑定到S3桶 resource "aws_s3_bucket_policy" "integrations_lite_staticfiles_s3_bucket_policy" { bucket = aws_s3_bucket.integrations_lite_staticfiles_s3_bucket.id policy = data.aws_iam_policy_document.integrations_lite_staticfiles_s3_bucket_policy.json }
关键修改点说明
- 修正桶策略引用:把
aws_s3_bucket_policy的policy字段改为引用专门的桶策略文档,确保包含Principal字段。 - 细化IAM用户权限:将原来过于宽泛的
s3:*权限缩小为仅必要的上传、删除和列桶操作,同时覆盖桶本身和桶内所有对象,遵循最小权限原则。 - 修正桶策略资源范围:把桶策略的
resources指向桶内所有对象(${arn}/*),因为s3:GetObject是针对对象的操作,不是桶本身。 - 升级Terraform语法:移除了过时的
${var.xxx}插值语法,改用Terraform 0.12+推荐的直接引用方式。
额外注意事项
- 执行
terraform apply后,记得把生成的aws_iam_access_key的id和secret配置到Django的settings.py中(对应AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY)。 - 公开S3桶存在安全风险,如果你的静态文件仅需特定域名访问,可以修改桶策略的
principals或添加条件限制来源。
内容的提问来源于stack exchange,提问作者ElmoVanKielmo
相关产品推荐
相关产品推荐

