Skip to content

Fix: directory bucket naming should follow [base_bucket]--[availability-zone-id]--x-s3 #272

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,13 +280,13 @@ Available targets:
| <a name="input_bucket_name"></a> [bucket\_name](#input\_bucket\_name) | Bucket name. If provided, the bucket will be created with this name instead of generating the name from the context | `string` | `null` | no |
| <a name="input_context"></a> [context](#input\_context) | Single object for setting entire context at once.<br/>See description of individual variables for details.<br/>Leave string and numeric variables as `null` to use default value.<br/>Individual variable settings (non-null) override settings in context object,<br/>except for attributes, tags, and additional\_tag\_map, which are merged. | `any` | <pre>{<br/> "additional_tag_map": {},<br/> "attributes": [],<br/> "delimiter": null,<br/> "descriptor_formats": {},<br/> "enabled": true,<br/> "environment": null,<br/> "id_length_limit": null,<br/> "label_key_case": null,<br/> "label_order": [],<br/> "label_value_case": null,<br/> "labels_as_tags": [<br/> "unset"<br/> ],<br/> "name": null,<br/> "namespace": null,<br/> "regex_replace_chars": null,<br/> "stage": null,<br/> "tags": {},<br/> "tenant": null<br/>}</pre> | no |
| <a name="input_cors_configuration"></a> [cors\_configuration](#input\_cors\_configuration) | Specifies the allowed headers, methods, origins and exposed headers when using CORS on this bucket | <pre>list(object({<br/> id = optional(string)<br/> allowed_headers = optional(list(string))<br/> allowed_methods = optional(list(string))<br/> allowed_origins = optional(list(string))<br/> expose_headers = optional(list(string))<br/> max_age_seconds = optional(number)<br/> }))</pre> | `[]` | no |
| <a name="input_create_s3_directory_bucket"></a> [create\_s3\_directory\_bucket](#input\_create\_s3\_directory\_bucket) | Control the creation of the S3 directory bucket. Set to true to create the bucket, false to skip. | `bool` | `false` | no |
| <a name="input_create_s3_directory_bucket"></a> [create\_s3\_directory\_bucket](#input\_create\_s3\_directory\_bucket) | DEPRECATED (use `s3_directory_bucket_enabled`) Control the creation of the S3 directory bucket. Set to true to create the bucket, false to skip. | `bool` | `false` | no |
| <a name="input_delimiter"></a> [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.<br/>Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no |
| <a name="input_descriptor_formats"></a> [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.<br/>Map of maps. Keys are names of descriptors. Values are maps of the form<br/>`{<br/> format = string<br/> labels = list(string)<br/>}`<br/>(Type is `any` so the map values can later be enhanced to provide additional options.)<br/>`format` is a Terraform format string to be passed to the `format()` function.<br/>`labels` is a list of labels, in order, to pass to `format()` function.<br/>Label values will be normalized before being passed to `format()` so they will be<br/>identical to how they appear in `id`.<br/>Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no |
| <a name="input_enabled"></a> [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no |
| <a name="input_environment"></a> [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no |
| <a name="input_event_notification_details"></a> [event\_notification\_details](#input\_event\_notification\_details) | S3 event notification details | <pre>object({<br/> enabled = bool<br/> eventbridge = optional(bool, false)<br/> lambda_list = optional(list(object({<br/> lambda_function_arn = string<br/> events = optional(list(string), ["s3:ObjectCreated:*"])<br/> filter_prefix = optional(string)<br/> filter_suffix = optional(string)<br/> })), [])<br/><br/> queue_list = optional(list(object({<br/> queue_arn = string<br/> events = optional(list(string), ["s3:ObjectCreated:*"])<br/> filter_prefix = optional(string)<br/> filter_suffix = optional(string)<br/> })), [])<br/><br/> topic_list = optional(list(object({<br/> topic_arn = string<br/> events = optional(list(string), ["s3:ObjectCreated:*"])<br/> filter_prefix = optional(string)<br/> filter_suffix = optional(string)<br/> })), [])<br/> })</pre> | <pre>{<br/> "enabled": false<br/>}</pre> | no |
| <a name="input_expected_bucket_owner"></a> [expected\_bucket\_owner](#input\_expected\_bucket\_owner) | Account ID of the expected bucket owner. <br/>More information: https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-owner-condition.html | `string` | `null` | no |
| <a name="input_expected_bucket_owner"></a> [expected\_bucket\_owner](#input\_expected\_bucket\_owner) | Account ID of the expected bucket owner.<br/>More information: https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-owner-condition.html | `string` | `null` | no |
| <a name="input_force_destroy"></a> [force\_destroy](#input\_force\_destroy) | When `true`, permits a non-empty S3 bucket to be deleted by first deleting all objects in the bucket.<br/>THESE OBJECTS ARE NOT RECOVERABLE even if they were versioned and stored in Glacier. | `bool` | `false` | no |
| <a name="input_grants"></a> [grants](#input\_grants) | A list of policy grants for the bucket, taking a list of permissions.<br/>Conflicts with `acl`. Set `acl` to `null` to use this.<br/>Deprecated by AWS in favor of bucket policies.<br/>Automatically disabled if `s3_object_ownership` is set to "BucketOwnerEnforced". | <pre>list(object({<br/> id = string<br/> type = string<br/> permissions = list(string)<br/> uri = string<br/> }))</pre> | `[]` | no |
| <a name="input_id_length_limit"></a> [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).<br/>Set to `0` for unlimited length.<br/>Set to `null` for keep the existing setting, which defaults to `0`.<br/>Does not affect `id_full`. | `number` | `null` | no |
Expand All @@ -309,6 +309,7 @@ Available targets:
| <a name="input_regex_replace_chars"></a> [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.<br/>Characters matching the regex will be removed from the ID elements.<br/>If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
| <a name="input_replication_rules"></a> [replication\_rules](#input\_replication\_rules) | DEPRECATED (use `s3_replication_rules`): Specifies the replication rules for S3 bucket replication if enabled. You must also set s3\_replication\_enabled to true. | `list(any)` | `null` | no |
| <a name="input_restrict_public_buckets"></a> [restrict\_public\_buckets](#input\_restrict\_public\_buckets) | Set to `false` to disable the restricting of making the bucket public | `bool` | `true` | no |
| <a name="input_s3_directory_bucket_enabled"></a> [s3\_directory\_bucket\_enabled](#input\_s3\_directory\_bucket\_enabled) | Set this to true to make your s3 bucket a directory bucket. This will generate a bucket will the fully qualified<br/>name following the convention: [bucket-name]--[availability-zone-id]--x-s3.<br/>For more information, see: https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-bucket-naming-rules.html | `bool` | `false` | no |
| <a name="input_s3_object_ownership"></a> [s3\_object\_ownership](#input\_s3\_object\_ownership) | Specifies the S3 object ownership control.<br/>Valid values are `ObjectWriter`, `BucketOwnerPreferred`, and 'BucketOwnerEnforced'.<br/>Defaults to "ObjectWriter" for backwards compatibility, but we recommend setting "BucketOwnerEnforced" instead. | `string` | `"ObjectWriter"` | no |
| <a name="input_s3_replica_bucket_arn"></a> [s3\_replica\_bucket\_arn](#input\_s3\_replica\_bucket\_arn) | A single S3 bucket ARN to use for all replication rules.<br/>Note: The destination bucket can be specified in the replication rule itself<br/>(which allows for multiple destinations), in which case it will take precedence over this variable. | `string` | `""` | no |
| <a name="input_s3_replication_enabled"></a> [s3\_replication\_enabled](#input\_s3\_replication\_enabled) | Set this to true and specify `s3_replication_rules` to enable replication. `versioning_enabled` must also be `true`. | `bool` | `false` | no |
Expand Down
5 changes: 3 additions & 2 deletions docs/terraform.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@
| <a name="input_bucket_name"></a> [bucket\_name](#input\_bucket\_name) | Bucket name. If provided, the bucket will be created with this name instead of generating the name from the context | `string` | `null` | no |
| <a name="input_context"></a> [context](#input\_context) | Single object for setting entire context at once.<br/>See description of individual variables for details.<br/>Leave string and numeric variables as `null` to use default value.<br/>Individual variable settings (non-null) override settings in context object,<br/>except for attributes, tags, and additional\_tag\_map, which are merged. | `any` | <pre>{<br/> "additional_tag_map": {},<br/> "attributes": [],<br/> "delimiter": null,<br/> "descriptor_formats": {},<br/> "enabled": true,<br/> "environment": null,<br/> "id_length_limit": null,<br/> "label_key_case": null,<br/> "label_order": [],<br/> "label_value_case": null,<br/> "labels_as_tags": [<br/> "unset"<br/> ],<br/> "name": null,<br/> "namespace": null,<br/> "regex_replace_chars": null,<br/> "stage": null,<br/> "tags": {},<br/> "tenant": null<br/>}</pre> | no |
| <a name="input_cors_configuration"></a> [cors\_configuration](#input\_cors\_configuration) | Specifies the allowed headers, methods, origins and exposed headers when using CORS on this bucket | <pre>list(object({<br/> id = optional(string)<br/> allowed_headers = optional(list(string))<br/> allowed_methods = optional(list(string))<br/> allowed_origins = optional(list(string))<br/> expose_headers = optional(list(string))<br/> max_age_seconds = optional(number)<br/> }))</pre> | `[]` | no |
| <a name="input_create_s3_directory_bucket"></a> [create\_s3\_directory\_bucket](#input\_create\_s3\_directory\_bucket) | Control the creation of the S3 directory bucket. Set to true to create the bucket, false to skip. | `bool` | `false` | no |
| <a name="input_create_s3_directory_bucket"></a> [create\_s3\_directory\_bucket](#input\_create\_s3\_directory\_bucket) | DEPRECATED (use `s3_directory_bucket_enabled`) Control the creation of the S3 directory bucket. Set to true to create the bucket, false to skip. | `bool` | `false` | no |
| <a name="input_delimiter"></a> [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.<br/>Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no |
| <a name="input_descriptor_formats"></a> [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.<br/>Map of maps. Keys are names of descriptors. Values are maps of the form<br/>`{<br/> format = string<br/> labels = list(string)<br/>}`<br/>(Type is `any` so the map values can later be enhanced to provide additional options.)<br/>`format` is a Terraform format string to be passed to the `format()` function.<br/>`labels` is a list of labels, in order, to pass to `format()` function.<br/>Label values will be normalized before being passed to `format()` so they will be<br/>identical to how they appear in `id`.<br/>Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no |
| <a name="input_enabled"></a> [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no |
| <a name="input_environment"></a> [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no |
| <a name="input_event_notification_details"></a> [event\_notification\_details](#input\_event\_notification\_details) | S3 event notification details | <pre>object({<br/> enabled = bool<br/> eventbridge = optional(bool, false)<br/> lambda_list = optional(list(object({<br/> lambda_function_arn = string<br/> events = optional(list(string), ["s3:ObjectCreated:*"])<br/> filter_prefix = optional(string)<br/> filter_suffix = optional(string)<br/> })), [])<br/><br/> queue_list = optional(list(object({<br/> queue_arn = string<br/> events = optional(list(string), ["s3:ObjectCreated:*"])<br/> filter_prefix = optional(string)<br/> filter_suffix = optional(string)<br/> })), [])<br/><br/> topic_list = optional(list(object({<br/> topic_arn = string<br/> events = optional(list(string), ["s3:ObjectCreated:*"])<br/> filter_prefix = optional(string)<br/> filter_suffix = optional(string)<br/> })), [])<br/> })</pre> | <pre>{<br/> "enabled": false<br/>}</pre> | no |
| <a name="input_expected_bucket_owner"></a> [expected\_bucket\_owner](#input\_expected\_bucket\_owner) | Account ID of the expected bucket owner. <br/>More information: https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-owner-condition.html | `string` | `null` | no |
| <a name="input_expected_bucket_owner"></a> [expected\_bucket\_owner](#input\_expected\_bucket\_owner) | Account ID of the expected bucket owner.<br/>More information: https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-owner-condition.html | `string` | `null` | no |
| <a name="input_force_destroy"></a> [force\_destroy](#input\_force\_destroy) | When `true`, permits a non-empty S3 bucket to be deleted by first deleting all objects in the bucket.<br/>THESE OBJECTS ARE NOT RECOVERABLE even if they were versioned and stored in Glacier. | `bool` | `false` | no |
| <a name="input_grants"></a> [grants](#input\_grants) | A list of policy grants for the bucket, taking a list of permissions.<br/>Conflicts with `acl`. Set `acl` to `null` to use this.<br/>Deprecated by AWS in favor of bucket policies.<br/>Automatically disabled if `s3_object_ownership` is set to "BucketOwnerEnforced". | <pre>list(object({<br/> id = string<br/> type = string<br/> permissions = list(string)<br/> uri = string<br/> }))</pre> | `[]` | no |
| <a name="input_id_length_limit"></a> [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).<br/>Set to `0` for unlimited length.<br/>Set to `null` for keep the existing setting, which defaults to `0`.<br/>Does not affect `id_full`. | `number` | `null` | no |
Expand All @@ -101,6 +101,7 @@
| <a name="input_regex_replace_chars"></a> [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.<br/>Characters matching the regex will be removed from the ID elements.<br/>If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
| <a name="input_replication_rules"></a> [replication\_rules](#input\_replication\_rules) | DEPRECATED (use `s3_replication_rules`): Specifies the replication rules for S3 bucket replication if enabled. You must also set s3\_replication\_enabled to true. | `list(any)` | `null` | no |
| <a name="input_restrict_public_buckets"></a> [restrict\_public\_buckets](#input\_restrict\_public\_buckets) | Set to `false` to disable the restricting of making the bucket public | `bool` | `true` | no |
| <a name="input_s3_directory_bucket_enabled"></a> [s3\_directory\_bucket\_enabled](#input\_s3\_directory\_bucket\_enabled) | Set this to true to make your s3 bucket a directory bucket. This will generate a bucket will the fully qualified<br/>name following the convention: [bucket-name]--[availability-zone-id]--x-s3.<br/>For more information, see: https://docs.aws.amazon.com/AmazonS3/latest/userguide/directory-bucket-naming-rules.html | `bool` | `false` | no |
| <a name="input_s3_object_ownership"></a> [s3\_object\_ownership](#input\_s3\_object\_ownership) | Specifies the S3 object ownership control.<br/>Valid values are `ObjectWriter`, `BucketOwnerPreferred`, and 'BucketOwnerEnforced'.<br/>Defaults to "ObjectWriter" for backwards compatibility, but we recommend setting "BucketOwnerEnforced" instead. | `string` | `"ObjectWriter"` | no |
| <a name="input_s3_replica_bucket_arn"></a> [s3\_replica\_bucket\_arn](#input\_s3\_replica\_bucket\_arn) | A single S3 bucket ARN to use for all replication rules.<br/>Note: The destination bucket can be specified in the replication rule itself<br/>(which allows for multiple destinations), in which case it will take precedence over this variable. | `string` | `""` | no |
| <a name="input_s3_replication_enabled"></a> [s3\_replication\_enabled](#input\_s3\_replication\_enabled) | Set this to true and specify `s3_replication_rules` to enable replication. `versioning_enabled` must also be `true`. | `bool` | `false` | no |
Expand Down
13 changes: 13 additions & 0 deletions examples/complete/directory-bucket-create-flag.us-east-2.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
stage = "test"

name = "s3-test"

acl = "private"

force_destroy = true

user_enabled = true

availability_zone_id = "use1-az2"

create_s3_directory_bucket = true
15 changes: 15 additions & 0 deletions examples/complete/directory-bucket.us-east-2.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
stage = "test"

name = "s3-test"

acl = "private"

force_destroy = true

user_enabled = true

availability_zone_id = "use1-az2"

s3_directory_bucket_enabled = true

create_s3_directory_bucket = true
16 changes: 9 additions & 7 deletions main.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
locals {
enabled = module.this.enabled
partition = join("", data.aws_partition.current[*].partition)
directory_bucket_name = var.create_s3_directory_bucket ? "${local.bucket_name}-${var.availability_zone_id}" : ""
enabled = module.this.enabled
partition = join("", data.aws_partition.current[*].partition)
fully_qualified_directory_bucket_name = var.s3_directory_bucket_enabled ? "${local.bucket_name}--${var.availability_zone_id}--x-s3" : ""
directory_bucket_name = var.create_s3_directory_bucket && local.fully_qualified_directory_bucket_name != "" ? "${local.bucket_name}-${var.availability_zone_id}" : ""

object_lock_enabled = local.enabled && var.object_lock_configuration != null
replication_enabled = local.enabled && var.s3_replication_enabled
Expand Down Expand Up @@ -581,7 +582,7 @@ resource "time_sleep" "wait_for_aws_s3_bucket_settings" {
destroy_duration = "30s"
}

# S3 event Bucket Notifications
# S3 event Bucket Notifications
resource "aws_s3_bucket_notification" "bucket_notification" {
count = var.event_notification_details.enabled ? 1 : 0
bucket = local.bucket_id
Expand Down Expand Up @@ -619,18 +620,19 @@ resource "aws_s3_bucket_notification" "bucket_notification" {
}
}

# Directory Bucket
# Directory Bucket
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_directory_bucket
resource "aws_s3_directory_bucket" "default" {
count = var.create_s3_directory_bucket ? 1 : 0
bucket = local.directory_bucket_name
count = var.s3_directory_bucket_enabled || var.create_s3_directory_bucket ? 1 : 0
bucket = var.s3_directory_bucket_enabled ? local.fully_qualified_directory_bucket_name : local.directory_bucket_name
force_destroy = var.force_destroy

location {
name = var.availability_zone_id
}
}


resource "aws_s3_bucket_request_payment_configuration" "default" {
count = local.enabled && var.s3_request_payment_configuration.enabled ? 1 : 0

Expand Down
Loading