diff --git a/README.md b/README.md index ef4b644..a7f1dbe 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ These features of S3 bucket configurations are supported: - Account-level Public Access Block - S3 Directory Bucket - S3 Table Bucket +- S3 Bucket ABAC (Attribute Based Access Control) ## Usage @@ -97,6 +98,20 @@ module "s3_bucket_for_waf_logs" { } ``` +### Bucket with ABAC enabled + +```hcl +module "s3_bucket" { + source = "terraform-aws-modules/s3-bucket/aws" + + bucket = "my-s3-bucket" + + abac_status = { + status = "Enabled" + } +} +``` + ### Bucket with a custom policy attached When you need to attach a custom policy to the bucket, you can use the `policy` argument. To keep bucket policy with correct S3 bucket and AWS account properties, you can use the placeholders `_S3_BUCKET_ID_`, `_S3_BUCKET_ARN_`, and `_AWS_ACCOUNT_ID_` in the policy document. Those values will be replaced with the actual values during the policy attachment. This is especially useful when using bucket prefixes. @@ -173,6 +188,7 @@ No modules. | Name | Type | |------|------| | [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_abac.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_abac) | resource | | [aws_s3_bucket_accelerate_configuration.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_accelerate_configuration) | resource | | [aws_s3_bucket_acl.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_acl) | resource | | [aws_s3_bucket_analytics_configuration.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_analytics_configuration) | resource | @@ -215,6 +231,7 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [abac\_status](#input\_abac\_status) | Map containing ABAC (Attribute Based Access Control) configuration | `any` | `{}` | no | | [acceleration\_status](#input\_acceleration\_status) | (Optional) Sets the accelerate configuration of an existing bucket. Can be Enabled or Suspended. | `string` | `null` | no | | [access\_log\_delivery\_policy\_source\_accounts](#input\_access\_log\_delivery\_policy\_source\_accounts) | (Optional) List of AWS Account IDs should be allowed to deliver access logs to this bucket. | `list(string)` | `[]` | no | | [access\_log\_delivery\_policy\_source\_buckets](#input\_access\_log\_delivery\_policy\_source\_buckets) | (Optional) List of S3 bucket ARNs which should be allowed to deliver access logs to this bucket. | `list(string)` | `[]` | no | @@ -292,6 +309,7 @@ No modules. | Name | Description | |------|-------------| | [aws\_s3\_bucket\_versioning\_status](#output\_aws\_s3\_bucket\_versioning\_status) | The versioning status of the bucket. Will be 'Enabled', 'Suspended', or 'Disabled'. | +| [s3\_bucket\_abac\_status](#output\_s3\_bucket\_abac\_status) | The ABAC status of the bucket. | | [s3\_bucket\_arn](#output\_s3\_bucket\_arn) | The ARN of the bucket. Will be of format arn:aws:s3:::bucketname. | | [s3\_bucket\_bucket\_domain\_name](#output\_s3\_bucket\_bucket\_domain\_name) | The bucket domain name. Will be of format bucketname.s3.amazonaws.com. | | [s3\_bucket\_bucket\_regional\_domain\_name](#output\_s3\_bucket\_bucket\_regional\_domain\_name) | The bucket region-specific domain name. The bucket domain name including the region name, please refer here for format. Note: The AWS CloudFront allows specifying S3 region-specific endpoint when creating S3 origin, it will prevent redirect issues from CloudFront to S3 Origin URL. | diff --git a/examples/complete/README.md b/examples/complete/README.md index 895ba1e..1382bb6 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -70,6 +70,7 @@ No inputs. | Name | Description | |------|-------------| +| [s3\_bucket\_abac\_status](#output\_s3\_bucket\_abac\_status) | The ABAC status of the bucket. | | [s3\_bucket\_arn](#output\_s3\_bucket\_arn) | The ARN of the bucket. Will be of format arn:aws:s3:::bucketname. | | [s3\_bucket\_bucket\_domain\_name](#output\_s3\_bucket\_bucket\_domain\_name) | The bucket domain name. Will be of format bucketname.s3.amazonaws.com. | | [s3\_bucket\_bucket\_regional\_domain\_name](#output\_s3\_bucket\_bucket\_regional\_domain\_name) | The bucket region-specific domain name. The bucket domain name including the region name, please refer here for format. Note: The AWS CloudFront allows specifying S3 region-specific endpoint when creating S3 origin, it will prevent redirect issues from CloudFront to S3 Origin URL. | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 33eddbf..1a528b8 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -410,6 +410,10 @@ module "s3_bucket" { # metadata_encryption_configuration = { # sse_algorithm = "AES256" # } + + abac_status = { + status = "Enabled" + } } module "disabled" { diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index eddd541..7b5378c 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -47,3 +47,8 @@ output "s3_bucket_website_domain" { description = "The domain of the website endpoint, if the bucket is configured with a website. If not, this will be an empty string. This is used to create Route 53 alias records. " value = module.s3_bucket.s3_bucket_website_domain } + +output "s3_bucket_abac_status" { + description = "The ABAC status of the bucket." + value = module.s3_bucket.s3_bucket_abac_status +} diff --git a/main.tf b/main.tf index f824047..ea1d92c 100644 --- a/main.tf +++ b/main.tf @@ -1409,3 +1409,16 @@ resource "aws_s3_bucket_metadata_configuration" "this" { } } } + +resource "aws_s3_bucket_abac" "this" { + count = local.create_bucket && length(keys(var.abac_status)) > 0 && !var.is_directory_bucket ? 1 : 0 + + region = var.region + + bucket = aws_s3_bucket.this[0].bucket + expected_bucket_owner = var.expected_bucket_owner + + abac_status { + status = try(var.abac_status["status"], "Enabled") + } +} diff --git a/outputs.tf b/outputs.tf index 3874afd..5823a7c 100644 --- a/outputs.tf +++ b/outputs.tf @@ -67,3 +67,8 @@ output "s3_bucket_tags" { description = "Tags of the bucket." value = try(aws_s3_bucket.this[0].tags, {}) } + +output "s3_bucket_abac_status" { + description = "The ABAC status of the bucket." + value = try(aws_s3_bucket_abac.this[0].abac_status[0].status, null) +} diff --git a/variables.tf b/variables.tf index 63f45be..e4a9bb2 100644 --- a/variables.tf +++ b/variables.tf @@ -419,6 +419,12 @@ variable "metadata_journal_table_record_expiration" { default = null } +variable "abac_status" { + description = "Map containing ABAC (Attribute Based Access Control) configuration" + type = any + default = {} +} + variable "putin_khuylo" { description = "Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo!" type = bool diff --git a/wrappers/main.tf b/wrappers/main.tf index 6e388ac..c04c291 100644 --- a/wrappers/main.tf +++ b/wrappers/main.tf @@ -3,6 +3,7 @@ module "wrapper" { for_each = var.items + abac_status = try(each.value.abac_status, var.defaults.abac_status, {}) acceleration_status = try(each.value.acceleration_status, var.defaults.acceleration_status, null) access_log_delivery_policy_source_accounts = try(each.value.access_log_delivery_policy_source_accounts, var.defaults.access_log_delivery_policy_source_accounts, []) access_log_delivery_policy_source_buckets = try(each.value.access_log_delivery_policy_source_buckets, var.defaults.access_log_delivery_policy_source_buckets, [])