From a51e0f6ae8eab6e3554493837f86887331aec3f4 Mon Sep 17 00:00:00 2001 From: Marcin Cuber Date: Tue, 4 May 2021 13:03:51 +0100 Subject: [PATCH] Module upgrade with logging filter support (#20) * Module upgrade with logging filter support * remove lock file --- .gitignore | 2 + .pre-commit-config.yaml | 4 +- README.md | 74 +++++++++++--------- examples/core/main.tf | 43 +++++++----- examples/wafv2-logging-configuration/main.tf | 61 +++++++++++----- main.tf | 34 +++++++++ variables.tf | 11 +++ versions.tf | 4 +- 8 files changed, 162 insertions(+), 71 deletions(-) diff --git a/.gitignore b/.gitignore index 7a3e2fd..a3b4f84 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ override.tf.json # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan # example: *tfplan* + +.terraform.lock.hcl \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2fe97d5..7bc1c4f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.3.0 + rev: v3.4.0 hooks: - id: check-added-large-files args: ['--maxkb=500'] @@ -18,7 +18,7 @@ repos: args: ['--allow-missing-credentials'] - id: trailing-whitespace - repo: git://github.com/antonbabenko/pre-commit-terraform - rev: v1.44.0 + rev: v1.50.0 hooks: - id: terraform_fmt - id: terraform_docs diff --git a/README.md b/README.md index 1a8bf27..fd88191 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ Supported WAF v2 components: ## Terraform versions -Terraform 0.12 and 0.13. Pin module version to `~> v1.0`. Submit pull-requests to `master` branch. +Terraform 0.13+ Pin module version to `~> v2.0`. Submit pull-requests to `master` branch. +Terraform 0.12 < 0.13. Pin module version to `~> v1.0`. ## Usage @@ -22,7 +23,7 @@ Please pin down version of this module to exact version. ```hcl module "waf" { source = "umotif-public/waf-webaclv2/aws" - version = "~> 1.5.0" + version = "~> 2.0.0" name_prefix = "test-waf-setup" alb_arn = module.alb.arn @@ -103,7 +104,7 @@ module "waf" { provider "aws" { alias = "us-east" - version = ">= 2.70" + version = ">= 3.38" region = "us-east-1" } @@ -113,7 +114,7 @@ module "waf" { } source = "umotif-public/waf-webaclv2/aws" - version = "~> 1.5.0" + version = "~> 2.0.0" name_prefix = "test-waf-setup-cloudfront" scope = "CLOUDFRONT" @@ -122,10 +123,6 @@ module "waf" { } ``` -## Assumptions - -Module is to be used with Terraform > 0.12. - ## Logging configuration When you enable logging configuration for WAFv2. Remember to follow naming convention defined in https://docs.aws.amazon.com/waf/latest/developerguide/logging.html. @@ -147,45 +144,58 @@ Module managed by [Marcin Cuber](https://github.com/marcincuber) [LinkedIn](http | Name | Version | |------|---------| -| terraform | >= 0.12.6 | -| aws | >= 2.70 | +| [terraform](#requirement\_terraform) | >= 0.13.0 | +| [aws](#requirement\_aws) | >= 3.38 | ## Providers | Name | Version | |------|---------| -| aws | >= 2.70 | +| [aws](#provider\_aws) | >= 3.38 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_wafv2_web_acl.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl) | resource | +| [aws_wafv2_web_acl_association.alb_list](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl_association) | resource | +| [aws_wafv2_web_acl_association.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl_association) | resource | +| [aws_wafv2_web_acl_logging_configuration.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl_logging_configuration) | resource | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| alb\_arn | Application Load Balancer ARN | `string` | `""` | no | -| alb\_arn\_list | Application Load Balancer ARN list | `list(string)` | `[]` | no | -| allow\_default\_action | Set to `true` for WAF to allow requests by default. Set to `false` for WAF to block requests by default. | `bool` | `true` | no | -| create\_alb\_association | Whether to create alb association with WAF web acl | `bool` | `true` | no | -| create\_logging\_configuration | Whether to create logging configuration in order start logging from a WAFv2 Web ACL to Amazon Kinesis Data Firehose. | `bool` | `false` | no | -| enabled | Whether to create the resources. Set to `false` to prevent the module from creating any resources | `bool` | `true` | no | -| geo\_match\_rules | List of WAF geo match rules to detect web requests coming from a particular set of contry codes. | `list` | `[]` | no | -| ip\_rate\_based\_rule | A rate-based rule tracks the rate of requests for each originating IP address, and triggers the rule action when the rate exceeds a limit that you specify on the number of requests in any 5-minute time span | `any` | `null` | no | -| ip\_set\_rules | List of WAF ip set rules to detect web requests coming from particular IP addresses or address ranges. | `list` | `[]` | no | -| log\_destination\_configs | The Amazon Kinesis Data Firehose Amazon Resource Name (ARNs) that you want to associate with the web ACL. Currently, only 1 ARN is supported. | `list(string)` | `[]` | no | -| name\_prefix | Name prefix used to create resources. | `string` | n/a | yes | -| redacted\_fields | The parts of the request that you want to keep out of the logs. Up to 100 `redacted_fields` blocks are supported. | `list` | `[]` | no | -| rules | List of WAF rules. | `list` | `[]` | no | -| scope | Specifies whether this is for an AWS CloudFront distribution or for a regional application. Valid values are CLOUDFRONT or REGIONAL. To work with CloudFront, you must also specify the region us-east-1 (N. Virginia) on the AWS provider. | `string` | `"REGIONAL"` | no | -| tags | A map of tags (key-value pairs) passed to resources. | `map(string)` | `{}` | no | -| visibility\_config | Visibility config for WAFv2 web acl. https://www.terraform.io/docs/providers/aws/r/wafv2_web_acl.html#visibility-configuration | `map(string)` | `{}` | no | +| [alb\_arn](#input\_alb\_arn) | Application Load Balancer ARN | `string` | `""` | no | +| [alb\_arn\_list](#input\_alb\_arn\_list) | Application Load Balancer ARN list | `list(string)` | `[]` | no | +| [allow\_default\_action](#input\_allow\_default\_action) | Set to `true` for WAF to allow requests by default. Set to `false` for WAF to block requests by default. | `bool` | `true` | no | +| [create\_alb\_association](#input\_create\_alb\_association) | Whether to create alb association with WAF web acl | `bool` | `true` | no | +| [create\_logging\_configuration](#input\_create\_logging\_configuration) | Whether to create logging configuration in order start logging from a WAFv2 Web ACL to Amazon Kinesis Data Firehose. | `bool` | `false` | no | +| [enabled](#input\_enabled) | Whether to create the resources. Set to `false` to prevent the module from creating any resources | `bool` | `true` | no | +| [geo\_match\_rules](#input\_geo\_match\_rules) | List of WAF geo match rules to detect web requests coming from a particular set of contry codes. | `any` | `[]` | no | +| [ip\_rate\_based\_rule](#input\_ip\_rate\_based\_rule) | A rate-based rule tracks the rate of requests for each originating IP address, and triggers the rule action when the rate exceeds a limit that you specify on the number of requests in any 5-minute time span | `any` | `null` | no | +| [ip\_set\_rules](#input\_ip\_set\_rules) | List of WAF ip set rules to detect web requests coming from particular IP addresses or address ranges. | `any` | `[]` | no | +| [log\_destination\_configs](#input\_log\_destination\_configs) | The Amazon Kinesis Data Firehose Amazon Resource Name (ARNs) that you want to associate with the web ACL. Currently, only 1 ARN is supported. | `list(string)` | `[]` | no | +| [logging\_filter](#input\_logging\_filter) | A configuration block that specifies which web requests are kept in the logs and which are dropped. You can filter on the rule action and on the web request labels that were applied by matching rules during web ACL evaluation. | `any` | `{}` | no | +| [name\_prefix](#input\_name\_prefix) | Name prefix used to create resources. | `string` | n/a | yes | +| [redacted\_fields](#input\_redacted\_fields) | The parts of the request that you want to keep out of the logs. Up to 100 `redacted_fields` blocks are supported. | `any` | `[]` | no | +| [rules](#input\_rules) | List of WAF rules. | `any` | `[]` | no | +| [scope](#input\_scope) | Specifies whether this is for an AWS CloudFront distribution or for a regional application. Valid values are CLOUDFRONT or REGIONAL. To work with CloudFront, you must also specify the region us-east-1 (N. Virginia) on the AWS provider. | `string` | `"REGIONAL"` | no | +| [tags](#input\_tags) | A map of tags (key-value pairs) passed to resources. | `map(string)` | `{}` | no | +| [visibility\_config](#input\_visibility\_config) | Visibility config for WAFv2 web acl. https://www.terraform.io/docs/providers/aws/r/wafv2_web_acl.html#visibility-configuration | `map(string)` | `{}` | no | ## Outputs | Name | Description | |------|-------------| -| web\_acl\_arn | The ARN of the WAFv2 WebACL. | -| web\_acl\_capacity | The web ACL capacity units (WCUs) currently being used by this web ACL. | -| web\_acl\_id | The ID of the WAFv2 WebACL. | -| web\_acl\_name | The name of the WAFv2 WebACL. | - +| [web\_acl\_arn](#output\_web\_acl\_arn) | The ARN of the WAFv2 WebACL. | +| [web\_acl\_capacity](#output\_web\_acl\_capacity) | The web ACL capacity units (WCUs) currently being used by this web ACL. | +| [web\_acl\_id](#output\_web\_acl\_id) | The ID of the WAFv2 WebACL. | +| [web\_acl\_name](#output\_web\_acl\_name) | The name of the WAFv2 WebACL. | ## License diff --git a/examples/core/main.tf b/examples/core/main.tf index 8412151..f06b07f 100644 --- a/examples/core/main.tf +++ b/examples/core/main.tf @@ -2,23 +2,15 @@ provider "aws" { region = "eu-west-1" } - ##### # VPC and subnets ##### -module "vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "~> 2.44" - - name = "simple-waf-test-vpc" - - cidr = "10.0.0.0/16" - - azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"] - private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] - public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"] +data "aws_vpc" "default" { + default = true +} - enable_nat_gateway = false +data "aws_subnet_ids" "all" { + vpc_id = data.aws_vpc.default.id } ##### @@ -26,13 +18,13 @@ module "vpc" { ##### module "alb" { source = "umotif-public/alb/aws" - version = "~> 1.2.0" + version = "~> 2.0.0" - name_prefix = "alb-example" + name_prefix = "alb-waf-example" load_balancer_type = "application" internal = false - vpc_id = module.vpc.vpc_id - subnets = module.vpc.public_subnets + vpc_id = data.aws_vpc.default.id + subnets = data.aws_subnet_ids.all.ids } ##### @@ -108,13 +100,28 @@ module "waf" { name = "AWSManagedRulesPHPRuleSet" vendor_name = "AWS" } + }, + { + name = "AWSManagedRulesBotControlRuleSet-rule-4" + priority = "4" + + visibility_config = { + cloudwatch_metrics_enabled = false + metric_name = "AWSManagedRulesBotControlRuleSet-metric" + sampled_requests_enabled = false + } + + managed_rule_group_statement = { + name = "AWSManagedRulesBotControlRuleSet" + vendor_name = "AWS" + } } ] geo_match_rules = [ { name = "block_country_codes" - priority = "4" + priority = "5" action = "block" diff --git a/examples/wafv2-logging-configuration/main.tf b/examples/wafv2-logging-configuration/main.tf index 8a42e2b..651826f 100644 --- a/examples/wafv2-logging-configuration/main.tf +++ b/examples/wafv2-logging-configuration/main.tf @@ -6,19 +6,12 @@ provider "aws" { ##### # VPC and subnets ##### -module "vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "~> 2.44" - - name = "simple-vpc" - - cidr = "10.0.0.0/16" - - azs = ["eu-west-1a", "eu-west-1b", "eu-west-1c"] - private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] - public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"] +data "aws_vpc" "default" { + default = true +} - enable_nat_gateway = false +data "aws_subnet_ids" "all" { + vpc_id = data.aws_vpc.default.id } ##### @@ -26,13 +19,13 @@ module "vpc" { ##### module "alb" { source = "umotif-public/alb/aws" - version = "~> 1.2.0" + version = "~> 2.0.0" - name_prefix = "alb-example" + name_prefix = "alb-waf-example" load_balancer_type = "application" internal = false - vpc_id = module.vpc.vpc_id - subnets = module.vpc.public_subnets + vpc_id = data.aws_vpc.default.id + subnets = data.aws_subnet_ids.all.ids } ##### @@ -128,6 +121,40 @@ module "wafv2" { } ] + logging_filter = { + default_behavior = "DROP" + + filter = [ + { + behavior = "KEEP" + requirement = "MEETS_ANY" + condition = [ + { + action_condition = { + action = "ALLOW" + } + }, + ] + }, + { + behavior = "DROP" + requirement = "MEETS_ALL" + condition = [ + { + action_condition = { + action = "COUNT" + } + }, + { + label_name_condition = { + label_name = "awswaf:111122223333:rulegroup:testRules:LabelNameZ" + } + } + ] + } + ] + } + visibility_config = { cloudwatch_metrics_enabled = false metric_name = "test-waf-setup-waf-main-metrics" @@ -181,7 +208,7 @@ module "wafv2" { } managed_rule_group_statement = { - name = "AWSManagedRulesPHPRuleSet" + name = "AWSManagedRulesBotControlRuleSet" vendor_name = "AWS" } } diff --git a/main.tf b/main.tf index 98c9921..9902c5f 100644 --- a/main.tf +++ b/main.tf @@ -258,4 +258,38 @@ resource "aws_wafv2_web_acl_logging_configuration" "main" { } } } + + dynamic "logging_filter" { + for_each = length(var.logging_filter) == 0 ? [] : [var.logging_filter] + content { + default_behavior = lookup(logging_filter.value, "default_behavior", "KEEP") + + dynamic "filter" { + for_each = length(lookup(logging_filter.value, "filter", {})) == 0 ? [] : toset(lookup(logging_filter.value, "filter")) + content { + behavior = lookup(filter.value, "behavior") + requirement = lookup(filter.value, "requirement", "MEETS_ANY") + + dynamic "condition" { + for_each = length(lookup(filter.value, "condition", {})) == 0 ? [] : toset(lookup(filter.value, "condition")) + content { + dynamic "action_condition" { + for_each = length(lookup(condition.value, "action_condition", {})) == 0 ? [] : [lookup(condition.value, "action_condition", {})] + content { + action = lookup(action_condition.value, "action") + } + } + + dynamic "label_name_condition" { + for_each = length(lookup(condition.value, "label_name_condition", {})) == 0 ? [] : [lookup(condition.value, "label_name_condition", {})] + content { + label_name = lookup(label_name_condition.value, "label_name") + } + } + } + } + } + } + } + } } diff --git a/variables.tf b/variables.tf index 23c5b0b..6a49056 100644 --- a/variables.tf +++ b/variables.tf @@ -29,21 +29,25 @@ variable "tags" { variable "rules" { description = "List of WAF rules." + type = any default = [] } variable "ip_set_rules" { description = "List of WAF ip set rules to detect web requests coming from particular IP addresses or address ranges." + type = any default = [] } variable "ip_rate_based_rule" { description = "A rate-based rule tracks the rate of requests for each originating IP address, and triggers the rule action when the rate exceeds a limit that you specify on the number of requests in any 5-minute time span" + type = any default = null } variable "geo_match_rules" { description = "List of WAF geo match rules to detect web requests coming from a particular set of contry codes." + type = any default = [] } @@ -73,6 +77,7 @@ variable "log_destination_configs" { variable "redacted_fields" { description = "The parts of the request that you want to keep out of the logs. Up to 100 `redacted_fields` blocks are supported." + type = any default = [] } @@ -87,3 +92,9 @@ variable "scope" { description = "Specifies whether this is for an AWS CloudFront distribution or for a regional application. Valid values are CLOUDFRONT or REGIONAL. To work with CloudFront, you must also specify the region us-east-1 (N. Virginia) on the AWS provider." default = "REGIONAL" } + +variable "logging_filter" { + type = any + description = "A configuration block that specifies which web requests are kept in the logs and which are dropped. You can filter on the rule action and on the web request labels that were applied by matching rules during web ACL evaluation." + default = {} +} diff --git a/versions.tf b/versions.tf index e76912b..6f39961 100644 --- a/versions.tf +++ b/versions.tf @@ -1,7 +1,7 @@ terraform { - required_version = ">= 0.12.6" + required_version = ">= 0.13.0" required_providers { - aws = ">= 2.70" + aws = ">= 3.38" } }