diff --git a/README.md b/README.md
index 14f8ec2d..72d509e2 100644
--- a/README.md
+++ b/README.md
@@ -213,13 +213,15 @@ Available targets:
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 0.13.0 |
-| [aws](#requirement\_aws) | >= 2.33 |
+| [aws](#requirement\_aws) | >= 3.0 |
+| [time](#requirement\_time) | >= 0.7 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 2.33 |
+| [aws](#provider\_aws) | >= 3.0 |
+| [time](#provider\_time) | >= 0.7 |
## Modules
@@ -236,8 +238,10 @@ Available targets:
| [aws_iam_role.replication](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy_attachment.replication](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_s3_bucket.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource |
+| [aws_s3_bucket_ownership_controls.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_ownership_controls) | resource |
| [aws_s3_bucket_policy.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource |
| [aws_s3_bucket_public_access_block.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource |
+| [time_sleep.wait_for_aws_s3_bucket_settings](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource |
| [aws_iam_policy_document.aggregated_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.replication](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
@@ -284,6 +288,7 @@ Available targets:
| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
| [replication\_rules](#input\_replication\_rules) | DEPRECATED: Use s3\_replication\_rules instead. | `list(any)` | `null` | no |
| [restrict\_public\_buckets](#input\_restrict\_public\_buckets) | Set to `false` to disable the restricting of making the bucket public | `bool` | `true` | no |
+| [s3\_object\_ownership](#input\_s3\_object\_ownership) | Specifies the S3 object ownership control. Valid values are `ObjectWriter` and `BucketOwnerPreferred` | `string` | `"ObjectWriter"` | no |
| [s3\_replica\_bucket\_arn](#input\_s3\_replica\_bucket\_arn) | A single S3 bucket ARN to use for all replication rules.
Note: The destination bucket can be specified in the replication rule itself
(which allows for multiple destinations), in which case it will take precedence over this variable. | `string` | `""` | no |
| [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 |
| [s3\_replication\_rules](#input\_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 |
diff --git a/docs/terraform.md b/docs/terraform.md
index 661c80a4..02eca5f2 100644
--- a/docs/terraform.md
+++ b/docs/terraform.md
@@ -4,13 +4,15 @@
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 0.13.0 |
-| [aws](#requirement\_aws) | >= 2.33 |
+| [aws](#requirement\_aws) | >= 3.0 |
+| [time](#requirement\_time) | >= 0.7 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 2.33 |
+| [aws](#provider\_aws) | >= 3.0 |
+| [time](#provider\_time) | >= 0.7 |
## Modules
@@ -27,8 +29,10 @@
| [aws_iam_role.replication](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy_attachment.replication](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_s3_bucket.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource |
+| [aws_s3_bucket_ownership_controls.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_ownership_controls) | resource |
| [aws_s3_bucket_policy.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource |
| [aws_s3_bucket_public_access_block.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource |
+| [time_sleep.wait_for_aws_s3_bucket_settings](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource |
| [aws_iam_policy_document.aggregated_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
| [aws_iam_policy_document.replication](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
@@ -75,6 +79,7 @@
| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
| [replication\_rules](#input\_replication\_rules) | DEPRECATED: Use s3\_replication\_rules instead. | `list(any)` | `null` | no |
| [restrict\_public\_buckets](#input\_restrict\_public\_buckets) | Set to `false` to disable the restricting of making the bucket public | `bool` | `true` | no |
+| [s3\_object\_ownership](#input\_s3\_object\_ownership) | Specifies the S3 object ownership control. Valid values are `ObjectWriter` and `BucketOwnerPreferred` | `string` | `"ObjectWriter"` | no |
| [s3\_replica\_bucket\_arn](#input\_s3\_replica\_bucket\_arn) | A single S3 bucket ARN to use for all replication rules.
Note: The destination bucket can be specified in the replication rule itself
(which allows for multiple destinations), in which case it will take precedence over this variable. | `string` | `""` | no |
| [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 |
| [s3\_replication\_rules](#input\_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 |
diff --git a/main.tf b/main.tf
index 3a961dd4..34d7acd1 100644
--- a/main.tf
+++ b/main.tf
@@ -388,3 +388,22 @@ resource "aws_s3_bucket_public_access_block" "default" {
ignore_public_acls = var.ignore_public_acls
restrict_public_buckets = var.restrict_public_buckets
}
+
+# Per https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html
+resource "aws_s3_bucket_ownership_controls" "default" {
+ count = local.enabled ? 1 : 0
+ bucket = join("", aws_s3_bucket.default.*.id)
+
+ rule {
+ object_ownership = var.s3_object_ownership
+ }
+ depends_on = [time_sleep.wait_for_aws_s3_bucket_settings]
+}
+
+# Workaround S3 eventual consistency for settings objects
+resource "time_sleep" "wait_for_aws_s3_bucket_settings" {
+ count = local.enabled ? 1 : 0
+ depends_on = [aws_s3_bucket_public_access_block.default, aws_s3_bucket_policy.default]
+ create_duration = "30s"
+ destroy_duration = "30s"
+}
diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go
index 99fb3768..4388418e 100644
--- a/test/src/examples_complete_test.go
+++ b/test/src/examples_complete_test.go
@@ -216,7 +216,6 @@ func TestExamplesCompleteWithReplication(t *testing.T) {
// Verify we're getting back the outputs we expect
assert.NotEmptyf(t, s3ReplicationRoleArn, "If replication is enabled, we should get a Replication Role ARN.")
-
}
func TestExamplesCompleteWithPrivilegedPrincipals(t *testing.T) {
@@ -373,5 +372,4 @@ func TestExamplesCompleteDisabled(t *testing.T) {
// Verify we're getting back the outputs we expect
assert.Empty(t, s3ReplicationBucketId, "When disabled, module should have no outputs.")
-
-}
+}
\ No newline at end of file
diff --git a/variables.tf b/variables.tf
index b93c2c3c..46390978 100644
--- a/variables.tf
+++ b/variables.tf
@@ -280,3 +280,9 @@ variable "transfer_acceleration_enabled" {
default = false
description = "Set this to true to enable S3 Transfer Acceleration for the bucket."
}
+
+variable "s3_object_ownership" {
+ type = string
+ default = "ObjectWriter"
+ description = "Specifies the S3 object ownership control. Valid values are `ObjectWriter` and `BucketOwnerPreferred`"
+}
diff --git a/versions.tf b/versions.tf
index 9d8788f2..ac1455dc 100644
--- a/versions.tf
+++ b/versions.tf
@@ -4,7 +4,11 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 2.33"
+ version = ">= 3.0"
+ }
+ time = {
+ source = "hashicorp/time"
+ version = ">= 0.7"
}
}
}