使用 Terraform 为 Django 静态文件配置 AWS S3 存储桶

Configure AWS S3 bucket for Django static files with Terraform

我是 Terraform 的新手。

我正在尝试配置 S3 存储桶以提供 Django 静态文件。
对这些静态文件的 HTTP GET 请求应该有不受限制的访问,但也应该有 AWS 用户 - Django 将使用此用户帐户将更新的静态文件上传到 S3 存储桶。

我写过这个:

resource "aws_iam_user" "integrations_lite_staticfiles_s3_bucket_user" {
  name = "Integrations-Lite-staticfiles-user"
}

resource "aws_iam_access_key" "integrations_lite_staticfiles_s3_bucket_user_key" {
  user = "${aws_iam_user.integrations_lite_staticfiles_s3_bucket_user.name}"
}

data "aws_iam_policy_document" "integrations_lite_staticfiles_s3_user_policy" {
  statement {
    effect = "Allow"
    actions = ["s3:*"]
    resources = ["${aws_s3_bucket.integrations_lite_staticfiles_s3_bucket.arn}"]
  }
}

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}"
}

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 {
      identifiers = ["*"]
      type = "AWS"
    }
  }
}

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_user_policy.json}"
}

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"
  }
}

terraform apply 结果:

* aws_s3_bucket_policy.integrations_lite_staticfiles_s3_bucket_policy: 1 error(s) occurred:

* aws_s3_bucket_policy.integrations_lite_staticfiles_s3_bucket_policy: Error putting S3 policy: MalformedPolicy: Missing required field Principal
    status code: 400, request id: 724BC650DFFCE3B7, host id: ####

然而,将 principals 添加到 aws_s3_bucket_policy.integrations_lite_staticfiles_s3_bucket_policy 会导致:

Error: aws_s3_bucket_policy.integrations_lite_staticfiles_s3_bucket_policy: : invalid or unknown key: principals

我找到了解决方案:

resource "aws_iam_group" "manage-integrations-lite-staticfiles-s3-bucket" {
  name = "Manage-Integrations-Lite-static-files"
}

resource "aws_iam_user" "manage-integrations-lite-staticfiles-s3-bucket" {
  name = "Manage-Integrations-Lite-static-files"
}

resource "aws_iam_group_membership" "manage-integrations-lite-staticfiles-s3-bucket" {
  group = "${aws_iam_group.manage-integrations-lite-staticfiles-s3-bucket.name}"
  name = "Manage-Integrations-Lite-static-files"
  users = ["${aws_iam_user.manage-integrations-lite-staticfiles-s3-bucket.name}"]
}

resource "aws_iam_group_policy" "manage-integrations-lite-staticfiles-s3-bucket" {
  group = "${aws_iam_group.manage-integrations-lite-staticfiles-s3-bucket.name}"
  policy =<<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ManageIntegrationsLiteStaticfilesBucket",
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": [
          "arn:aws:s3:::integrations-lite-staticfiles",
          "arn:aws:s3:::integrations-lite-staticfiles/*"
      ]
    }
  ]
}
POLICY
}

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 = ["GET", "HEAD"]
    allowed_origins = ["*"]
    expose_headers = ["ETag"]
    max_age_seconds = 3000
  }
  website {
    index_document = "index.html"
  }
  policy =<<POLICY
{
  "Version":"2012-10-17",
  "Statement":[{
    "Sid":"PublicReadGetObject",
    "Effect":"Allow",
    "Principal": "*",
    "Action":["s3:GetObject"],
    "Resource":[
      "arn:aws:s3:::integrations-lite-staticfiles",
      "arn:aws:s3:::integrations-lite-staticfiles/*"
    ]
  }]
}
POLICY
}

注意:我特意删除了 api 关键部分。我更喜欢通过 AWS 控制台手动生成密钥 ID 和密钥。