diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 398767c..daf3160 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -3,6 +3,7 @@ name: pre-commit-check on: push: branches: + - main - master - prod - develop diff --git a/.github/workflows/pullRequest.yaml b/.github/workflows/pullRequest.yaml index 8f1eba5..101b621 100644 --- a/.github/workflows/pullRequest.yaml +++ b/.github/workflows/pullRequest.yaml @@ -24,7 +24,7 @@ jobs: terraform_tflint_deep, no-commit-to-branch, terraform_tflint_nocreds, - terraform_tfsec + terraform_trivy tflint: runs-on: ubuntu-latest steps: @@ -41,7 +41,7 @@ jobs: filter_mode: added flags: --module level: error - tfsec: + trivy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/tfsec.yaml b/.github/workflows/tfsec.yaml deleted file mode 100644 index 2f75a3e..0000000 --- a/.github/workflows/tfsec.yaml +++ /dev/null @@ -1,26 +0,0 @@ ---- -name: tfsec -on: - push: - branches: - - main - - master - - prod - - develop - -jobs: - tfsec: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Install prerequisites - run: ./bin/install-ubuntu.sh - - name: Terraform init - run: terraform init --backend=false - - name: tfsec - uses: reviewdog/action-tfsec@master - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - reporter: github-check - filter_mode: nofilter - level: error diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml new file mode 100644 index 0000000..53a9d16 --- /dev/null +++ b/.github/workflows/trivy.yaml @@ -0,0 +1,31 @@ +--- +name: trivy +on: + push: + branches: + - master + +jobs: + trivy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install prerequisites + run: ./bin/install-ubuntu.sh + - name: Terraform init + run: terraform init --backend=false + - name: Trivy scan + uses: aquasecurity/trivy-action@master + with: + scan-type: 'config' + hide-progress: false + format: 'sarif' + output: 'trivy-results.sarif' + exit-code: '1' + ignore-unfixed: true + severity: 'CRITICAL,HIGH' + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: 'trivy-results.sarif' diff --git a/.gitignore b/.gitignore index 1fef4ab..371d818 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,9 @@ # .tfvars files *.tfvars + +# macs +.DS_Store + +# temp folders +tmp diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8273282..f209b71 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,63 +1,27 @@ exclude: ".terraform" repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.77.1 + rev: v1.92.2 hooks: - id: terraform_docs always_run: true - id: terraform_fmt + - id: terraform_validate + args: + - --hook-config=--retry-once-with-cleanup=true + exclude: ^examples - id: terraform_tflint alias: terraform_tflint_nocreds + exclude: ^examples name: terraform_tflint_nocreds - - id: terraform_tfsec - - repo: local - hooks: - - id: terraform_validate - name: terraform_validate - entry: | - bash -c ' - AWS_DEFAULT_REGION=us-east-1 - declare -a DIRS - for FILE in "$@" - do - DIRS+=($(dirname "$FILE")) - done - for DIR in $(printf "%s\n" "${DIRS[@]}" | sort -u) - do - cd $(dirname "$FILE") - terraform init --backend=false - terraform validate . - cd .. - done - ' - language: system - verbose: true - files: \.tf(vars)?$ - exclude: examples - - id: tflock - name: provider_locks - entry: | - bash -c ' - AWS_DEFAULT_REGION=us-east-1 - declare -a DIRS - for FILE in "$@" - do - DIRS+=($(dirname "$FILE")) - done - for DIR in $(printf "%s\n" "${DIRS[@]}" | sort -u) - do - cd $(dirname "$FILE") - terraform providers lock -platform=windows_amd64 -platform=darwin_amd64 -platform=linux_amd64 - cd .. - done - ' - language: system - verbose: true - files: \.tf(vars)?$ - exclude: examples + - id: terraform_trivy + args: + - --args=--skip-dirs="**/.terraform,examples/*" + - id: terraform_providers_lock - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.6.0 hooks: + - id: check-added-large-files - id: check-case-conflict - id: check-json - id: check-merge-conflict @@ -65,6 +29,7 @@ repos: - id: check-yaml args: - --unsafe + - id: detect-private-key - id: end-of-file-fixer - id: mixed-line-ending args: @@ -86,4 +51,4 @@ repos: - --markdown-linebreak-ext=md exclude: README.md ci: - skip: [terraform_docs, terraform_fmt, terraform_tflint, terraform_tfsec, tflock] + skip: [terraform_docs, terraform_fmt, terraform_validate, terraform_tflint, terraform_trivy, terraform_providers_lock] diff --git a/.terraform-version b/.terraform-version index 4f20ea7..5a13b33 100644 --- a/.terraform-version +++ b/.terraform-version @@ -1 +1 @@ -latest:^1.1 +latest:^1.6 diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl index f9f245d..f0469ad 100644 --- a/.terraform.lock.hcl +++ b/.terraform.lock.hcl @@ -2,26 +2,24 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "4.56.0" - constraints = ">= 3.8.0" + version = "5.66.0" + constraints = ">= 5.0.0" hashes = [ - "h1:1I44mXVvhYDRFehbw9MFq2xKxlDoEFBz7Ou8HLaNtXk=", - "h1:CnpBvf3mH16Kcez47OsjmIeGkY2PUVihKRwbkyOvo48=", - "h1:koDunHl/LUmCAKy3VFie6MakXN7ng93v8HBRpKI8He8=", - "zh:1d2b7693a102da015a86b9235b554272b9280597011216c3ddd1a6dc95ad8dab", - "zh:28c3e8ebaa077f65c4ac5fd051c95887070293fcff0386dfc2e4b7e248a0aefa", - "zh:2a620bc4a87be06e7acac1bc15e966dba45df643bf6c3efb811e74e6c2122b03", - "zh:30d3ac148fa0634e7ba1de66e1af1328481c92cd774adcfc0e27f828103b17e0", - "zh:3d3eebf916f25e11b12dd3c692f8fe1e4c4e9a0c414af9d0d881ddebd28dcd39", - "zh:3f4600f2881c02fcc69080df68747c9a0b9b11cb002117fd918b7800f2ac402b", - "zh:7156fb12c3b4f2964f7e78cee97f31d95b43045467f90749d2ed545725c36baa", + "h1:yGcVdhj9IKbS/b7BSHtgGjCiFnKK+81ImkK/x7UCgEI=", + "zh:071c908eb18627f4becdaf0a9fe95d7a61f69be365080aba2ef5e24f6314392b", + "zh:3dea2a474c6ad4be5b508de4e90064ec485e3fbcebb264cb6c4dec660e3ea8b5", + "zh:56c0b81e3bbf4e9ccb2efb984f8758e2bc563ce179ff3aecc1145df268b046d1", + "zh:5f34b75a9ef69cad8c79115ecc0697427d7f673143b81a28c3cf8d5decfd7f93", + "zh:65632bc2c408775ee44cb32a72e7c48376001a9a7b3adbc2c9b4d088a7d58650", + "zh:6d0550459941dfb39582fadd20bfad8816255a827bfaafb932d51d66030fcdd5", + "zh:7f1811ef179e507fdcc9776eb8dc3d650339f8b84dd084642cf7314c5ca26745", + "zh:8a793d816d7ef57e71758fe95bf830cfca70d121df70778b65cc11065ad004fd", + "zh:8c7cda08adba01b5ae8cc4e5fbf16761451f0fab01327e5f44fc47b7248ba653", + "zh:96d855f1771342771855c0fb2d47ff6a731e8f2fa5d242b18037c751fd63e6c3", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:a5bbc84fd37d468c7b016009776b6d2a287bbb746af81aba786cdf8eb5fce4a1", - "zh:d5322bcd4e11caddbbfaa1198893824d4b4d28f504517a3a87902cf86d75bd87", - "zh:d766eb9f86a40060d63e12ef674d7c9c47ec4e47ade487f1f49af8c89b441711", - "zh:df23f592b99f6617f09e449009bbb49068a69fc926b15ca29e30b068c9c67365", - "zh:e7b0acee2d98549731547259b539f598e18db07c0c202d3a34b922beff711054", - "zh:ec317f79fdcce934c39458ea312862e7f7ec48cafb8bcc9b5a00d9b78b629d81", - "zh:f78ec7a771867d96dfee96bf74523341ba42feeb64ce2f108b5bf2e7ebef0fef", + "zh:b2a62669b72c2471820410b58d764102b11c24e326831ddcfae85c7d20795acf", + "zh:b4a6b251ac24c8f5522581f8d55238d249d0008d36f64475beefc3791f229e1d", + "zh:ca519fa7ee1cac30439c7e2d311a0ecea6a5dae2d175fe8440f30133688b6272", + "zh:fbcd54e7d65806b0038fc8a0fbdc717e1284298ff66e22aac39dcc5a22cc99e5", ] } diff --git a/.tflint.hcl b/.tflint.hcl index 854fb92..c700b79 100644 --- a/.tflint.hcl +++ b/.tflint.hcl @@ -2,6 +2,12 @@ config { module = true } +plugin "aws" { + enabled = true + version = "0.30.0" + source = "github.com/terraform-linters/tflint-ruleset-aws" +} + rule "terraform_deprecated_interpolation" { enabled = true } diff --git a/LICENSE b/LICENSE index c026f1a..9f1b0ba 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Rhythmic Technologies, Inc. +Copyright (c) 2024 Rhythmic Technologies, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a232bd5..f27bd21 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ # terraform-aws-config -[![](https://github.com/rhythmictech/terraform-aws-config/workflows/check/badge.svg)](https://github.com/rhythmictech/terraform-aws-config/actions) +[![tflint](https://github.com/rhythmictech/terraform-aws-config/workflows/tflint/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-config/actions?query=workflow%3Atflint+event%3Apush+branch%3Amaster) +[![trivy](https://github.com/rhythmictech/terraform-aws-config/workflows/trivy/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-config/actions?query=workflow%3Atrivy+event%3Apush+branch%3Amaster) +[![yamllint](https://github.com/rhythmictech/terraform-aws-config/workflows/yamllint/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-config/actions?query=workflow%3Ayamllint+event%3Apush+branch%3Amaster) +[![misspell](https://github.com/rhythmictech/terraform-aws-config/workflows/misspell/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-config/actions?query=workflow%3Amisspell+event%3Apush+branch%3Amaster) +[![pre-commit-check](https://github.com/rhythmictech/terraform-aws-config/workflows/pre-commit-check/badge.svg?branch=master&event=push)](https://github.com/rhythmictech/terraform-aws-config/actions?query=workflow%3Apre-commit-check+event%3Apush+branch%3Amaster) +follow on Twitter + @@ -8,14 +14,14 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13.4 | -| [aws](#requirement\_aws) | >= 3.8 | +| [terraform](#requirement\_terraform) | >= 1.1 | +| [aws](#requirement\_aws) | >= 5.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | 4.56.0 | +| [aws](#provider\_aws) | 5.66.0 | ## Modules @@ -33,7 +39,11 @@ No modules. | [aws_iam_role_policy_attachment.awsconfig_managed_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | +| [aws_s3_bucket_logging.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | 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.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 | +| [aws_sns_topic.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -46,16 +56,35 @@ No modules. |------|-------------|------|---------|:--------:| | [bucket\_name](#input\_bucket\_name) | Name of the S3 bucket to record to (do not use with multi-region module) | `string` | `null` | no | | [bucket\_suffix](#input\_bucket\_suffix) | Suffix to append to S3 bucket name | `string` | `"awsconfig"` | no | +| [create\_sns\_topic](#input\_create\_sns\_topic) | Whether to create an SNS topic | `bool` | `false` | no | | [delivery\_channel\_name](#input\_delivery\_channel\_name) | Name of the delivery channel | `string` | `"awsconfig-s3"` | no | -| [enable\_global\_logging](#input\_enable\_global\_logging) | Enable recording of global events (E.g., IAM) | `bool` | `true` | no | +| [grant\_s3\_kms\_access](#input\_grant\_s3\_kms\_access) | Whether to grant the IAM role access to the S3 bucket KMS key | `bool` | `true` | no | +| [grant\_sns\_kms\_access](#input\_grant\_sns\_kms\_access) | Whether to grant the IAM role access to the SNS topic KMS key | `bool` | `true` | no | | [logging\_bucket](#input\_logging\_bucket) | Optional target for S3 access logging | `string` | `null` | no | | [logging\_prefix](#input\_logging\_prefix) | Optional target prefix for S3 access logging (only used if `s3_access_logging_bucket` is set) | `string` | `null` | no | | [recorder\_name](#input\_recorder\_name) | Name of the config recorder | `string` | `"awsconfig"` | no | -| [snapshot\_delivery\_frequency](#input\_snapshot\_delivery\_frequency) | Deliery frequency: One\_Hour, Three\_Hours, Six\_Hours, Twelve\_Hours, TwentyFour\_Hours | `string` | `"Six_Hours"` | no | +| [recording\_group\_all\_supported](#input\_recording\_group\_all\_supported) | Specifies whether AWS Config records configuration changes for every supported type of regional resource. If set to 'false', you must specify resource types in 'recording\_group\_resource\_types'. | `bool` | `true` | no | +| [recording\_group\_exclusion\_resource\_types](#input\_recording\_group\_exclusion\_resource\_types) | A list of resource types to exclude from recording. Only valid when 'recording\_group\_all\_supported' is true. | `list(string)` | `[]` | no | +| [recording\_group\_include\_global\_resource\_types](#input\_recording\_group\_include\_global\_resource\_types) | Specifies whether AWS Config includes all supported types of global resources with the resources that it records. Only valid when 'recording\_group\_all\_supported' is true. | `bool` | `true` | no | +| [recording\_group\_recording\_strategy\_use\_only](#input\_recording\_group\_recording\_strategy\_use\_only) | Specifies whether AWS Config limits recording to the resource types specified in 'recording\_group\_resource\_types'. Valid values: 'ALL\_SUPPORTED\_RESOURCE\_TYPES' or 'INCLUSION\_BY\_RESOURCE\_TYPES'. | `string` | `null` | no | +| [recording\_group\_resource\_types](#input\_recording\_group\_resource\_types) | A list of valid AWS resource types to include in this recording group. Only used if 'recording\_group\_all\_supported' is false. | `list(string)` | `[]` | no | +| [recording\_mode\_override\_description](#input\_recording\_mode\_override\_description) | A description for the recording mode override. | `string` | `null` | no | +| [recording\_mode\_override\_enabled](#input\_recording\_mode\_override\_enabled) | Specifies whether to enable recording mode override. | `bool` | `false` | no | +| [recording\_mode\_override\_recording\_frequency](#input\_recording\_mode\_override\_recording\_frequency) | The frequency for the recording mode override. Valid values: CONTINUOUS, PERIODIC\_1\_HOUR, PERIODIC\_3\_HOURS, PERIODIC\_6\_HOURS, PERIODIC\_12\_HOURS, PERIODIC\_24\_HOURS | `string` | `"CONTINUOUS"` | no | +| [recording\_mode\_override\_resource\_types](#input\_recording\_mode\_override\_resource\_types) | A list of resource types to be recorded at the frequency specified in recording\_mode\_override\_recording\_frequency. | `list(string)` | `[]` | no | +| [recording\_mode\_recording\_frequency](#input\_recording\_mode\_recording\_frequency) | The frequency with which AWS Config records configuration changes. Valid values: CONTINUOUS, PERIODIC\_1\_HOUR, PERIODIC\_3\_HOURS, PERIODIC\_6\_HOURS, PERIODIC\_12\_HOURS, PERIODIC\_24\_HOURS | `string` | `"CONTINUOUS"` | no | +| [s3\_bucket\_kms\_key\_id](#input\_s3\_bucket\_kms\_key\_id) | The ARN of the KMS key to use for encrypting the S3 bucket. If not provided, AES256 encryption will be used. | `string` | `null` | no | +| [s3\_key\_prefix](#input\_s3\_key\_prefix) | The prefix for the specified S3 bucket. | `string` | `null` | no | +| [snapshot\_delivery\_frequency](#input\_snapshot\_delivery\_frequency) | Delivery frequency. Valid values: One\_Hour, Three\_Hours, Six\_Hours, Twelve\_Hours, TwentyFour\_Hours | `string` | `"Six_Hours"` | no | | [sns\_topic\_arn](#input\_sns\_topic\_arn) | SNS topic to deliver config rule notifications to | `string` | `null` | no | +| [sns\_topic\_kms\_key\_id](#input\_sns\_topic\_kms\_key\_id) | The ARN of the KMS key to use for encrypting the SNS topic. If not provided, the default AWS managed key for SNS will be used. | `string` | `null` | no | | [tags](#input\_tags) | Tags to add to resources that support it | `map(string)` | `{}` | no | ## Outputs No outputs. + +## Additional Information + +The SNS topic created by this module (when `sns_topic_arn` is not provided) will have a name prefix based on the `recorder_name` variable, followed by "-config-topic-". AWS will append a unique suffix to this prefix to ensure uniqueness. diff --git a/bin/install-macos.sh b/bin/install-macos.sh index 3800165..349bb9d 100755 --- a/bin/install-macos.sh +++ b/bin/install-macos.sh @@ -2,9 +2,8 @@ echo 'installing brew packages' brew update -brew tap liamg/tfsec -brew install tfenv tflint terraform-docs pre-commit liamg/tfsec/tfsec coreutils -brew upgrade tfenv tflint terraform-docs pre-commit liamg/tfsec/tfsec coreutils +brew install tfenv tflint terraform-docs aquasecurity/trivy/trivy pre-commit coreutils +brew upgrade tfenv tflint terraform-docs aquasecurity/trivy/trivy pre-commit coreutils echo 'installing pre-commit hooks' pre-commit install diff --git a/bin/install-ubuntu.sh b/bin/install-ubuntu.sh index 670d0b9..331e45b 100755 --- a/bin/install-ubuntu.sh +++ b/bin/install-ubuntu.sh @@ -7,7 +7,7 @@ pip3 install pre-commit # terraform docs mkdir tmp cd tmp -curl -Lo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-$(uname)-amd64.tar.gz +curl -Lo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.18.0/terraform-docs-v0.18.0-$(uname)-amd64.tar.gz tar -xzf terraform-docs.tar.gz chmod +x terraform-docs sudo mv terraform-docs /usr/bin/ @@ -30,3 +30,6 @@ pre-commit init-templatedir ~/.git-template echo 'installing terraform with tfenv' tfenv install + +wget https://github.com/aquasecurity/trivy/releases/download/v0.54.1/trivy_0.54.1_Linux-64bit.deb +sudo dpkg -i trivy_0.54.1_Linux-64bit.deb diff --git a/iam.tf b/iam.tf index 0caf81f..c7c8a51 100644 --- a/iam.tf +++ b/iam.tf @@ -1,4 +1,3 @@ - #tfsec:ignore:aws-iam-no-policy-wildcards data "aws_iam_policy_document" "this" { statement { @@ -20,6 +19,36 @@ data "aws_iam_policy_document" "this" { aws_s3_bucket.this.arn, ] } + + # Conditional SNS topic permissions + dynamic "statement" { + for_each = var.sns_topic_arn != null || var.create_sns_topic ? [1] : [] + content { + effect = "Allow" + actions = ["sns:Publish"] + resources = [var.sns_topic_arn != null ? var.sns_topic_arn : aws_sns_topic.this[0].arn] + } + } + + # Conditional KMS permissions for S3 + dynamic "statement" { + for_each = var.grant_s3_kms_access && var.s3_bucket_kms_key_id != null ? [1] : [] + content { + effect = "Allow" + actions = ["kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey"] + resources = [var.s3_bucket_kms_key_id] + } + } + + # Conditional KMS permissions for SNS + dynamic "statement" { + for_each = var.grant_sns_kms_access && var.sns_topic_kms_key_id != null ? [1] : [] + content { + effect = "Allow" + actions = ["kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey"] + resources = [var.sns_topic_kms_key_id] + } + } } resource "aws_iam_policy" "this" { diff --git a/main.tf b/main.tf index b2e6e61..1c59dac 100644 --- a/main.tf +++ b/main.tf @@ -12,40 +12,37 @@ locals { bucket_name = var.bucket_name == null ? "${local.account_id}-${local.region}-${var.bucket_suffix}" : var.bucket_name partition = data.aws_partition.current.partition region = data.aws_region.current.name - - logging = var.logging_bucket == null ? [] : [{ - bucket = var.logging_bucket - prefix = var.logging_prefix == null ? local.bucket_name : var.logging_prefix - }] } -#tfsec:ignore:aws-s3-encryption-customer-key tfsec:ignore:aws-s3-enable-bucket-logging +#trivy:ignore:AVD-AWS-0089 resource "aws_s3_bucket" "this" { bucket = local.bucket_name - acl = "private" - tags = merge(var.tags, { + tags = merge(var.tags, { "Name" = local.bucket_name }) +} - versioning { - enabled = true +resource "aws_s3_bucket_versioning" "this" { + bucket = aws_s3_bucket.this.id + versioning_configuration { + status = "Enabled" } +} - dynamic "logging" { - iterator = log - for_each = local.logging +resource "aws_s3_bucket_logging" "this" { + count = var.logging_bucket != null ? 1 : 0 + bucket = aws_s3_bucket.this.id + target_bucket = var.logging_bucket + target_prefix = var.logging_prefix == null ? local.bucket_name : var.logging_prefix +} - content { - target_bucket = log.value.bucket - target_prefix = lookup(log.value, "prefix", null) - } - } +resource "aws_s3_bucket_server_side_encryption_configuration" "this" { + bucket = aws_s3_bucket.this.id - server_side_encryption_configuration { - rule { - apply_server_side_encryption_by_default { - sse_algorithm = "aws:kms" - } + rule { + apply_server_side_encryption_by_default { + sse_algorithm = var.s3_bucket_kms_key_id != null ? "aws:kms" : "AES256" + kms_master_key_id = var.s3_bucket_kms_key_id } } } @@ -63,20 +60,50 @@ resource "aws_config_configuration_recorder" "this" { role_arn = aws_iam_role.this.arn recording_group { - all_supported = true - include_global_resource_types = var.enable_global_logging + all_supported = var.recording_group_all_supported + include_global_resource_types = var.recording_group_include_global_resource_types + resource_types = var.recording_group_resource_types + exclusion_by_resource_types { + resource_types = var.recording_group_exclusion_resource_types + } + recording_strategy { + use_only = var.recording_group_recording_strategy_use_only + } + } + + recording_mode { + recording_frequency = var.recording_mode_recording_frequency + + dynamic "recording_mode_override" { + for_each = var.recording_mode_override_enabled ? [1] : [] + content { + description = var.recording_mode_override_description + resource_types = var.recording_mode_override_resource_types + recording_frequency = var.recording_mode_override_recording_frequency + } + } } } +resource "aws_sns_topic" "this" { + count = var.create_sns_topic ? 1 : 0 + name_prefix = "${var.recorder_name}-config-topic-" + + kms_master_key_id = var.sns_topic_kms_key_id +} + resource "aws_config_delivery_channel" "this" { name = var.delivery_channel_name s3_bucket_name = aws_s3_bucket.this.bucket - sns_topic_arn = var.sns_topic_arn + s3_key_prefix = var.s3_key_prefix + sns_topic_arn = var.create_sns_topic ? aws_sns_topic.this[0].arn : var.sns_topic_arn snapshot_delivery_properties { delivery_frequency = var.snapshot_delivery_frequency } + s3_kms_key_arn = var.s3_bucket_kms_key_id + depends_on = [aws_config_configuration_recorder.this] } diff --git a/variables.tf b/variables.tf index b3df5f2..612d353 100644 --- a/variables.tf +++ b/variables.tf @@ -20,12 +20,6 @@ variable "delivery_channel_name" { type = string } -variable "enable_global_logging" { - default = true - description = "Enable recording of global events (E.g., IAM)" - type = bool -} - variable "logging_bucket" { default = null description = "Optional target for S3 access logging" @@ -45,9 +39,9 @@ variable "recorder_name" { } variable "snapshot_delivery_frequency" { - default = "Six_Hours" - description = "Deliery frequency: One_Hour, Three_Hours, Six_Hours, Twelve_Hours, TwentyFour_Hours" + description = "Delivery frequency. Valid values: One_Hour, Three_Hours, Six_Hours, Twelve_Hours, TwentyFour_Hours" type = string + default = "Six_Hours" } variable "sns_topic_arn" { @@ -61,3 +55,99 @@ variable "tags" { description = "Tags to add to resources that support it" type = map(string) } + +variable "s3_bucket_kms_key_id" { + description = "The ARN of the KMS key to use for encrypting the S3 bucket. If not provided, AES256 encryption will be used." + type = string + default = null +} + +variable "sns_topic_kms_key_id" { + description = "The ARN of the KMS key to use for encrypting the SNS topic. If not provided, the default AWS managed key for SNS will be used." + type = string + default = null +} + +variable "recording_group_all_supported" { + description = "Specifies whether AWS Config records configuration changes for every supported type of regional resource. If set to 'false', you must specify resource types in 'recording_group_resource_types'." + type = bool + default = true +} + +variable "recording_group_include_global_resource_types" { + description = "Specifies whether AWS Config includes all supported types of global resources with the resources that it records. Only valid when 'recording_group_all_supported' is true." + type = bool + default = true +} + +variable "recording_group_resource_types" { + description = "A list of valid AWS resource types to include in this recording group. Only used if 'recording_group_all_supported' is false." + type = list(string) + default = [] +} + +variable "recording_group_exclusion_resource_types" { + description = "A list of resource types to exclude from recording. Only valid when 'recording_group_all_supported' is true." + type = list(string) + default = [] +} + +variable "recording_group_recording_strategy_use_only" { + description = "Specifies whether AWS Config limits recording to the resource types specified in 'recording_group_resource_types'. Valid values: 'ALL_SUPPORTED_RESOURCE_TYPES' or 'INCLUSION_BY_RESOURCE_TYPES'." + type = string + default = null +} + +variable "recording_mode_recording_frequency" { + description = "The frequency with which AWS Config records configuration changes. Valid values: CONTINUOUS, PERIODIC_1_HOUR, PERIODIC_3_HOURS, PERIODIC_6_HOURS, PERIODIC_12_HOURS, PERIODIC_24_HOURS" + type = string + default = "CONTINUOUS" +} + +variable "recording_mode_override_enabled" { + description = "Specifies whether to enable recording mode override." + type = bool + default = false +} + +variable "recording_mode_override_description" { + description = "A description for the recording mode override." + type = string + default = null +} + +variable "recording_mode_override_resource_types" { + description = "A list of resource types to be recorded at the frequency specified in recording_mode_override_recording_frequency." + type = list(string) + default = [] +} + +variable "recording_mode_override_recording_frequency" { + description = "The frequency for the recording mode override. Valid values: CONTINUOUS, PERIODIC_1_HOUR, PERIODIC_3_HOURS, PERIODIC_6_HOURS, PERIODIC_12_HOURS, PERIODIC_24_HOURS" + type = string + default = "CONTINUOUS" +} + +variable "s3_key_prefix" { + description = "The prefix for the specified S3 bucket." + type = string + default = null +} + +variable "grant_s3_kms_access" { + description = "Whether to grant the IAM role access to the S3 bucket KMS key" + type = bool + default = true +} + +variable "grant_sns_kms_access" { + description = "Whether to grant the IAM role access to the SNS topic KMS key" + type = bool + default = true +} + +variable "create_sns_topic" { + description = "Whether to create an SNS topic" + type = bool + default = false +} diff --git a/versions.tf b/versions.tf index 6b4dc4e..5c7c4d1 100644 --- a/versions.tf +++ b/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.13.4" + required_version = ">= 1.1" required_providers { aws = { source = "hashicorp/aws" - version = ">= 3.8" + version = ">= 5.0" } } }