WAF Module
A Terraform module for creating and managing AWS WAFv2 Web ACLs. This module wraps the cloudposse/waf/aws module and provides a simplified interface for common WAF configurations.
Features
- Create regional or CloudFront WAF Web ACLs
- Configure managed rule groups with customizable actions
- Support for various rule types (byte match, rate-based, geo match, etc.)
- Automatic CloudWatch logging
- Header-based rule bypass for authorized traffic
Header-Based Rule Bypass
The module supports bypassing specific WAF rules when requests contain a designated header with a secret value. This is useful for allowing trusted services (e.g., load testing tools, internal services) to bypass certain rules.
How It Works
- The module generates a random secret and stores it in AWS Parameter Store
- WAF rules specified in
rules_to_bypassare configured with scope-down statements - Requests containing the bypass header with the correct secret value skip those rules
- Requests without the header (or with incorrect values) are evaluated normally
Usage Example
module "waf" {
source = "./modules/wafv2"
name = "my-application-waf"
create = true
bypass_config = {
header_name = "X-WAF-Bypass"
parameter_store_name = "/myapp/waf/bypass-secret"
rules_to_bypass = [
"AWS-AWSManagedRulesAnonymousIpList",
"AWS-AWSManagedRulesAmazonIpReputationList"
]
}
}
Retrieving the Bypass Secret
Services that need to bypass WAF rules must retrieve the secret from Parameter Store. Grant IAM permissions to the parameter ARN output:
# IAM policy for retrieving the bypass secret
data "aws_iam_policy_document" "waf_bypass" {
statement {
actions = ["ssm:GetParameter"]
resources = [module.waf.bypass_parameter_arn]
}
}
Then retrieve the secret using the AWS SDK or CLI:
aws ssm get-parameter --name "/myapp/waf/bypass-secret" --with-decryption --query "Parameter.Value" --output text
Include the secret in requests as a header:
Modules
| Name | Source | Version |
|---|---|---|
| bypass_secret | ./modules/random_password | n/a |
| waf | ./modules/wafv2-cloudposse-fork | n/a |
Inputs
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| association_arns | List of ARNs of the resources to associate with the WAF | list(string) |
[] |
no |
| bypass_config | Configuration for header-based rule bypass. When configured, specific WAF rules can be bypassed if a request contains the designated header with a secret value stored in Parameter Store. | object({ |
null |
no |
| byte_match_statement_rules | Byte Match Statement Rules | list(any) |
[] |
no |
| cloudwatch_metrics_enabled | Whether the associated resource sends metrics to CloudWatch | bool |
true |
no |
| create | Create WAF | bool |
n/a | yes |
| create_log_group | Create CloudWatch Log Group, conflicts with log_destination_configs | bool |
true |
no |
| default_action | Default action for the WAF, either allow or block | string |
"allow" |
no |
| exclude_rules | List of rules to exclude | list(string) |
[] |
no |
| geo_allowlist_statement_rules | Geo Allowlist Statement Rules | list(any) |
[] |
no |
| geo_match_statement_rules | Geo Match Statement Rules | list(any) |
[] |
no |
| ip_set_reference_statement_rules | IP Set Reference Statement Rules | list(any) |
[] |
no |
| log_destination_configs | The Amazon Kinesis Data Firehose, CloudWatch Log log group, or S3 bucket Amazon Resource Names (ARNs) that you want to associate with the web ACL. Will not be used if create_log_group is set to true | list(string) |
[] |
no |
| name | Name of the WAF | string |
n/a | yes |
| nested_statement_rules | Nested Statement Rules for complex AND/OR/NOT logic. See https://registry.terraform.io/modules/cloudposse/waf/aws/latest#nested_statement_rules | list(any) |
[] |
no |
| rate_based_statement_rules | Rate Based Statement Rules | list(any) |
[] |
no |
| regex_match_statement_rules | Regex Match Statement Rules | list(any) |
[] |
no |
| regex_pattern_set_reference_statement_rules | Regex Pattern Set Reference Statement Rules | list(any) |
[] |
no |
| rule_action_override | Map of rule action overrides | map(list(string)) |
{} |
no |
| sampled_requests_enabled | Whether AWS WAF should store a sampling of the web requests that match the rules | bool |
false |
no |
| scope | Specifies whether this is for an AWS CloudFront distribution or for a regional application. Valid values are CLOUDFRONT and REGIONAL. | string |
"REGIONAL" |
no |
| size_constraint_statement_rules | Size Constraint Statement Rules | list(any) |
[] |
no |
| sqli_match_statement_rules | SQLi Match Statement Rules | list(any) |
[] |
no |
| xss_match_statement_rules | XSS Match Statement Rules | list(any) |
[] |
no |
Outputs
| Name | Description |
|---|---|
| arn | The ARN of the WAF WebACL. |
| bypass_parameter_arn | ARN of the SSM parameter storing the bypass secret. Use this for IAM policy configuration. |
| bypass_parameter_name | Name of the SSM parameter storing the bypass secret. |
| bypass_secret_value | The bypass secret value. Use this to pass to E2E test config. |
| capacity | The web ACL capacity units (WCUs) currently being used by this web ACL. |
| id | The ID of the WAF WebACL. |
| logging_config_id | The ARN of the WAFv2 Web ACL logging configuration. |