Skip to content
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ module "s3_bucket" {
| <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 |
| <a name="input_s3_replication_permissions_boundary_arn"></a> [s3\_replication\_permissions\_boundary\_arn](#input\_s3\_replication\_permissions\_boundary\_arn) | Permissions boundary ARN for the created IAM replication role. | `string` | `null` | no |
| <a name="input_s3_replication_iam_role_name"></a> [s3\_replication\_iam\_role\_name](#input\_s3\_replication\_iam\_role\_name) | Name of the created IAM replication role. | `string` | `null` | no |
| <a name="input_s3_replication_rules"></a> [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. | <pre>list(object({<br/> id = optional(string)<br/> priority = optional(number)<br/> prefix = optional(string)<br/> status = optional(string, "Enabled")<br/> # delete_marker_replication { status } had been flattened for convenience<br/> delete_marker_replication_status = optional(string, "Disabled")<br/> # Add the configuration as it appears in the resource, for consistency<br/> # this nested version takes precedence if both are provided.<br/> delete_marker_replication = optional(object({<br/> status = string<br/> }))<br/><br/> # destination_bucket is specified here rather than inside the destination object because before optional<br/> # attributes, it made it easier to work with the Terraform type system and create a list of consistent type.<br/> # It is preserved for backward compatibility, but the nested version takes priority if both are provided.<br/> destination_bucket = optional(string) # destination bucket ARN, overrides s3_replica_bucket_arn<br/><br/> destination = object({<br/> bucket = optional(string) # destination bucket ARN, overrides s3_replica_bucket_arn<br/> storage_class = optional(string, "STANDARD")<br/> # replica_kms_key_id at this level is for backward compatibility, and is overridden by the one in `encryption_configuration`<br/> replica_kms_key_id = optional(string, "")<br/> encryption_configuration = optional(object({<br/> replica_kms_key_id = string<br/> }))<br/> access_control_translation = optional(object({<br/> owner = string<br/> }))<br/> # account_id is for backward compatibility, overridden by account<br/> account_id = optional(string)<br/> account = optional(string)<br/> # For convenience, specifying either metrics or replication_time enables both<br/> metrics = optional(object({<br/> event_threshold = optional(object({<br/> minutes = optional(number, 15) # Currently 15 is the only valid number<br/> }), { minutes = 15 })<br/> status = optional(string, "Enabled")<br/> }), { status = "Disabled" })<br/> # To preserve backward compatibility, Replication Time Control (RTC) is automatically enabled<br/> # when metrics are enabled. To enable metrics without RTC, you must explicitly configure<br/> # replication_time.status = "Disabled".<br/> replication_time = optional(object({<br/> time = optional(object({<br/> minutes = optional(number, 15) # Currently 15 is the only valid number<br/> }), { minutes = 15 })<br/> status = optional(string)<br/> }))<br/> })<br/><br/> source_selection_criteria = optional(object({<br/> replica_modifications = optional(object({<br/> status = string # Either Enabled or Disabled<br/> }))<br/> sse_kms_encrypted_objects = optional(object({<br/> status = optional(string)<br/> }))<br/> }))<br/> # filter.prefix overrides top level prefix<br/> filter = optional(object({<br/> prefix = optional(string)<br/> tags = optional(map(string), {})<br/> }))<br/> }))</pre> | `null` | no |
| <a name="input_s3_replication_source_roles"></a> [s3\_replication\_source\_roles](#input\_s3\_replication\_source\_roles) | Cross-account IAM Role ARNs that will be allowed to perform S3 replication to this bucket (for replication within the same AWS account, it's not necessary to adjust the bucket policy). | `list(string)` | `[]` | no |
| <a name="input_s3_request_payment_configuration"></a> [s3\_request\_payment\_configuration](#input\_s3\_request\_payment\_configuration) | S3 request payment configuration | <pre>object({<br/> enabled = bool<br/> expected_bucket_owner = optional(string)<br/> payer = string<br/> })</pre> | <pre>{<br/> "enabled": false,<br/> "payer": "BucketOwner"<br/>}</pre> | no |
Expand Down
1 change: 1 addition & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ locals {

object_lock_enabled = local.enabled && var.object_lock_configuration != null
replication_enabled = local.enabled && var.s3_replication_enabled
s3_replication_iam_role_name = coalesce(var.s3_replication_iam_role_name, format("%s-replication", local.bucket_name))
versioning_enabled = local.enabled && var.versioning_enabled
transfer_acceleration_enabled = local.enabled && var.transfer_acceleration_enabled

Expand Down
18 changes: 17 additions & 1 deletion replication.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
resource "aws_iam_role" "replication" {
count = local.replication_enabled ? 1 : 0

name = format("%s-replication", local.bucket_name)
name = local.s3_replication_iam_role_name
assume_role_policy = data.aws_iam_policy_document.replication_sts[0].json
permissions_boundary = var.s3_replication_permissions_boundary_arn

Expand Down Expand Up @@ -67,6 +67,22 @@ data "aws_iam_policy_document" "replication" {
[for rule in local.s3_replication_rules : "${rule.destination.bucket}/*" if try(length(rule.destination.bucket), 0) > 0],
))
}

statement {
sid = "AllowKMSForReplication"
effect = "Allow"
actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
]

resources = toset(concat(
[for rule in local.s3_replication_rules : "${rule.encryption_configuration.replica_kms_key_id}" if try(length(rule.encryption_configuration.replica_kms_key_id), 0) > 0],
))
}
}

resource "aws_iam_role_policy_attachment" "replication" {
Expand Down
6 changes: 6 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,12 @@ variable "s3_replication_permissions_boundary_arn" {
description = "Permissions boundary ARN for the created IAM replication role."
}

variable "s3_replication_iam_role_name" {
type = string
default = null
description = "Name of the created IAM replication role."
}

variable "bucket_name" {
type = string
default = null
Expand Down