From b97c32f9720a3d81a8d6313e1fcac778cc0be1c4 Mon Sep 17 00:00:00 2001 From: kmobl Date: Wed, 16 Aug 2023 11:16:20 -0500 Subject: [PATCH 01/16] initial commit --- main.tf | 510 +++++++++++++++++++++++++++++++++++++++++++++++++++ outputs.tf | 17 ++ variables.tf | 414 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 941 insertions(+) create mode 100644 main.tf create mode 100644 outputs.tf create mode 100644 variables.tf diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..c4e9f4d --- /dev/null +++ b/main.tf @@ -0,0 +1,510 @@ +##---------------------------------------------------------------------------------- +## Terraform resource to create S3 bucket with different combination type specific features. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket" "s3_default" { + count = var.create_bucket == true ? 1 : 0 + + bucket = var.name + force_destroy = var.force_destroy + tags = var.tags + + dynamic "object_lock_configuration" { + for_each = var.object_lock_configuration != null ? [1] : [] + + content { + object_lock_enabled = "Enabled" + } + } +} + +##---------------------------------------------------------------------------------- +## Terraform resource which creates policy for S3 bucket on AWS. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_policy" "s3_default" { + count = var.bucket_policy == true ? 1 : 0 + bucket = join("", aws_s3_bucket.s3_default.*.id) + policy = var.aws_iam_policy_document +} + +##---------------------------------------------------------------------------------- +## Provides an S3 bucket accelerate configuration resource. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_accelerate_configuration" "example" { + count = var.create_bucket && var.acceleration_status == true ? 1 : 0 + + bucket = join("", aws_s3_bucket.s3_default.*.id) + status = "Enabled" +} + +##---------------------------------------------------------------------------------- +## Provides an S3 bucket request payment configuration resource. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_request_payment_configuration" "example" { + count = var.create_bucket && var.request_payer == true ? 1 : 0 + + bucket = join("", aws_s3_bucket.s3_default.*.id) + payer = "Requester" +} + +##---------------------------------------------------------------------------------- +## Provides a resource for controlling versioning on an S3 bucket. +## Deleting this resource will either suspend versioning on the associated S3 bucket or simply remove the resource from Terraform state if the associated S3 bucket is unversioned. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_versioning" "example" { + count = var.create_bucket && var.versioning == true ? 1 : 0 + + bucket = join("", aws_s3_bucket.s3_default.*.id) + versioning_configuration { + status = "Enabled" + } +} + +##---------------------------------------------------------------------------------- +## Provides an S3 bucket (server access) logging resource. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_logging" "example" { + count = var.create_bucket && var.logging == true ? 1 : 0 + bucket = join("", aws_s3_bucket.s3_default.*.id) + + target_bucket = var.target_bucket + target_prefix = var.target_prefix +} + +##---------------------------------------------------------------------------------- +## Provides a S3 bucket server-side encryption configuration resource. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_server_side_encryption_configuration" "example" { + count = var.create_bucket && var.enable_server_side_encryption == true ? 1 : 0 + bucket = join("", aws_s3_bucket.s3_default.*.id) + + rule { + apply_server_side_encryption_by_default { + sse_algorithm = var.enable_kms == true ? "aws:kms" : var.sse_algorithm + kms_master_key_id = var.kms_master_key_id + } + } +} + +##---------------------------------------------------------------------------------- +## Provides an S3 bucket Object Lock configuration resource. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_object_lock_configuration" "example" { + count = var.create_bucket && var.object_lock_configuration != null ? 1 : 0 + + bucket = join("", aws_s3_bucket.s3_default.*.id) + + object_lock_enabled = "Enabled" + + rule { + default_retention { + mode = var.object_lock_configuration.mode + days = var.object_lock_configuration.days + years = var.object_lock_configuration.years + } + } +} + +##---------------------------------------------------------------------------------- +## Provides an S3 bucket CORS configuration resource. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_cors_configuration" "example" { + count = var.create_bucket && var.cors_rule != null ? 1 : 0 + + bucket = join("", aws_s3_bucket.s3_default.*.id) + + dynamic "cors_rule" { + for_each = var.cors_rule == null ? [] : var.cors_rule + + content { + allowed_headers = cors_rule.value.allowed_headers + allowed_methods = cors_rule.value.allowed_methods + allowed_origins = cors_rule.value.allowed_origins + expose_headers = cors_rule.value.expose_headers + max_age_seconds = cors_rule.value.max_age_seconds + } + } +} + +##---------------------------------------------------------------------------------- +## Provides an S3 bucket website configuration resource. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_website_configuration" "example" { + count = var.create_bucket && var.website_config_enable == true ? 1 : 0 + + bucket = join("", aws_s3_bucket.s3_default.*.id) + + index_document { + suffix = "index.html" + } + + error_document { + key = "error.html" + } + + routing_rule { + condition { + key_prefix_equals = "docs/" + } + redirect { + replace_key_prefix_with = "documents/" + } + } +} + +locals { + acl_grants = var.grants == null ? var.acl_grants : flatten( + [ + for g in var.grants : [ + for p in g.permissions : { + id = g.id + type = g.type + permission = p + uri = g.uri + } + ] + ]) +} + +##---------------------------------------------------------------------------------- +## Provides an S3 bucket ACL resource. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_acl" "default" { + + count = var.create_bucket ? var.grants != null ? var.acl != null ? 1 : 0 : 0 : 0 + bucket = join("", aws_s3_bucket.s3_default.*.id) + + + acl = try(length(local.acl_grants), 0) == 0 ? var.acl : null + + dynamic "access_control_policy" { + for_each = try(length(local.acl_grants), 0) == 0 || try(length(var.acl), 0) > 0 ? [] : [1] + + content { + dynamic "grant" { + for_each = local.acl_grants + + content { + grantee { + id = grant.value.id + type = grant.value.type + uri = grant.value.uri + } + permission = grant.value.permission + } + } + + owner { + id = var.owner_id + } + } + } +} + +##---------------------------------------------------------------------------------- +## Provides an independent configuration resource for S3 bucket lifecycle configuration. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_lifecycle_configuration" "default" { + count = var.create_bucket && var.enable_lifecycle_configuration_rules == true ? 1 : 0 + bucket = join("", aws_s3_bucket.s3_default.*.id) + + dynamic "rule" { + for_each = var.lifecycle_configuration_rules + + content { + id = rule.value.id + status = rule.value.enabled == true ? "Enabled" : "Disabled" + + # Filter is always required due to https://github.com/hashicorp/terraform-provider-aws/issues/23299 + filter { + dynamic "and" { + for_each = (try(length(rule.value.prefix), 0) + try(length(rule.value.tags), 0)) > 0 ? [1] : [] + content { + prefix = rule.value.prefix == null ? "" : rule.value.prefix + tags = try(length(rule.value.tags), 0) > 0 ? rule.value.tags : {} + } + } + } + + dynamic "abort_incomplete_multipart_upload" { + for_each = try(tonumber(rule.value.abort_incomplete_multipart_upload_days), null) != null ? [1] : [] + content { + days_after_initiation = rule.value.abort_incomplete_multipart_upload_days + } + } + + dynamic "noncurrent_version_expiration" { + for_each = rule.value.enable_noncurrent_version_expiration ? [1] : [] + + content { + noncurrent_days = rule.value.noncurrent_version_expiration_days + } + } + + dynamic "noncurrent_version_transition" { + for_each = rule.value.enable_glacier_transition ? [1] : [] + + content { + noncurrent_days = rule.value.noncurrent_version_glacier_transition_days + storage_class = "GLACIER" + } + } + + dynamic "noncurrent_version_transition" { + for_each = rule.value.enable_deeparchive_transition ? [1] : [] + + content { + noncurrent_days = rule.value.noncurrent_version_deeparchive_transition_days + storage_class = "DEEP_ARCHIVE" + } + } + + dynamic "transition" { + for_each = rule.value.enable_glacier_transition ? [1] : [] + + content { + days = rule.value.glacier_transition_days + storage_class = "GLACIER" + } + } + + dynamic "transition" { + for_each = rule.value.enable_deeparchive_transition ? [1] : [] + + content { + days = rule.value.deeparchive_transition_days + storage_class = "DEEP_ARCHIVE" + } + } + + dynamic "transition" { + for_each = rule.value.enable_standard_ia_transition ? [1] : [] + + content { + days = rule.value.standard_transition_days + storage_class = "STANDARD_IA" + } + } + + dynamic "expiration" { + for_each = rule.value.enable_current_object_expiration ? [1] : [] + + content { + days = rule.value.expiration_days + } + } + } + } + + depends_on = [ + # versioning must be set before lifecycle configuration + aws_s3_bucket_versioning.example + ] +} + +##---------------------------------------------------------------------------------- +## Provides an independent configuration resource for S3 bucket replication configuration. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_replication_configuration" "this" { + count = var.create_bucket && length(keys(var.replication_configuration)) > 0 ? 1 : 0 + + bucket = aws_s3_bucket.s3_default[0].id + role = var.replication_configuration["role"] + + dynamic "rule" { + for_each = flatten(try([var.replication_configuration["rule"]], [var.replication_configuration["rules"]], [])) + + content { + id = try(rule.value.id, null) + priority = try(rule.value.priority, null) + prefix = try(rule.value.prefix, null) + status = try(tobool(rule.value.status) ? "Enabled" : "Disabled", title(lower(rule.value.status)), "Enabled") + + dynamic "delete_marker_replication" { + for_each = flatten(try([rule.value.delete_marker_replication_status], [rule.value.delete_marker_replication], [])) + + content { + # Valid values: "Enabled" or "Disabled" + status = try(tobool(delete_marker_replication.value) ? "Enabled" : "Disabled", title(lower(delete_marker_replication.value))) + } + } + + # Amazon S3 does not support this argument according to: + # https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_replication_configuration + # More infor about what does Amazon S3 replicate? + # https://docs.aws.amazon.com/AmazonS3/latest/userguide/replication-what-is-isnot-replicated.html + dynamic "existing_object_replication" { + for_each = flatten(try([rule.value.existing_object_replication_status], [rule.value.existing_object_replication], [])) + + content { + # Valid values: "Enabled" or "Disabled" + status = try(tobool(existing_object_replication.value) ? "Enabled" : "Disabled", title(lower(existing_object_replication.value))) + } + } + + dynamic "destination" { + for_each = try(flatten([rule.value.destination]), []) + + content { + bucket = destination.value.bucket + storage_class = try(destination.value.storage_class, null) + account = try(destination.value.account_id, destination.value.account, null) + + dynamic "access_control_translation" { + for_each = try(flatten([destination.value.access_control_translation]), []) + + content { + owner = title(lower(access_control_translation.value.owner)) + } + } + + dynamic "encryption_configuration" { + for_each = flatten([try(destination.value.encryption_configuration.replica_kms_key_id, destination.value.replica_kms_key_id, [])]) + + content { + replica_kms_key_id = encryption_configuration.value + } + } + + dynamic "replication_time" { + for_each = try(flatten([destination.value.replication_time]), []) + + content { + # Valid values: "Enabled" or "Disabled" + status = try(tobool(replication_time.value.status) ? "Enabled" : "Disabled", title(lower(replication_time.value.status)), "Disabled") + + dynamic "time" { + for_each = try(flatten([replication_time.value.minutes]), []) + + content { + minutes = replication_time.value.minutes + } + } + } + + } + + dynamic "metrics" { + for_each = try(flatten([destination.value.metrics]), []) + + content { + # Valid values: "Enabled" or "Disabled" + status = try(tobool(metrics.value.status) ? "Enabled" : "Disabled", title(lower(metrics.value.status)), "Disabled") + + dynamic "event_threshold" { + for_each = try(flatten([metrics.value.minutes]), []) + + content { + minutes = metrics.value.minutes + } + } + } + } + } + } + + dynamic "source_selection_criteria" { + for_each = try(flatten([rule.value.source_selection_criteria]), []) + + content { + dynamic "replica_modifications" { + for_each = flatten([try(source_selection_criteria.value.replica_modifications.enabled, source_selection_criteria.value.replica_modifications.status, [])]) + + content { + # Valid values: "Enabled" or "Disabled" + status = try(tobool(replica_modifications.value) ? "Enabled" : "Disabled", title(lower(replica_modifications.value)), "Disabled") + } + } + + dynamic "sse_kms_encrypted_objects" { + for_each = flatten([try(source_selection_criteria.value.sse_kms_encrypted_objects.enabled, source_selection_criteria.value.sse_kms_encrypted_objects.status, [])]) + + content { + # Valid values: "Enabled" or "Disabled" + status = try(tobool(sse_kms_encrypted_objects.value) ? "Enabled" : "Disabled", title(lower(sse_kms_encrypted_objects.value)), "Disabled") + } + } + } + } + + # Max 1 block - filter - without any key arguments or tags + dynamic "filter" { + for_each = length(try(flatten([rule.value.filter]), [])) == 0 ? [true] : [] + + content { + } + } + + # Max 1 block - filter - with one key argument or a single tag + dynamic "filter" { + for_each = [for v in try(flatten([rule.value.filter]), []) : v if max(length(keys(v)), length(try(rule.value.filter.tags, rule.value.filter.tag, []))) == 1] + + content { + prefix = try(filter.value.prefix, null) + + dynamic "tag" { + for_each = try(filter.value.tags, filter.value.tag, []) + + content { + key = tag.key + value = tag.value + } + } + } + } + + # Max 1 block - filter - with more than one key arguments or multiple tags + dynamic "filter" { + for_each = [for v in try(flatten([rule.value.filter]), []) : v if max(length(keys(v)), length(try(rule.value.filter.tags, rule.value.filter.tag, []))) > 1] + + content { + and { + prefix = try(filter.value.prefix, null) + tags = try(filter.value.tags, filter.value.tag, null) + } + } + } + } + } + + # Must have bucket versioning enabled first + depends_on = [aws_s3_bucket_versioning.example] +} + +locals { + attach_policy = var.attach_require_latest_tls_policy || var.attach_elb_log_delivery_policy || var.attach_lb_log_delivery_policy || var.attach_deny_insecure_transport_policy || var.attach_policy + +} + +##---------------------------------------------------------------------------------- +## Manages S3 bucket-level Public Access Block configuration. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_public_access_block" "this" { + count = var.create_bucket && var.attach_public_policy ? 1 : 0 + + bucket = local.attach_policy ? aws_s3_bucket_policy.s3_default[0].id : aws_s3_bucket.s3_default[0].id + + block_public_acls = var.block_public_acls + block_public_policy = var.block_public_policy + ignore_public_acls = var.ignore_public_acls + restrict_public_buckets = var.restrict_public_buckets +} + +##---------------------------------------------------------------------------------- +## Provides a resource to manage S3 Bucket Ownership Controls. +##---------------------------------------------------------------------------------- +resource "aws_s3_bucket_ownership_controls" "this" { + count = var.create_bucket && var.control_object_ownership ? 1 : 0 + + bucket = local.attach_policy ? aws_s3_bucket_policy.s3_default[0].id : aws_s3_bucket.s3_default[0].id + + rule { + object_ownership = var.object_ownership + } + + # This `depends_on` is to prevent "A conflicting conditional operation is currently in progress against this resource." + depends_on = [ + aws_s3_bucket_policy.s3_default, + aws_s3_bucket_public_access_block.this, + aws_s3_bucket.s3_default + ] +} \ No newline at end of file diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..928fecc --- /dev/null +++ b/outputs.tf @@ -0,0 +1,17 @@ +# Module : S3 BUCKET +# Description : Terraform module to create default S3 bucket with logging and encryption +# type specific features. +output "id" { + value = join("", aws_s3_bucket.s3_default.*.id) + description = "The ID of the s3 bucket." +} + +output "arn" { + value = join("", aws_s3_bucket.s3_default.*.arn) + description = "The ARN of the s3 bucket." +} + +output "bucket_domain_name" { + value = join("", aws_s3_bucket.s3_default.*.bucket_domain_name) + description = "The Domain of the s3 bucket." +} \ No newline at end of file diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..4589a9b --- /dev/null +++ b/variables.tf @@ -0,0 +1,414 @@ +#Module : LABEL +#Description : Terraform label module variables. +variable "name" { + type = string + default = "" + description = "Name (e.g. `app` or `cluster`)." +} + +variable "repository" { + type = string + default = "https://github.com/clouddrove/terraform-aws-s3" + description = "Terraform current module repo" +} + +variable "environment" { + type = string + default = "" + description = "Environment (e.g. `prod`, `dev`, `staging`)." +} + +variable "label_order" { + type = list(any) + default = [] + description = "Label order, e.g. `name`,`application`." +} + +variable "managedby" { + type = string + default = "hello@clouddrove.com" + description = "ManagedBy, eg 'CloudDrove'." +} + +variable "delimiter" { + type = string + default = "-" + description = "Delimiter to be used between `organization`, `environment`, `name` and `attributes`." +} + +variable "tags" { + type = map(any) + default = {} + description = "Additional tags (e.g. map(`BusinessUnit`,`XYZ`)." +} + +# Module : S3 BUCKET +# Description : Terraform S3 Bucket module variables. +variable "create_bucket" { + type = bool + default = true + description = "Conditionally create S3 bucket." +} + +variable "versioning" { + type = bool + default = true + description = "Enable Versioning of S3." +} + +variable "acl" { + type = string + default = null + description = "Canned ACL to apply to the S3 bucket." +} + +variable "mfa_delete" { + type = bool + default = false + description = "Enable MFA delete for either Change the versioning state of your bucket or Permanently delete an object version." +} + +variable "enable_server_side_encryption" { + type = bool + default = false + description = "Enable enable_server_side_encryption" +} + +variable "sse_algorithm" { + type = string + default = "AES256" + description = "The server-side encryption algorithm to use. Valid values are AES256 and aws:kms." +} + +variable "enable_kms" { + type = bool + default = false + description = "Enable enable_server_side_encryption" +} + +variable "kms_master_key_id" { + type = string + default = "" + description = "The AWS KMS master key ID used for the SSE-KMS encryption. This can only be used when you set the value of sse_algorithm as aws:kms. The default aws/s3 AWS KMS master key is used if this element is absent while the sse_algorithm is aws:kms." +} + +variable "enable_lifecycle_configuration_rules" { + type = bool + default = false + description = "enable or disable lifecycle_configuration_rules" +} + +variable "lifecycle_configuration_rules" { + type = list(object({ + id = string + prefix = string + enabled = bool + tags = map(string) + + enable_glacier_transition = bool + enable_deeparchive_transition = bool + enable_standard_ia_transition = bool + enable_current_object_expiration = bool + enable_noncurrent_version_expiration = bool + + abort_incomplete_multipart_upload_days = number + noncurrent_version_glacier_transition_days = number + noncurrent_version_deeparchive_transition_days = number + noncurrent_version_expiration_days = number + + standard_transition_days = number + glacier_transition_days = number + deeparchive_transition_days = number + expiration_days = number + })) + default = null + description = "A list of lifecycle rules" +} + +variable "lifecycle_infrequent_storage_transition_enabled" { + type = bool + default = false + description = "Specifies infrequent storage transition lifecycle rule status." +} + +variable "lifecycle_infrequent_storage_object_prefix" { + type = string + default = "" + sensitive = true + description = "Object key prefix identifying one or more objects to which the lifecycle rule applies." +} + +variable "lifecycle_days_to_infrequent_storage_transition" { + type = number + default = 60 + description = "Specifies the number of days after object creation when it will be moved to standard infrequent access storage." +} + +variable "lifecycle_glacier_transition_enabled" { + type = bool + default = false + description = "Specifies Glacier transition lifecycle rule status." +} + +variable "lifecycle_glacier_object_prefix" { + type = string + default = "" + sensitive = true + description = "Object key prefix identifying one or more objects to which the lifecycle rule applies." +} + +variable "lifecycle_days_to_deep_archive_transition" { + type = number + default = 180 + description = "Specifies the number of days after object creation when it will be moved to DEEP ARCHIVE ." +} + +variable "lifecycle_deep_archive_transition_enabled" { + type = bool + default = false + description = "Specifies DEEP ARCHIVE transition lifecycle rule status." +} + +variable "lifecycle_deep_archive_object_prefix" { + type = string + default = "" + sensitive = true + description = "Object key prefix identifying one or more objects to which the lifecycle rule applies." +} + +variable "lifecycle_days_to_glacier_transition" { + type = number + default = 180 + description = "Specifies the number of days after object creation when it will be moved to Glacier storage." +} + +variable "lifecycle_expiration_enabled" { + type = bool + default = false + description = "Specifies expiration lifecycle rule status." +} + +variable "lifecycle_expiration_object_prefix" { + type = string + default = "" + description = "Object key prefix identifying one or more objects to which the lifecycle rule applies." +} + +variable "lifecycle_days_to_expiration" { + type = number + default = 365 + description = "Specifies the number of days after object creation when the object expires." +} + +# Module : S3 BUCKET POLICY +# Description : Terraform S3 Bucket Policy module variables. +variable "aws_iam_policy_document" { + type = string + default = "" + sensitive = true + description = "The text of the policy. Although this is a bucket policy rather than an IAM policy, the aws_iam_policy_document data source may be used, so long as it specifies a principal. For more information about building AWS IAM policy documents with Terraform, see the AWS IAM Policy Document Guide. Note: Bucket policies are limited to 20 KB in size." +} + +variable "bucket_policy" { + type = bool + default = false + description = "Conditionally create S3 bucket policy." +} + +variable "force_destroy" { + type = bool + default = false + description = "A boolean that indicates all objects should be deleted from the bucket so that the bucket can be destroyed without error. These objects are not recoverable." +} + +variable "bucket_prefix" { + type = string + default = null + description = " (Optional, Forces new resource) Creates a unique bucket name beginning with the specified prefix." +} + +variable "grants" { + type = list(object({ + id = string + type = string + permissions = list(string) + uri = string + })) + default = null + description = "ACL Policy grant.conflict with acl.set acl null to use this" +} + +variable "acl_grants" { + type = list(object({ + id = string + type = string + permission = string + uri = string + })) + default = null + + description = "A list of policy grants for the bucket. Conflicts with `acl`. Set `acl` to `null` to use this." +} + +variable "owner_id" { + type = string + default = "" + description = "The canonical user ID associated with the AWS account." +} + +variable "website_config_enable" { + type = bool + default = false + description = "enable or disable aws_s3_bucket_website_configuration" +} + +variable "index_document" { + type = string + default = "index.html" + description = "The name of the index document for the website" +} +variable "error_document" { + type = string + default = "error.html" + description = "he name of the error document for the website " +} +variable "routing_rule" { + type = string + default = "docs/" + description = "ist of rules that define when a redirect is applied and the redirect behavior " +} +variable "redirect" { + type = string + default = "documents/" + description = "The redirect behavior for every request to this bucket's website endpoint " +} + +variable "logging" { + type = bool + default = false + description = "Logging Object to enable and disable logging" +} + +variable "target_bucket" { + type = string + default = "" + description = "The bucket where you want Amazon S3 to store server access logs." +} + +variable "target_prefix" { + type = string + default = "" + description = "A prefix for all log object keys." +} + +variable "acceleration_status" { + type = bool + default = false + description = "Sets the accelerate configuration of an existing bucket. Can be Enabled or Suspended" +} + +variable "request_payer" { + type = bool + default = false + description = "Specifies who should bear the cost of Amazon S3 data transfer. Can be either BucketOwner or Requester. By default, the owner of the S3 bucket would incur the costs of any data transfer" +} + + +variable "object_lock_configuration" { + type = object({ + mode = string #Valid values are GOVERNANCE and COMPLIANCE. + days = number + years = number + }) + default = null + description = "With S3 Object Lock, you can store objects using a write-once-read-many (WORM) model. Object Lock can help prevent objects from being deleted or overwritten for a fixed amount of time or indefinitely." + +} + +variable "cors_rule" { + type = list(object({ + allowed_headers = list(string) + allowed_methods = list(string) + allowed_origins = list(string) + expose_headers = list(string) + max_age_seconds = number + })) + default = null + description = "CORS Configuration specification for this bucket" +} + +variable "replication_configuration" { + description = "Map containing cross-region replication configuration." + type = any + default = {} +} + +variable "attach_public_policy" { + description = "Controls if a user defined public bucket policy will be attached (set to `false` to allow upstream to apply defaults to the bucket)" + type = bool + default = true +} +variable "attach_elb_log_delivery_policy" { + description = "Controls if S3 bucket should have ELB log delivery policy attached" + type = bool + default = false +} + +variable "attach_lb_log_delivery_policy" { + description = "Controls if S3 bucket should have ALB/NLB log delivery policy attached" + type = bool + default = false +} + +variable "attach_deny_insecure_transport_policy" { + description = "Controls if S3 bucket should have deny non-SSL transport policy attached" + type = bool + default = false +} + +variable "attach_require_latest_tls_policy" { + description = "Controls if S3 bucket should require the latest version of TLS" + type = bool + default = false +} + +variable "block_public_acls" { + description = "Whether Amazon S3 should block public ACLs for this bucket." + type = bool + default = false +} + +variable "block_public_policy" { + description = "Whether Amazon S3 should block public bucket policies for this bucket." + type = bool + default = false +} + +variable "ignore_public_acls" { + description = "Whether Amazon S3 should ignore public ACLs for this bucket." + type = bool + default = false +} + +variable "restrict_public_buckets" { + description = "Whether Amazon S3 should restrict public bucket policies for this bucket." + type = bool + default = false +} + +variable "control_object_ownership" { + description = "Whether to manage S3 Bucket Ownership Controls on this bucket." + type = bool + default = false +} + +variable "object_ownership" { + description = "Object ownership. Valid values: BucketOwnerEnforced, BucketOwnerPreferred or ObjectWriter. 'BucketOwnerEnforced': ACLs are disabled, and the bucket owner automatically owns and has full control over every object in the bucket. 'BucketOwnerPreferred': Objects uploaded to the bucket change ownership to the bucket owner if the objects are uploaded with the bucket-owner-full-control canned ACL. 'ObjectWriter': The uploading account will own the object if the object is uploaded with the bucket-owner-full-control canned ACL." + type = string + default = "ObjectWriter" +} +variable "attach_policy" { + description = "Controls if S3 bucket should have bucket policy attached (set to `true` to use value of `policy` as bucket policy)" + type = bool + default = false +} \ No newline at end of file From c398ab54172daeda31219477727d8ff43e6c4b94 Mon Sep 17 00:00:00 2001 From: kmobl Date: Wed, 16 Aug 2023 17:50:46 -0500 Subject: [PATCH 02/16] initial commit --- main.tf | 51 +-------------------------------------------------- 1 file changed, 1 insertion(+), 50 deletions(-) diff --git a/main.tf b/main.tf index c4e9f4d..2f85270 100644 --- a/main.tf +++ b/main.tf @@ -1,6 +1,3 @@ -##---------------------------------------------------------------------------------- -## Terraform resource to create S3 bucket with different combination type specific features. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket" "s3_default" { count = var.create_bucket == true ? 1 : 0 @@ -8,27 +5,14 @@ resource "aws_s3_bucket" "s3_default" { force_destroy = var.force_destroy tags = var.tags - dynamic "object_lock_configuration" { - for_each = var.object_lock_configuration != null ? [1] : [] - - content { - object_lock_enabled = "Enabled" - } - } } -##---------------------------------------------------------------------------------- -## Terraform resource which creates policy for S3 bucket on AWS. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_policy" "s3_default" { count = var.bucket_policy == true ? 1 : 0 bucket = join("", aws_s3_bucket.s3_default.*.id) policy = var.aws_iam_policy_document } -##---------------------------------------------------------------------------------- -## Provides an S3 bucket accelerate configuration resource. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_accelerate_configuration" "example" { count = var.create_bucket && var.acceleration_status == true ? 1 : 0 @@ -36,9 +20,6 @@ resource "aws_s3_bucket_accelerate_configuration" "example" { status = "Enabled" } -##---------------------------------------------------------------------------------- -## Provides an S3 bucket request payment configuration resource. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_request_payment_configuration" "example" { count = var.create_bucket && var.request_payer == true ? 1 : 0 @@ -59,9 +40,6 @@ resource "aws_s3_bucket_versioning" "example" { } } -##---------------------------------------------------------------------------------- -## Provides an S3 bucket (server access) logging resource. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_logging" "example" { count = var.create_bucket && var.logging == true ? 1 : 0 bucket = join("", aws_s3_bucket.s3_default.*.id) @@ -70,9 +48,6 @@ resource "aws_s3_bucket_logging" "example" { target_prefix = var.target_prefix } -##---------------------------------------------------------------------------------- -## Provides a S3 bucket server-side encryption configuration resource. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_server_side_encryption_configuration" "example" { count = var.create_bucket && var.enable_server_side_encryption == true ? 1 : 0 bucket = join("", aws_s3_bucket.s3_default.*.id) @@ -85,9 +60,6 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "example" { } } -##---------------------------------------------------------------------------------- -## Provides an S3 bucket Object Lock configuration resource. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_object_lock_configuration" "example" { count = var.create_bucket && var.object_lock_configuration != null ? 1 : 0 @@ -104,9 +76,6 @@ resource "aws_s3_bucket_object_lock_configuration" "example" { } } -##---------------------------------------------------------------------------------- -## Provides an S3 bucket CORS configuration resource. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_cors_configuration" "example" { count = var.create_bucket && var.cors_rule != null ? 1 : 0 @@ -125,9 +94,6 @@ resource "aws_s3_bucket_cors_configuration" "example" { } } -##---------------------------------------------------------------------------------- -## Provides an S3 bucket website configuration resource. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_website_configuration" "example" { count = var.create_bucket && var.website_config_enable == true ? 1 : 0 @@ -165,9 +131,6 @@ locals { ]) } -##---------------------------------------------------------------------------------- -## Provides an S3 bucket ACL resource. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_acl" "default" { count = var.create_bucket ? var.grants != null ? var.acl != null ? 1 : 0 : 0 : 0 @@ -200,9 +163,6 @@ resource "aws_s3_bucket_acl" "default" { } } -##---------------------------------------------------------------------------------- -## Provides an independent configuration resource for S3 bucket lifecycle configuration. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_lifecycle_configuration" "default" { count = var.create_bucket && var.enable_lifecycle_configuration_rules == true ? 1 : 0 bucket = join("", aws_s3_bucket.s3_default.*.id) @@ -301,9 +261,6 @@ resource "aws_s3_bucket_lifecycle_configuration" "default" { ] } -##---------------------------------------------------------------------------------- -## Provides an independent configuration resource for S3 bucket replication configuration. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_replication_configuration" "this" { count = var.create_bucket && length(keys(var.replication_configuration)) > 0 ? 1 : 0 @@ -316,7 +273,7 @@ resource "aws_s3_bucket_replication_configuration" "this" { content { id = try(rule.value.id, null) priority = try(rule.value.priority, null) - prefix = try(rule.value.prefix, null) + filter = try(rule.value.prefix, null) status = try(tobool(rule.value.status) ? "Enabled" : "Disabled", title(lower(rule.value.status)), "Enabled") dynamic "delete_marker_replication" { @@ -475,9 +432,6 @@ locals { } -##---------------------------------------------------------------------------------- -## Manages S3 bucket-level Public Access Block configuration. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_public_access_block" "this" { count = var.create_bucket && var.attach_public_policy ? 1 : 0 @@ -489,9 +443,6 @@ resource "aws_s3_bucket_public_access_block" "this" { restrict_public_buckets = var.restrict_public_buckets } -##---------------------------------------------------------------------------------- -## Provides a resource to manage S3 Bucket Ownership Controls. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_ownership_controls" "this" { count = var.create_bucket && var.control_object_ownership ? 1 : 0 From d6546bb2cedaf39bbabb1c36f89754ba726a76ff Mon Sep 17 00:00:00 2001 From: kmobl Date: Thu, 17 Aug 2023 07:29:07 -0500 Subject: [PATCH 03/16] initial commit --- main.tf | 4 ---- outputs.tf | 3 --- variables.tf | 36 +----------------------------------- 3 files changed, 1 insertion(+), 42 deletions(-) diff --git a/main.tf b/main.tf index 2f85270..71e3db5 100644 --- a/main.tf +++ b/main.tf @@ -27,10 +27,6 @@ resource "aws_s3_bucket_request_payment_configuration" "example" { payer = "Requester" } -##---------------------------------------------------------------------------------- -## Provides a resource for controlling versioning on an S3 bucket. -## Deleting this resource will either suspend versioning on the associated S3 bucket or simply remove the resource from Terraform state if the associated S3 bucket is unversioned. -##---------------------------------------------------------------------------------- resource "aws_s3_bucket_versioning" "example" { count = var.create_bucket && var.versioning == true ? 1 : 0 diff --git a/outputs.tf b/outputs.tf index 928fecc..0fa380c 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,6 +1,3 @@ -# Module : S3 BUCKET -# Description : Terraform module to create default S3 bucket with logging and encryption -# type specific features. output "id" { value = join("", aws_s3_bucket.s3_default.*.id) description = "The ID of the s3 bucket." diff --git a/variables.tf b/variables.tf index 4589a9b..3cb27d6 100644 --- a/variables.tf +++ b/variables.tf @@ -1,39 +1,7 @@ -#Module : LABEL -#Description : Terraform label module variables. variable "name" { type = string default = "" - description = "Name (e.g. `app` or `cluster`)." -} - -variable "repository" { - type = string - default = "https://github.com/clouddrove/terraform-aws-s3" - description = "Terraform current module repo" -} - -variable "environment" { - type = string - default = "" - description = "Environment (e.g. `prod`, `dev`, `staging`)." -} - -variable "label_order" { - type = list(any) - default = [] - description = "Label order, e.g. `name`,`application`." -} - -variable "managedby" { - type = string - default = "hello@clouddrove.com" - description = "ManagedBy, eg 'CloudDrove'." -} - -variable "delimiter" { - type = string - default = "-" - description = "Delimiter to be used between `organization`, `environment`, `name` and `attributes`." + description = "Name of RDS" } variable "tags" { @@ -42,8 +10,6 @@ variable "tags" { description = "Additional tags (e.g. map(`BusinessUnit`,`XYZ`)." } -# Module : S3 BUCKET -# Description : Terraform S3 Bucket module variables. variable "create_bucket" { type = bool default = true From f2d076f8befc096e836a9bb0bfe5104a8a883b02 Mon Sep 17 00:00:00 2001 From: kmobl Date: Fri, 18 Aug 2023 07:38:09 -0500 Subject: [PATCH 04/16] ANOTHA ONE --- main.tf | 166 -------------------------------------------------------- 1 file changed, 166 deletions(-) diff --git a/main.tf b/main.tf index 71e3db5..99de251 100644 --- a/main.tf +++ b/main.tf @@ -257,172 +257,6 @@ resource "aws_s3_bucket_lifecycle_configuration" "default" { ] } -resource "aws_s3_bucket_replication_configuration" "this" { - count = var.create_bucket && length(keys(var.replication_configuration)) > 0 ? 1 : 0 - - bucket = aws_s3_bucket.s3_default[0].id - role = var.replication_configuration["role"] - - dynamic "rule" { - for_each = flatten(try([var.replication_configuration["rule"]], [var.replication_configuration["rules"]], [])) - - content { - id = try(rule.value.id, null) - priority = try(rule.value.priority, null) - filter = try(rule.value.prefix, null) - status = try(tobool(rule.value.status) ? "Enabled" : "Disabled", title(lower(rule.value.status)), "Enabled") - - dynamic "delete_marker_replication" { - for_each = flatten(try([rule.value.delete_marker_replication_status], [rule.value.delete_marker_replication], [])) - - content { - # Valid values: "Enabled" or "Disabled" - status = try(tobool(delete_marker_replication.value) ? "Enabled" : "Disabled", title(lower(delete_marker_replication.value))) - } - } - - # Amazon S3 does not support this argument according to: - # https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_replication_configuration - # More infor about what does Amazon S3 replicate? - # https://docs.aws.amazon.com/AmazonS3/latest/userguide/replication-what-is-isnot-replicated.html - dynamic "existing_object_replication" { - for_each = flatten(try([rule.value.existing_object_replication_status], [rule.value.existing_object_replication], [])) - - content { - # Valid values: "Enabled" or "Disabled" - status = try(tobool(existing_object_replication.value) ? "Enabled" : "Disabled", title(lower(existing_object_replication.value))) - } - } - - dynamic "destination" { - for_each = try(flatten([rule.value.destination]), []) - - content { - bucket = destination.value.bucket - storage_class = try(destination.value.storage_class, null) - account = try(destination.value.account_id, destination.value.account, null) - - dynamic "access_control_translation" { - for_each = try(flatten([destination.value.access_control_translation]), []) - - content { - owner = title(lower(access_control_translation.value.owner)) - } - } - - dynamic "encryption_configuration" { - for_each = flatten([try(destination.value.encryption_configuration.replica_kms_key_id, destination.value.replica_kms_key_id, [])]) - - content { - replica_kms_key_id = encryption_configuration.value - } - } - - dynamic "replication_time" { - for_each = try(flatten([destination.value.replication_time]), []) - - content { - # Valid values: "Enabled" or "Disabled" - status = try(tobool(replication_time.value.status) ? "Enabled" : "Disabled", title(lower(replication_time.value.status)), "Disabled") - - dynamic "time" { - for_each = try(flatten([replication_time.value.minutes]), []) - - content { - minutes = replication_time.value.minutes - } - } - } - - } - - dynamic "metrics" { - for_each = try(flatten([destination.value.metrics]), []) - - content { - # Valid values: "Enabled" or "Disabled" - status = try(tobool(metrics.value.status) ? "Enabled" : "Disabled", title(lower(metrics.value.status)), "Disabled") - - dynamic "event_threshold" { - for_each = try(flatten([metrics.value.minutes]), []) - - content { - minutes = metrics.value.minutes - } - } - } - } - } - } - - dynamic "source_selection_criteria" { - for_each = try(flatten([rule.value.source_selection_criteria]), []) - - content { - dynamic "replica_modifications" { - for_each = flatten([try(source_selection_criteria.value.replica_modifications.enabled, source_selection_criteria.value.replica_modifications.status, [])]) - - content { - # Valid values: "Enabled" or "Disabled" - status = try(tobool(replica_modifications.value) ? "Enabled" : "Disabled", title(lower(replica_modifications.value)), "Disabled") - } - } - - dynamic "sse_kms_encrypted_objects" { - for_each = flatten([try(source_selection_criteria.value.sse_kms_encrypted_objects.enabled, source_selection_criteria.value.sse_kms_encrypted_objects.status, [])]) - - content { - # Valid values: "Enabled" or "Disabled" - status = try(tobool(sse_kms_encrypted_objects.value) ? "Enabled" : "Disabled", title(lower(sse_kms_encrypted_objects.value)), "Disabled") - } - } - } - } - - # Max 1 block - filter - without any key arguments or tags - dynamic "filter" { - for_each = length(try(flatten([rule.value.filter]), [])) == 0 ? [true] : [] - - content { - } - } - - # Max 1 block - filter - with one key argument or a single tag - dynamic "filter" { - for_each = [for v in try(flatten([rule.value.filter]), []) : v if max(length(keys(v)), length(try(rule.value.filter.tags, rule.value.filter.tag, []))) == 1] - - content { - prefix = try(filter.value.prefix, null) - - dynamic "tag" { - for_each = try(filter.value.tags, filter.value.tag, []) - - content { - key = tag.key - value = tag.value - } - } - } - } - - # Max 1 block - filter - with more than one key arguments or multiple tags - dynamic "filter" { - for_each = [for v in try(flatten([rule.value.filter]), []) : v if max(length(keys(v)), length(try(rule.value.filter.tags, rule.value.filter.tag, []))) > 1] - - content { - and { - prefix = try(filter.value.prefix, null) - tags = try(filter.value.tags, filter.value.tag, null) - } - } - } - } - } - - # Must have bucket versioning enabled first - depends_on = [aws_s3_bucket_versioning.example] -} - locals { attach_policy = var.attach_require_latest_tls_policy || var.attach_elb_log_delivery_policy || var.attach_lb_log_delivery_policy || var.attach_deny_insecure_transport_policy || var.attach_policy From 320a8d763d46ecfb8578699385b9843ff72bc424 Mon Sep 17 00:00:00 2001 From: kmobl Date: Fri, 18 Aug 2023 08:20:49 -0500 Subject: [PATCH 05/16] added org-terraform-docs.yml --- .github/workflows/org-terraform-docs.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/workflows/org-terraform-docs.yml diff --git a/.github/workflows/org-terraform-docs.yml b/.github/workflows/org-terraform-docs.yml new file mode 100644 index 0000000..273ff8a --- /dev/null +++ b/.github/workflows/org-terraform-docs.yml @@ -0,0 +1,8 @@ +name: Org Terraform Docs +on: + pull_request: + workflow_call: + +jobs: + terraform-docs: + uses: Coalfire-CF/Actions/.github/workflows/org-terraform-docs.yml@main \ No newline at end of file From b17433d7fa0fdf4bd4e4058b12b3a4edcd950e7b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 18 Aug 2023 13:21:10 +0000 Subject: [PATCH 06/16] terraform-docs: automated action --- README.md | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 01e169d..fa1e9fd 100644 --- a/README.md +++ b/README.md @@ -128,9 +128,6 @@ module "core_sa" { ``` - -ALLOW TERRAFORM MARKDOWN GITHUB ACTION TO POPULATE THE BELOW - ## Requirements No requirements. @@ -139,27 +136,99 @@ No requirements. | Name | Version | |------|---------| +| [aws](#provider\_aws) | n/a | ## Modules -| Name | Source | Version | -|------|--------|---------| +No modules. ## Resources | Name | Type | |------|------| +| [aws_s3_bucket.s3_default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_accelerate_configuration.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_accelerate_configuration) | resource | +| [aws_s3_bucket_acl.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_acl) | resource | +| [aws_s3_bucket_cors_configuration.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_cors_configuration) | resource | +| [aws_s3_bucket_lifecycle_configuration.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource | +| [aws_s3_bucket_logging.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | +| [aws_s3_bucket_object_lock_configuration.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_object_lock_configuration) | resource | +| [aws_s3_bucket_ownership_controls.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_ownership_controls) | resource | +| [aws_s3_bucket_policy.s3_default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | +| [aws_s3_bucket_public_access_block.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_s3_bucket_request_payment_configuration.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_request_payment_configuration) | resource | +| [aws_s3_bucket_server_side_encryption_configuration.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [aws_s3_bucket_versioning.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | +| [aws_s3_bucket_website_configuration.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_website_configuration) | resource | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [acceleration\_status](#input\_acceleration\_status) | Sets the accelerate configuration of an existing bucket. Can be Enabled or Suspended | `bool` | `false` | no | +| [acl](#input\_acl) | Canned ACL to apply to the S3 bucket. | `string` | `null` | no | +| [acl\_grants](#input\_acl\_grants) | A list of policy grants for the bucket. Conflicts with `acl`. Set `acl` to `null` to use this. |
list(object({
id = string
type = string
permission = string
uri = string
}))
| `null` | no | +| [attach\_deny\_insecure\_transport\_policy](#input\_attach\_deny\_insecure\_transport\_policy) | Controls if S3 bucket should have deny non-SSL transport policy attached | `bool` | `false` | no | +| [attach\_elb\_log\_delivery\_policy](#input\_attach\_elb\_log\_delivery\_policy) | Controls if S3 bucket should have ELB log delivery policy attached | `bool` | `false` | no | +| [attach\_lb\_log\_delivery\_policy](#input\_attach\_lb\_log\_delivery\_policy) | Controls if S3 bucket should have ALB/NLB log delivery policy attached | `bool` | `false` | no | +| [attach\_policy](#input\_attach\_policy) | Controls if S3 bucket should have bucket policy attached (set to `true` to use value of `policy` as bucket policy) | `bool` | `false` | no | +| [attach\_public\_policy](#input\_attach\_public\_policy) | Controls if a user defined public bucket policy will be attached (set to `false` to allow upstream to apply defaults to the bucket) | `bool` | `true` | no | +| [attach\_require\_latest\_tls\_policy](#input\_attach\_require\_latest\_tls\_policy) | Controls if S3 bucket should require the latest version of TLS | `bool` | `false` | no | +| [aws\_iam\_policy\_document](#input\_aws\_iam\_policy\_document) | The text of the policy. Although this is a bucket policy rather than an IAM policy, the aws\_iam\_policy\_document data source may be used, so long as it specifies a principal. For more information about building AWS IAM policy documents with Terraform, see the AWS IAM Policy Document Guide. Note: Bucket policies are limited to 20 KB in size. | `string` | `""` | no | +| [block\_public\_acls](#input\_block\_public\_acls) | Whether Amazon S3 should block public ACLs for this bucket. | `bool` | `false` | no | +| [block\_public\_policy](#input\_block\_public\_policy) | Whether Amazon S3 should block public bucket policies for this bucket. | `bool` | `false` | no | +| [bucket\_policy](#input\_bucket\_policy) | Conditionally create S3 bucket policy. | `bool` | `false` | no | +| [bucket\_prefix](#input\_bucket\_prefix) | (Optional, Forces new resource) Creates a unique bucket name beginning with the specified prefix. | `string` | `null` | no | +| [control\_object\_ownership](#input\_control\_object\_ownership) | Whether to manage S3 Bucket Ownership Controls on this bucket. | `bool` | `false` | no | +| [cors\_rule](#input\_cors\_rule) | CORS Configuration specification for this bucket |
list(object({
allowed_headers = list(string)
allowed_methods = list(string)
allowed_origins = list(string)
expose_headers = list(string)
max_age_seconds = number
}))
| `null` | no | +| [create\_bucket](#input\_create\_bucket) | Conditionally create S3 bucket. | `bool` | `true` | no | +| [enable\_kms](#input\_enable\_kms) | Enable enable\_server\_side\_encryption | `bool` | `false` | no | +| [enable\_lifecycle\_configuration\_rules](#input\_enable\_lifecycle\_configuration\_rules) | enable or disable lifecycle\_configuration\_rules | `bool` | `false` | no | +| [enable\_server\_side\_encryption](#input\_enable\_server\_side\_encryption) | Enable enable\_server\_side\_encryption | `bool` | `false` | no | +| [error\_document](#input\_error\_document) | he name of the error document for the website | `string` | `"error.html"` | no | +| [force\_destroy](#input\_force\_destroy) | A boolean that indicates all objects should be deleted from the bucket so that the bucket can be destroyed without error. These objects are not recoverable. | `bool` | `false` | no | +| [grants](#input\_grants) | ACL Policy grant.conflict with acl.set acl null to use this |
list(object({
id = string
type = string
permissions = list(string)
uri = string
}))
| `null` | no | +| [ignore\_public\_acls](#input\_ignore\_public\_acls) | Whether Amazon S3 should ignore public ACLs for this bucket. | `bool` | `false` | no | +| [index\_document](#input\_index\_document) | The name of the index document for the website | `string` | `"index.html"` | no | +| [kms\_master\_key\_id](#input\_kms\_master\_key\_id) | The AWS KMS master key ID used for the SSE-KMS encryption. This can only be used when you set the value of sse\_algorithm as aws:kms. The default aws/s3 AWS KMS master key is used if this element is absent while the sse\_algorithm is aws:kms. | `string` | `""` | no | +| [lifecycle\_configuration\_rules](#input\_lifecycle\_configuration\_rules) | A list of lifecycle rules |
list(object({
id = string
prefix = string
enabled = bool
tags = map(string)

enable_glacier_transition = bool
enable_deeparchive_transition = bool
enable_standard_ia_transition = bool
enable_current_object_expiration = bool
enable_noncurrent_version_expiration = bool

abort_incomplete_multipart_upload_days = number
noncurrent_version_glacier_transition_days = number
noncurrent_version_deeparchive_transition_days = number
noncurrent_version_expiration_days = number

standard_transition_days = number
glacier_transition_days = number
deeparchive_transition_days = number
expiration_days = number
}))
| `null` | no | +| [lifecycle\_days\_to\_deep\_archive\_transition](#input\_lifecycle\_days\_to\_deep\_archive\_transition) | Specifies the number of days after object creation when it will be moved to DEEP ARCHIVE . | `number` | `180` | no | +| [lifecycle\_days\_to\_expiration](#input\_lifecycle\_days\_to\_expiration) | Specifies the number of days after object creation when the object expires. | `number` | `365` | no | +| [lifecycle\_days\_to\_glacier\_transition](#input\_lifecycle\_days\_to\_glacier\_transition) | Specifies the number of days after object creation when it will be moved to Glacier storage. | `number` | `180` | no | +| [lifecycle\_days\_to\_infrequent\_storage\_transition](#input\_lifecycle\_days\_to\_infrequent\_storage\_transition) | Specifies the number of days after object creation when it will be moved to standard infrequent access storage. | `number` | `60` | no | +| [lifecycle\_deep\_archive\_object\_prefix](#input\_lifecycle\_deep\_archive\_object\_prefix) | Object key prefix identifying one or more objects to which the lifecycle rule applies. | `string` | `""` | no | +| [lifecycle\_deep\_archive\_transition\_enabled](#input\_lifecycle\_deep\_archive\_transition\_enabled) | Specifies DEEP ARCHIVE transition lifecycle rule status. | `bool` | `false` | no | +| [lifecycle\_expiration\_enabled](#input\_lifecycle\_expiration\_enabled) | Specifies expiration lifecycle rule status. | `bool` | `false` | no | +| [lifecycle\_expiration\_object\_prefix](#input\_lifecycle\_expiration\_object\_prefix) | Object key prefix identifying one or more objects to which the lifecycle rule applies. | `string` | `""` | no | +| [lifecycle\_glacier\_object\_prefix](#input\_lifecycle\_glacier\_object\_prefix) | Object key prefix identifying one or more objects to which the lifecycle rule applies. | `string` | `""` | no | +| [lifecycle\_glacier\_transition\_enabled](#input\_lifecycle\_glacier\_transition\_enabled) | Specifies Glacier transition lifecycle rule status. | `bool` | `false` | no | +| [lifecycle\_infrequent\_storage\_object\_prefix](#input\_lifecycle\_infrequent\_storage\_object\_prefix) | Object key prefix identifying one or more objects to which the lifecycle rule applies. | `string` | `""` | no | +| [lifecycle\_infrequent\_storage\_transition\_enabled](#input\_lifecycle\_infrequent\_storage\_transition\_enabled) | Specifies infrequent storage transition lifecycle rule status. | `bool` | `false` | no | +| [logging](#input\_logging) | Logging Object to enable and disable logging | `bool` | `false` | no | +| [mfa\_delete](#input\_mfa\_delete) | Enable MFA delete for either Change the versioning state of your bucket or Permanently delete an object version. | `bool` | `false` | no | +| [name](#input\_name) | Name of RDS | `string` | `""` | no | +| [object\_lock\_configuration](#input\_object\_lock\_configuration) | With S3 Object Lock, you can store objects using a write-once-read-many (WORM) model. Object Lock can help prevent objects from being deleted or overwritten for a fixed amount of time or indefinitely. |
object({
mode = string #Valid values are GOVERNANCE and COMPLIANCE.
days = number
years = number
})
| `null` | no | +| [object\_ownership](#input\_object\_ownership) | Object ownership. Valid values: BucketOwnerEnforced, BucketOwnerPreferred or ObjectWriter. 'BucketOwnerEnforced': ACLs are disabled, and the bucket owner automatically owns and has full control over every object in the bucket. 'BucketOwnerPreferred': Objects uploaded to the bucket change ownership to the bucket owner if the objects are uploaded with the bucket-owner-full-control canned ACL. 'ObjectWriter': The uploading account will own the object if the object is uploaded with the bucket-owner-full-control canned ACL. | `string` | `"ObjectWriter"` | no | +| [owner\_id](#input\_owner\_id) | The canonical user ID associated with the AWS account. | `string` | `""` | no | +| [redirect](#input\_redirect) | The redirect behavior for every request to this bucket's website endpoint | `string` | `"documents/"` | no | +| [replication\_configuration](#input\_replication\_configuration) | Map containing cross-region replication configuration. | `any` | `{}` | no | +| [request\_payer](#input\_request\_payer) | Specifies who should bear the cost of Amazon S3 data transfer. Can be either BucketOwner or Requester. By default, the owner of the S3 bucket would incur the costs of any data transfer | `bool` | `false` | no | +| [restrict\_public\_buckets](#input\_restrict\_public\_buckets) | Whether Amazon S3 should restrict public bucket policies for this bucket. | `bool` | `false` | no | +| [routing\_rule](#input\_routing\_rule) | ist of rules that define when a redirect is applied and the redirect behavior | `string` | `"docs/"` | no | +| [sse\_algorithm](#input\_sse\_algorithm) | The server-side encryption algorithm to use. Valid values are AES256 and aws:kms. | `string` | `"AES256"` | no | +| [tags](#input\_tags) | Additional tags (e.g. map(`BusinessUnit`,`XYZ`). | `map(any)` | `{}` | no | +| [target\_bucket](#input\_target\_bucket) | The bucket where you want Amazon S3 to store server access logs. | `string` | `""` | no | +| [target\_prefix](#input\_target\_prefix) | A prefix for all log object keys. | `string` | `""` | no | +| [versioning](#input\_versioning) | Enable Versioning of S3. | `bool` | `true` | no | +| [website\_config\_enable](#input\_website\_config\_enable) | enable or disable aws\_s3\_bucket\_website\_configuration | `bool` | `false` | no | ## Outputs | Name | Description | |------|-------------| - +| [arn](#output\_arn) | The ARN of the s3 bucket. | +| [bucket\_domain\_name](#output\_bucket\_domain\_name) | The Domain of the s3 bucket. | +| [id](#output\_id) | The ID of the s3 bucket. | ## Contributing From 56b2166e4ce55f6c85f50b197879897e74730c1d Mon Sep 17 00:00:00 2001 From: kmobl Date: Tue, 12 Sep 2023 13:10:27 -0500 Subject: [PATCH 07/16] updated readme.md --- README.md | 97 ++++--------------------------------------------------- 1 file changed, 7 insertions(+), 90 deletions(-) diff --git a/README.md b/README.md index e589e55..8b0fedc 100644 --- a/README.md +++ b/README.md @@ -3,82 +3,29 @@ -# Coalfire pak README Template -## Repository Title +## ACE AWS S3 -Include the name of the Repository as the header above e.g. `ACE-Cloud-Service` ## Dependencies -List any dependencies here. E.g. security-core, region-setup +- kms keys from ACE-AWS-Account ## Resource List Insert a high-level list of resources created as a part of this module. E.g. -- Storage Account -- Containers -- Storage share -- Lifecycle policy -- CMK key and Iam Role Assignment -- Monitor diagnostic setting +- S3 bucket +- S3 bucket IAM policies ## Code Updates -If applicable, add here. For example, updating variables, updating `tstate.tf`, or remote data sources. - -`tstate.tf` Update to the appropriate version and storage accounts, see sample - -``` hcl -terraform { - required_version = ">= 1.1.7" - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 3.45.0" - } - } - backend "azurerm" { - resource_group_name = "prod-mp-core-rg" - storage_account_name = "prodmpsatfstate" - container_name = "tfstatecontainer" - environment = "usgovernment" - key = "ad.tfstate" - } -} -``` - -Change directory to the `active-directory` folder - -Run `terraform init` to download modules and create initial local state file. - -Run `terraform plan` to ensure no errors and validate plan is deploying expected resources. - -Run `terraform apply` to deploy infrastructure. - -Update the `remote-data.tf` file to add the security state key - -``` hcl - -data "terraform_remote_state" "usgv-ad" { - backend = "azurerm" - config = { - storage_account_name = "${local.storage_name_prefix}satfstate" - resource_group_name = "${local.resource_prefix}-core-rg" - container_name = "${var.location_abbreviation}${var.app_abbreviation}tfstatecontainer" - environment = var.az_environment - key = "${var.location_abbreviation}-ad.tfstate" - } -} -``` - ## Deployment Steps This module can be called as outlined below. - Change directories to the `reponame` directory. -- From the `terraform/azure/reponame` directory run `terraform init`. +- From the `terraform/aws/reponame` directory run `terraform init`. - Run `terraform plan` to review the resources being created. - If everything looks correct in the plan output, run `terraform apply`. @@ -92,38 +39,8 @@ provider "azurerm" { } module "core_sa" { - source = "github.com/Coalfire-CF/ACE-Azure-StorageAccount?ref=vX.X.X" - name = "${replace(var.resource_prefix, "-", "")}tfstatesa" - resource_group_name = azurerm_resource_group.management.name - location = var.location - account_kind = "StorageV2" - ip_rules = var.ip_for_remote_access - diag_log_analytics_id = azurerm_log_analytics_workspace.core-la.id - virtual_network_subnet_ids = var.fw_virtual_network_subnet_ids - tags = var.tags - - #OPTIONAL - public_network_access_enabled = true - enable_customer_managed_key = true - cmk_key_vault_id = module.core_kv.id - cmk_key_vault_key_name = azurerm_key_vault_key.tfstate-cmk.name - storage_containers = [ - "tfstate" - ] - storage_shares = [ - { - name = "test" - quota = 500 - } - ] - lifecycle_policies = [ - { - prefix_match = ["tfstate"] - version = { - delete_after_days_since_creation = 90 - } - } - ] + source = "github.com/Coalfire-CF/ACE-AWS-S3?ref=vX.X.X" + } ``` From 690df5a59161ffcfae5b19075fc7141cddc44593 Mon Sep 17 00:00:00 2001 From: kmobl Date: Tue, 12 Sep 2023 13:33:50 -0500 Subject: [PATCH 08/16] updated readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b0fedc..53ac878 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ No inputs. ## Outputs No outputs. - + ## Contributing From 73922bf8dbb72faa5bcf8feafcd64b3038c4cd45 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 12 Sep 2023 18:34:12 +0000 Subject: [PATCH 09/16] terraform-docs: automated action --- README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/README.md b/README.md index 53ac878..72cfad9 100644 --- a/README.md +++ b/README.md @@ -146,15 +146,6 @@ No modules. | [arn](#output\_arn) | The ARN of the s3 bucket. | | [bucket\_domain\_name](#output\_bucket\_domain\_name) | The Domain of the s3 bucket. | | [id](#output\_id) | The ID of the s3 bucket. | - - -## Inputs - -No inputs. - -## Outputs - -No outputs. ## Contributing From b717e4837cfad3aa9f7885f3ec24aeaea3caa922 Mon Sep 17 00:00:00 2001 From: kmobl Date: Tue, 12 Sep 2023 14:06:03 -0500 Subject: [PATCH 10/16] updated readme.md --- .github/workflows/workflows/org-checkov.yml | 12 ++++++++++++ .github/workflows/workflows/org-md-lint.yml | 12 ++++++++++++ .github/workflows/workflows/org-release.yml | 11 +++++++++++ .github/workflows/workflows/org-terraform-docs.yml | 8 ++++++++ 4 files changed, 43 insertions(+) create mode 100644 .github/workflows/workflows/org-checkov.yml create mode 100644 .github/workflows/workflows/org-md-lint.yml create mode 100644 .github/workflows/workflows/org-release.yml create mode 100644 .github/workflows/workflows/org-terraform-docs.yml diff --git a/.github/workflows/workflows/org-checkov.yml b/.github/workflows/workflows/org-checkov.yml new file mode 100644 index 0000000..1d3a1b4 --- /dev/null +++ b/.github/workflows/workflows/org-checkov.yml @@ -0,0 +1,12 @@ +name: Org Checkov +on: + pull_request: + paths: + - '**.tf' + branches: + - main + workflow_call: + +jobs: + check-markdown: + uses: Coalfire-CF/Actions/.github/workflows/org-checkov.yml@main \ No newline at end of file diff --git a/.github/workflows/workflows/org-md-lint.yml b/.github/workflows/workflows/org-md-lint.yml new file mode 100644 index 0000000..43447a0 --- /dev/null +++ b/.github/workflows/workflows/org-md-lint.yml @@ -0,0 +1,12 @@ +name: Markdown Lint +on: + pull_request: + paths: + - '**.md' + branches: + - main + workflow_call: + +jobs: + check-markdown: + uses: Coalfire-CF/Actions/.github/workflows/org-markdown-lint.yml@main \ No newline at end of file diff --git a/.github/workflows/workflows/org-release.yml b/.github/workflows/workflows/org-release.yml new file mode 100644 index 0000000..5095d16 --- /dev/null +++ b/.github/workflows/workflows/org-release.yml @@ -0,0 +1,11 @@ +name: Org Release +on: + pull_request: + types: + - closed + branches: + - main + +jobs: + create-release: + uses: Coalfire-CF/Actions/.github/workflows/org-release.yml@main \ No newline at end of file diff --git a/.github/workflows/workflows/org-terraform-docs.yml b/.github/workflows/workflows/org-terraform-docs.yml new file mode 100644 index 0000000..273ff8a --- /dev/null +++ b/.github/workflows/workflows/org-terraform-docs.yml @@ -0,0 +1,8 @@ +name: Org Terraform Docs +on: + pull_request: + workflow_call: + +jobs: + terraform-docs: + uses: Coalfire-CF/Actions/.github/workflows/org-terraform-docs.yml@main \ No newline at end of file From dc3ba6a8cbb3b400a76735856168c9fa7ddc3654 Mon Sep 17 00:00:00 2001 From: kmobl Date: Wed, 13 Sep 2023 08:14:31 -0500 Subject: [PATCH 11/16] update variables.tf --- variables.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/variables.tf b/variables.tf index 3cb27d6..bd7b5c7 100644 --- a/variables.tf +++ b/variables.tf @@ -36,7 +36,7 @@ variable "mfa_delete" { variable "enable_server_side_encryption" { type = bool - default = false + default = true description = "Enable enable_server_side_encryption" } @@ -48,7 +48,7 @@ variable "sse_algorithm" { variable "enable_kms" { type = bool - default = false + default = true description = "Enable enable_server_side_encryption" } From aae00edc0eb8e947f739fc88485f26cd210a0502 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 13 Sep 2023 13:15:52 +0000 Subject: [PATCH 12/16] terraform-docs: automated action --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 72cfad9..d95aa27 100644 --- a/README.md +++ b/README.md @@ -99,9 +99,9 @@ No modules. | [control\_object\_ownership](#input\_control\_object\_ownership) | Whether to manage S3 Bucket Ownership Controls on this bucket. | `bool` | `false` | no | | [cors\_rule](#input\_cors\_rule) | CORS Configuration specification for this bucket |
list(object({
allowed_headers = list(string)
allowed_methods = list(string)
allowed_origins = list(string)
expose_headers = list(string)
max_age_seconds = number
}))
| `null` | no | | [create\_bucket](#input\_create\_bucket) | Conditionally create S3 bucket. | `bool` | `true` | no | -| [enable\_kms](#input\_enable\_kms) | Enable enable\_server\_side\_encryption | `bool` | `false` | no | +| [enable\_kms](#input\_enable\_kms) | Enable enable\_server\_side\_encryption | `bool` | `true` | no | | [enable\_lifecycle\_configuration\_rules](#input\_enable\_lifecycle\_configuration\_rules) | enable or disable lifecycle\_configuration\_rules | `bool` | `false` | no | -| [enable\_server\_side\_encryption](#input\_enable\_server\_side\_encryption) | Enable enable\_server\_side\_encryption | `bool` | `false` | no | +| [enable\_server\_side\_encryption](#input\_enable\_server\_side\_encryption) | Enable enable\_server\_side\_encryption | `bool` | `true` | no | | [error\_document](#input\_error\_document) | he name of the error document for the website | `string` | `"error.html"` | no | | [force\_destroy](#input\_force\_destroy) | A boolean that indicates all objects should be deleted from the bucket so that the bucket can be destroyed without error. These objects are not recoverable. | `bool` | `false` | no | | [grants](#input\_grants) | ACL Policy grant.conflict with acl.set acl null to use this |
list(object({
id = string
type = string
permissions = list(string)
uri = string
}))
| `null` | no | From ff350c38b799afdd9e6886b4980b21d650272815 Mon Sep 17 00:00:00 2001 From: kmobl Date: Wed, 13 Sep 2023 10:15:24 -0500 Subject: [PATCH 13/16] update variables.tf --- variables.tf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/variables.tf b/variables.tf index bd7b5c7..5dd4c7c 100644 --- a/variables.tf +++ b/variables.tf @@ -1,7 +1,7 @@ variable "name" { type = string default = "" - description = "Name of RDS" + description = "Name of S3 bucket" } variable "tags" { @@ -54,8 +54,7 @@ variable "enable_kms" { variable "kms_master_key_id" { type = string - default = "" - description = "The AWS KMS master key ID used for the SSE-KMS encryption. This can only be used when you set the value of sse_algorithm as aws:kms. The default aws/s3 AWS KMS master key is used if this element is absent while the sse_algorithm is aws:kms." + description = "The AWS KMS master key ID used for the SSE-KMS encryption. This can only be used when you set the value of sse_algorithm as aws:kms. The default aws/s3 AWS KMS master key is used if this element is absent while the sse_algorithm is aws:kms." } variable "enable_lifecycle_configuration_rules" { From e0cbc7dd2af12ff4bb5579e19fa5506f5862c3d8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 13 Sep 2023 15:15:53 +0000 Subject: [PATCH 14/16] terraform-docs: automated action --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d95aa27..d913c2e 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ No modules. | [grants](#input\_grants) | ACL Policy grant.conflict with acl.set acl null to use this |
list(object({
id = string
type = string
permissions = list(string)
uri = string
}))
| `null` | no | | [ignore\_public\_acls](#input\_ignore\_public\_acls) | Whether Amazon S3 should ignore public ACLs for this bucket. | `bool` | `false` | no | | [index\_document](#input\_index\_document) | The name of the index document for the website | `string` | `"index.html"` | no | -| [kms\_master\_key\_id](#input\_kms\_master\_key\_id) | The AWS KMS master key ID used for the SSE-KMS encryption. This can only be used when you set the value of sse\_algorithm as aws:kms. The default aws/s3 AWS KMS master key is used if this element is absent while the sse\_algorithm is aws:kms. | `string` | `""` | no | +| [kms\_master\_key\_id](#input\_kms\_master\_key\_id) | The AWS KMS master key ID used for the SSE-KMS encryption. This can only be used when you set the value of sse\_algorithm as aws:kms. The default aws/s3 AWS KMS master key is used if this element is absent while the sse\_algorithm is aws:kms. | `string` | n/a | yes | | [lifecycle\_configuration\_rules](#input\_lifecycle\_configuration\_rules) | A list of lifecycle rules |
list(object({
id = string
prefix = string
enabled = bool
tags = map(string)

enable_glacier_transition = bool
enable_deeparchive_transition = bool
enable_standard_ia_transition = bool
enable_current_object_expiration = bool
enable_noncurrent_version_expiration = bool

abort_incomplete_multipart_upload_days = number
noncurrent_version_glacier_transition_days = number
noncurrent_version_deeparchive_transition_days = number
noncurrent_version_expiration_days = number

standard_transition_days = number
glacier_transition_days = number
deeparchive_transition_days = number
expiration_days = number
}))
| `null` | no | | [lifecycle\_days\_to\_deep\_archive\_transition](#input\_lifecycle\_days\_to\_deep\_archive\_transition) | Specifies the number of days after object creation when it will be moved to DEEP ARCHIVE . | `number` | `180` | no | | [lifecycle\_days\_to\_expiration](#input\_lifecycle\_days\_to\_expiration) | Specifies the number of days after object creation when the object expires. | `number` | `365` | no | @@ -123,7 +123,7 @@ No modules. | [lifecycle\_infrequent\_storage\_transition\_enabled](#input\_lifecycle\_infrequent\_storage\_transition\_enabled) | Specifies infrequent storage transition lifecycle rule status. | `bool` | `false` | no | | [logging](#input\_logging) | Logging Object to enable and disable logging | `bool` | `false` | no | | [mfa\_delete](#input\_mfa\_delete) | Enable MFA delete for either Change the versioning state of your bucket or Permanently delete an object version. | `bool` | `false` | no | -| [name](#input\_name) | Name of RDS | `string` | `""` | no | +| [name](#input\_name) | Name of S3 bucket | `string` | `""` | no | | [object\_lock\_configuration](#input\_object\_lock\_configuration) | With S3 Object Lock, you can store objects using a write-once-read-many (WORM) model. Object Lock can help prevent objects from being deleted or overwritten for a fixed amount of time or indefinitely. |
object({
mode = string #Valid values are GOVERNANCE and COMPLIANCE.
days = number
years = number
})
| `null` | no | | [object\_ownership](#input\_object\_ownership) | Object ownership. Valid values: BucketOwnerEnforced, BucketOwnerPreferred or ObjectWriter. 'BucketOwnerEnforced': ACLs are disabled, and the bucket owner automatically owns and has full control over every object in the bucket. 'BucketOwnerPreferred': Objects uploaded to the bucket change ownership to the bucket owner if the objects are uploaded with the bucket-owner-full-control canned ACL. 'ObjectWriter': The uploading account will own the object if the object is uploaded with the bucket-owner-full-control canned ACL. | `string` | `"ObjectWriter"` | no | | [owner\_id](#input\_owner\_id) | The canonical user ID associated with the AWS account. | `string` | `""` | no | From f3908f3f0a9e15cf57732dddbac77023587e6606 Mon Sep 17 00:00:00 2001 From: kmobl Date: Fri, 22 Sep 2023 11:12:58 -0500 Subject: [PATCH 15/16] Addressing PR comments --- README.md | 3 ++- main.tf | 48 ++++++++---------------------------------------- outputs.tf | 5 +++++ variables.tf | 9 +++++---- 4 files changed, 20 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index d913c2e..f2cb3ba 100644 --- a/README.md +++ b/README.md @@ -34,13 +34,14 @@ This module can be called as outlined below. Include example for how to call the module below with generic variables ```hcl -provider "azurerm" { +provider "aws" { features {} } module "core_sa" { source = "github.com/Coalfire-CF/ACE-AWS-S3?ref=vX.X.X" + } ``` diff --git a/main.tf b/main.tf index 99de251..423eaae 100644 --- a/main.tf +++ b/main.tf @@ -96,19 +96,19 @@ resource "aws_s3_bucket_website_configuration" "example" { bucket = join("", aws_s3_bucket.s3_default.*.id) index_document { - suffix = "index.html" + suffix = var.index_document } error_document { - key = "error.html" + key = var.error_document } routing_rule { condition { - key_prefix_equals = "docs/" + key_prefix_equals = var.routing_rule } redirect { - replace_key_prefix_with = "documents/" + replace_key_prefix_with = var.redirect } } } @@ -127,38 +127,6 @@ locals { ]) } -resource "aws_s3_bucket_acl" "default" { - - count = var.create_bucket ? var.grants != null ? var.acl != null ? 1 : 0 : 0 : 0 - bucket = join("", aws_s3_bucket.s3_default.*.id) - - - acl = try(length(local.acl_grants), 0) == 0 ? var.acl : null - - dynamic "access_control_policy" { - for_each = try(length(local.acl_grants), 0) == 0 || try(length(var.acl), 0) > 0 ? [] : [1] - - content { - dynamic "grant" { - for_each = local.acl_grants - - content { - grantee { - id = grant.value.id - type = grant.value.type - uri = grant.value.uri - } - permission = grant.value.permission - } - } - - owner { - id = var.owner_id - } - } - } -} - resource "aws_s3_bucket_lifecycle_configuration" "default" { count = var.create_bucket && var.enable_lifecycle_configuration_rules == true ? 1 : 0 bucket = join("", aws_s3_bucket.s3_default.*.id) @@ -253,7 +221,7 @@ resource "aws_s3_bucket_lifecycle_configuration" "default" { depends_on = [ # versioning must be set before lifecycle configuration - aws_s3_bucket_versioning.example + aws_s3_bucket_versioning.example[0] ] } @@ -284,8 +252,8 @@ resource "aws_s3_bucket_ownership_controls" "this" { # This `depends_on` is to prevent "A conflicting conditional operation is currently in progress against this resource." depends_on = [ - aws_s3_bucket_policy.s3_default, - aws_s3_bucket_public_access_block.this, - aws_s3_bucket.s3_default + aws_s3_bucket_policy.s3_default[0], + aws_s3_bucket_public_access_block.this[0], + aws_s3_bucket.s3_default[0] ] } \ No newline at end of file diff --git a/outputs.tf b/outputs.tf index 0fa380c..32f79c4 100644 --- a/outputs.tf +++ b/outputs.tf @@ -11,4 +11,9 @@ output "arn" { output "bucket_domain_name" { value = join("", aws_s3_bucket.s3_default.*.bucket_domain_name) description = "The Domain of the s3 bucket." +} + +output "key_iam" { + value = join("", aws_s3_bucket.s3_default.*.bucket_domain_name) + description = "The Domain of the s3 bucket." } \ No newline at end of file diff --git a/variables.tf b/variables.tf index 5dd4c7c..bf8921e 100644 --- a/variables.tf +++ b/variables.tf @@ -1,6 +1,5 @@ variable "name" { type = string - default = "" description = "Name of S3 bucket" } @@ -49,12 +48,13 @@ variable "sse_algorithm" { variable "enable_kms" { type = bool default = true - description = "Enable enable_server_side_encryption" + description = "Enable KMS key for enable_server_side_encryption" } variable "kms_master_key_id" { type = string - description = "The AWS KMS master key ID used for the SSE-KMS encryption. This can only be used when you set the value of sse_algorithm as aws:kms. The default aws/s3 AWS KMS master key is used if this element is absent while the sse_algorithm is aws:kms." + description = "The AWS KMS master key ID used for the SSE-KMS encryption. This can only be used when you set the value of sse_algorithm as aws:kms. The default aws/s3 AWS KMS master key is used if this element is absent while the sse_algorithm is aws:kms." + default = null } variable "enable_lifecycle_configuration_rules" { @@ -172,6 +172,7 @@ variable "aws_iam_policy_document" { default = "" sensitive = true description = "The text of the policy. Although this is a bucket policy rather than an IAM policy, the aws_iam_policy_document data source may be used, so long as it specifies a principal. For more information about building AWS IAM policy documents with Terraform, see the AWS IAM Policy Document Guide. Note: Bucket policies are limited to 20 KB in size." + #https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document } variable "bucket_policy" { @@ -240,7 +241,7 @@ variable "error_document" { variable "routing_rule" { type = string default = "docs/" - description = "ist of rules that define when a redirect is applied and the redirect behavior " + description = "List of rules that define when a redirect is applied and the redirect behavior " } variable "redirect" { type = string From 29564b74da0b18e0e3f6233b8b089e058993b6f3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 22 Sep 2023 16:13:26 +0000 Subject: [PATCH 16/16] terraform-docs: automated action --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f2cb3ba..246a143 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,6 @@ No modules. |------|------| | [aws_s3_bucket.s3_default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket_accelerate_configuration.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_accelerate_configuration) | resource | -| [aws_s3_bucket_acl.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_acl) | resource | | [aws_s3_bucket_cors_configuration.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_cors_configuration) | resource | | [aws_s3_bucket_lifecycle_configuration.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource | | [aws_s3_bucket_logging.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | @@ -100,7 +99,7 @@ No modules. | [control\_object\_ownership](#input\_control\_object\_ownership) | Whether to manage S3 Bucket Ownership Controls on this bucket. | `bool` | `false` | no | | [cors\_rule](#input\_cors\_rule) | CORS Configuration specification for this bucket |
list(object({
allowed_headers = list(string)
allowed_methods = list(string)
allowed_origins = list(string)
expose_headers = list(string)
max_age_seconds = number
}))
| `null` | no | | [create\_bucket](#input\_create\_bucket) | Conditionally create S3 bucket. | `bool` | `true` | no | -| [enable\_kms](#input\_enable\_kms) | Enable enable\_server\_side\_encryption | `bool` | `true` | no | +| [enable\_kms](#input\_enable\_kms) | Enable KMS key for enable\_server\_side\_encryption | `bool` | `true` | no | | [enable\_lifecycle\_configuration\_rules](#input\_enable\_lifecycle\_configuration\_rules) | enable or disable lifecycle\_configuration\_rules | `bool` | `false` | no | | [enable\_server\_side\_encryption](#input\_enable\_server\_side\_encryption) | Enable enable\_server\_side\_encryption | `bool` | `true` | no | | [error\_document](#input\_error\_document) | he name of the error document for the website | `string` | `"error.html"` | no | @@ -108,7 +107,7 @@ No modules. | [grants](#input\_grants) | ACL Policy grant.conflict with acl.set acl null to use this |
list(object({
id = string
type = string
permissions = list(string)
uri = string
}))
| `null` | no | | [ignore\_public\_acls](#input\_ignore\_public\_acls) | Whether Amazon S3 should ignore public ACLs for this bucket. | `bool` | `false` | no | | [index\_document](#input\_index\_document) | The name of the index document for the website | `string` | `"index.html"` | no | -| [kms\_master\_key\_id](#input\_kms\_master\_key\_id) | The AWS KMS master key ID used for the SSE-KMS encryption. This can only be used when you set the value of sse\_algorithm as aws:kms. The default aws/s3 AWS KMS master key is used if this element is absent while the sse\_algorithm is aws:kms. | `string` | n/a | yes | +| [kms\_master\_key\_id](#input\_kms\_master\_key\_id) | The AWS KMS master key ID used for the SSE-KMS encryption. This can only be used when you set the value of sse\_algorithm as aws:kms. The default aws/s3 AWS KMS master key is used if this element is absent while the sse\_algorithm is aws:kms. | `string` | `null` | no | | [lifecycle\_configuration\_rules](#input\_lifecycle\_configuration\_rules) | A list of lifecycle rules |
list(object({
id = string
prefix = string
enabled = bool
tags = map(string)

enable_glacier_transition = bool
enable_deeparchive_transition = bool
enable_standard_ia_transition = bool
enable_current_object_expiration = bool
enable_noncurrent_version_expiration = bool

abort_incomplete_multipart_upload_days = number
noncurrent_version_glacier_transition_days = number
noncurrent_version_deeparchive_transition_days = number
noncurrent_version_expiration_days = number

standard_transition_days = number
glacier_transition_days = number
deeparchive_transition_days = number
expiration_days = number
}))
| `null` | no | | [lifecycle\_days\_to\_deep\_archive\_transition](#input\_lifecycle\_days\_to\_deep\_archive\_transition) | Specifies the number of days after object creation when it will be moved to DEEP ARCHIVE . | `number` | `180` | no | | [lifecycle\_days\_to\_expiration](#input\_lifecycle\_days\_to\_expiration) | Specifies the number of days after object creation when the object expires. | `number` | `365` | no | @@ -124,7 +123,7 @@ No modules. | [lifecycle\_infrequent\_storage\_transition\_enabled](#input\_lifecycle\_infrequent\_storage\_transition\_enabled) | Specifies infrequent storage transition lifecycle rule status. | `bool` | `false` | no | | [logging](#input\_logging) | Logging Object to enable and disable logging | `bool` | `false` | no | | [mfa\_delete](#input\_mfa\_delete) | Enable MFA delete for either Change the versioning state of your bucket or Permanently delete an object version. | `bool` | `false` | no | -| [name](#input\_name) | Name of S3 bucket | `string` | `""` | no | +| [name](#input\_name) | Name of S3 bucket | `string` | n/a | yes | | [object\_lock\_configuration](#input\_object\_lock\_configuration) | With S3 Object Lock, you can store objects using a write-once-read-many (WORM) model. Object Lock can help prevent objects from being deleted or overwritten for a fixed amount of time or indefinitely. |
object({
mode = string #Valid values are GOVERNANCE and COMPLIANCE.
days = number
years = number
})
| `null` | no | | [object\_ownership](#input\_object\_ownership) | Object ownership. Valid values: BucketOwnerEnforced, BucketOwnerPreferred or ObjectWriter. 'BucketOwnerEnforced': ACLs are disabled, and the bucket owner automatically owns and has full control over every object in the bucket. 'BucketOwnerPreferred': Objects uploaded to the bucket change ownership to the bucket owner if the objects are uploaded with the bucket-owner-full-control canned ACL. 'ObjectWriter': The uploading account will own the object if the object is uploaded with the bucket-owner-full-control canned ACL. | `string` | `"ObjectWriter"` | no | | [owner\_id](#input\_owner\_id) | The canonical user ID associated with the AWS account. | `string` | `""` | no | @@ -132,7 +131,7 @@ No modules. | [replication\_configuration](#input\_replication\_configuration) | Map containing cross-region replication configuration. | `any` | `{}` | no | | [request\_payer](#input\_request\_payer) | Specifies who should bear the cost of Amazon S3 data transfer. Can be either BucketOwner or Requester. By default, the owner of the S3 bucket would incur the costs of any data transfer | `bool` | `false` | no | | [restrict\_public\_buckets](#input\_restrict\_public\_buckets) | Whether Amazon S3 should restrict public bucket policies for this bucket. | `bool` | `false` | no | -| [routing\_rule](#input\_routing\_rule) | ist of rules that define when a redirect is applied and the redirect behavior | `string` | `"docs/"` | no | +| [routing\_rule](#input\_routing\_rule) | List of rules that define when a redirect is applied and the redirect behavior | `string` | `"docs/"` | no | | [sse\_algorithm](#input\_sse\_algorithm) | The server-side encryption algorithm to use. Valid values are AES256 and aws:kms. | `string` | `"AES256"` | no | | [tags](#input\_tags) | Additional tags (e.g. map(`BusinessUnit`,`XYZ`). | `map(any)` | `{}` | no | | [target\_bucket](#input\_target\_bucket) | The bucket where you want Amazon S3 to store server access logs. | `string` | `""` | no | @@ -147,6 +146,7 @@ No modules. | [arn](#output\_arn) | The ARN of the s3 bucket. | | [bucket\_domain\_name](#output\_bucket\_domain\_name) | The Domain of the s3 bucket. | | [id](#output\_id) | The ID of the s3 bucket. | +| [key\_iam](#output\_key\_iam) | The Domain of the s3 bucket. | ## Contributing