diff --git a/README.md b/README.md
index 7a139a1c..cc438fea 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,7 @@ These features of S3 bucket configurations are supported:
- ALB/NLB log delivery bucket policy
- Account-level Public Access Block
- S3 Directory Bucket
+- S3 Table Bucket
## Usage
@@ -124,6 +125,7 @@ Users of Terragrunt can achieve similar results by using modules provided in the
- [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.
- [S3 Directory Bucket](https://github.com/terraform-aws-modules/terraform-aws-s3-bucket/tree/master/examples/directory-bucket) - S3 Directory Bucket configuration.
+- [S3 Table Bucket](https://github.com/terraform-aws-modules/terraform-aws-s3-bucket/tree/master/examples/table-bucket) - S3 Table Bucket configuration.
## Requirements
diff --git a/examples/table-bucket/README.md b/examples/table-bucket/README.md
new file mode 100644
index 00000000..874bd561
--- /dev/null
+++ b/examples/table-bucket/README.md
@@ -0,0 +1,68 @@
+# S3 Table Bucket
+
+Configuration in this directory creates S3 table bucket with bucket policy and S3 Tables with table policies.
+
+## 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.83 |
+| [random](#requirement\_random) | >= 2.0 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [aws](#provider\_aws) | >= 5.83 |
+| [random](#provider\_random) | >= 2.0 |
+
+## Modules
+
+| Name | Source | Version |
+|------|--------|---------|
+| [table\_bucket](#module\_table\_bucket) | ../../modules/table-bucket | n/a |
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [aws_s3tables_namespace.namespace](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3tables_namespace) | resource |
+| [random_pet.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
+| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
+
+## Inputs
+
+No inputs.
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| [owner\_account\_id](#output\_owner\_account\_id) | Account ID of the account that owns the table bucket. |
+| [s3\_table\_arns](#output\_s3\_table\_arns) | The table ARNs. |
+| [s3\_table\_bucket\_arn](#output\_s3\_table\_bucket\_arn) | ARN of the table bucket. |
+| [s3\_table\_bucket\_created\_at](#output\_s3\_table\_bucket\_created\_at) | Date and time when the bucket was created. |
+| [s3\_table\_created\_at](#output\_s3\_table\_created\_at) | Dates and times when the tables were created. |
+| [s3\_table\_created\_by](#output\_s3\_table\_created\_by) | Account IDs of the accounts that created the tables |
+| [s3\_table\_metadata\_locations](#output\_s3\_table\_metadata\_locations) | Locations of table metadata. |
+| [s3\_table\_modified\_at](#output\_s3\_table\_modified\_at) | Dates and times when the tables was last modified. |
+| [s3\_table\_modified\_by](#output\_s3\_table\_modified\_by) | Account IDs of the accounts that last modified the tables. |
+| [s3\_table\_owner\_account\_ids](#output\_s3\_table\_owner\_account\_ids) | Account IDs of the accounts that owns the tables. |
+| [s3\_table\_types](#output\_s3\_table\_types) | Types of the tables. One of customer or aws. |
+| [s3\_table\_version\_tokens](#output\_s3\_table\_version\_tokens) | Identifiers for the current version of table data. |
+| [s3\_table\_warehouse\_locations](#output\_s3\_table\_warehouse\_locations) | S3 URIs pointing to the S3 Bucket that contains the table data. |
+
diff --git a/examples/table-bucket/main.tf b/examples/table-bucket/main.tf
new file mode 100644
index 00000000..b69dcfb5
--- /dev/null
+++ b/examples/table-bucket/main.tf
@@ -0,0 +1,105 @@
+provider "aws" {
+ region = "eu-west-1"
+
+ # Make it faster by skipping something
+ skip_metadata_api_check = true
+ skip_region_validation = true
+ skip_credentials_validation = true
+}
+
+locals {
+ bucket_name = "s3-table-bucket-${random_pet.this.id}"
+}
+
+data "aws_caller_identity" "this" {}
+
+module "table_bucket" {
+ source = "../../modules/table-bucket"
+
+ table_bucket_name = local.bucket_name
+
+ maintenance_configuration = {
+ iceberg_unreferenced_file_removal = {
+ status = "enabled"
+
+ settings = {
+ non_current_days = 7
+ unreferenced_days = 3
+ }
+ }
+ }
+
+ create_table_bucket_policy = true
+ table_bucket_policy_statements = [
+ {
+ effect = "Allow"
+ principals = [{
+ type = "AWS"
+ identifiers = [data.aws_caller_identity.this.account_id]
+ }]
+ actions = [
+ "s3tables:GetTableData",
+ "s3tables:GetTableMetadataLocation"
+ ]
+ }
+ ]
+
+ tables = {
+ table1 = {
+ format = "ICEBERG"
+ namespace = aws_s3tables_namespace.namespace.namespace
+
+ maintenance_configuration = {
+ iceberg_compaction = {
+ status = "enabled"
+ settings = {
+ target_file_size_mb = 64
+ }
+ }
+ iceberg_snapshot_management = {
+ status = "enabled"
+ settings = {
+ max_snapshot_age_hours = 40
+ min_snapshots_to_keep = 3
+ }
+ }
+ }
+
+ create_table_policy = true
+ policy_statements = [
+ {
+ sid = "DeleteTable"
+ effect = "Allow"
+ principals = [{
+ type = "AWS"
+ identifiers = [data.aws_caller_identity.this.account_id]
+ }]
+ actions = [
+ "s3tables:DeleteTable",
+ "s3tables:UpdateTableMetadataLocation",
+ "s3tables:PutTableData",
+ "s3tables:GetTableMetadataLocation"
+ ]
+ }
+ ]
+ }
+ table2 = {
+ format = "ICEBERG"
+ name = "table2"
+ namespace = aws_s3tables_namespace.namespace.namespace
+ }
+ table3 = {
+ format = "ICEBERG"
+ namespace = aws_s3tables_namespace.namespace.namespace
+ }
+ }
+}
+
+resource "random_pet" "this" {
+ length = 2
+}
+
+resource "aws_s3tables_namespace" "namespace" {
+ namespace = "example_namespace"
+ table_bucket_arn = module.table_bucket.s3_table_bucket_arn
+}
diff --git a/examples/table-bucket/outputs.tf b/examples/table-bucket/outputs.tf
new file mode 100644
index 00000000..637e493a
--- /dev/null
+++ b/examples/table-bucket/outputs.tf
@@ -0,0 +1,64 @@
+output "s3_table_bucket_arn" {
+ description = "ARN of the table bucket."
+ value = module.table_bucket.s3_table_bucket_arn
+}
+
+output "s3_table_bucket_created_at" {
+ description = "Date and time when the bucket was created."
+ value = module.table_bucket.s3_table_bucket_created_at
+}
+
+output "owner_account_id" {
+ description = "Account ID of the account that owns the table bucket."
+ value = module.table_bucket.s3_table_bucket_owner_account_id
+}
+
+output "s3_table_arns" {
+ description = "The table ARNs."
+ value = module.table_bucket.s3_table_arns
+}
+
+output "s3_table_created_at" {
+ description = "Dates and times when the tables were created."
+ value = module.table_bucket.s3_table_created_at
+}
+
+output "s3_table_created_by" {
+ description = "Account IDs of the accounts that created the tables"
+ value = module.table_bucket.s3_table_created_by
+}
+
+output "s3_table_metadata_locations" {
+ description = "Locations of table metadata."
+ value = module.table_bucket.s3_table_metadata_locations
+}
+
+output "s3_table_modified_at" {
+ description = "Dates and times when the tables was last modified."
+ value = module.table_bucket.s3_table_modified_at
+}
+
+output "s3_table_modified_by" {
+ description = "Account IDs of the accounts that last modified the tables."
+ value = module.table_bucket.s3_table_modified_by
+}
+
+output "s3_table_owner_account_ids" {
+ description = "Account IDs of the accounts that owns the tables."
+ value = module.table_bucket.s3_table_owner_account_ids
+}
+
+output "s3_table_types" {
+ description = "Types of the tables. One of customer or aws."
+ value = module.table_bucket.s3_table_types
+}
+
+output "s3_table_version_tokens" {
+ description = "Identifiers for the current version of table data."
+ value = module.table_bucket.s3_table_version_tokens
+}
+
+output "s3_table_warehouse_locations" {
+ description = "S3 URIs pointing to the S3 Bucket that contains the table data."
+ value = module.table_bucket.s3_table_warehouse_locations
+}
diff --git a/examples/table-bucket/variables.tf b/examples/table-bucket/variables.tf
new file mode 100644
index 00000000..e69de29b
diff --git a/examples/table-bucket/versions.tf b/examples/table-bucket/versions.tf
new file mode 100644
index 00000000..9ef2d5d8
--- /dev/null
+++ b/examples/table-bucket/versions.tf
@@ -0,0 +1,14 @@
+terraform {
+ required_version = ">= 1.0"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 5.83"
+ }
+ random = {
+ source = "hashicorp/random"
+ version = ">= 2.0"
+ }
+ }
+}
diff --git a/modules/table-bucket/README.md b/modules/table-bucket/README.md
new file mode 100644
index 00000000..03e0b2b1
--- /dev/null
+++ b/modules/table-bucket/README.md
@@ -0,0 +1,65 @@
+# S3 Table Bucket
+
+Creates S3 Table Bucket and Tables with various configurations.
+
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 1.0 |
+| [aws](#requirement\_aws) | >= 5.83 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [aws](#provider\_aws) | >= 5.83 |
+
+## Modules
+
+No modules.
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [aws_s3tables_table.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3tables_table) | resource |
+| [aws_s3tables_table_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3tables_table_bucket) | resource |
+| [aws_s3tables_table_bucket_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3tables_table_bucket_policy) | resource |
+| [aws_s3tables_table_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3tables_table_policy) | resource |
+| [aws_iam_policy_document.table_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+| [aws_iam_policy_document.table_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [create](#input\_create) | Whether to create s3 table resources | `bool` | `true` | no |
+| [create\_table\_bucket\_policy](#input\_create\_table\_bucket\_policy) | Whether to create s3 table bucket policy | `bool` | `false` | no |
+| [maintenance\_configuration](#input\_maintenance\_configuration) | Map of table bucket maintenance configurations | `any` | `{}` | no |
+| [table\_bucket\_name](#input\_table\_bucket\_name) | Name of the table bucket. Must be between 3 and 63 characters in length. Can consist of lowercase letters, numbers, and hyphens, and must begin and end with a lowercase letter or number | `string` | `null` | no |
+| [table\_bucket\_override\_policy\_documents](#input\_table\_bucket\_override\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. In merging, statements with non-blank `sid`s will override statements with the same `sid` | `list(string)` | `[]` | no |
+| [table\_bucket\_policy](#input\_table\_bucket\_policy) | Amazon Web Services resource-based policy document in JSON format | `string` | `null` | no |
+| [table\_bucket\_policy\_statements](#input\_table\_bucket\_policy\_statements) | A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage | `any` | `{}` | no |
+| [table\_bucket\_source\_policy\_documents](#input\_table\_bucket\_source\_policy\_documents) | List of IAM policy documents that are merged together into the exported document. Statements must have unique `sid`s | `list(string)` | `[]` | no |
+| [tables](#input\_tables) | Map of table configurations | `any` | `{}` | no |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| [s3\_table\_arns](#output\_s3\_table\_arns) | The table ARNs. |
+| [s3\_table\_bucket\_arn](#output\_s3\_table\_bucket\_arn) | ARN of the table bucket. |
+| [s3\_table\_bucket\_created\_at](#output\_s3\_table\_bucket\_created\_at) | Date and time when the bucket was created. |
+| [s3\_table\_bucket\_owner\_account\_id](#output\_s3\_table\_bucket\_owner\_account\_id) | Account ID of the account that owns the table bucket. |
+| [s3\_table\_created\_at](#output\_s3\_table\_created\_at) | Dates and times when the tables were created. |
+| [s3\_table\_created\_by](#output\_s3\_table\_created\_by) | Account IDs of the accounts that created the tables |
+| [s3\_table\_metadata\_locations](#output\_s3\_table\_metadata\_locations) | Locations of table metadata. |
+| [s3\_table\_modified\_at](#output\_s3\_table\_modified\_at) | Dates and times when the tables was last modified. |
+| [s3\_table\_modified\_by](#output\_s3\_table\_modified\_by) | Account IDs of the accounts that last modified the tables. |
+| [s3\_table\_owner\_account\_ids](#output\_s3\_table\_owner\_account\_ids) | Account IDs of the accounts that owns the tables. |
+| [s3\_table\_types](#output\_s3\_table\_types) | Types of the tables. One of customer or aws. |
+| [s3\_table\_version\_tokens](#output\_s3\_table\_version\_tokens) | Identifiers for the current version of table data. |
+| [s3\_table\_warehouse\_locations](#output\_s3\_table\_warehouse\_locations) | S3 URIs pointing to the S3 Bucket that contains the table data. |
+
diff --git a/modules/table-bucket/main.tf b/modules/table-bucket/main.tf
new file mode 100644
index 00000000..f2eb65f1
--- /dev/null
+++ b/modules/table-bucket/main.tf
@@ -0,0 +1,124 @@
+resource "aws_s3tables_table_bucket" "this" {
+ count = var.create ? 1 : 0
+
+ name = var.table_bucket_name
+ maintenance_configuration = var.maintenance_configuration
+}
+
+resource "aws_s3tables_table_bucket_policy" "this" {
+ count = var.create && var.create_table_bucket_policy ? 1 : 0
+
+ resource_policy = var.table_bucket_policy != null ? var.table_bucket_policy : data.aws_iam_policy_document.table_bucket_policy[0].json
+ table_bucket_arn = aws_s3tables_table_bucket.this[0].arn
+}
+
+data "aws_iam_policy_document" "table_bucket_policy" {
+ count = var.create && var.create_table_bucket_policy && var.table_bucket_policy == null ? 1 : 0
+
+ source_policy_documents = var.table_bucket_source_policy_documents
+ override_policy_documents = var.table_bucket_override_policy_documents
+
+ dynamic "statement" {
+ for_each = var.table_bucket_policy_statements
+
+ content {
+ sid = try(statement.value.sid, null)
+ actions = try(statement.value.actions, null)
+ not_actions = try(statement.value.not_actions, null)
+ effect = try(statement.value.effect, null)
+ resources = try(statement.value.resources, ["${aws_s3tables_table_bucket.this[0].arn}/table/*"])
+ not_resources = try(statement.value.not_resources, null)
+
+ dynamic "principals" {
+ for_each = try(statement.value.principals, [])
+
+ content {
+ type = principals.value.type
+ identifiers = principals.value.identifiers
+ }
+ }
+
+ dynamic "not_principals" {
+ for_each = try(statement.value.not_principals, [])
+
+ content {
+ type = not_principals.value.type
+ identifiers = not_principals.value.identifiers
+ }
+ }
+
+ dynamic "condition" {
+ for_each = try(statement.value.conditions, [])
+
+ content {
+ test = condition.value.test
+ values = condition.value.values
+ variable = condition.value.variable
+ }
+ }
+ }
+ }
+}
+
+resource "aws_s3tables_table" "this" {
+ for_each = { for k, v in var.tables : k => v if var.create }
+
+ format = each.value.format
+ name = try(each.value.table_name, each.key)
+ namespace = each.value.namespace
+ table_bucket_arn = aws_s3tables_table_bucket.this[0].arn
+ maintenance_configuration = try(each.value.maintenance_configuration, null)
+}
+
+resource "aws_s3tables_table_policy" "this" {
+ for_each = { for k, v in var.tables : k => v if var.create && try(v.create_table_policy, false) }
+
+ name = aws_s3tables_table.this[each.key].name
+ namespace = each.value.namespace
+ resource_policy = data.aws_iam_policy_document.table_policy[each.key].json
+ table_bucket_arn = aws_s3tables_table_bucket.this[0].arn
+}
+
+data "aws_iam_policy_document" "table_policy" {
+ for_each = { for k, v in var.tables : k => v.policy_statements if var.create && try(v.create_table_policy, false) }
+
+ dynamic "statement" {
+ for_each = each.value
+
+ content {
+ sid = try(statement.value.sid, null)
+ actions = try(statement.value.actions, null)
+ not_actions = try(statement.value.not_actions, null)
+ effect = try(statement.value.effect, null)
+ resources = [aws_s3tables_table.this[each.key].arn]
+
+ dynamic "principals" {
+ for_each = try(statement.value.principals, [])
+
+ content {
+ type = principals.value.type
+ identifiers = principals.value.identifiers
+ }
+ }
+
+ dynamic "not_principals" {
+ for_each = try(statement.value.not_principals, [])
+
+ content {
+ type = not_principals.value.type
+ identifiers = not_principals.value.identifiers
+ }
+ }
+
+ dynamic "condition" {
+ for_each = try(statement.value.conditions, [])
+
+ content {
+ test = condition.value.test
+ values = condition.value.values
+ variable = condition.value.variable
+ }
+ }
+ }
+ }
+}
diff --git a/modules/table-bucket/outputs.tf b/modules/table-bucket/outputs.tf
new file mode 100644
index 00000000..fb952f0e
--- /dev/null
+++ b/modules/table-bucket/outputs.tf
@@ -0,0 +1,64 @@
+output "s3_table_bucket_arn" {
+ description = "ARN of the table bucket."
+ value = try(aws_s3tables_table_bucket.this[0].arn, null)
+}
+
+output "s3_table_bucket_created_at" {
+ description = "Date and time when the bucket was created."
+ value = try(aws_s3tables_table_bucket.this[0].created_at, null)
+}
+
+output "s3_table_bucket_owner_account_id" {
+ description = "Account ID of the account that owns the table bucket."
+ value = try(aws_s3tables_table_bucket.this[0].owner_account_id, null)
+}
+
+output "s3_table_arns" {
+ description = "The table ARNs."
+ value = { for k, v in aws_s3tables_table.this : k => v.arn }
+}
+
+output "s3_table_created_at" {
+ description = "Dates and times when the tables were created."
+ value = { for k, v in aws_s3tables_table.this : k => v.created_at }
+}
+
+output "s3_table_created_by" {
+ description = "Account IDs of the accounts that created the tables"
+ value = { for k, v in aws_s3tables_table.this : k => v.created_by }
+}
+
+output "s3_table_metadata_locations" {
+ description = "Locations of table metadata."
+ value = { for k, v in aws_s3tables_table.this : k => v.metadata_location }
+}
+
+output "s3_table_modified_at" {
+ description = "Dates and times when the tables was last modified."
+ value = { for k, v in aws_s3tables_table.this : k => v.modified_at }
+}
+
+output "s3_table_modified_by" {
+ description = "Account IDs of the accounts that last modified the tables."
+ value = { for k, v in aws_s3tables_table.this : k => v.modified_by }
+}
+
+output "s3_table_owner_account_ids" {
+ description = "Account IDs of the accounts that owns the tables."
+ value = { for k, v in aws_s3tables_table.this : k => v.owner_account_id }
+}
+
+output "s3_table_types" {
+ description = "Types of the tables. One of customer or aws."
+ value = { for k, v in aws_s3tables_table.this : k => v.type }
+}
+
+output "s3_table_version_tokens" {
+ description = "Identifiers for the current version of table data."
+ value = { for k, v in aws_s3tables_table.this : k => v.version_token }
+}
+
+output "s3_table_warehouse_locations" {
+ description = "S3 URIs pointing to the S3 Bucket that contains the table data."
+ value = { for k, v in aws_s3tables_table.this : k => v.warehouse_location }
+}
diff --git a/modules/table-bucket/variables.tf b/modules/table-bucket/variables.tf
new file mode 100644
index 00000000..3d332407
--- /dev/null
+++ b/modules/table-bucket/variables.tf
@@ -0,0 +1,53 @@
+variable "create" {
+ description = "Whether to create s3 table resources"
+ type = bool
+ default = true
+}
+
+variable "table_bucket_name" {
+ description = "Name of the table bucket. Must be between 3 and 63 characters in length. Can consist of lowercase letters, numbers, and hyphens, and must begin and end with a lowercase letter or number"
+ type = string
+ default = null
+}
+
+variable "maintenance_configuration" {
+ description = "Map of table bucket maintenance configurations"
+ type = any
+ default = {}
+}
+
+variable "create_table_bucket_policy" {
+ description = "Whether to create s3 table bucket policy"
+ type = bool
+ default = false
+}
+
+variable "table_bucket_policy" {
+ description = "Amazon Web Services resource-based policy document in JSON format"
+ type = string
+ default = null
+}
+
+variable "table_bucket_source_policy_documents" {
+ description = "List of IAM policy documents that are merged together into the exported document. Statements must have unique `sid`s"
+ type = list(string)
+ default = []
+}
+
+variable "table_bucket_override_policy_documents" {
+ description = "List of IAM policy documents that are merged together into the exported document. In merging, statements with non-blank `sid`s will override statements with the same `sid`"
+ type = list(string)
+ default = []
+}
+
+variable "table_bucket_policy_statements" {
+ description = "A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage"
+ type = any
+ default = {}
+}
+
+variable "tables" {
+ description = "Map of table configurations"
+ type = any
+ default = {}
+}
diff --git a/modules/table-bucket/versions.tf b/modules/table-bucket/versions.tf
new file mode 100644
index 00000000..e0d68841
--- /dev/null
+++ b/modules/table-bucket/versions.tf
@@ -0,0 +1,10 @@
+terraform {
+ required_version = ">= 1.0"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 5.83"
+ }
+ }
+}
diff --git a/wrappers/table-bucket/README.md b/wrappers/table-bucket/README.md
new file mode 100644
index 00000000..57f82ce7
--- /dev/null
+++ b/wrappers/table-bucket/README.md
@@ -0,0 +1,100 @@
+# Wrapper for module: `modules/table-bucket`
+
+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/table-bucket"
+ # Alternative source:
+ # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers/table-bucket?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/table-bucket"
+
+ 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/table-bucket/main.tf b/wrappers/table-bucket/main.tf
new file mode 100644
index 00000000..b33d64b0
--- /dev/null
+++ b/wrappers/table-bucket/main.tf
@@ -0,0 +1,15 @@
+module "wrapper" {
+ source = "../../modules/table-bucket"
+
+ for_each = var.items
+
+ create = try(each.value.create, var.defaults.create, true)
+ create_table_bucket_policy = try(each.value.create_table_bucket_policy, var.defaults.create_table_bucket_policy, false)
+ maintenance_configuration = try(each.value.maintenance_configuration, var.defaults.maintenance_configuration, {})
+ table_bucket_name = try(each.value.table_bucket_name, var.defaults.table_bucket_name, null)
+ table_bucket_override_policy_documents = try(each.value.table_bucket_override_policy_documents, var.defaults.table_bucket_override_policy_documents, [])
+ table_bucket_policy = try(each.value.table_bucket_policy, var.defaults.table_bucket_policy, null)
+ table_bucket_policy_statements = try(each.value.table_bucket_policy_statements, var.defaults.table_bucket_policy_statements, {})
+ table_bucket_source_policy_documents = try(each.value.table_bucket_source_policy_documents, var.defaults.table_bucket_source_policy_documents, [])
+ tables = try(each.value.tables, var.defaults.tables, {})
+}
diff --git a/wrappers/table-bucket/outputs.tf b/wrappers/table-bucket/outputs.tf
new file mode 100644
index 00000000..ec6da5f4
--- /dev/null
+++ b/wrappers/table-bucket/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/table-bucket/variables.tf b/wrappers/table-bucket/variables.tf
new file mode 100644
index 00000000..a6ea0962
--- /dev/null
+++ b/wrappers/table-bucket/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/table-bucket/versions.tf b/wrappers/table-bucket/versions.tf
new file mode 100644
index 00000000..e0d68841
--- /dev/null
+++ b/wrappers/table-bucket/versions.tf
@@ -0,0 +1,10 @@
+terraform {
+ required_version = ">= 1.0"
+
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = ">= 5.83"
+ }
+ }
+}