Skip to content

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

  1. The module generates a random secret and stores it in AWS Parameter Store
  2. WAF rules specified in rules_to_bypass are configured with scope-down statements
  3. Requests containing the bypass header with the correct secret value skip those rules
  4. 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:

X-WAF-Bypass: <secret-value>

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({
header_name = string # HTTP header name to check for bypass (e.g., "X-Bypass-Token")
parameter_store_name = string # SSM Parameter Store path for the secret (e.g., "/waf/bypass-secret")
rules_to_bypass = list(string) # List of rule names to bypass (e.g., ["AWS-AWSManagedRulesAnonymousIpList"])
})
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.