diff --git a/README.md b/README.md
index 179ed856..b6eba6c0 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,7 @@ These features of S3 bucket configurations are supported:
- Cross-Region Replication (CRR)
- ELB log delivery bucket policy
- ALB/NLB log delivery bucket policy
+- Account-level Public Access Block
## Usage
@@ -117,8 +118,11 @@ Users of Terragrunt can achieve similar results by using modules provided in the
- [Complete](https://github.com/terraform-aws-modules/terraform-aws-s3-bucket/tree/master/examples/complete) - Complete S3 bucket with most of supported features enabled
- [Cross-Region Replication](https://github.com/terraform-aws-modules/terraform-aws-s3-bucket/tree/master/examples/s3-replication) - S3 bucket with Cross-Region Replication (CRR) enabled
-- [S3 Bucket Notifications](https://github.com/terraform-aws-modules/terraform-aws-s3-bucket/tree/master/examples/notification) - S3 bucket notifications to Lambda functions, SQS queues, and SNS topics.
-- [S3 Bucket Object](https://github.com/terraform-aws-modules/terraform-aws-s3-bucket/tree/master/examples/object) - Manage S3 bucket objects.
+- [S3 Notifications](https://github.com/terraform-aws-modules/terraform-aws-s3-bucket/tree/master/examples/notification) - S3 bucket notifications to Lambda functions, SQS queues, and SNS topics.
+- [S3 Object](https://github.com/terraform-aws-modules/terraform-aws-s3-bucket/tree/master/examples/object) - Manage S3 bucket objects.
+- [S3 Analytics](https://github.com/terraform-aws-modules/terraform-aws-s3-bucket/tree/master/examples/s3-analytics) - S3 bucket Analytics Configurations.
+- [S3 Inventory](https://github.com/terraform-aws-modules/terraform-aws-s3-bucket/tree/master/examples/s3-inventory) - S3 bucket Inventory configuration.
+- [S3 Account-level Public Access Block](https://github.com/terraform-aws-modules/terraform-aws-s3-bucket/tree/master/examples/account-public-access) - Manage S3 account-level Public Access Block.
## Requirements
diff --git a/examples/account-public-access/README.md b/examples/account-public-access/README.md
new file mode 100644
index 00000000..9dae8331
--- /dev/null
+++ b/examples/account-public-access/README.md
@@ -0,0 +1,49 @@
+# S3 account-level Public Access Block
+
+Configuration in this directory creates S3 account-level Public Access Block.
+
+## Usage
+
+To run this example you need to execute:
+
+```bash
+$ terraform init
+$ terraform plan
+$ terraform apply
+```
+
+Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.
+
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 1.0 |
+| [aws](#requirement\_aws) | >= 5.70 |
+| [random](#requirement\_random) | >= 2.0 |
+
+## Providers
+
+No providers.
+
+## Modules
+
+| Name | Source | Version |
+|------|--------|---------|
+| [account\_public\_access](#module\_account\_public\_access) | ../../modules/account-public-access | n/a |
+
+## Resources
+
+No resources.
+
+## Inputs
+
+No inputs.
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| [s3\_account\_public\_access\_block\_id](#output\_s3\_account\_public\_access\_block\_id) | AWS account ID |
+
diff --git a/examples/account-public-access/main.tf b/examples/account-public-access/main.tf
new file mode 100644
index 00000000..3f506fdd
--- /dev/null
+++ b/examples/account-public-access/main.tf
@@ -0,0 +1,21 @@
+provider "aws" {
+ region = local.region
+
+ # Make it faster by skipping something
+ skip_metadata_api_check = true
+ skip_region_validation = true
+ skip_credentials_validation = true
+}
+
+locals {
+ region = "eu-west-1"
+}
+
+module "account_public_access" {
+ source = "../../modules/account-public-access"
+
+ block_public_acls = true
+ block_public_policy = true
+ ignore_public_acls = true
+ restrict_public_buckets = true
+}
diff --git a/examples/account-public-access/outputs.tf b/examples/account-public-access/outputs.tf
new file mode 100644
index 00000000..9f284883
--- /dev/null
+++ b/examples/account-public-access/outputs.tf
@@ -0,0 +1,4 @@
+output "s3_account_public_access_block_id" {
+ description = "AWS account ID"
+ value = module.account_public_access.s3_account_public_access_block_id
+}
diff --git a/examples/account-public-access/variables.tf b/examples/account-public-access/variables.tf
new file mode 100644
index 00000000..e69de29b
diff --git a/examples/account-public-access/versions.tf b/examples/account-public-access/versions.tf
new file mode 100644
index 00000000..6d9488f3
--- /dev/null
+++ b/examples/account-public-access/versions.tf
@@ -0,0 +1,14 @@
+terraform {
+ required_version = ">= 1.0"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 5.70"
+ }
+ random = {
+ source = "hashicorp/random"
+ version = ">= 2.0"
+ }
+ }
+}
diff --git a/main.tf b/main.tf
index 4bffeb08..6554c26c 100644
--- a/main.tf
+++ b/main.tf
@@ -39,8 +39,7 @@ resource "aws_s3_bucket_logging" "this" {
bucket = aws_s3_bucket.this[0].id
target_bucket = var.logging["target_bucket"]
- target_prefix = try(var.logging["target_prefix"], null)
-
+ target_prefix = var.logging["target_prefix"]
dynamic "target_object_key_format" {
for_each = try([var.logging["target_object_key_format"]], [])
@@ -55,7 +54,7 @@ resource "aws_s3_bucket_logging" "this" {
}
dynamic "simple_prefix" {
- for_each = contains(keys(target_object_key_format.value), "simple_prefix") ? [true] : []
+ for_each = length(try(target_object_key_format.value["partitioned_prefix"], [])) == 0 || can(target_object_key_format.value["simple_prefix"]) ? [true] : []
content {}
}
@@ -166,7 +165,7 @@ resource "aws_s3_bucket_versioning" "this" {
versioning_configuration {
# Valid values: "Enabled" or "Suspended"
- status = try(var.versioning["enabled"] ? "Enabled" : "Suspended", tobool(var.versioning["status"]) ? "Enabled" : "Suspended", title(lower(var.versioning["status"])))
+ status = try(var.versioning["enabled"] ? "Enabled" : "Suspended", tobool(var.versioning["status"]) ? "Enabled" : "Suspended", title(lower(var.versioning["status"])), "Enabled")
# Valid values: "Enabled" or "Disabled"
mfa_delete = try(tobool(var.versioning["mfa_delete"]) ? "Enabled" : "Disabled", title(lower(var.versioning["mfa_delete"])), null)
@@ -381,7 +380,6 @@ resource "aws_s3_bucket_replication_configuration" "this" {
content {
id = try(rule.value.id, null)
priority = try(rule.value.priority, null)
- prefix = try(rule.value.prefix, null)
status = try(tobool(rule.value.status) ? "Enabled" : "Disabled", title(lower(rule.value.status)), "Enabled")
dynamic "delete_marker_replication" {
diff --git a/modules/account-public-access/README.md b/modules/account-public-access/README.md
new file mode 100644
index 00000000..4c6fadd5
--- /dev/null
+++ b/modules/account-public-access/README.md
@@ -0,0 +1,49 @@
+# S3 account-level Public Access Block
+
+Manages S3 account-level Public Access Block configuration.
+
+## Note
+
+Each AWS account may only have one S3 Public Access Block configuration.
+
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 1.0 |
+| [aws](#requirement\_aws) | >= 3.74 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [aws](#provider\_aws) | >= 3.74 |
+
+## Modules
+
+No modules.
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [aws_s3_account_public_access_block.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_account_public_access_block) | resource |
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [account\_id](#input\_account\_id) | AWS account ID | `string` | `null` | no |
+| [block\_public\_acls](#input\_block\_public\_acls) | Whether Amazon S3 should block public ACLs for buckets in this account. | `bool` | `false` | no |
+| [block\_public\_policy](#input\_block\_public\_policy) | Whether Amazon S3 should block public bucket policies for buckets in this account. | `bool` | `false` | no |
+| [create](#input\_create) | Whether to create this resource or not? | `bool` | `true` | no |
+| [ignore\_public\_acls](#input\_ignore\_public\_acls) | Whether Amazon S3 should ignore public ACLs for buckets in this account. | `bool` | `false` | no |
+| [restrict\_public\_buckets](#input\_restrict\_public\_buckets) | Whether Amazon S3 should restrict public bucket policies for buckets in this account. | `bool` | `false` | no |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| [s3\_account\_public\_access\_block\_id](#output\_s3\_account\_public\_access\_block\_id) | AWS account ID |
+
diff --git a/modules/account-public-access/main.tf b/modules/account-public-access/main.tf
new file mode 100644
index 00000000..bd27b8f2
--- /dev/null
+++ b/modules/account-public-access/main.tf
@@ -0,0 +1,10 @@
+resource "aws_s3_account_public_access_block" "this" {
+ count = var.create ? 1 : 0
+
+ account_id = var.account_id
+
+ block_public_acls = var.block_public_acls
+ block_public_policy = var.block_public_policy
+ ignore_public_acls = var.ignore_public_acls
+ restrict_public_buckets = var.restrict_public_buckets
+}
diff --git a/modules/account-public-access/outputs.tf b/modules/account-public-access/outputs.tf
new file mode 100644
index 00000000..ce31327c
--- /dev/null
+++ b/modules/account-public-access/outputs.tf
@@ -0,0 +1,4 @@
+output "s3_account_public_access_block_id" {
+ description = "AWS account ID"
+ value = try(aws_s3_account_public_access_block.this[0].id, "")
+}
diff --git a/modules/account-public-access/variables.tf b/modules/account-public-access/variables.tf
new file mode 100644
index 00000000..09d9758b
--- /dev/null
+++ b/modules/account-public-access/variables.tf
@@ -0,0 +1,35 @@
+variable "create" {
+ description = "Whether to create this resource or not?"
+ type = bool
+ default = true
+}
+
+variable "account_id" {
+ description = "AWS account ID"
+ type = string
+ default = null
+}
+
+variable "block_public_acls" {
+ description = "Whether Amazon S3 should block public ACLs for buckets in this account."
+ type = bool
+ default = false
+}
+
+variable "block_public_policy" {
+ description = "Whether Amazon S3 should block public bucket policies for buckets in this account."
+ type = bool
+ default = false
+}
+
+variable "ignore_public_acls" {
+ description = "Whether Amazon S3 should ignore public ACLs for buckets in this account."
+ type = bool
+ default = false
+}
+
+variable "restrict_public_buckets" {
+ description = "Whether Amazon S3 should restrict public bucket policies for buckets in this account."
+ type = bool
+ default = false
+}
diff --git a/modules/account-public-access/versions.tf b/modules/account-public-access/versions.tf
new file mode 100644
index 00000000..ff97a040
--- /dev/null
+++ b/modules/account-public-access/versions.tf
@@ -0,0 +1,10 @@
+terraform {
+ required_version = ">= 1.0"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 3.74"
+ }
+ }
+}
diff --git a/wrappers/account-public-access/README.md b/wrappers/account-public-access/README.md
new file mode 100644
index 00000000..e9acd236
--- /dev/null
+++ b/wrappers/account-public-access/README.md
@@ -0,0 +1,100 @@
+# Wrapper for module: `modules/account-public-access`
+
+The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt).
+
+You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module.
+
+This wrapper does not implement any extra functionality.
+
+## Usage with Terragrunt
+
+`terragrunt.hcl`:
+
+```hcl
+terraform {
+ source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers/account-public-access"
+ # Alternative source:
+ # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers/account-public-access?ref=master"
+}
+
+inputs = {
+ defaults = { # Default values
+ create = true
+ tags = {
+ Terraform = "true"
+ Environment = "dev"
+ }
+ }
+
+ items = {
+ my-item = {
+ # omitted... can be any argument supported by the module
+ }
+ my-second-item = {
+ # omitted... can be any argument supported by the module
+ }
+ # omitted...
+ }
+}
+```
+
+## Usage with Terraform
+
+```hcl
+module "wrapper" {
+ source = "terraform-aws-modules/s3-bucket/aws//wrappers/account-public-access"
+
+ defaults = { # Default values
+ create = true
+ tags = {
+ Terraform = "true"
+ Environment = "dev"
+ }
+ }
+
+ items = {
+ my-item = {
+ # omitted... can be any argument supported by the module
+ }
+ my-second-item = {
+ # omitted... can be any argument supported by the module
+ }
+ # omitted...
+ }
+}
+```
+
+## Example: Manage multiple S3 buckets in one Terragrunt layer
+
+`eu-west-1/s3-buckets/terragrunt.hcl`:
+
+```hcl
+terraform {
+ source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers"
+ # Alternative source:
+ # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master"
+}
+
+inputs = {
+ defaults = {
+ force_destroy = true
+
+ attach_elb_log_delivery_policy = true
+ attach_lb_log_delivery_policy = true
+ attach_deny_insecure_transport_policy = true
+ attach_require_latest_tls_policy = true
+ }
+
+ items = {
+ bucket1 = {
+ bucket = "my-random-bucket-1"
+ }
+ bucket2 = {
+ bucket = "my-random-bucket-2"
+ tags = {
+ Secure = "probably"
+ }
+ }
+ }
+}
+```
diff --git a/wrappers/account-public-access/main.tf b/wrappers/account-public-access/main.tf
new file mode 100644
index 00000000..e0ab498b
--- /dev/null
+++ b/wrappers/account-public-access/main.tf
@@ -0,0 +1,12 @@
+module "wrapper" {
+ source = "../../modules/account-public-access"
+
+ for_each = var.items
+
+ account_id = try(each.value.account_id, var.defaults.account_id, null)
+ block_public_acls = try(each.value.block_public_acls, var.defaults.block_public_acls, false)
+ block_public_policy = try(each.value.block_public_policy, var.defaults.block_public_policy, false)
+ create = try(each.value.create, var.defaults.create, true)
+ ignore_public_acls = try(each.value.ignore_public_acls, var.defaults.ignore_public_acls, false)
+ restrict_public_buckets = try(each.value.restrict_public_buckets, var.defaults.restrict_public_buckets, false)
+}
diff --git a/wrappers/account-public-access/outputs.tf b/wrappers/account-public-access/outputs.tf
new file mode 100644
index 00000000..ec6da5f4
--- /dev/null
+++ b/wrappers/account-public-access/outputs.tf
@@ -0,0 +1,5 @@
+output "wrapper" {
+ description = "Map of outputs of a wrapper."
+ value = module.wrapper
+ # sensitive = false # No sensitive module output found
+}
diff --git a/wrappers/account-public-access/variables.tf b/wrappers/account-public-access/variables.tf
new file mode 100644
index 00000000..a6ea0962
--- /dev/null
+++ b/wrappers/account-public-access/variables.tf
@@ -0,0 +1,11 @@
+variable "defaults" {
+ description = "Map of default values which will be used for each item."
+ type = any
+ default = {}
+}
+
+variable "items" {
+ description = "Maps of items to create a wrapper from. Values are passed through to the module."
+ type = any
+ default = {}
+}
diff --git a/wrappers/account-public-access/versions.tf b/wrappers/account-public-access/versions.tf
new file mode 100644
index 00000000..ff97a040
--- /dev/null
+++ b/wrappers/account-public-access/versions.tf
@@ -0,0 +1,10 @@
+terraform {
+ required_version = ">= 1.0"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 3.74"
+ }
+ }
+}