diff --git a/.github/workflows/terraform-lint-validate.yml b/.github/workflows/terraform-lint-validate.yml new file mode 100644 index 0000000..82b5011 --- /dev/null +++ b/.github/workflows/terraform-lint-validate.yml @@ -0,0 +1,11 @@ +name: Terraform Lint & Validate +on: + pull_request: {} +permissions: + statuses: write + checks: write + contents: read + pull-requests: read +jobs: + terraform-lint-validate: + uses: tfstack/actions/.github/workflows/terraform-lint-validate.yml@main diff --git a/README.md b/README.md index c49902c..ba55fad 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,13 @@ Terraform module to create an S3 bucket ## Requirements -| Name | Version | -|------|---------| -| [aws](#requirement\_aws) | 5.84.0 | +No requirements. ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | 5.84.0 | +| [aws](#provider\_aws) | 5.94.1 | ## Modules @@ -22,18 +20,18 @@ No modules. | Name | Type | |------|------| -| [aws_s3_bucket.logging](https://registry.terraform.io/providers/hashicorp/aws/5.84.0/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/5.84.0/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket_acl.this](https://registry.terraform.io/providers/hashicorp/aws/5.84.0/docs/resources/s3_bucket_acl) | resource | -| [aws_s3_bucket_lifecycle_configuration.logging](https://registry.terraform.io/providers/hashicorp/aws/5.84.0/docs/resources/s3_bucket_lifecycle_configuration) | resource | -| [aws_s3_bucket_logging.logging](https://registry.terraform.io/providers/hashicorp/aws/5.84.0/docs/resources/s3_bucket_logging) | resource | -| [aws_s3_bucket_ownership_controls.logging](https://registry.terraform.io/providers/hashicorp/aws/5.84.0/docs/resources/s3_bucket_ownership_controls) | resource | -| [aws_s3_bucket_ownership_controls.this](https://registry.terraform.io/providers/hashicorp/aws/5.84.0/docs/resources/s3_bucket_ownership_controls) | resource | -| [aws_s3_bucket_policy.this](https://registry.terraform.io/providers/hashicorp/aws/5.84.0/docs/resources/s3_bucket_policy) | resource | -| [aws_s3_bucket_public_access_block.this](https://registry.terraform.io/providers/hashicorp/aws/5.84.0/docs/resources/s3_bucket_public_access_block) | resource | -| [aws_s3_bucket_server_side_encryption_configuration.logging](https://registry.terraform.io/providers/hashicorp/aws/5.84.0/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | -| [aws_s3_bucket_server_side_encryption_configuration.this](https://registry.terraform.io/providers/hashicorp/aws/5.84.0/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | -| [aws_s3_bucket_versioning.this](https://registry.terraform.io/providers/hashicorp/aws/5.84.0/docs/resources/s3_bucket_versioning) | resource | +| [aws_s3_bucket.logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_acl.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_acl) | resource | +| [aws_s3_bucket_lifecycle_configuration.logging](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_ownership_controls.logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_ownership_controls) | 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.this](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_server_side_encryption_configuration.logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [aws_s3_bucket_server_side_encryption_configuration.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [aws_s3_bucket_versioning.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | ## Inputs @@ -51,10 +49,10 @@ No modules. | [logging\_enabled](#input\_logging\_enabled) | Enable logging for the S3 bucket | `bool` | `false` | no | | [logging\_encryption\_algorithm](#input\_logging\_encryption\_algorithm) | The encryption algorithm used for S3 logging. Valid values: 'AES256', 'aws:kms'. | `string` | `"AES256"` | no | | [logging\_encryption\_enabled](#input\_logging\_encryption\_enabled) | Enable encryption for S3 logging. | `bool` | `true` | no | +| [logging\_lifecycle\_filter\_prefix](#input\_logging\_lifecycle\_filter\_prefix) | Prefix to apply S3 lifecycle rule to. Set to "" to apply to all objects. | `string` | `""` | no | | [logging\_log\_retention\_days](#input\_logging\_log\_retention\_days) | Number of days to retain S3 logging data before expiration. | `number` | `30` | no | | [logging\_s3\_prefix](#input\_logging\_s3\_prefix) | Prefix for S3 logging objects. | `string` | `"s3/"` | no | | [object\_ownership](#input\_object\_ownership) | Defines who owns newly uploaded objects in the bucket. | `string` | `"BucketOwnerPreferred"` | no | -| [region](#input\_region) | AWS region for the provider. Defaults to ap-southeast-2 if not specified. | `string` | `"ap-southeast-2"` | no | | [restrict\_public\_buckets](#input\_restrict\_public\_buckets) | Whether to restrict public access to the bucket. | `bool` | `true` | no | | [sse\_algorithm](#input\_sse\_algorithm) | The encryption algorithm for S3 bucket | `string` | `"AES256"` | no | | [tags](#input\_tags) | Tags for the S3 bucket | `map(string)` | `{}` | no | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 451ab9a..551333f 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "5.84.0" + version = "5.94.0" } } } @@ -48,11 +48,12 @@ module "s3_bucket" { enable_versioning = true # Logging Configuration - logging_enabled = true - logging_encryption_enabled = true - logging_encryption_algorithm = "AES256" - logging_log_retention_days = 90 - logging_s3_prefix = "logs/" + logging_enabled = true + logging_encryption_enabled = true + logging_encryption_algorithm = "AES256" + logging_lifecycle_filter_prefix = "access-logs/" + logging_log_retention_days = 90 + logging_s3_prefix = "logs/" } # Outputs diff --git a/main.tf b/main.tf index 125afd2..e0d5d8d 100644 --- a/main.tf +++ b/main.tf @@ -1,8 +1,8 @@ locals { base_bucket_name = ( - var.bucket_suffix == "" ? - var.bucket_name : - "${var.bucket_name}-${var.bucket_suffix}") + var.bucket_suffix == "" ? + var.bucket_name : + "${var.bucket_name}-${var.bucket_suffix}") } ############################################ @@ -127,6 +127,10 @@ resource "aws_s3_bucket_lifecycle_configuration" "logging" { id = "log-retention" status = "Enabled" + filter { + prefix = var.logging_lifecycle_filter_prefix + } + expiration { days = var.logging_log_retention_days } diff --git a/tests/s3_bucket.tftest.hcl b/tests/s3_bucket.tftest.hcl index 4ebb106..62bac97 100644 --- a/tests/s3_bucket.tftest.hcl +++ b/tests/s3_bucket.tftest.hcl @@ -6,8 +6,6 @@ run "setup" { run "test_s3_bucket" { variables { - region = run.setup.region - bucket_name = "test-s3-bucket" bucket_suffix = run.setup.suffix force_destroy = true @@ -34,11 +32,12 @@ run "test_s3_bucket" { enable_versioning = true # Logging Configuration - logging_enabled = true - logging_encryption_enabled = true - logging_encryption_algorithm = "AES256" - logging_log_retention_days = 90 - logging_s3_prefix = "logs/" + logging_enabled = true + logging_encryption_enabled = true + logging_encryption_algorithm = "AES256" + logging_log_retention_days = 90 + logging_s3_prefix = "logs/" + logging_lifecycle_filter_prefix = "logs/" } # Assertions referencing actual Terraform resources @@ -97,4 +96,9 @@ run "test_s3_bucket" { condition = aws_s3_bucket_logging.logging[0].target_prefix == "logs/" error_message = "Logging S3 prefix is not set to 'logs/'." } + + assert { + condition = aws_s3_bucket_lifecycle_configuration.logging[0].rule[0].filter[0].prefix == "logs/" + error_message = "Lifecycle rule prefix is not set to the expected value 'logs/'." + } } diff --git a/tests/setup/main.tf b/tests/setup/main.tf index 43cf341..d1012ee 100644 --- a/tests/setup/main.tf +++ b/tests/setup/main.tf @@ -20,7 +20,3 @@ output "suffix" { output "account_id" { value = data.aws_caller_identity.current.account_id } - -output "region" { - value = "ap-southeast-2" -} diff --git a/variables.tf b/variables.tf index bbe2771..47d78b5 100644 --- a/variables.tf +++ b/variables.tf @@ -129,6 +129,17 @@ variable "logging_encryption_algorithm" { } } +variable "logging_lifecycle_filter_prefix" { + description = "Prefix to apply S3 lifecycle rule to. Set to \"\" to apply to all objects." + type = string + default = "" + + validation { + condition = can(regex("^[a-zA-Z0-9!_.*'()/~\\-]*$", var.logging_lifecycle_filter_prefix)) + error_message = "The lifecycle prefix must be a valid S3 object key prefix or an empty string." + } +} + variable "logging_log_retention_days" { description = "Number of days to retain S3 logging data before expiration." type = number