diff --git a/modules/storage/s3_bucket_2023/README.md b/modules/storage/s3_bucket_2023/README.md index f92afed..f86df20 100644 --- a/modules/storage/s3_bucket_2023/README.md +++ b/modules/storage/s3_bucket_2023/README.md @@ -1,263 +1,68 @@ -# s3_bucket_2023 module -This module creates s3 bucket, following new terraform standards. + +## Requirements -If lifecycle policy is enabled, provide the expiration days. -Transition days are hard-coded with intelligent-tiering class to simplify administration. +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| aws | >= 3.72.0 | -## Example -```hcl -module "bucket1" { - source = "../../../../whk1-bea-sys-ss-prd-codecommit-sharedmodules/Storage/s3_bucket_2023" +## Providers - bucket_name = var.bucket_name1 - bucket_policy_json = jsonencode( - { - "Version" : "2012-10-17", - "Id" : "", - "Statement" : [ - { - "Sid" : "Set permissions for objects", - "Effect" : "Allow", - "Principal" : { - "AWS" : "851239346925" - }, - "Action" : ["s3:ReplicateObject", "s3:ReplicateDelete"], - "Resource" : "arn:aws:s3:::${var.bucket_name1}/*" - } - ] - } - ) - enable_encryption = true - encryption_key_arn = var.encryption_key_arn - enable_versioning = false - enable_bucket_logging = false - enable_bucket_lifecycle = true - current_version_expiration_days = 731 - noncurrent_version_expiration_days = 731 -} +| Name | Version | +|------|---------| +| aws | >= 3.72.0 | -``` +## Modules -## Note on bucket replication -To securely replicate a bucket to a bucket in another aws account, kms key is required. +No modules. -Steps to setup replication are: -1. Create replication iam role on the source account, with an assume role policy trusting s3 -```json - { - "Effect":"Allow", - "Principal":{ - "Service":"s3.amazonaws.com" - }, - "Action":"sts:AssumeRole" - } -``` -The role needs permissions granted in the role iam policy. For example: -```json -{ - "Statement": [ - { - "Action": [ - "s3:ListBucket", - "s3:GetReplicationConfiguration" - ], - "Effect": "Allow", - "Resource": "arn:aws:s3:::whk1-bea-icc-mbk-prd-vpc01-flowlog-s3-accept", - "Sid": "" - }, - { - "Action": [ - "s3:GetObjectVersionTagging", - "s3:GetObjectVersionForReplication", - "s3:GetObjectVersionAcl" - ], - "Effect": "Allow", - "Resource": "arn:aws:s3:::whk1-bea-icc-mbk-prd-vpc01-flowlog-s3-accept/*", - "Sid": "" - }, - { - "Action": [ - "s3:ReplicateTags", - "s3:ReplicateObject", - "s3:ReplicateDelete", - "s3:ObjectOwnerOverrideToBucketOwner" - ], - "Effect": "Allow", - "Resource": "arn:aws:s3:::whk1-bea-icc-log-mbk-prd-vpc01-flowlog-s3-accept/*", - "Sid": "" - }, - { - "Effect": "Allow", - "Action": [ - "kms:Decrypt", - "kms:GenerateDataKey" - ], - "Resource": [ - "arn:aws:kms:ap-east-1:851239346925:key/708b6ece-05f5-40ed-a91c-dbcf2af46407" - ] - }, - { - "Effect": "Allow", - "Action": [ - "kms:GenerateDataKey", - "kms:Encrypt" - ], - "Resource": [ - "arn:aws:kms:ap-east-1:894849410890:key/b555d9d6-d451-4ec8-8ca2-cb6849cadee4" - ] - } - ], - "Version": "2012-10-17" -} -``` -If bucket key is used, then additional permission needs to be granted -```json -{ - "Action":[ - "kms:Decrypt" - ], - "Effect":"Allow", - "Condition":{ - "StringLike":{ - "kms:ViaService":"s3.ap-east-1.amazonaws.com", - "kms:EncryptionContext:aws:s3:arn":[ - "arn:aws:s3:::/*" - ] - } - }, - "Resource":[ - "arn:aws:kms:ap-east-1::key/" - ] - }, - { - "Action":[ - "kms:Encrypt" - ], - "Effect":"Allow", - "Condition":{ - "StringLike":{ - "kms:ViaService":"s3.ap-east-1.amazonaws.com", - "kms:EncryptionContext:aws:s3:arn":[ - "arn:aws:s3:::/*" - ] - } - }, - "Resource":[ - "arn:aws:kms:ap-east-1::key/" - ] - } -``` +## Resources -2. On the destination account, grant access in KMS key policy -```json -{ - "Version": "2012-10-17", - "Id": "key-consolepolicy-3", - "Statement": [ - { - "Sid": "Enable IAM User Permissions", - "Effect": "Allow", - "Principal": { - "AWS": "arn:aws:iam:::root" - }, - "Action": "kms:*", - "Resource": "*" - }, - { - "Sid": "Allow use of the key", - "Effect": "Allow", - "Principal": { - "AWS": [ - "arn:aws:iam:::root", - "arn:aws:iam:::root" - ] - }, - "Action": [ - "kms:Encrypt", - "kms:Decrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*", - "kms:DescribeKey" - ], - "Resource": "*" - }, - { - "Sid": "Allow attachment of persistent resources", - "Effect": "Allow", - "Principal": { - "AWS": [ - "arn:aws:iam:::root", - "arn:aws:iam:::root" - ] - }, - "Action": [ - "kms:CreateGrant", - "kms:ListGrants", - "kms:RevokeGrant" - ], - "Resource": "*", - "Condition": { - "Bool": { - "kms:GrantIsForAWSResource": "true" - } - } - }, - { - "Sid": "Allow AWS Service to use the key", - "Effect": "Allow", - "Principal": { - "Service": [ - "s3.amazonaws.com", - "delivery.logs.amazonaws.com", - "cloudtrail.amazonaws.com" - ] - }, - "Action": [ - "kms:Encrypt", - "kms:Decrypt", - "kms:ReEncrypt*", - "kms:GenerateDataKey*", - "kms:DescribeKey" - ], - "Resource": "*" - } - ] -} -``` +| Name | Type | +|------|------| +| [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_intelligent_tiering_configuration.intel_tiering_config](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_intelligent_tiering_configuration) | resource | +| [aws_s3_bucket_lifecycle_configuration.lifecycle](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource | +| [aws_s3_bucket_logging.logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | +| [aws_s3_bucket_policy.bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | +| [aws_s3_bucket_public_access_block.block_public_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | +| [aws_s3_bucket_replication_configuration.replication](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_replication_configuration) | resource | +| [aws_s3_bucket_server_side_encryption_configuration.encryption](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [aws_s3_bucket_versioning.versioning](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | +| [aws_iam_policy_document.bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -3. Edit destination bucket policy -```json -{ - "Version": "2012-10-17", - "Id": "", - "Statement": [ - { - "Sid": "Set permissions for objects", - "Effect": "Allow", - "Principal": { - "AWS": "arn:aws:iam:::root" - }, - "Action": [ - "s3:ReplicateDelete", - "s3:ReplicateObject", - "s3:ReplicateTags", - "s3:ObjectOwnerOverrideToBucketOwner" - ], - "Resource": "arn:aws:s3:::/*" - }, - { - "Sid": "Set permissions on bucket", - "Effect": "Allow", - "Principal": { - "AWS": "arn:aws:iam:::root" - }, - "Action": [ - "s3:List*", - "s3:GetBucketVersioning", - "s3:PutBucketVersioning" - ], - "Resource": "arn:aws:s3:::" - } - ] -} -``` +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| bucket\_name | Name of bucket | `string` | n/a | yes | +| bucket\_policy\_json | Json-encoded bucket policy. The AllowSSLRequestsOnly policy is merged with this input. | `string` | `"{}"` | no | +| current-version-archive-tier | Current version archive storage class. Valid values are GLACIER, STANDARD\_IA, ONEZONE\_IA, INTELLIGENT\_TIERING, DEEP\_ARCHIVE, GLACIER\_IR | `string` | `null` | no | +| current-version-transition-days | Days to transition current version to archive | `number` | `15` | no | +| current\_version\_expiration\_days | 731 for flowlogs | `number` | `2560` | no | +| enable\_bucket\_lifecycle | Enable s3 bucket lifecycle | `bool` | n/a | yes | +| enable\_bucket\_logging | Enable bucket logging | `bool` | n/a | yes | +| enable\_encryption | Enable encryption for s3 bucket | `bool` | n/a | yes | +| enable\_intelligent\_tiering | Enable intelligent tiering | `bool` | `true` | no | +| enable\_replication | Enable s3 bucket replication | `bool` | `false` | no | +| enable\_versioning | Enable s3 bucket versioning | `bool` | n/a | yes | +| encryption\_key\_arn | Leave blank to use AES256 | `string` | `""` | no | +| logging\_bucket\_id | Logging bucket id | `string` | `null` | no | +| noncurrent-version-archive-tier | Non-current version archive storage class. Valid values are GLACIER, STANDARD\_IA, ONEZONE\_IA, INTELLIGENT\_TIERING, DEEP\_ARCHIVE, GLACIER\_IR | `string` | `"GLACIER"` | no | +| noncurrent-version-transition-days | Days to transition non-current version to archive | `number` | `15` | no | +| noncurrent\_version\_expiration\_days | 731 for flowlogs | `number` | `2560` | no | +| replication\_dest\_bucket\_name | Replica bucket name | `string` | `null` | no | +| replication\_destination\_aws\_account\_id | AWS account id of replica bucket | `number` | `null` | no | +| replication\_destination\_kms\_key\_arn | KMS key ARN of destination bucket | `string` | `null` | no | +| replication\_role\_arn | IAM role of s3 bucket replication | `string` | `null` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| bucket\_arn | n/a | +| bucket\_name | n/a | + +--- +## Authorship +This module was developed by UPDATE_THIS. \ No newline at end of file diff --git a/modules/storage/s3_bucket_2023/example/main.tf b/modules/storage/s3_bucket_2023/example/main.tf new file mode 100644 index 0000000..e3f7d7e --- /dev/null +++ b/modules/storage/s3_bucket_2023/example/main.tf @@ -0,0 +1,14 @@ +module "example-bucket" { + source = "../" + + bucket_name = "example-bucket" + enable_bucket_lifecycle = true + current-version-archive-tier = "DEEP_ARCHIVE" + current-version-transition-days = 30 + current_version_expiration_days = 365 + enable_intelligent_tiering = false + enable_bucket_logging = false + enable_encryption = true + enable_versioning = false + encryption_key_arn = var.s3-cmk-arn +} \ No newline at end of file diff --git a/modules/storage/s3_bucket_2023/main.tf b/modules/storage/s3_bucket_2023/main.tf index 75e2960..c037c78 100644 --- a/modules/storage/s3_bucket_2023/main.tf +++ b/modules/storage/s3_bucket_2023/main.tf @@ -1,6 +1,5 @@ resource "aws_s3_bucket" "this" { - bucket = var.bucket_name - force_destroy = var.bucket_force_destroy + bucket = var.bucket_name } resource "aws_s3_bucket_public_access_block" "block_public_access" { @@ -47,41 +46,41 @@ resource "aws_s3_bucket_lifecycle_configuration" "lifecycle" { bucket = aws_s3_bucket.this.id rule { id = "CurrentVersion" - + filter {} expiration { days = var.current_version_expiration_days } status = "Enabled" - transition { - days = 15 - storage_class = "INTELLIGENT_TIERING" + dynamic "transition" { + for_each = var.enable_intelligent_tiering ? [1] : [] + content { + days = var.current-version-transition-days + storage_class = "INTELLIGENT_TIERING" + } } - - filter {} } rule { id = "NonCurrentVersion" - + filter {} noncurrent_version_expiration { noncurrent_days = var.noncurrent_version_expiration_days } noncurrent_version_transition { - noncurrent_days = 15 - storage_class = "INTELLIGENT_TIERING" + noncurrent_days = var.noncurrent-version-transition-days + storage_class = var.enable_intelligent_tiering ? "INTELLIGENT_TIERING" : var.noncurrent-version-archive-tier } - filter {} - status = var.enable_versioning ? "Enabled" : "Disabled" } } resource "aws_s3_bucket_intelligent_tiering_configuration" "intel_tiering_config" { + count = var.enable_intelligent_tiering ? 1 : 0 bucket = aws_s3_bucket.this.id name = "IntelligentTieringArchiveConfigurations" @@ -110,7 +109,7 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "encryption" { kms_master_key_id = var.encryption_key_arn sse_algorithm = length(var.encryption_key_arn) > 0 ? "aws:kms" : "AES256" } - bucket_key_enabled = length(var.encryption_key_arn) > 0 ? true : false + bucket_key_enabled = var.encryption-enable-bucket-key } } diff --git a/modules/storage/s3_bucket_2023/variables.tf b/modules/storage/s3_bucket_2023/variables.tf index 7812a72..a67fb76 100644 --- a/modules/storage/s3_bucket_2023/variables.tf +++ b/modules/storage/s3_bucket_2023/variables.tf @@ -3,12 +3,6 @@ variable "bucket_name" { description = "Name of bucket" } -variable "bucket_force_destroy" { - type = bool - default = false - description = "Indicates all objects should be deleted from the bucket when the bucket is destroyed." -} - variable "bucket_policy_json" { type = string default = "{}" @@ -19,10 +13,6 @@ variable "current_version_expiration_days" { type = number default = 2560 description = "731 for flowlogs" - validation { - condition = var.current_version_expiration_days > 15 - error_message = "Must be greater than 15 days" - } } variable "noncurrent_version_expiration_days" { @@ -86,4 +76,40 @@ variable "replication_destination_kms_key_arn" { type = string default = null description = "KMS key ARN of destination bucket" +} + +variable "enable_intelligent_tiering" { + type = bool + default = true + description = "Enable intelligent tiering" +} + +variable "current-version-archive-tier" { + type = string + description = "Current version archive storage class. Valid values are GLACIER, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, DEEP_ARCHIVE, GLACIER_IR" + default = null +} + +variable "noncurrent-version-archive-tier" { + type = string + description = "Non-current version archive storage class. Valid values are GLACIER, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING, DEEP_ARCHIVE, GLACIER_IR" + default = "GLACIER" +} + +variable "current-version-transition-days" { + type = number + description = "Days to transition current version to archive" + default = 15 +} + +variable "noncurrent-version-transition-days" { + type = number + description = "Days to transition non-current version to archive" + default = 15 +} + +variable "encryption-enable-bucket-key" { + type = bool + default = false + description = "Enable bucket key" } \ No newline at end of file