Skip to content

Commit 2b434f3

Browse files
authored
feat: Support aws_cloudwatch_log_data_protection_policy (#70)
Co-authored-by: magreenbaum <magreenbaum>
1 parent 235046c commit 2b434f3

File tree

16 files changed

+506
-0
lines changed

16 files changed

+506
-0
lines changed

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,36 @@ module "cis_alarms" {
120120

121121
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).
122122

123+
### Log Group Data Protection Policy
124+
125+
```hcl
126+
module "log_group_data_protection" {
127+
source = "terraform-aws-modules/cloudwatch/aws//modules/log-data-protection-policy"
128+
version = "~> 4.0"
129+
130+
log_group_name = "my-log-group"
131+
create_log_data_protection_policy = true
132+
log_data_protection_policy_name = "RedactAddress"
133+
134+
data_identifiers = ["arn:aws:dataprotection::aws:data-identifier/Address"]
135+
findings_destination_cloudwatch_log_group = "audit-log-group"
136+
}
137+
```
138+
139+
### Log Subscription Filter
140+
141+
```hcl
142+
module "log_subscription_filter" {
143+
source = "terraform-aws-modules/cloudwatch/aws//modules/log-subscription-filter"
144+
145+
name = "my-filter"
146+
destination_arn = "arn:aws:firehose:eu-west-1:835367859852:deliverystream/cw-logs"
147+
filter_pattern = "%test%"
148+
log_group_name = "my-log-group"
149+
role_arn = "arn:aws:iam::835367859852:role/cw-logs-to-firehose"
150+
}
151+
```
152+
123153
### Metric Stream
124154

125155
```hcl
@@ -234,6 +264,8 @@ module "log_account_policy" {
234264
- [Cloudwatch query definition](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/query-definition)
235265
- [Cloudwatch Metric Stream](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/metric-stream)
236266
- [Cloudwatch Composite Alarm](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/composite-alarm)
267+
- [Cloudwatch log subscription filter](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/log-subscription-filter)
268+
- [Cloudwatch log data protection policy](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/log-group-with-data-protection-policy)
237269
- [Cloudwatch Log Account Policy](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/log-account-policy)
238270

239271
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Complete Cloudwatch log group and data protection policy
2+
3+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
4+
## Requirements
5+
6+
| Name | Version |
7+
|------|---------|
8+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
9+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |
10+
11+
## Providers
12+
13+
No providers.
14+
15+
## Modules
16+
17+
| Name | Source | Version |
18+
|------|--------|---------|
19+
| <a name="module_audit_destination_group"></a> [audit\_destination\_group](#module\_audit\_destination\_group) | ../../modules/log-group | n/a |
20+
| <a name="module_custom_data_protection_policy_log_group"></a> [custom\_data\_protection\_policy\_log\_group](#module\_custom\_data\_protection\_policy\_log\_group) | ../../modules/log-group | n/a |
21+
| <a name="module_custom_log_data_protection_policy"></a> [custom\_log\_data\_protection\_policy](#module\_custom\_log\_data\_protection\_policy) | ../../modules/log-data-protection-policy | n/a |
22+
| <a name="module_log_data_protection_policy"></a> [log\_data\_protection\_policy](#module\_log\_data\_protection\_policy) | ../../modules/log-data-protection-policy | n/a |
23+
| <a name="module_log_group"></a> [log\_group](#module\_log\_group) | ../../modules/log-group | n/a |
24+
25+
## Resources
26+
27+
No resources.
28+
29+
## Inputs
30+
31+
No inputs.
32+
33+
## Outputs
34+
35+
| Name | Description |
36+
|------|-------------|
37+
| <a name="output_cloudwatch_log_group_arn"></a> [cloudwatch\_log\_group\_arn](#output\_cloudwatch\_log\_group\_arn) | ARN of Cloudwatch log group |
38+
| <a name="output_cloudwatch_log_group_name"></a> [cloudwatch\_log\_group\_name](#output\_cloudwatch\_log\_group\_name) | Name of Cloudwatch log group |
39+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
provider "aws" {
2+
region = "eu-west-1"
3+
}
4+
5+
module "log_group" {
6+
source = "../../modules/log-group"
7+
8+
name_prefix = "my-log-group-"
9+
retention_in_days = 7
10+
}
11+
12+
module "custom_data_protection_policy_log_group" {
13+
source = "../../modules/log-group"
14+
15+
name_prefix = "my-custom-policy-log-group-"
16+
retention_in_days = 7
17+
}
18+
19+
20+
module "audit_destination_group" {
21+
source = "../../modules/log-group"
22+
23+
name_prefix = "audit-destination-log-group-"
24+
retention_in_days = 7
25+
}
26+
27+
module "log_data_protection_policy" {
28+
source = "../../modules/log-data-protection-policy"
29+
30+
log_group_name = module.log_group.cloudwatch_log_group_name
31+
create_log_data_protection_policy = true
32+
log_data_protection_policy_name = "RedactAddress"
33+
34+
data_identifiers = ["arn:aws:dataprotection::aws:data-identifier/Address"]
35+
findings_destination_cloudwatch_log_group = module.audit_destination_group.cloudwatch_log_group_name
36+
}
37+
38+
module "custom_log_data_protection_policy" {
39+
source = "../../modules/log-data-protection-policy"
40+
41+
log_group_name = module.custom_data_protection_policy_log_group.cloudwatch_log_group_name
42+
43+
# custom data identifier not yet supported by the data source for aws_cloudwatch_log_data_protection_policy within the module
44+
# specify your own json policy document if this is needed
45+
# https://github.com/hashicorp/terraform-provider-aws/issues/35682
46+
policy_document = jsonencode({
47+
Name = "RedactCustomerId"
48+
Version = "2021-06-01"
49+
50+
Configuration = {
51+
CustomDataIdentifier = [
52+
{
53+
Name = "CustomerId",
54+
Regex = "CustomerId-\\d{5}"
55+
}
56+
]
57+
}
58+
59+
Statement = [
60+
{
61+
Sid = "Audit"
62+
DataIdentifier = ["CustomerId"]
63+
Operation = {
64+
Audit = {
65+
FindingsDestination = {
66+
CloudWatchLogs = {
67+
LogGroup = module.audit_destination_group.cloudwatch_log_group_name
68+
}
69+
}
70+
}
71+
}
72+
},
73+
{
74+
Sid = "Redact"
75+
DataIdentifier = ["CustomerId"]
76+
Operation = {
77+
Deidentify = {
78+
MaskConfig = {}
79+
}
80+
}
81+
}
82+
]
83+
})
84+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
output "cloudwatch_log_group_name" {
2+
description = "Name of Cloudwatch log group"
3+
value = module.log_group.cloudwatch_log_group_name
4+
}
5+
6+
output "cloudwatch_log_group_arn" {
7+
description = "ARN of Cloudwatch log group"
8+
value = module.log_group.cloudwatch_log_group_arn
9+
}

examples/log-group-with-data-protection-policy/variables.tf

Whitespace-only changes.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
terraform {
2+
required_version = ">= 1.0"
3+
4+
required_providers {
5+
aws = {
6+
source = "hashicorp/aws"
7+
version = ">= 5.0"
8+
}
9+
}
10+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# log-data-protection-policy
2+
3+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
4+
## Requirements
5+
6+
| Name | Version |
7+
|------|---------|
8+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
9+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |
10+
11+
## Providers
12+
13+
| Name | Version |
14+
|------|---------|
15+
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.0 |
16+
17+
## Modules
18+
19+
No modules.
20+
21+
## Resources
22+
23+
| Name | Type |
24+
|------|------|
25+
| [aws_cloudwatch_log_data_protection_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_data_protection_policy) | resource |
26+
| [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 |
27+
28+
## Inputs
29+
30+
| Name | Description | Type | Default | Required |
31+
|------|-------------|------|---------|:--------:|
32+
| <a name="input_audit_statement_sid"></a> [audit\_statement\_sid](#input\_audit\_statement\_sid) | Name of the audit statement. | `string` | `"audit-policy"` | no |
33+
| <a name="input_create"></a> [create](#input\_create) | Whether to create the cloudwatch log data protection policy. | `bool` | `true` | no |
34+
| <a name="input_create_log_data_protection_policy"></a> [create\_log\_data\_protection\_policy](#input\_create\_log\_data\_protection\_policy) | Whether to create the cloudwatch log data protection policy. | `bool` | `false` | no |
35+
| <a name="input_data_identifiers"></a> [data\_identifiers](#input\_data\_identifiers) | Set of at least 1 sensitive data identifiers that you want to mask. | `list(string)` | `null` | no |
36+
| <a name="input_deidentify_statement_sid"></a> [deidentify\_statement\_sid](#input\_deidentify\_statement\_sid) | Name of the deidentify statement. | `string` | `"redact-policy"` | no |
37+
| <a name="input_findings_destination_cloudwatch_log_group"></a> [findings\_destination\_cloudwatch\_log\_group](#input\_findings\_destination\_cloudwatch\_log\_group) | Configures CloudWatch Logs as a findings destination. | `string` | `null` | no |
38+
| <a name="input_findings_destination_firehose_delivery_stream"></a> [findings\_destination\_firehose\_delivery\_stream](#input\_findings\_destination\_firehose\_delivery\_stream) | Configures Kinesis Firehose as a findings destination. | `string` | `null` | no |
39+
| <a name="input_findings_destination_s3_bucket"></a> [findings\_destination\_s3\_bucket](#input\_findings\_destination\_s3\_bucket) | Configures S3 as a findings destination. | `string` | `null` | no |
40+
| <a name="input_log_data_protection_description"></a> [log\_data\_protection\_description](#input\_log\_data\_protection\_description) | The description of the data protection policy document. | `string` | `null` | no |
41+
| <a name="input_log_data_protection_policy_name"></a> [log\_data\_protection\_policy\_name](#input\_log\_data\_protection\_policy\_name) | The name of the data protection policy document. | `string` | `null` | no |
42+
| <a name="input_log_group_name"></a> [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 |
43+
| <a name="input_policy_document"></a> [policy\_document](#input\_policy\_document) | Specifies the data protection policy in JSON. | `string` | `null` | no |
44+
45+
## Outputs
46+
47+
| Name | Description |
48+
|------|-------------|
49+
| <a name="output_log_group_name"></a> [log\_group\_name](#output\_log\_group\_name) | Name of Cloudwatch log group |
50+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
resource "aws_cloudwatch_log_data_protection_policy" "this" {
2+
count = var.create ? 1 : 0
3+
4+
log_group_name = var.log_group_name
5+
policy_document = var.create_log_data_protection_policy ? data.aws_cloudwatch_log_data_protection_policy_document.this[0].json : var.policy_document
6+
}
7+
8+
data "aws_cloudwatch_log_data_protection_policy_document" "this" {
9+
count = var.create && var.create_log_data_protection_policy ? 1 : 0
10+
11+
name = var.log_data_protection_policy_name
12+
description = var.log_data_protection_description
13+
14+
statement {
15+
sid = var.audit_statement_sid
16+
data_identifiers = var.data_identifiers
17+
18+
operation {
19+
audit {
20+
findings_destination {
21+
22+
dynamic "cloudwatch_logs" {
23+
for_each = var.findings_destination_cloudwatch_log_group != null ? [true] : []
24+
25+
content {
26+
log_group = var.findings_destination_cloudwatch_log_group
27+
}
28+
}
29+
30+
dynamic "firehose" {
31+
for_each = var.findings_destination_firehose_delivery_stream != null ? [true] : []
32+
33+
content {
34+
delivery_stream = var.findings_destination_firehose_delivery_stream
35+
}
36+
}
37+
38+
dynamic "s3" {
39+
for_each = var.findings_destination_s3_bucket != null ? [true] : []
40+
41+
content {
42+
bucket = var.findings_destination_s3_bucket
43+
}
44+
}
45+
}
46+
}
47+
}
48+
}
49+
50+
statement {
51+
sid = var.deidentify_statement_sid
52+
data_identifiers = var.data_identifiers
53+
54+
operation {
55+
deidentify {
56+
mask_config {}
57+
}
58+
}
59+
}
60+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
output "log_group_name" {
2+
description = "Name of Cloudwatch log group"
3+
value = var.log_group_name
4+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
variable "create" {
2+
description = "Whether to create the cloudwatch log data protection policy."
3+
type = bool
4+
default = true
5+
}
6+
7+
variable "create_log_data_protection_policy" {
8+
description = "Whether to create the cloudwatch log data protection policy."
9+
type = bool
10+
default = false
11+
}
12+
13+
variable "log_group_name" {
14+
description = "The name of the log group under which the log stream is to be created."
15+
type = string
16+
default = null
17+
}
18+
19+
variable "policy_document" {
20+
description = "Specifies the data protection policy in JSON."
21+
type = string
22+
default = null
23+
}
24+
25+
variable "log_data_protection_policy_name" {
26+
description = "The name of the data protection policy document."
27+
type = string
28+
default = null
29+
}
30+
31+
variable "log_data_protection_description" {
32+
description = "The description of the data protection policy document."
33+
type = string
34+
default = null
35+
}
36+
37+
variable "audit_statement_sid" {
38+
description = "Name of the audit statement."
39+
type = string
40+
default = "audit-policy"
41+
}
42+
43+
variable "deidentify_statement_sid" {
44+
description = "Name of the deidentify statement."
45+
type = string
46+
default = "redact-policy"
47+
}
48+
49+
variable "data_identifiers" {
50+
description = "Set of at least 1 sensitive data identifiers that you want to mask."
51+
type = list(string)
52+
default = null
53+
}
54+
55+
variable "findings_destination_cloudwatch_log_group" {
56+
description = "Configures CloudWatch Logs as a findings destination."
57+
type = string
58+
default = null
59+
}
60+
61+
variable "findings_destination_firehose_delivery_stream" {
62+
description = "Configures Kinesis Firehose as a findings destination."
63+
type = string
64+
default = null
65+
}
66+
67+
variable "findings_destination_s3_bucket" {
68+
description = "Configures S3 as a findings destination."
69+
type = string
70+
default = null
71+
}

0 commit comments

Comments
 (0)