Web Application Firewall
AWS WAF on the load balancer with managed rule groups and an optional rate limit.
GovCloudView source
- Module
- waf
- Layer
- Edge
- Interface
- 7 inputs, 2 outputs
- Used by
- 3 Kaizen apps
Why it matters
Automated scanners probe public web apps for SQL injection, cross site scripting, and known exploits soon after launch. This module puts AWS managed rule sets in front of the load balancer, so those requests are blocked before they reach application code. Teams can add a per IP rate limit and an allowlist with one setting each, without writing any rules.
Use it when
- The app has a public load balancer from the alb module.
- You need to slow down floods from one source IP. Set rate_limit_per_5min.
- A few upload routes need request bodies larger than 8 KB. List them in body_size_exempt_paths.
Reach for something else when
- You need WAF request logs in S3 or CloudWatch. The module creates no logging configuration, so add aws_wafv2_web_acl_logging_configuration in the app stack.
- The site sits behind CloudFront. This ACL has REGIONAL scope and attaches only to a load balancer.
What it creates
aws_wafv2_web_acl(REGIONAL scope, default action allow)AWSManagedRulesAmazonIpReputationList(priority 10)AWSManagedRulesCommonRuleSet(priority 20)AWSManagedRulesKnownBadInputsRuleSet(priority 30)RateLimitPerIprule (priority 5, only when rate_limit_per_5min is set)aws_wafv2_ip_setand AllowListedIps rule (priority 0, only when allowed_ip_cidrs is set)BlockOversizeBodyExceptPathsrule (priority 25, only when body_size_exempt_paths is set)aws_wafv2_web_acl_association(attaches the ACL to alb_arn)
Secure by default
- AWS IP reputation list, core rule set, and known bad inputs rule set are on for every ACL.
- CloudWatch metrics and request sampling are on for every rule.
Commercial and GovCloud
module "waf" {
source = "git::ssh://git@github.com/the-kaizen-labs/terraform-modules.git//waf?ref=v1.7.0"
app_name = local.app_name
alb_arn = module.alb.alb_arn
rate_limit_per_5min = 2000
tags = local.tags
}How it connects
- From alb: alb_arn
Inputs
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
alb_arn | string | yes | ARN of the ALB to associate with the WAF ACL | |
app_name | string | yes | Application name used in resource naming | |
allowed_ip_cidrs | set(string) | [] | no | IPv4 CIDRs allowed before every other rule, skipping rate limiting and managed rule groups. Empty adds no rule. |
body_size_exempt_paths | set(string) | [] | no | Exact URI paths exempt from the over-8192-byte request-body limit. Empty preserves the managed CommonRuleSet behavior. |
environment | string | "" | no | Environment suffix. Leave empty for accounts with no env concept. |
rate_limit_per_5min | number | null | no | L7-DDoS rate-based rule threshold: requests per source IP over a 5-minute window. Null disables the rule. AWS WAF minimum is 100. |
tags | map(string) | {} | no | Tags to apply to all resources |
Outputs
| Name | Description |
|---|---|
web_acl_arn | Value: aws_wafv2_web_acl.main.arn |
web_acl_id | Value: aws_wafv2_web_acl.main.id |
Used by
| App | Pinned ref |
|---|---|
| evergreen | v1.0.0 |
| oak | v1.5.0 |
| saplings | v1.4.0 |