Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support aws_cloudwatch_log_data_protection_policy #70

32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,36 @@ module "cis_alarms" {

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

### 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"
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"
}
```

### 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
Expand Down Expand Up @@ -234,6 +264,8 @@ module "log_account_policy" {
- [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)
- [Cloudwatch Log Account Policy](https://github.com/terraform-aws-modules/terraform-aws-cloudwatch/tree/master/examples/log-account-policy)

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Expand Down
39 changes: 39 additions & 0 deletions examples/log-group-with-data-protection-policy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Complete Cloudwatch log group and data protection policy

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |

## Providers

No providers.

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_audit_destination_group"></a> [audit\_destination\_group](#module\_audit\_destination\_group) | ../../modules/log-group | n/a |
| <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 |
| <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 |
| <a name="module_log_data_protection_policy"></a> [log\_data\_protection\_policy](#module\_log\_data\_protection\_policy) | ../../modules/log-data-protection-policy | n/a |
| <a name="module_log_group"></a> [log\_group](#module\_log\_group) | ../../modules/log-group | n/a |

## Resources

No resources.

## Inputs

No inputs.

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_cloudwatch_log_group_arn"></a> [cloudwatch\_log\_group\_arn](#output\_cloudwatch\_log\_group\_arn) | ARN of Cloudwatch log group |
| <a name="output_cloudwatch_log_group_name"></a> [cloudwatch\_log\_group\_name](#output\_cloudwatch\_log\_group\_name) | Name of Cloudwatch log group |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
84 changes: 84 additions & 0 deletions examples/log-group-with-data-protection-policy/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
provider "aws" {
region = "eu-west-1"
}

module "log_group" {
source = "../../modules/log-group"

name_prefix = "my-log-group-"
retention_in_days = 7
}

module "custom_data_protection_policy_log_group" {
source = "../../modules/log-group"

name_prefix = "my-custom-policy-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
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

# 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 = "RedactCustomerId"
Version = "2021-06-01"

Configuration = {
CustomDataIdentifier = [
{
Name = "CustomerId",
Regex = "CustomerId-\\d{5}"
}
]
}

Statement = [
{
Sid = "Audit"
DataIdentifier = ["CustomerId"]
Operation = {
Audit = {
FindingsDestination = {
CloudWatchLogs = {
LogGroup = module.audit_destination_group.cloudwatch_log_group_name
}
}
}
}
},
{
Sid = "Redact"
DataIdentifier = ["CustomerId"]
Operation = {
Deidentify = {
MaskConfig = {}
}
}
}
]
})
}
9 changes: 9 additions & 0 deletions examples/log-group-with-data-protection-policy/outputs.tf
Original file line number Diff line number Diff line change
@@ -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
}
Empty file.
10 changes: 10 additions & 0 deletions examples/log-group-with-data-protection-policy/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}
50 changes: 50 additions & 0 deletions modules/log-data-protection-policy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# log-data-protection-policy

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [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 |
| [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 |
|------|-------------|------|---------|:--------:|
| <a name="input_audit_statement_sid"></a> [audit\_statement\_sid](#input\_audit\_statement\_sid) | Name of the audit statement. | `string` | `"audit-policy"` | no |
| <a name="input_create"></a> [create](#input\_create) | Whether to create the cloudwatch log data protection policy. | `bool` | `true` | no |
| <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 |
| <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 |
| <a name="input_deidentify_statement_sid"></a> [deidentify\_statement\_sid](#input\_deidentify\_statement\_sid) | Name of the deidentify statement. | `string` | `"redact-policy"` | no |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <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 |
| <a name="input_policy_document"></a> [policy\_document](#input\_policy\_document) | Specifies the data protection policy in JSON. | `string` | `null` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_log_group_name"></a> [log\_group\_name](#output\_log\_group\_name) | Name of Cloudwatch log group |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
60 changes: 60 additions & 0 deletions modules/log-data-protection-policy/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
resource "aws_cloudwatch_log_data_protection_policy" "this" {
count = var.create ? 1 : 0

log_group_name = var.log_group_name
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 = var.log_data_protection_description

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 {}
}
}
}
}
4 changes: 4 additions & 0 deletions modules/log-data-protection-policy/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
output "log_group_name" {
description = "Name of Cloudwatch log group"
value = var.log_group_name
}
71 changes: 71 additions & 0 deletions modules/log-data-protection-policy/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
variable "create" {
description = "Whether to create the cloudwatch log data protection policy."
type = bool
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
default = null
}

variable "policy_document" {
description = "Specifies the data protection policy in JSON."
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
}
10 changes: 10 additions & 0 deletions modules/log-data-protection-policy/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}
Loading