I'm new to Terraform.
I'm trying to configure S3 bucket to serve Django static files.
There should be unrestricted access for HTTP GET requests for these static files but there should also be AWS user - this user account will be used by Django to upload updated static files to S3 bucket.
I've written this:
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"
}
}
but terraform apply
results in:
* 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: ####
However adding principals
to aws_s3_bucket_policy.integrations_lite_staticfiles_s3_bucket_policy
results in:
Error: aws_s3_bucket_policy.integrations_lite_staticfiles_s3_bucket_policy: : invalid or unknown key: principals
I've found a solution:
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
}
Note: I intentionally removed api key part. I prefer to generate key id and secret manually via AWS console.