From a4ee0cc657113f86bb928ceb32a8efa205c1b087 Mon Sep 17 00:00:00 2001 From: KyleKotowick Date: Thu, 2 Jun 2022 19:34:16 -0400 Subject: [PATCH] Initial code --- LICENSE | 21 +++ README.md | 3 + main.tf | 12 ++ outputs.tf | 179 +++++++++++++++++++++++++ s3.tf | 92 +++++++++++++ validation.tf | 6 + variables.tf | 360 ++++++++++++++++++++++++++++++++++++++++++++++++++ versions.tf | 10 ++ 8 files changed, 683 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 main.tf create mode 100644 outputs.tf create mode 100644 s3.tf create mode 100644 validation.tf create mode 100644 variables.tf create mode 100644 versions.tf diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..dbe2a5e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Invicton Labs (https://invictonlabs.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..dd6a574 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Terraform AWS Replicated Secure S3 Buckets + +This module creates two [Invicton-Labs/secure-s3-bucket/aws](https://registry.terraform.io/modules/Invicton-Labs/secure-s3-bucket/aws/0.2.2) modules and a [Invicton-Labs/secure-s3-bucket-replication/aws](https://registry.terraform.io/modules/Invicton-Labs/secure-s3-bucket-replication/aws/0.1.0) module to replicate between them. diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..97f0abf --- /dev/null +++ b/main.tf @@ -0,0 +1,12 @@ +data "aws_caller_identity" "a" { + provider = aws.a +} +data "aws_caller_identity" "b" { + provider = aws.b +} +data "aws_region" "a" { + provider = aws.a +} +data "aws_region" "b" { + provider = aws.b +} diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..2faeb40 --- /dev/null +++ b/outputs.tf @@ -0,0 +1,179 @@ +//================================================== +// Outputs that match the input variables +//================================================== +output "name_a" { + description = "The value of the `name_a` input variable." + value = var.name_a +} +output "name_b" { + description = "The value of the `name_b` input variable" + value = var.name_b +} +output "mfa_delete_enabled_a" { + description = "The value of the `mfa_delete_enabled_a` input variable, or the default value if the input was `null`." + value = local.mfa_delete_enabled_a +} +output "mfa_delete_enabled_b" { + description = "The value of the `mfa_delete_enabled_b` input variable, or the default value if the input was `null`." + value = local.mfa_delete_enabled_b +} +output "bucket_policy_json_documents_a" { + description = "The value of the `bucket_policy_json_documents_a` input variable, or the default value if the input was `null`." + value = local.bucket_policy_json_documents_a +} +output "bucket_policy_json_documents_b" { + description = "The value of the `bucket_policy_json_documents_b` input variable, or the default value if the input was `null`." + value = local.bucket_policy_json_documents_b +} +output "bucket_policy_json_documents_both" { + description = "The value of the `bucket_policy_json_documents_both` input variable, or the default value if the input was `null`." + value = local.bucket_policy_json_documents_both +} +output "kms_key_arn_a" { + description = "The value of the `kms_key_arn_a` input variable, or the default value if the input was `null`." + value = var.kms_key_arn_a +} +output "kms_key_arn_b" { + description = "The value of the `kms_key_arn_b` input variable, or the default value if the input was `null`." + value = var.kms_key_arn_b +} +output "create_new_kms_key_a" { + description = "The value of the `create_new_kms_key_a` input variable, or the default value if the input was `null`." + value = local.create_new_kms_key_a +} +output "create_new_kms_key_b" { + description = "The value of the `create_new_kms_key_b` input variable, or the default value if the input was `null`." + value = local.create_new_kms_key_b +} +output "create_replica_kms_key_a" { + description = "The value of the `create_replica_kms_key_a` input variable, or the default value if the input was `null`." + value = local.create_replica_kms_key_a +} +output "create_replica_kms_key_b" { + description = "The value of the `create_replica_kms_key_b` input variable, or the default value if the input was `null`." + value = local.create_replica_kms_key_b +} +output "kms_key_policy_json_documents_a" { + description = "The value of the `kms_key_policy_json_documents_a` input variable, or the default value if the input was `null`." + value = local.kms_key_policy_json_documents_a +} +output "kms_key_policy_json_documents_b" { + description = "The value of the `kms_key_policy_json_documents_b` input variable, or the default value if the input was `null`." + value = local.kms_key_policy_json_documents_b +} +output "kms_key_policy_json_documents_both" { + description = "The value of the `kms_key_policy_json_documents_both` input variable, or the default value if the input was `null`." + value = local.kms_key_policy_json_documents_both +} +output "enable_transfer_acceleration_a" { + description = "The value of the `enable_transfer_acceleration_a` input variable, or the default value if the input was `null`." + value = local.enable_transfer_acceleration_a +} +output "enable_transfer_acceleration_b" { + description = "The value of the `enable_transfer_acceleration_b` input variable, or the default value if the input was `null`." + value = local.enable_transfer_acceleration_b +} +output "block_public_acls_a" { + description = "The value of the `block_public_acls_a` input variable, or the default value if the input was `null`." + value = local.block_public_acls_a +} +output "block_public_acls_b" { + description = "The value of the `block_public_acls_b` input variable, or the default value if the input was `null`." + value = local.block_public_acls_b +} +output "block_public_policy_a" { + description = "The value of the `block_public_policy_a` input variable, or the default value if the input was `null`." + value = local.block_public_policy_a +} +output "block_public_policy_b" { + description = "The value of the `block_public_policy_b` input variable, or the default value if the input was `null`." + value = local.block_public_policy_b +} +output "ignore_public_acls_a" { + description = "The value of the `ignore_public_acls_a` input variable, or the default value if the input was `null`." + value = local.ignore_public_acls_a +} +output "ignore_public_acls_b" { + description = "The value of the `ignore_public_acls_b` input variable, or the default value if the input was `null`." + value = local.ignore_public_acls_b +} +output "restrict_public_buckets_a" { + description = "The value of the `restrict_public_buckets_a` input variable, or the default value if the input was `null`." + value = local.restrict_public_buckets_a +} +output "restrict_public_buckets_b" { + description = "The value of the `restrict_public_buckets_b` input variable, or the default value if the input was `null`." + value = local.restrict_public_buckets_b +} +output "object_ownership_a" { + description = "The value of the `object_ownership_a` input variable, or the default value if the input was `null`." + value = local.object_ownership_a +} +output "object_ownership_b" { + description = "The value of the `object_ownership_b` input variable, or the default value if the input was `null`." + value = local.object_ownership_b +} +output "append_region_suffix_a" { + description = "The value of the `append_region_suffix_a` input variable, or the default value if the input was `null`." + value = local.append_region_suffix_a +} +output "append_region_suffix_b" { + description = "The value of the `append_region_suffix_b` input variable, or the default value if the input was `null`." + value = local.append_region_suffix_b +} +output "object_lock_enabled_a" { + description = "The value of the `object_lock_enabled_a` input variable, or the default value if the input was `null`." + value = local.object_lock_enabled_a +} +output "object_lock_enabled_b" { + description = "The value of the `object_lock_enabled_b` input variable, or the default value if the input was `null`." + value = local.object_lock_enabled_b +} +output "force_destroy_a" { + description = "The value of the `force_destroy_a` input variable, or the default value if the input was `null`." + value = local.force_destroy_a +} +output "force_destroy_b" { + description = "The value of the `force_destroy_b` input variable, or the default value if the input was `null`." + value = local.force_destroy_b +} +output "force_allow_cloudtrail_digest_a" { + description = "The value of the `force_allow_cloudtrail_digest_a` input variable, or the default value if the input was `null`." + value = local.force_allow_cloudtrail_digest_a +} +output "force_allow_cloudtrail_digest_b" { + description = "The value of the `force_allow_cloudtrail_digest_b` input variable, or the default value if the input was `null`." + value = local.force_allow_cloudtrail_digest_b +} +output "replicate_a_to_b" { + description = "The value of the `replicate_a_to_b` input variable, or the default value if the input was `null`." + value = var.replicate_a_to_b +} +output "replicate_b_to_a" { + description = "The value of the `replicate_b_to_a` input variable, or the default value if the input was `null`." + value = var.replicate_b_to_a +} +output "a_to_b_rules" { + description = "The value of the `a_to_b_rules` input variable, or the default value if the input was `null`." + value = local.a_to_b_rules +} +output "b_to_a_rules" { + description = "The value of the `b_to_a_rules` input variable, or the default value if the input was `null`." + value = local.b_to_a_rules +} + +//================================================== +// Outputs generated by this module +//================================================== +output "bucket_a" { + description = "The Invicton-Labs/secure-s3-bucket/aws module that was created for bucket A." + value = module.bucket_a +} +output "bucket_b" { + description = "The Invicton-Labs/secure-s3-bucket/aws module that was created for bucket B." + value = module.bucket_b +} +output "replication" { + description = "The Invicton-Labs/secure-s3-bucket-replication/aws module that was created for the bucket replication." + value = module.replication +} diff --git a/s3.tf b/s3.tf new file mode 100644 index 0000000..238ba63 --- /dev/null +++ b/s3.tf @@ -0,0 +1,92 @@ +module "bucket_a" { + source = "Invicton-Labs/secure-s3-bucket/aws" + version = "~>0.2.2" + providers = { + aws = aws.a + } + depends_on = [ + module.assert_same_account + ] + // Versioning always required for replication + versioned = true + name = var.name_a + mfa_delete_enabled = local.mfa_delete_enabled_a + bucket_policy_json_documents = concat(local.bucket_policy_json_documents_a, local.bucket_policy_json_documents_both) + kms_key_arn = var.kms_key_arn_a + create_new_kms_key = local.create_new_kms_key_a + create_replica_kms_key = local.create_replica_kms_key_a + kms_key_policy_json_documents = concat(local.kms_key_policy_json_documents_a, local.kms_key_policy_json_documents_both) + enable_transfer_acceleration = local.enable_transfer_acceleration_a + block_public_acls = local.block_public_acls_a + block_public_policy = local.block_public_policy_a + ignore_public_acls = local.ignore_public_acls_a + restrict_public_buckets = local.restrict_public_buckets_a + object_ownership = local.object_ownership_a + append_region_suffix = local.append_region_suffix_a + object_lock_enabled = local.object_lock_enabled_a + force_destroy = local.force_destroy_a + force_allow_cloudtrail_digest = local.force_allow_cloudtrail_digest_a +} + +locals { + // If a specific key was provided for bucket B, use that. + // Otherwise, use the key that was used for bucket A as the base key + b_kms_key_arn = var.kms_key_arn_b != null ? var.kms_key_arn_b : module.bucket_a.kms_key_arn + // If a specific key was provided for bucket B, or we're supposed to create a new key for bucket B, + // use the input `create_replica_kms_key_b` variable as-is. + b_create_replica_key = var.kms_key_arn_b != null || local.create_new_kms_key_b ? local.create_replica_kms_key_b : ( + // Otherwise, check if a key was used for Bucket A (one provided, or new one created) + var.kms_key_arn_a != null || local.create_new_kms_key_a ? ( + // If a key was used for bucket A, only create a replica for bucket B if B is in a different region + data.aws_region.a.name != data.aws_region.b.name + ) : ( + // No key was used for bucket A, so we don't need a replica key for bucket B + false + ) + ) +} + +module "bucket_b" { + source = "Invicton-Labs/secure-s3-bucket/aws" + version = "~>0.2.2" + providers = { + aws = aws.b + } + depends_on = [ + module.assert_same_account + ] + // Versioning always required for replication + versioned = true + name = var.name_b + mfa_delete_enabled = local.mfa_delete_enabled_b + bucket_policy_json_documents = concat(local.bucket_policy_json_documents_b, local.bucket_policy_json_documents_both) + kms_key_arn = local.b_kms_key_arn + create_new_kms_key = local.create_new_kms_key_b + create_replica_kms_key = local.b_create_replica_key + kms_key_policy_json_documents = concat(local.kms_key_policy_json_documents_b, local.kms_key_policy_json_documents_both) + enable_transfer_acceleration = local.enable_transfer_acceleration_b + block_public_acls = local.block_public_acls_b + block_public_policy = local.block_public_policy_b + ignore_public_acls = local.ignore_public_acls_b + restrict_public_buckets = local.restrict_public_buckets_b + object_ownership = local.object_ownership_b + append_region_suffix = local.append_region_suffix_b + object_lock_enabled = local.object_lock_enabled_b + force_destroy = local.force_destroy_b + force_allow_cloudtrail_digest = local.force_allow_cloudtrail_digest_b +} + +module "replication" { + source = "Invicton-Labs/secure-s3-bucket-replication/aws" + version = "~>0.1.0" + providers = { + aws.a = aws.a + aws.b = aws.b + } + bucket_a_module = module.bucket_a + bucket_b_module = module.bucket_b + replicate_a_to_b = var.replicate_a_to_b + replicate_b_to_a = var.replicate_b_to_a + a_to_b_rules = local.a_to_b_rules + b_to_a_rules = local.b_to_a_rules +} diff --git a/validation.tf b/validation.tf new file mode 100644 index 0000000..9690f1c --- /dev/null +++ b/validation.tf @@ -0,0 +1,6 @@ +module "assert_same_account" { + source = "Invicton-Labs/assertion/null" + version = "~>0.2.1" + condition = data.aws_caller_identity.a.account_id == data.aws_caller_identity.b.account_id + error_message = "Replication may only be configured with this module for two buckets in the same AWS account." +} diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..5d72932 --- /dev/null +++ b/variables.tf @@ -0,0 +1,360 @@ +variable "name_a" { + description = "The name to use for bucket A." + type = string + validation { + condition = var.name_a != null + error_message = "`name_a` may not be `null`." + } +} + +variable "name_b" { + description = "The name to use for bucket B." + type = string + validation { + condition = var.name_b != null + error_message = "`name_b` may not be `null`." + } +} + +variable "mfa_delete_enabled_a" { + description = "Whether MFA Delete should be enabled for the bucket A." + type = bool + default = false +} +locals { + mfa_delete_enabled_a = var.mfa_delete_enabled_a != null ? var.mfa_delete_enabled_a : false +} +variable "mfa_delete_enabled_b" { + description = "Whether MFA Delete should be enabled for the bucket B. If not provided, will default to the value of `mfa_delete_enabled_a`." + type = bool + default = null +} +locals { + mfa_delete_enabled_b = var.mfa_delete_enabled_b != null ? var.mfa_delete_enabled_b : var.mfa_delete_enabled_a +} + +variable "bucket_policy_json_documents_a" { + description = "A list of JSON-encoded policy documents to apply to bucket A. The placeholder \"{BUCKET_ARN}\" can be used to reference the ARN of the bucket the policy is being applied to." + type = list(string) + default = [] +} +locals { + bucket_policy_json_documents_a = var.bucket_policy_json_documents_a != null ? var.bucket_policy_json_documents_a : [] +} + +variable "bucket_policy_json_documents_b" { + description = "A list of JSON-encoded policy documents to apply to bucket B. The placeholder \"{BUCKET_ARN}\" can be used to reference the ARN of the bucket the policy is being applied to." + type = list(string) + default = [] +} +locals { + bucket_policy_json_documents_b = var.bucket_policy_json_documents_b != null ? var.bucket_policy_json_documents_b : [] +} + +variable "bucket_policy_json_documents_both" { + description = "A list of JSON-encoded policy documents to apply to both buckets. The placeholder \"{BUCKET_ARN}\" can be used to reference the ARN of the bucket the policy is being applied to." + type = list(string) + default = [] +} +locals { + bucket_policy_json_documents_both = var.bucket_policy_json_documents_both != null ? var.bucket_policy_json_documents_both : [] +} + +variable "kms_key_arn_a" { + description = "The ARN of the KMS key to use for bucket A. If not provided, AES256 encryption will be enforced instead, unless `create_new_kms_key_a` is set to `true`." + type = string + default = null +} + +variable "kms_key_arn_b" { + description = "The ARN of the KMS key to use for bucket B. If not provided, AES256 encryption will be enforced instead, unless `create_new_kms_key_b` is set to `true`." + type = string + default = null +} + +variable "create_new_kms_key_a" { + description = "Whether to create a new KMS key for use with bucket A. If `kms_key_arn_a` is not provided (null), a new key will be created. If `kms_key_arn_a` is provided, a replica of that key will be created." + type = bool + default = false +} +locals { + create_new_kms_key_a = var.create_new_kms_key_a != null ? var.create_new_kms_key_a : false +} + +variable "create_new_kms_key_b" { + description = "Whether to create a new KMS key for use with bucket B. If `kms_key_arn_b` is not provided (null), a new key will be created. If `kms_key_arn_b` is provided, a replica of that key will be created." + type = bool + default = false +} +locals { + create_new_kms_key_b = var.create_new_kms_key_b != null ? var.create_new_kms_key_b : false +} + +variable "create_replica_kms_key_a" { + description = "Whether to create a replica of the `kms_key_arn_a` key for use with bucket A, if `kms_key_arn_a` was provided." + type = bool + default = false +} +locals { + create_replica_kms_key_a = var.create_replica_kms_key_a != null ? var.create_replica_kms_key_a : false +} +variable "create_replica_kms_key_b" { + description = "Whether to create a replica of the `kms_key_arn_b` key for use with bucket B, if `kms_key_arn_b` was provided." + type = bool + default = false +} +locals { + create_replica_kms_key_b = var.create_replica_kms_key_b != null ? var.create_replica_kms_key_b : false +} + +variable "kms_key_policy_json_documents_a" { + description = "A list of JSON-encoded policy documents to apply to the KMS key created for bucket A, if one should be created." + type = list(string) + default = [] +} +locals { + kms_key_policy_json_documents_a = var.kms_key_policy_json_documents_a != null ? var.kms_key_policy_json_documents_a : [] +} + +variable "kms_key_policy_json_documents_b" { + description = "A list of JSON-encoded policy documents to apply to the KMS key created for bucket B, if one should be created." + type = list(string) + default = [] +} +locals { + kms_key_policy_json_documents_b = var.kms_key_policy_json_documents_b != null ? var.kms_key_policy_json_documents_b : [] +} + +variable "kms_key_policy_json_documents_both" { + description = "A list of JSON-encoded policy documents to apply to the KMS keys created for each bucket, if a KMS key was created." + type = list(string) + default = [] +} +locals { + kms_key_policy_json_documents_both = var.kms_key_policy_json_documents_both != null ? var.kms_key_policy_json_documents_both : [] +} + +variable "enable_transfer_acceleration_a" { + description = "Whether to enable transfer acceleration for bucket A." + type = bool + default = false +} +locals { + enable_transfer_acceleration_a = var.enable_transfer_acceleration_a != null ? var.enable_transfer_acceleration_a : false +} +variable "enable_transfer_acceleration_b" { + description = "Whether to enable transfer acceleration for bucket B. If not provided, will default to the value of `enable_transfer_acceleration_a`." + type = bool + default = null +} +locals { + enable_transfer_acceleration_b = var.enable_transfer_acceleration_b != null ? var.enable_transfer_acceleration_b : local.enable_transfer_acceleration_a +} + +variable "block_public_acls_a" { + description = "The `block_public_acls` value of an `aws_s3_bucket_public_access_block` resource that is applied to bucket A." + type = bool + default = true +} +locals { + block_public_acls_a = var.block_public_acls_a != null ? var.block_public_acls_a : true +} +variable "block_public_acls_b" { + description = "The `block_public_acls` value of an `aws_s3_bucket_public_access_block` resource that is applied to bucket B. If not provided, will default to the value of `enable_transfer_acceleration_a`." + type = bool + default = null +} +locals { + block_public_acls_b = var.block_public_acls_b != null ? var.block_public_acls_b : local.block_public_acls_a +} + +variable "block_public_policy_a" { + description = "The `block_public_policy` value of an `aws_s3_bucket_public_access_block` resource that is applied to bucket A." + type = bool + default = true +} +locals { + block_public_policy_a = var.block_public_policy_a != null ? var.block_public_policy_a : true +} +variable "block_public_policy_b" { + description = "The `block_public_policy` value of an `aws_s3_bucket_public_access_block` resource that is applied to bucket B. If not provided, will default to the value of `block_public_policy_a`." + type = bool + default = null +} +locals { + block_public_policy_b = var.block_public_policy_b != null ? var.block_public_policy_b : local.block_public_policy_a +} + +variable "ignore_public_acls_a" { + description = "The `ignore_public_acls` value of an `aws_s3_bucket_public_access_block` resource that is applied to bucket A." + type = bool + default = true +} +locals { + ignore_public_acls_a = var.ignore_public_acls_a != null ? var.ignore_public_acls_a : true +} +variable "ignore_public_acls_b" { + description = "The `ignore_public_acls` value of an `aws_s3_bucket_public_access_block` resource that is applied to bucket B. If not provided, will default to the value of `block_public_policy_a`." + type = bool + default = null +} +locals { + ignore_public_acls_b = var.ignore_public_acls_b != null ? var.ignore_public_acls_b : local.ignore_public_acls_a +} + +variable "restrict_public_buckets_a" { + description = "The `restrict_public_buckets` value of an `aws_s3_bucket_public_access_block` resource that is applied to bucket A." + type = bool + default = true +} +locals { + restrict_public_buckets_a = var.restrict_public_buckets_a != null ? var.restrict_public_buckets_a : true +} +variable "restrict_public_buckets_b" { + description = "The `restrict_public_buckets` value of an `aws_s3_bucket_public_access_block` resource that is applied to bucket B. If not provided, will default to the value of `restrict_public_buckets_a`." + type = bool + default = null +} +locals { + restrict_public_buckets_b = var.restrict_public_buckets_b != null ? var.restrict_public_buckets_b : local.restrict_public_buckets_a +} + +variable "object_ownership_a" { + description = "The `rule.object_ownership` value of an `aws_s3_bucket_ownership_controls` resource that is applied to bucket A." + type = string + default = "BucketOwnerEnforced" +} +locals { + object_ownership_a = var.object_ownership_a != null ? var.object_ownership_a : "BucketOwnerEnforced" +} +variable "object_ownership_b" { + description = "The `rule.object_ownership` value of an `aws_s3_bucket_ownership_controls` resource that is applied to bucket B. If not provided, will default to the value of `object_ownership_a`." + type = string + default = null +} +locals { + object_ownership_b = var.object_ownership_b != null ? var.object_ownership_b : local.object_ownership_a +} + +variable "append_region_suffix_a" { + description = "If `true`, a suffix in the form of `-{region_name}` will be appended to the name of bucket A. This is convenient if you're creating buckets in multiple regions and don't want to manually specify the region name in each one for uniqueness." + type = bool + default = false +} +locals { + append_region_suffix_a = var.append_region_suffix_a != null ? var.append_region_suffix_a : false +} +variable "append_region_suffix_b" { + description = "If `true`, a suffix in the form of `-{region_name}` will be appended to the name of bucket B. This is convenient if you're creating buckets in multiple regions and don't want to manually specify the region name in each one for uniqueness. If not provided, will default to the value of `append_region_suffix_a`." + type = bool + default = null +} +locals { + append_region_suffix_b = var.append_region_suffix_b != null ? var.append_region_suffix_b : local.append_region_suffix_a +} + +variable "object_lock_enabled_a" { + description = "Whether to enable Object Lock for bucket A." + type = bool + default = false +} +locals { + object_lock_enabled_a = var.object_lock_enabled_a != null ? var.object_lock_enabled_a : false +} +variable "object_lock_enabled_b" { + description = "Whether to enable Object Lock for bucket B. If not provided, will default to the value of `object_lock_enabled_a`." + type = bool + default = false +} +locals { + object_lock_enabled_b = var.object_lock_enabled_b != null ? var.object_lock_enabled_b : local.object_lock_enabled_a +} + +variable "force_destroy_a" { + description = "Whether all objects (including any locked objects) should be deleted from bucket A so that the bucket can be destroyed without error." + type = bool + default = false +} +locals { + force_destroy_a = var.force_destroy_a != null ? var.force_destroy_a : false +} +variable "force_destroy_b" { + description = "Whether all objects (including any locked objects) should be deleted from bucket B so that the bucket can be destroyed without error. If not provided, will default to the value of `force_destroy_a`." + type = bool + default = null +} +locals { + force_destroy_b = var.force_destroy_b != null ? var.force_destroy_b : local.force_destroy_a +} + +variable "force_allow_cloudtrail_digest_a" { + description = "Whether to allow AES256 (AWS-managed key) encryption for paths checked by CloudTrail digest writers for bucket A. Even when a bucket and a CloudTrail are both set to use KMS encryption, digests are still written using AWS-managed key AES256 encryption (). This variable only has an effect when the `kms_key_id` variable is provided and not `null`." + type = bool + default = false +} +locals { + force_allow_cloudtrail_digest_a = var.force_allow_cloudtrail_digest_a != null ? var.force_allow_cloudtrail_digest_a : false +} +variable "force_allow_cloudtrail_digest_b" { + description = "Whether to allow AES256 (AWS-managed key) encryption for paths checked by CloudTrail digest writers for bucket B. Even when a bucket and a CloudTrail are both set to use KMS encryption, digests are still written using AWS-managed key AES256 encryption (). This variable only has an effect when the `kms_key_id` variable is provided and not `null`. If not provided, will default to the value of `force_allow_cloudtrail_digest_a`." + type = bool + default = null +} +locals { + force_allow_cloudtrail_digest_b = var.force_allow_cloudtrail_digest_b != null ? var.force_allow_cloudtrail_digest_b : local.force_allow_cloudtrail_digest_a +} + +variable "replicate_a_to_b" { + description = "Whether to replicate objects from bucket A to bucket B." + type = bool + validation { + condition = var.replicate_a_to_b != null + error_message = "`replicate_a_to_b` may not be `null`." + } +} + +variable "replicate_b_to_a" { + description = "Whether to replicate objects from bucket B to bucket A." + type = bool + validation { + condition = var.replicate_b_to_a != null + error_message = "`replicate_b_to_a` may not be `null`." + } +} + +variable "a_to_b_rules" { + description = "A list of rules for replicating objects from bucket A to bucket B, ordered by descending priority. If none are provided, it will default to replicating everything, including delete markers and replica modifications." + type = list(object({ + id = string + delete_marker_replication = bool + existing_object_replication = bool + replica_modifications = bool + prefix = string + tags = map(string) + replication_time = number + event_threshold = number + storage_class = string + })) + default = [] +} + +variable "b_to_a_rules" { + description = "A list of rules for replicating objects from bucket B to bucket A, ordered by descending priority. If none are provided, it will default to replicating everything, including delete markers and replica modifications." + type = list(object({ + id = string + delete_marker_replication = bool + existing_object_replication = bool + replica_modifications = bool + prefix = string + tags = map(string) + replication_time = number + event_threshold = number + storage_class = string + })) + default = [] +} + +locals { + a_to_b_rules = var.a_to_b_rules != null ? var.a_to_b_rules : [] + b_to_a_rules = var.b_to_a_rules != null ? var.b_to_a_rules : [] +} diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..e37e26f --- /dev/null +++ b/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 1.2" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + configuration_aliases = [aws.a, aws.b] + } + } +}