From 9f58e625d6bf055204156c80e19feec19f0213ee Mon Sep 17 00:00:00 2001 From: magreenbaum Date: Fri, 25 Aug 2023 21:22:21 -0400 Subject: [PATCH 01/11] add data protection policy --- .../README.md | 37 +++++++ .../main.tf | 52 +++++++++ .../outputs.tf | 9 ++ .../variables.tf | 0 .../versions.tf | 10 ++ modules/log-data-protection-policy/README.md | 40 +++++++ modules/log-data-protection-policy/main.tf | 6 ++ modules/log-data-protection-policy/outputs.tf | 4 + .../log-data-protection-policy/variables.tf | 15 +++ .../log-data-protection-policy/versions.tf | 10 ++ wrappers/log-data-protection-policy/README.md | 100 ++++++++++++++++++ wrappers/log-data-protection-policy/main.tf | 9 ++ .../log-data-protection-policy/outputs.tf | 5 + .../log-data-protection-policy/variables.tf | 11 ++ .../log-data-protection-policy/versions.tf | 3 + 15 files changed, 311 insertions(+) create mode 100644 examples/log-group-with-data-protection-policy/README.md create mode 100644 examples/log-group-with-data-protection-policy/main.tf create mode 100644 examples/log-group-with-data-protection-policy/outputs.tf create mode 100644 examples/log-group-with-data-protection-policy/variables.tf create mode 100644 examples/log-group-with-data-protection-policy/versions.tf create mode 100644 modules/log-data-protection-policy/README.md create mode 100644 modules/log-data-protection-policy/main.tf create mode 100644 modules/log-data-protection-policy/outputs.tf create mode 100644 modules/log-data-protection-policy/variables.tf create mode 100644 modules/log-data-protection-policy/versions.tf create mode 100644 wrappers/log-data-protection-policy/README.md create mode 100644 wrappers/log-data-protection-policy/main.tf create mode 100644 wrappers/log-data-protection-policy/outputs.tf create mode 100644 wrappers/log-data-protection-policy/variables.tf create mode 100644 wrappers/log-data-protection-policy/versions.tf diff --git a/examples/log-group-with-data-protection-policy/README.md b/examples/log-group-with-data-protection-policy/README.md new file mode 100644 index 0000000..c8af47b --- /dev/null +++ b/examples/log-group-with-data-protection-policy/README.md @@ -0,0 +1,37 @@ +# Complete Cloudwatch log group and data protection policy + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 5.0 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [audit\_destination\_group](#module\_audit\_destination\_group) | ../../modules/log-group | n/a | +| [log\_data\_protection\_policy](#module\_log\_data\_protection\_policy) | ../../modules/log-data-protection-policy | n/a | +| [log\_group](#module\_log\_group) | ../../modules/log-group | n/a | + +## Resources + +No resources. + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [cloudwatch\_log\_group\_arn](#output\_cloudwatch\_log\_group\_arn) | ARN of Cloudwatch log group | +| [cloudwatch\_log\_group\_name](#output\_cloudwatch\_log\_group\_name) | Name of Cloudwatch log group | + diff --git a/examples/log-group-with-data-protection-policy/main.tf b/examples/log-group-with-data-protection-policy/main.tf new file mode 100644 index 0000000..425c27d --- /dev/null +++ b/examples/log-group-with-data-protection-policy/main.tf @@ -0,0 +1,52 @@ +provider "aws" { + region = "eu-west-1" +} + +module "log_group" { + source = "../../modules/log-group" + + name_prefix = "my-log-group-" + retention_in_days = 7 +} + +module "audit_destination_group" { + source = "../../modules/log-group" + + name_prefix = "audit-destination-log-group-" + retention_in_days = 7 +} + +module "log_data_protection_policy" { + source = "../../modules/log-data-protection-policy" + + log_group_name = module.log_group.cloudwatch_log_group_name + policy_document = jsonencode({ + Name = "Example" + Version = "2021-06-01" + + Statement = [ + { + Sid = "Audit" + DataIdentifier = ["arn:aws:dataprotection::aws:data-identifier/Address"] + Operation = { + Audit = { + FindingsDestination = { + CloudWatchLogs = { + LogGroup = module.audit_destination_group.cloudwatch_log_group_name + } + } + } + } + }, + { + Sid = "Redact" + DataIdentifier = ["arn:aws:dataprotection::aws:data-identifier/Address"] + Operation = { + Deidentify = { + MaskConfig = {} + } + } + } + ] + }) +} diff --git a/examples/log-group-with-data-protection-policy/outputs.tf b/examples/log-group-with-data-protection-policy/outputs.tf new file mode 100644 index 0000000..e11eab4 --- /dev/null +++ b/examples/log-group-with-data-protection-policy/outputs.tf @@ -0,0 +1,9 @@ +output "cloudwatch_log_group_name" { + description = "Name of Cloudwatch log group" + value = module.log_group.cloudwatch_log_group_name +} + +output "cloudwatch_log_group_arn" { + description = "ARN of Cloudwatch log group" + value = module.log_group.cloudwatch_log_group_arn +} diff --git a/examples/log-group-with-data-protection-policy/variables.tf b/examples/log-group-with-data-protection-policy/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/examples/log-group-with-data-protection-policy/versions.tf b/examples/log-group-with-data-protection-policy/versions.tf new file mode 100644 index 0000000..ddfcb0e --- /dev/null +++ b/examples/log-group-with-data-protection-policy/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.0" + } + } +} diff --git a/modules/log-data-protection-policy/README.md b/modules/log-data-protection-policy/README.md new file mode 100644 index 0000000..bb2acf3 --- /dev/null +++ b/modules/log-data-protection-policy/README.md @@ -0,0 +1,40 @@ +# log-data-protection-policy + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 5.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 5.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_cloudwatch_log_data_protection_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_data_protection_policy) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [create](#input\_create) | Whether to create the cloudwatch log data protection policy. | `bool` | `true` | no | +| [log\_group\_name](#input\_log\_group\_name) | The name of the log group under which the log stream is to be created. | `string` | n/a | yes | +| [policy\_document](#input\_policy\_document) | Specifies the data protection policy in JSON. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [log\_group\_name](#output\_log\_group\_name) | Name of Cloudwatch log group | + diff --git a/modules/log-data-protection-policy/main.tf b/modules/log-data-protection-policy/main.tf new file mode 100644 index 0000000..7954224 --- /dev/null +++ b/modules/log-data-protection-policy/main.tf @@ -0,0 +1,6 @@ +resource "aws_cloudwatch_log_data_protection_policy" "this" { + count = var.create ? 1 : 0 + + log_group_name = var.log_group_name + policy_document = var.policy_document +} diff --git a/modules/log-data-protection-policy/outputs.tf b/modules/log-data-protection-policy/outputs.tf new file mode 100644 index 0000000..dda9933 --- /dev/null +++ b/modules/log-data-protection-policy/outputs.tf @@ -0,0 +1,4 @@ +output "log_group_name" { + description = "Name of Cloudwatch log group" + value = var.log_group_name +} diff --git a/modules/log-data-protection-policy/variables.tf b/modules/log-data-protection-policy/variables.tf new file mode 100644 index 0000000..9e8fe06 --- /dev/null +++ b/modules/log-data-protection-policy/variables.tf @@ -0,0 +1,15 @@ +variable "create" { + description = "Whether to create the cloudwatch log data protection policy." + type = bool + default = true +} + +variable "log_group_name" { + description = "The name of the log group under which the log stream is to be created." + type = string +} + +variable "policy_document" { + description = "Specifies the data protection policy in JSON." + type = string +} diff --git a/modules/log-data-protection-policy/versions.tf b/modules/log-data-protection-policy/versions.tf new file mode 100644 index 0000000..ddfcb0e --- /dev/null +++ b/modules/log-data-protection-policy/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.0" + } + } +} diff --git a/wrappers/log-data-protection-policy/README.md b/wrappers/log-data-protection-policy/README.md new file mode 100644 index 0000000..0d9a0d0 --- /dev/null +++ b/wrappers/log-data-protection-policy/README.md @@ -0,0 +1,100 @@ +# Wrapper for module: `modules/log-data-protection-policy` + +The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt). + +You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module. + +This wrapper does not implement any extra functionality. + +## Usage with Terragrunt + +`terragrunt.hcl`: + +```hcl +terraform { + source = "tfr:///terraform-aws-modules/cloudwatch/aws//wrappers/log-data-protection-policy" + # Alternative source: + # source = "git::git@github.com:terraform-aws-modules/terraform-aws-cloudwatch.git//wrappers/log-data-protection-policy?ref=master" +} + +inputs = { + defaults = { # Default values + create = true + tags = { + Terraform = "true" + Environment = "dev" + } + } + + items = { + my-item = { + # omitted... can be any argument supported by the module + } + my-second-item = { + # omitted... can be any argument supported by the module + } + # omitted... + } +} +``` + +## Usage with Terraform + +```hcl +module "wrapper" { + source = "terraform-aws-modules/cloudwatch/aws//wrappers/log-data-protection-policy" + + defaults = { # Default values + create = true + tags = { + Terraform = "true" + Environment = "dev" + } + } + + items = { + my-item = { + # omitted... can be any argument supported by the module + } + my-second-item = { + # omitted... can be any argument supported by the module + } + # omitted... + } +} +``` + +## Example: Manage multiple S3 buckets in one Terragrunt layer + +`eu-west-1/s3-buckets/terragrunt.hcl`: + +```hcl +terraform { + source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers" + # Alternative source: + # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master" +} + +inputs = { + defaults = { + force_destroy = true + + attach_elb_log_delivery_policy = true + attach_lb_log_delivery_policy = true + attach_deny_insecure_transport_policy = true + attach_require_latest_tls_policy = true + } + + items = { + bucket1 = { + bucket = "my-random-bucket-1" + } + bucket2 = { + bucket = "my-random-bucket-2" + tags = { + Secure = "probably" + } + } + } +} +``` diff --git a/wrappers/log-data-protection-policy/main.tf b/wrappers/log-data-protection-policy/main.tf new file mode 100644 index 0000000..a730e35 --- /dev/null +++ b/wrappers/log-data-protection-policy/main.tf @@ -0,0 +1,9 @@ +module "wrapper" { + source = "../../modules/log-data-protection-policy" + + for_each = var.items + + create = try(each.value.create, var.defaults.create, true) + log_group_name = try(each.value.log_group_name, var.defaults.log_group_name) + policy_document = try(each.value.policy_document, var.defaults.policy_document) +} diff --git a/wrappers/log-data-protection-policy/outputs.tf b/wrappers/log-data-protection-policy/outputs.tf new file mode 100644 index 0000000..5da7c09 --- /dev/null +++ b/wrappers/log-data-protection-policy/outputs.tf @@ -0,0 +1,5 @@ +output "wrapper" { + description = "Map of outputs of a wrapper." + value = module.wrapper + # sensitive = false # No sensitive module output found +} diff --git a/wrappers/log-data-protection-policy/variables.tf b/wrappers/log-data-protection-policy/variables.tf new file mode 100644 index 0000000..a6ea096 --- /dev/null +++ b/wrappers/log-data-protection-policy/variables.tf @@ -0,0 +1,11 @@ +variable "defaults" { + description = "Map of default values which will be used for each item." + type = any + default = {} +} + +variable "items" { + description = "Maps of items to create a wrapper from. Values are passed through to the module." + type = any + default = {} +} diff --git a/wrappers/log-data-protection-policy/versions.tf b/wrappers/log-data-protection-policy/versions.tf new file mode 100644 index 0000000..51cad10 --- /dev/null +++ b/wrappers/log-data-protection-policy/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 0.13.1" +} From 271248f42f4eac6289d6d79e93e7872cec760777 Mon Sep 17 00:00:00 2001 From: magreenbaum Date: Sat, 2 Sep 2023 22:48:44 -0400 Subject: [PATCH 02/11] update required min version --- examples/log-group-with-data-protection-policy/README.md | 2 +- examples/log-group-with-data-protection-policy/versions.tf | 2 +- modules/log-data-protection-policy/README.md | 4 ++-- modules/log-data-protection-policy/versions.tf | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/log-group-with-data-protection-policy/README.md b/examples/log-group-with-data-protection-policy/README.md index c8af47b..9eb2a9f 100644 --- a/examples/log-group-with-data-protection-policy/README.md +++ b/examples/log-group-with-data-protection-policy/README.md @@ -6,7 +6,7 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 4.42 | ## Providers diff --git a/examples/log-group-with-data-protection-policy/versions.tf b/examples/log-group-with-data-protection-policy/versions.tf index ddfcb0e..b8fc66b 100644 --- a/examples/log-group-with-data-protection-policy/versions.tf +++ b/examples/log-group-with-data-protection-policy/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 4.42" } } } diff --git a/modules/log-data-protection-policy/README.md b/modules/log-data-protection-policy/README.md index bb2acf3..faeeb86 100644 --- a/modules/log-data-protection-policy/README.md +++ b/modules/log-data-protection-policy/README.md @@ -6,13 +6,13 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.0 | +| [aws](#requirement\_aws) | >= 4.42 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 4.42 | ## Modules diff --git a/modules/log-data-protection-policy/versions.tf b/modules/log-data-protection-policy/versions.tf index ddfcb0e..b8fc66b 100644 --- a/modules/log-data-protection-policy/versions.tf +++ b/modules/log-data-protection-policy/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 5.0" + version = ">= 4.42" } } } From 6c27eaf5c16812128eaad1b3df7b366eaf34279c Mon Sep 17 00:00:00 2001 From: magreenbaum Date: Sat, 4 Nov 2023 20:27:34 -0400 Subject: [PATCH 03/11] update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d0c344c..3cdfa5d 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,7 @@ AWS CloudTrail normally publishes logs into AWS CloudWatch Logs. This module cre - [Cloudwatch metric alarms for AWS Lambda](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/lambda-metric-alarm) - [Cloudwatch metric alarms for AWS Lambda with multiple dimensions](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/multiple-lambda-metric-alarm) - [CIS AWS Foundations Controls: Metrics + Alarms](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/cis-alarms) +- [Cloudwatch log data protection policy](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/log-group-with-data-protection-policy) From 3d52b36c89eb10e7d14fc7c6a289120fb7c0795f Mon Sep 17 00:00:00 2001 From: magreenbaum Date: Sun, 5 Nov 2023 18:25:59 -0500 Subject: [PATCH 04/11] update readme example --- README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/README.md b/README.md index 3cdfa5d..9f70b0d 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,46 @@ module "cis_alarms" { } ``` +### Log Group Data Protection Policy + +```hcl +module "log_group_data_protection" { + source = "terraform-aws-modules/cloudwatch/aws//modules/log-data-protection-policy" + version = "~> 4.0" + + log_group_name = "my-log-group" + policy_document = jsonencode({ + Name = "Example" + Version = "2021-06-01" + + Statement = [ + { + Sid = "Audit" + DataIdentifier = ["arn:aws:dataprotection::aws:data-identifier/Address"] + Operation = { + Audit = { + FindingsDestination = { + CloudWatchLogs = { + LogGroup = module.audit_destination_group.cloudwatch_log_group_name + } + } + } + } + }, + { + Sid = "Redact" + DataIdentifier = ["arn:aws:dataprotection::aws:data-identifier/Address"] + Operation = { + Deidentify = { + MaskConfig = {} + } + } + } + ] + }) +} +``` + AWS CloudTrail normally publishes logs into AWS CloudWatch Logs. This module creates log metric filters together with metric alarms according to [CIS AWS Foundations Benchmark v1.4.0 (05-28-2021)](https://www.cisecurity.org/benchmark/amazon_web_services/). Read more about [CIS AWS Foundations Controls](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-cis-controls.html). ## Examples From c93d2ef2517abf7e65420cb19a575ef6583eb4fa Mon Sep 17 00:00:00 2001 From: magreenbaum Date: Sun, 5 Nov 2023 18:26:21 -0500 Subject: [PATCH 05/11] update readme example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f70b0d..947b789 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ module "log_group_data_protection" { source = "terraform-aws-modules/cloudwatch/aws//modules/log-data-protection-policy" version = "~> 4.0" - log_group_name = "my-log-group" + log_group_name = "my-log-group" policy_document = jsonencode({ Name = "Example" Version = "2021-06-01" From daa7b1de10a70237ae3c3820725662807ba6e6d1 Mon Sep 17 00:00:00 2001 From: magreenbaum Date: Mon, 19 Feb 2024 20:57:03 -0500 Subject: [PATCH 06/11] adjust version --- examples/log-group-with-data-protection-policy/README.md | 2 +- examples/log-group-with-data-protection-policy/main.tf | 2 +- examples/log-group-with-data-protection-policy/versions.tf | 2 +- modules/log-data-protection-policy/README.md | 4 ++-- modules/log-data-protection-policy/versions.tf | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/log-group-with-data-protection-policy/README.md b/examples/log-group-with-data-protection-policy/README.md index 9eb2a9f..c8af47b 100644 --- a/examples/log-group-with-data-protection-policy/README.md +++ b/examples/log-group-with-data-protection-policy/README.md @@ -6,7 +6,7 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 4.42 | +| [aws](#requirement\_aws) | >= 5.0 | ## Providers diff --git a/examples/log-group-with-data-protection-policy/main.tf b/examples/log-group-with-data-protection-policy/main.tf index 425c27d..d75c67b 100644 --- a/examples/log-group-with-data-protection-policy/main.tf +++ b/examples/log-group-with-data-protection-policy/main.tf @@ -21,7 +21,7 @@ module "log_data_protection_policy" { log_group_name = module.log_group.cloudwatch_log_group_name policy_document = jsonencode({ - Name = "Example" + Name = "RedactAddresses" Version = "2021-06-01" Statement = [ diff --git a/examples/log-group-with-data-protection-policy/versions.tf b/examples/log-group-with-data-protection-policy/versions.tf index b8fc66b..ddfcb0e 100644 --- a/examples/log-group-with-data-protection-policy/versions.tf +++ b/examples/log-group-with-data-protection-policy/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.42" + version = ">= 5.0" } } } diff --git a/modules/log-data-protection-policy/README.md b/modules/log-data-protection-policy/README.md index faeeb86..bb2acf3 100644 --- a/modules/log-data-protection-policy/README.md +++ b/modules/log-data-protection-policy/README.md @@ -6,13 +6,13 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 4.42 | +| [aws](#requirement\_aws) | >= 5.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 4.42 | +| [aws](#provider\_aws) | >= 5.0 | ## Modules diff --git a/modules/log-data-protection-policy/versions.tf b/modules/log-data-protection-policy/versions.tf index b8fc66b..ddfcb0e 100644 --- a/modules/log-data-protection-policy/versions.tf +++ b/modules/log-data-protection-policy/versions.tf @@ -4,7 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.42" + version = ">= 5.0" } } } From d6b66f950641715e5d29a129a9d3cde2774445ce Mon Sep 17 00:00:00 2001 From: magreenbaum Date: Tue, 20 Feb 2024 21:03:26 -0500 Subject: [PATCH 07/11] add default values --- modules/log-data-protection-policy/README.md | 4 ++-- modules/log-data-protection-policy/variables.tf | 2 ++ wrappers/log-data-protection-policy/main.tf | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/log-data-protection-policy/README.md b/modules/log-data-protection-policy/README.md index bb2acf3..c017bc1 100644 --- a/modules/log-data-protection-policy/README.md +++ b/modules/log-data-protection-policy/README.md @@ -29,8 +29,8 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [create](#input\_create) | Whether to create the cloudwatch log data protection policy. | `bool` | `true` | no | -| [log\_group\_name](#input\_log\_group\_name) | The name of the log group under which the log stream is to be created. | `string` | n/a | yes | -| [policy\_document](#input\_policy\_document) | Specifies the data protection policy in JSON. | `string` | n/a | yes | +| [log\_group\_name](#input\_log\_group\_name) | The name of the log group under which the log stream is to be created. | `string` | `null` | no | +| [policy\_document](#input\_policy\_document) | Specifies the data protection policy in JSON. | `string` | `null` | no | ## Outputs diff --git a/modules/log-data-protection-policy/variables.tf b/modules/log-data-protection-policy/variables.tf index 9e8fe06..daf7e94 100644 --- a/modules/log-data-protection-policy/variables.tf +++ b/modules/log-data-protection-policy/variables.tf @@ -7,9 +7,11 @@ variable "create" { variable "log_group_name" { description = "The name of the log group under which the log stream is to be created." type = string + default = null } variable "policy_document" { description = "Specifies the data protection policy in JSON." type = string + default = null } diff --git a/wrappers/log-data-protection-policy/main.tf b/wrappers/log-data-protection-policy/main.tf index a730e35..9556736 100644 --- a/wrappers/log-data-protection-policy/main.tf +++ b/wrappers/log-data-protection-policy/main.tf @@ -4,6 +4,6 @@ module "wrapper" { for_each = var.items create = try(each.value.create, var.defaults.create, true) - log_group_name = try(each.value.log_group_name, var.defaults.log_group_name) - policy_document = try(each.value.policy_document, var.defaults.policy_document) + log_group_name = try(each.value.log_group_name, var.defaults.log_group_name, null) + policy_document = try(each.value.policy_document, var.defaults.policy_document, null) } From b59cfaabff4639be71d866558155f653789d6b76 Mon Sep 17 00:00:00 2001 From: magreenbaum Date: Sun, 30 Jun 2024 11:19:10 -0400 Subject: [PATCH 08/11] use data source for data protection policy document --- README.md | 38 +++---------- .../README.md | 2 + .../main.tf | 28 ++++++++-- modules/log-data-protection-policy/README.md | 10 ++++ modules/log-data-protection-policy/main.tf | 56 ++++++++++++++++++- .../log-data-protection-policy/variables.tf | 54 ++++++++++++++++++ wrappers/log-data-protection-policy/main.tf | 15 ++++- 7 files changed, 164 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 68d779e..6819884 100644 --- a/README.md +++ b/README.md @@ -128,39 +128,15 @@ module "log_group_data_protection" { version = "~> 4.0" log_group_name = "my-log-group" - policy_document = jsonencode({ - Name = "Example" - Version = "2021-06-01" - - Statement = [ - { - Sid = "Audit" - DataIdentifier = ["arn:aws:dataprotection::aws:data-identifier/Address"] - Operation = { - Audit = { - FindingsDestination = { - CloudWatchLogs = { - LogGroup = module.audit_destination_group.cloudwatch_log_group_name - } - } - } - } - }, - { - Sid = "Redact" - DataIdentifier = ["arn:aws:dataprotection::aws:data-identifier/Address"] - Operation = { - Deidentify = { - MaskConfig = {} - } - } - } - ] - }) + create_log_data_protection_policy = true + log_data_protection_policy_name = "RedactAddress" + + data_identifiers = ["arn:aws:dataprotection::aws:data-identifier/Address"] + findings_destination_cloudwatch_log_group = "audit-log-group" } ``` -### Metric Stream +### Metric Stream ```hcl module "metric_stream" { @@ -210,7 +186,7 @@ module "metric_stream" { module "query_definition" { source = "terraform-aws-modules/cloudwatch/aws//modules/query-definition" version = "~> 4.0" - + name = "my-query-definition" log_group_names = ["my-log-group-name"] query_string = < [audit\_destination\_group](#module\_audit\_destination\_group) | ../../modules/log-group | n/a | +| [custom\_data\_protection\_policy\_log\_group](#module\_custom\_data\_protection\_policy\_log\_group) | ../../modules/log-group | n/a | +| [custom\_log\_data\_protection\_policy](#module\_custom\_log\_data\_protection\_policy) | ../../modules/log-data-protection-policy | n/a | | [log\_data\_protection\_policy](#module\_log\_data\_protection\_policy) | ../../modules/log-data-protection-policy | n/a | | [log\_group](#module\_log\_group) | ../../modules/log-group | n/a | diff --git a/examples/log-group-with-data-protection-policy/main.tf b/examples/log-group-with-data-protection-policy/main.tf index d75c67b..47f6d8b 100644 --- a/examples/log-group-with-data-protection-policy/main.tf +++ b/examples/log-group-with-data-protection-policy/main.tf @@ -9,6 +9,14 @@ module "log_group" { retention_in_days = 7 } +module "custom_data_protection_policy_log_group" { + source = "../../modules/log-group" + + name_prefix = "my-log-group-" + retention_in_days = 7 +} + + module "audit_destination_group" { source = "../../modules/log-group" @@ -19,15 +27,27 @@ module "audit_destination_group" { module "log_data_protection_policy" { source = "../../modules/log-data-protection-policy" - log_group_name = module.log_group.cloudwatch_log_group_name + log_group_name = module.log_group.cloudwatch_log_group_name + create_log_data_protection_policy = true + log_data_protection_policy_name = "RedactAddress" + + data_identifiers = ["arn:aws:dataprotection::aws:data-identifier/Address"] + findings_destination_cloudwatch_log_group = module.audit_destination_group.cloudwatch_log_group_name +} + +module "custom_log_data_protection_policy" { + source = "../../modules/log-data-protection-policy" + + log_group_name = module.custom_data_protection_policy_log_group.cloudwatch_log_group_name + policy_document = jsonencode({ - Name = "RedactAddresses" + Name = "RedactCreditCardNumbers" Version = "2021-06-01" Statement = [ { Sid = "Audit" - DataIdentifier = ["arn:aws:dataprotection::aws:data-identifier/Address"] + DataIdentifier = ["arn:aws:dataprotection::aws:data-identifier/CreditCardNumber"] Operation = { Audit = { FindingsDestination = { @@ -40,7 +60,7 @@ module "log_data_protection_policy" { }, { Sid = "Redact" - DataIdentifier = ["arn:aws:dataprotection::aws:data-identifier/Address"] + DataIdentifier = ["arn:aws:dataprotection::aws:data-identifier/CreditCardNumber"] Operation = { Deidentify = { MaskConfig = {} diff --git a/modules/log-data-protection-policy/README.md b/modules/log-data-protection-policy/README.md index c017bc1..65d8994 100644 --- a/modules/log-data-protection-policy/README.md +++ b/modules/log-data-protection-policy/README.md @@ -23,12 +23,22 @@ No modules. | Name | Type | |------|------| | [aws_cloudwatch_log_data_protection_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_data_protection_policy) | resource | +| [aws_cloudwatch_log_data_protection_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/cloudwatch_log_data_protection_policy_document) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [audit\_statement\_sid](#input\_audit\_statement\_sid) | Name of the audit statement. | `string` | `"audit-policy"` | no | | [create](#input\_create) | Whether to create the cloudwatch log data protection policy. | `bool` | `true` | no | +| [create\_log\_data\_protection\_policy](#input\_create\_log\_data\_protection\_policy) | Whether to create the cloudwatch log data protection policy. | `bool` | `false` | no | +| [data\_identifiers](#input\_data\_identifiers) | Set of at least 1 sensitive data identifiers that you want to mask. | `list(string)` | `null` | no | +| [deidentify\_statement\_sid](#input\_deidentify\_statement\_sid) | Name of the deidentify statement. | `string` | `"redact-policy"` | no | +| [findings\_destination\_cloudwatch\_log\_group](#input\_findings\_destination\_cloudwatch\_log\_group) | Configures CloudWatch Logs as a findings destination. | `string` | `null` | no | +| [findings\_destination\_firehose\_delivery\_stream](#input\_findings\_destination\_firehose\_delivery\_stream) | Configures Kinesis Firehose as a findings destination. | `string` | `null` | no | +| [findings\_destination\_s3\_bucket](#input\_findings\_destination\_s3\_bucket) | Configures S3 as a findings destination. | `string` | `null` | no | +| [log\_data\_protection\_description](#input\_log\_data\_protection\_description) | The description of the data protection policy document. | `string` | `null` | no | +| [log\_data\_protection\_policy\_name](#input\_log\_data\_protection\_policy\_name) | The name of the data protection policy document. | `string` | `null` | no | | [log\_group\_name](#input\_log\_group\_name) | The name of the log group under which the log stream is to be created. | `string` | `null` | no | | [policy\_document](#input\_policy\_document) | Specifies the data protection policy in JSON. | `string` | `null` | no | diff --git a/modules/log-data-protection-policy/main.tf b/modules/log-data-protection-policy/main.tf index 7954224..cfe2d1f 100644 --- a/modules/log-data-protection-policy/main.tf +++ b/modules/log-data-protection-policy/main.tf @@ -2,5 +2,59 @@ resource "aws_cloudwatch_log_data_protection_policy" "this" { count = var.create ? 1 : 0 log_group_name = var.log_group_name - policy_document = var.policy_document + policy_document = var.create_log_data_protection_policy ? data.aws_cloudwatch_log_data_protection_policy_document.this[0].json : var.policy_document +} + +data "aws_cloudwatch_log_data_protection_policy_document" "this" { + count = var.create && var.create_log_data_protection_policy ? 1 : 0 + + name = var.log_data_protection_policy_name + description = try(var.log_data_protection_description, null) + + statement { + sid = var.audit_statement_sid + data_identifiers = var.data_identifiers + + operation { + audit { + findings_destination { + + dynamic "cloudwatch_logs" { + for_each = var.findings_destination_cloudwatch_log_group != null ? [true] : [] + + content { + log_group = var.findings_destination_cloudwatch_log_group + } + } + + dynamic "firehose" { + for_each = var.findings_destination_firehose_delivery_stream != null ? [true] : [] + + content { + delivery_stream = var.findings_destination_firehose_delivery_stream + } + } + + dynamic "s3" { + for_each = var.findings_destination_s3_bucket != null ? [true] : [] + + content { + bucket = var.findings_destination_s3_bucket + } + } + } + } + } + } + + statement { + sid = var.deidentify_statement_sid + data_identifiers = var.data_identifiers + + operation { + deidentify { + mask_config {} + } + } + } } diff --git a/modules/log-data-protection-policy/variables.tf b/modules/log-data-protection-policy/variables.tf index daf7e94..0e1a65c 100644 --- a/modules/log-data-protection-policy/variables.tf +++ b/modules/log-data-protection-policy/variables.tf @@ -4,6 +4,12 @@ variable "create" { default = true } +variable "create_log_data_protection_policy" { + description = "Whether to create the cloudwatch log data protection policy." + type = bool + default = false +} + variable "log_group_name" { description = "The name of the log group under which the log stream is to be created." type = string @@ -15,3 +21,51 @@ variable "policy_document" { type = string default = null } + +variable "log_data_protection_policy_name" { + description = "The name of the data protection policy document." + type = string + default = null +} + +variable "log_data_protection_description" { + description = "The description of the data protection policy document." + type = string + default = null +} + +variable "audit_statement_sid" { + description = "Name of the audit statement." + type = string + default = "audit-policy" +} + +variable "deidentify_statement_sid" { + description = "Name of the deidentify statement." + type = string + default = "redact-policy" +} + +variable "data_identifiers" { + description = "Set of at least 1 sensitive data identifiers that you want to mask." + type = list(string) + default = null +} + +variable "findings_destination_cloudwatch_log_group" { + description = "Configures CloudWatch Logs as a findings destination." + type = string + default = null +} + +variable "findings_destination_firehose_delivery_stream" { + description = "Configures Kinesis Firehose as a findings destination." + type = string + default = null +} + +variable "findings_destination_s3_bucket" { + description = "Configures S3 as a findings destination." + type = string + default = null +} diff --git a/wrappers/log-data-protection-policy/main.tf b/wrappers/log-data-protection-policy/main.tf index 9556736..e02421d 100644 --- a/wrappers/log-data-protection-policy/main.tf +++ b/wrappers/log-data-protection-policy/main.tf @@ -3,7 +3,16 @@ module "wrapper" { for_each = var.items - create = try(each.value.create, var.defaults.create, true) - log_group_name = try(each.value.log_group_name, var.defaults.log_group_name, null) - policy_document = try(each.value.policy_document, var.defaults.policy_document, null) + create = try(each.value.create, var.defaults.create, true) + create_log_data_protection_policy = try(each.value.create_log_data_protection_policy, var.defaults.create_log_data_protection_policy, false) + log_group_name = try(each.value.log_group_name, var.defaults.log_group_name, null) + policy_document = try(each.value.policy_document, var.defaults.policy_document, null) + log_data_protection_policy_name = try(each.value.log_data_protection_policy_name, var.defaults.log_data_protection_policy_name, null) + log_data_protection_description = try(each.value.log_data_protection_description, var.defaults.log_data_protection_description, null) + audit_statement_sid = try(each.value.audit_statement_sid, var.defaults.audit_statement_sid, "audit-policy") + deidentify_statement_sid = try(each.value.deidentify_statement_sid, var.defaults.deidentify_statement_sid, "redact-policy") + data_identifiers = try(each.value.data_identifiers, var.defaults.data_identifiers, null) + findings_destination_cloudwatch_log_group = try(each.value.findings_destination_cloudwatch_log_group, var.defaults.findings_destination_cloudwatch_log_group, null) + findings_destination_firehose_delivery_stream = try(each.value.findings_destination_firehose_delivery_stream, var.defaults.findings_destination_firehose_delivery_stream, null) + findings_destination_s3_bucket = try(each.value.findings_destination_s3_bucket, var.defaults.findings_destination_s3_bucket, null) } From 0a1569b0b3d50f4722437d3364db5cea4779bb0e Mon Sep 17 00:00:00 2001 From: magreenbaum Date: Sun, 30 Jun 2024 14:08:52 -0400 Subject: [PATCH 09/11] adjust example and update README --- README.md | 15 +++++++++++++++ .../log-group-with-data-protection-policy/main.tf | 2 +- wrappers/log-data-protection-policy/main.tf | 12 ++++++------ wrappers/log-data-protection-policy/outputs.tf | 2 +- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 6819884..1d1320e 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,20 @@ module "log_group_data_protection" { } ``` +### Log Subscription Filter + +```hcl +module "log_subscription_filter" { + source = "terraform-aws-modules/cloudwatch/aws//modules/log-subscription-filter" + + name = "my-filter" + destination_arn = "arn:aws:firehose:eu-west-1:835367859852:deliverystream/cw-logs" + filter_pattern = "%test%" + log_group_name = "my-log-group" + role_arn = "arn:aws:iam::835367859852:role/cw-logs-to-firehose" +} +``` + ### Metric Stream ```hcl @@ -233,6 +247,7 @@ module "composite_alarm" { - [Cloudwatch query definition](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/query-definition) - [Cloudwatch Metric Stream](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/metric-stream) - [Cloudwatch Composite Alarm](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/composite-alarm) +- [Cloudwatch log subscription filter](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/log-subscription-filter) - [Cloudwatch log data protection policy](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/log-group-with-data-protection-policy) diff --git a/examples/log-group-with-data-protection-policy/main.tf b/examples/log-group-with-data-protection-policy/main.tf index 47f6d8b..025dba4 100644 --- a/examples/log-group-with-data-protection-policy/main.tf +++ b/examples/log-group-with-data-protection-policy/main.tf @@ -12,7 +12,7 @@ module "log_group" { module "custom_data_protection_policy_log_group" { source = "../../modules/log-group" - name_prefix = "my-log-group-" + name_prefix = "my-custom-policy-log-group-" retention_in_days = 7 } diff --git a/wrappers/log-data-protection-policy/main.tf b/wrappers/log-data-protection-policy/main.tf index e02421d..61bdb98 100644 --- a/wrappers/log-data-protection-policy/main.tf +++ b/wrappers/log-data-protection-policy/main.tf @@ -3,16 +3,16 @@ module "wrapper" { for_each = var.items + audit_statement_sid = try(each.value.audit_statement_sid, var.defaults.audit_statement_sid, "audit-policy") create = try(each.value.create, var.defaults.create, true) create_log_data_protection_policy = try(each.value.create_log_data_protection_policy, var.defaults.create_log_data_protection_policy, false) - log_group_name = try(each.value.log_group_name, var.defaults.log_group_name, null) - policy_document = try(each.value.policy_document, var.defaults.policy_document, null) - log_data_protection_policy_name = try(each.value.log_data_protection_policy_name, var.defaults.log_data_protection_policy_name, null) - log_data_protection_description = try(each.value.log_data_protection_description, var.defaults.log_data_protection_description, null) - audit_statement_sid = try(each.value.audit_statement_sid, var.defaults.audit_statement_sid, "audit-policy") - deidentify_statement_sid = try(each.value.deidentify_statement_sid, var.defaults.deidentify_statement_sid, "redact-policy") data_identifiers = try(each.value.data_identifiers, var.defaults.data_identifiers, null) + deidentify_statement_sid = try(each.value.deidentify_statement_sid, var.defaults.deidentify_statement_sid, "redact-policy") findings_destination_cloudwatch_log_group = try(each.value.findings_destination_cloudwatch_log_group, var.defaults.findings_destination_cloudwatch_log_group, null) findings_destination_firehose_delivery_stream = try(each.value.findings_destination_firehose_delivery_stream, var.defaults.findings_destination_firehose_delivery_stream, null) findings_destination_s3_bucket = try(each.value.findings_destination_s3_bucket, var.defaults.findings_destination_s3_bucket, null) + log_data_protection_description = try(each.value.log_data_protection_description, var.defaults.log_data_protection_description, null) + log_data_protection_policy_name = try(each.value.log_data_protection_policy_name, var.defaults.log_data_protection_policy_name, null) + log_group_name = try(each.value.log_group_name, var.defaults.log_group_name, null) + policy_document = try(each.value.policy_document, var.defaults.policy_document, null) } diff --git a/wrappers/log-data-protection-policy/outputs.tf b/wrappers/log-data-protection-policy/outputs.tf index 5da7c09..ec6da5f 100644 --- a/wrappers/log-data-protection-policy/outputs.tf +++ b/wrappers/log-data-protection-policy/outputs.tf @@ -1,5 +1,5 @@ output "wrapper" { description = "Map of outputs of a wrapper." value = module.wrapper - # sensitive = false # No sensitive module output found + # sensitive = false # No sensitive module output found } From 7aaef4ee400b614a0c78f719cc58e75397595aeb Mon Sep 17 00:00:00 2001 From: magreenbaum Date: Sun, 30 Jun 2024 14:27:05 -0400 Subject: [PATCH 10/11] update example with custom data identifier --- .../main.tf | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/examples/log-group-with-data-protection-policy/main.tf b/examples/log-group-with-data-protection-policy/main.tf index 025dba4..dd43255 100644 --- a/examples/log-group-with-data-protection-policy/main.tf +++ b/examples/log-group-with-data-protection-policy/main.tf @@ -40,14 +40,26 @@ module "custom_log_data_protection_policy" { log_group_name = module.custom_data_protection_policy_log_group.cloudwatch_log_group_name + # custom data identifier not yet supported by the data source for aws_cloudwatch_log_data_protection_policy within the module + # specify your own json policy document if this is needed + # https://github.com/hashicorp/terraform-provider-aws/issues/35682 policy_document = jsonencode({ - Name = "RedactCreditCardNumbers" + Name = "RedactCustomerId" Version = "2021-06-01" + Configuration = { + CustomDataIdentifier = [ + { + Name = "CustomerId", + Regex = "CustomerId-\\d{5}" + } + ] + } + Statement = [ { Sid = "Audit" - DataIdentifier = ["arn:aws:dataprotection::aws:data-identifier/CreditCardNumber"] + DataIdentifier = ["CustomerId"] Operation = { Audit = { FindingsDestination = { @@ -60,7 +72,7 @@ module "custom_log_data_protection_policy" { }, { Sid = "Redact" - DataIdentifier = ["arn:aws:dataprotection::aws:data-identifier/CreditCardNumber"] + DataIdentifier = ["CustomerId"] Operation = { Deidentify = { MaskConfig = {} From 0ea4f88984debbfa9be3e6f7c36e9508a5a64ae4 Mon Sep 17 00:00:00 2001 From: magreenbaum Date: Mon, 1 Jul 2024 07:40:31 -0400 Subject: [PATCH 11/11] adjust description variable --- modules/log-data-protection-policy/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/log-data-protection-policy/main.tf b/modules/log-data-protection-policy/main.tf index cfe2d1f..8360a10 100644 --- a/modules/log-data-protection-policy/main.tf +++ b/modules/log-data-protection-policy/main.tf @@ -9,7 +9,7 @@ data "aws_cloudwatch_log_data_protection_policy_document" "this" { count = var.create && var.create_log_data_protection_policy ? 1 : 0 name = var.log_data_protection_policy_name - description = try(var.log_data_protection_description, null) + description = var.log_data_protection_description statement { sid = var.audit_statement_sid