diff --git a/infra/content/public/output.tf b/infra/content/public/output.tf new file mode 100644 index 00000000..d4b04e88 --- /dev/null +++ b/infra/content/public/output.tf @@ -0,0 +1,9 @@ +output "bucket_domains" { + description = "Domain names of the buckets" + value = [ + for bucket_name, bucket in aws_s3_bucket.buckets : { + name = bucket_name + domain = bucket.website_domain != null ? bucket.website_domain : null + } if bucket.website_domain != null + ] +} diff --git a/infra/public-content/images/s3.tf b/infra/content/public/s3.tf similarity index 52% rename from infra/public-content/images/s3.tf rename to infra/content/public/s3.tf index 037426fe..9a20b144 100644 --- a/infra/public-content/images/s3.tf +++ b/infra/content/public/s3.tf @@ -1,9 +1,14 @@ -resource "aws_s3_bucket" "public_bucket" { - bucket = var.bucket_name + +resource "aws_s3_bucket" "buckets" { + for_each = { for idx, name in var.bucket_names : idx => name } + + bucket = each.value } -resource "aws_s3_bucket_cors_configuration" "public_bucket" { - bucket = aws_s3_bucket.public_bucket.id +resource "aws_s3_bucket_cors_configuration" "buckets" { + for_each = aws_s3_bucket.buckets + + bucket = each.value.id cors_rule { allowed_headers = ["*"] @@ -14,15 +19,19 @@ resource "aws_s3_bucket_cors_configuration" "public_bucket" { } } -resource "aws_s3_bucket_acl" "public_bucket" { - bucket = aws_s3_bucket.public_bucket.id +resource "aws_s3_bucket_acl" "buckets" { + for_each = aws_s3_bucket.buckets + + bucket = each.value.id acl = "public-read" depends_on = [aws_s3_bucket_ownership_controls.s3_bucket_acl_ownership] } resource "aws_s3_bucket_ownership_controls" "s3_bucket_acl_ownership" { - bucket = aws_s3_bucket.public_bucket.id - rule { + for_each = aws_s3_bucket.buckets + + bucket = each.value.id + rule { object_ownership = "BucketOwnerPreferred" } depends_on = [aws_s3_bucket_public_access_block.example] @@ -33,40 +42,43 @@ resource "aws_iam_user" "bucket_owner" { } resource "aws_s3_bucket_public_access_block" "example" { - bucket = aws_s3_bucket.public_bucket.id + for_each = aws_s3_bucket.buckets + + bucket = each.value.id block_public_acls = false block_public_policy = false ignore_public_acls = false restrict_public_buckets = false } - resource "aws_s3_bucket_policy" "prod" { - bucket = aws_s3_bucket.public_bucket.id + for_each = aws_s3_bucket.buckets + + bucket = each.value.id + policy = jsonencode({ - Version = "2012-10-17" + Version = "2012-10-17" Statement = [ { + Sid = "PublicListBucket" + Effect = "Allow" Principal = "*" - Action = [ - "s3:*", + Action = [ + "s3:ListBucket" ] - Effect = "Allow" - Resource = [ - "arn:aws:s3:::${var.bucket_name}", - "arn:aws:s3:::${var.bucket_name}/*" + Resource = [ + "${each.value.arn}", ] }, { - Sid = "PublicReadGetObject" + Sid = "PublicGetObject" + Effect = "Allow" Principal = "*" - Action = [ - "s3:GetObject", + Action = [ + "s3:GetObject" ] - Effect = "Allow" - Resource = [ - "arn:aws:s3:::${var.bucket_name}", - "arn:aws:s3:::${var.bucket_name}/*" + Resource = [ + "${each.value.arn}/*", ] }, ] diff --git a/infra/content/public/variables.tf b/infra/content/public/variables.tf new file mode 100644 index 00000000..de235755 --- /dev/null +++ b/infra/content/public/variables.tf @@ -0,0 +1,15 @@ + +variable "bucket_names" { + type = list(string) + default = [ "ashgw-blog-public-general", "ashgw-blog-public-images"] +} + + + +variable "bucket_owner" { + type = string + + default = "i-own-ashgw-blog-public-content" +} + + diff --git a/infra/main.tf b/infra/main.tf index ace0286a..056e379a 100644 --- a/infra/main.tf +++ b/infra/main.tf @@ -3,8 +3,8 @@ provider "aws" { region = var.aws_region } -module "images_s3_bucket" { - source = "./public-content/images" +module "public_content" { + source = "./content/public" } module "ecr" { diff --git a/infra/public-content/images/output.tf b/infra/public-content/images/output.tf deleted file mode 100644 index 1d5bdc1f..00000000 --- a/infra/public-content/images/output.tf +++ /dev/null @@ -1,4 +0,0 @@ -output "domain" { - description = "Domain name of the bucket" - value = aws_s3_bucket.public_bucket.website_domain -} \ No newline at end of file diff --git a/infra/public-content/images/variables.tf b/infra/public-content/images/variables.tf deleted file mode 100644 index 1448ac1b..00000000 --- a/infra/public-content/images/variables.tf +++ /dev/null @@ -1,12 +0,0 @@ -variable "bucket_name" { - type = string - default = "ashgw-blog-public-images" -} - -variable "bucket_owner" { - type = string - - default = "i-own-ashgw-blog-public-images" -} - - diff --git a/infra/terraform.tfstate b/infra/terraform.tfstate index 16aa55ef..c5eec4c7 100644 --- a/infra/terraform.tfstate +++ b/infra/terraform.tfstate @@ -1,7 +1,7 @@ { "version": 4, "terraform_version": "1.8.0", - "serial": 10, + "serial": 50, "lineage": "842ab499-3270-37e7-9cdf-aefcb1290e6f", "outputs": {}, "resources": [ @@ -43,7 +43,7 @@ ] }, { - "module": "module.images_s3_bucket", + "module": "module.public_content", "mode": "managed", "type": "aws_iam_user", "name": "bucket_owner", @@ -52,15 +52,15 @@ { "schema_version": 0, "attributes": { - "arn": "arn:aws:iam::032507467607:user/i-own-ashgw-blog-public-images", + "arn": "arn:aws:iam::032507467607:user/i-own-ashgw-blog-public-content", "force_destroy": false, - "id": "i-own-ashgw-blog-public-images", - "name": "i-own-ashgw-blog-public-images", + "id": "i-own-ashgw-blog-public-content", + "name": "i-own-ashgw-blog-public-content", "path": "/", "permissions_boundary": null, "tags": null, "tags_all": {}, - "unique_id": "AIDAQPEMYS5L7SHRXFB7H" + "unique_id": "AIDAQPEMYS5LTJLZXLSRW" }, "sensitive_attributes": [], "private": "bnVsbA==" @@ -68,13 +68,76 @@ ] }, { - "module": "module.images_s3_bucket", + "module": "module.public_content", "mode": "managed", "type": "aws_s3_bucket", - "name": "public_bucket", + "name": "buckets", "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]", "instances": [ { + "index_key": "0", + "schema_version": 0, + "attributes": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::ashgw-blog-public-general", + "bucket": "ashgw-blog-public-general", + "bucket_domain_name": "ashgw-blog-public-general.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "ashgw-blog-public-general.s3.us-east-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "e420affff348dc73cd2e823658c3fbe2bcfda717547ca27db9df24c350f45e75", + "permissions": ["FULL_CONTROL"], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z2O1EMRO9K5GLX", + "id": "ashgw-blog-public-general", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-east-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": null, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "sensitive_attributes": [], + "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxMjAwMDAwMDAwMDAwLCJkZWxldGUiOjM2MDAwMDAwMDAwMDAsInJlYWQiOjEyMDAwMDAwMDAwMDAsInVwZGF0ZSI6MTIwMDAwMDAwMDAwMH19" + }, + { + "index_key": "1", "schema_version": 0, "attributes": { "acceleration_status": "", @@ -138,13 +201,67 @@ ] }, { - "module": "module.images_s3_bucket", + "module": "module.public_content", "mode": "managed", "type": "aws_s3_bucket_acl", - "name": "public_bucket", + "name": "buckets", "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]", "instances": [ { + "index_key": "0", + "schema_version": 0, + "attributes": { + "access_control_policy": [ + { + "grant": [ + { + "grantee": [ + { + "display_name": "", + "email_address": "", + "id": "", + "type": "Group", + "uri": "http://acs.amazonaws.com/groups/global/AllUsers" + } + ], + "permission": "READ" + }, + { + "grantee": [ + { + "display_name": "", + "email_address": "", + "id": "e420affff348dc73cd2e823658c3fbe2bcfda717547ca27db9df24c350f45e75", + "type": "CanonicalUser", + "uri": "" + } + ], + "permission": "FULL_CONTROL" + } + ], + "owner": [ + { + "display_name": "", + "id": "e420affff348dc73cd2e823658c3fbe2bcfda717547ca27db9df24c350f45e75" + } + ] + } + ], + "acl": "public-read", + "bucket": "ashgw-blog-public-general", + "expected_bucket_owner": "", + "id": "ashgw-blog-public-general,public-read" + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": [ + "module.public_content.aws_s3_bucket.buckets", + "module.public_content.aws_s3_bucket_ownership_controls.s3_bucket_acl_ownership", + "module.public_content.aws_s3_bucket_public_access_block.example" + ] + }, + { + "index_key": "1", "schema_version": 0, "attributes": { "access_control_policy": [ @@ -191,21 +308,44 @@ "sensitive_attributes": [], "private": "bnVsbA==", "dependencies": [ - "module.images_s3_bucket.aws_s3_bucket.public_bucket", - "module.images_s3_bucket.aws_s3_bucket_ownership_controls.s3_bucket_acl_ownership", - "module.images_s3_bucket.aws_s3_bucket_public_access_block.example" + "module.public_content.aws_s3_bucket.buckets", + "module.public_content.aws_s3_bucket_ownership_controls.s3_bucket_acl_ownership", + "module.public_content.aws_s3_bucket_public_access_block.example" ] } ] }, { - "module": "module.images_s3_bucket", + "module": "module.public_content", "mode": "managed", "type": "aws_s3_bucket_cors_configuration", - "name": "public_bucket", + "name": "buckets", "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]", "instances": [ { + "index_key": "0", + "schema_version": 0, + "attributes": { + "bucket": "ashgw-blog-public-general", + "cors_rule": [ + { + "allowed_headers": ["*"], + "allowed_methods": ["GET", "HEAD"], + "allowed_origins": ["*"], + "expose_headers": ["ETag"], + "id": "", + "max_age_seconds": 3000 + } + ], + "expected_bucket_owner": "", + "id": "ashgw-blog-public-general" + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": ["module.public_content.aws_s3_bucket.buckets"] + }, + { + "index_key": "1", "schema_version": 0, "attributes": { "bucket": "ashgw-blog-public-images", @@ -224,20 +364,38 @@ }, "sensitive_attributes": [], "private": "bnVsbA==", - "dependencies": [ - "module.images_s3_bucket.aws_s3_bucket.public_bucket" - ] + "dependencies": ["module.public_content.aws_s3_bucket.buckets"] } ] }, { - "module": "module.images_s3_bucket", + "module": "module.public_content", "mode": "managed", "type": "aws_s3_bucket_ownership_controls", "name": "s3_bucket_acl_ownership", "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]", "instances": [ { + "index_key": "0", + "schema_version": 0, + "attributes": { + "bucket": "ashgw-blog-public-general", + "id": "ashgw-blog-public-general", + "rule": [ + { + "object_ownership": "BucketOwnerPreferred" + } + ] + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": [ + "module.public_content.aws_s3_bucket.buckets", + "module.public_content.aws_s3_bucket_public_access_block.example" + ] + }, + { + "index_key": "1", "schema_version": 0, "attributes": { "bucket": "ashgw-blog-public-images", @@ -251,43 +409,75 @@ "sensitive_attributes": [], "private": "bnVsbA==", "dependencies": [ - "module.images_s3_bucket.aws_s3_bucket.public_bucket", - "module.images_s3_bucket.aws_s3_bucket_public_access_block.example" + "module.public_content.aws_s3_bucket.buckets", + "module.public_content.aws_s3_bucket_public_access_block.example" ] } ] }, { - "module": "module.images_s3_bucket", + "module": "module.public_content", "mode": "managed", "type": "aws_s3_bucket_policy", "name": "prod", "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]", "instances": [ { + "index_key": "0", + "schema_version": 0, + "attributes": { + "bucket": "ashgw-blog-public-general", + "id": "ashgw-blog-public-general", + "policy": "{\"Statement\":[{\"Action\":[\"s3:ListBucket\"],\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":[\"arn:aws:s3:::ashgw-blog-public-general\"],\"Sid\":\"PublicListBucket\"},{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":[\"arn:aws:s3:::ashgw-blog-public-general/*\"],\"Sid\":\"PublicGetObject\"}],\"Version\":\"2012-10-17\"}" + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": [ + "module.public_content.aws_s3_bucket.buckets", + "module.public_content.aws_s3_bucket_public_access_block.example" + ] + }, + { + "index_key": "1", "schema_version": 0, "attributes": { "bucket": "ashgw-blog-public-images", "id": "ashgw-blog-public-images", - "policy": "{\"Statement\":[{\"Action\":[\"s3:*\"],\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":[\"arn:aws:s3:::ashgw-blog-public-images\",\"arn:aws:s3:::ashgw-blog-public-images/*\"]},{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":[\"arn:aws:s3:::ashgw-blog-public-images\",\"arn:aws:s3:::ashgw-blog-public-images/*\"],\"Sid\":\"PublicReadGetObject\"}],\"Version\":\"2012-10-17\"}" + "policy": "{\"Statement\":[{\"Action\":[\"s3:ListBucket\"],\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":[\"arn:aws:s3:::ashgw-blog-public-images\"],\"Sid\":\"PublicListBucket\"},{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":[\"arn:aws:s3:::ashgw-blog-public-images/*\"],\"Sid\":\"PublicGetObject\"}],\"Version\":\"2012-10-17\"}" }, "sensitive_attributes": [], "private": "bnVsbA==", "dependencies": [ - "module.images_s3_bucket.aws_s3_bucket.public_bucket", - "module.images_s3_bucket.aws_s3_bucket_public_access_block.example" + "module.public_content.aws_s3_bucket.buckets", + "module.public_content.aws_s3_bucket_public_access_block.example" ] } ] }, { - "module": "module.images_s3_bucket", + "module": "module.public_content", "mode": "managed", "type": "aws_s3_bucket_public_access_block", "name": "example", "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]", "instances": [ { + "index_key": "0", + "schema_version": 0, + "attributes": { + "block_public_acls": false, + "block_public_policy": false, + "bucket": "ashgw-blog-public-general", + "id": "ashgw-blog-public-general", + "ignore_public_acls": false, + "restrict_public_buckets": false + }, + "sensitive_attributes": [], + "private": "bnVsbA==", + "dependencies": ["module.public_content.aws_s3_bucket.buckets"] + }, + { + "index_key": "1", "schema_version": 0, "attributes": { "block_public_acls": false, @@ -299,9 +489,7 @@ }, "sensitive_attributes": [], "private": "bnVsbA==", - "dependencies": [ - "module.images_s3_bucket.aws_s3_bucket.public_bucket" - ] + "dependencies": ["module.public_content.aws_s3_bucket.buckets"] } ] } diff --git a/infra/terraform.tfstate.backup b/infra/terraform.tfstate.backup index d3462563..d5fce554 100644 --- a/infra/terraform.tfstate.backup +++ b/infra/terraform.tfstate.backup @@ -1,7 +1,7 @@ { "version": 4, "terraform_version": "1.8.0", - "serial": 1, + "serial": 35, "lineage": "842ab499-3270-37e7-9cdf-aefcb1290e6f", "outputs": {}, "resources": [], diff --git a/infra/variables.tf b/infra/variables.tf index b725987a..e3c12126 100644 --- a/infra/variables.tf +++ b/infra/variables.tf @@ -1,4 +1,4 @@ variable "aws_region" { - type = string + type = string default = "us-east-2" } \ No newline at end of file