This Terraform module creates a baseline AWS WAF v2 configuration that provides essential security protections for both CloudFront distributions and regional resources (ALB, API Gateway, etc.). The module is based on proven CDK constructs and implements industry best practices for web application security.
- Dual Scope Support: Works with both CloudFront (CLOUDFRONT) and Regional (REGIONAL) deployments
- Custom Rate Limiting: Configurable rate limiting rules for login endpoints and country-based restrictions
- AWS Managed Rules: Includes multiple AWS managed rule sets for comprehensive protection
- Geo-blocking: Country-based blocking with customizable country codes
- Comprehensive Logging: CloudWatch logging with configurable retention periods and optional encryption
- NIST 800-171 Compliance: Support for log encryption using AWS KMS for compliance requirements
- Flexible Configuration: Count or active mode for all rules
- URI Country Based Rule: Rate limiting for specific URI paths from certain countries
- Login Rate Limit Rule: Aggressive rate limiting for login endpoints
- AWSManagedRulesCommonRuleSet: Protection against common web vulnerabilities
- AWSManagedRulesKnownBadInputsRuleSet: Blocks known malicious inputs
- AWSManagedRulesAnonymousIpList: Blocks requests from anonymous IP addresses
- AWSManagedRulesAmazonIpReputationList: Blocks requests from IP addresses with poor reputation
module "cloudfront_waf" {
source = "path/to/this/module"
scope = "CLOUDFRONT"
mode = "count" # Use "active" for production
web_acl_name = "MyCloudFrontWAF"
rule_group_name = "MySecurityRules"
# Custom rule configuration
search_string = "/api/login"
country_codes = ["CN", "RU", "KP"]
uri_country_rule_limit = 100
uri_country_action = "block"
rate_based_rule_limit = 200
# Logging configuration
log_retention_days = 30
tags = {
Environment = "production"
Project = "web-security"
}
}
# Associate with CloudFront distribution
resource "aws_cloudfront_distribution" "example" {
# ... other configuration ...
web_acl_id = module.cloudfront_waf.web_acl_id
}
module "regional_waf" {
source = "path/to/this/module"
scope = "REGIONAL"
mode = "active"
web_acl_name = "MyRegionalWAF"
# Custom rule configuration
search_string = "/auth/login"
country_codes = ["CN", "RU"]
uri_country_rule_limit = 150
uri_country_action = "count"
rate_based_rule_limit = 300
# Logging configuration
log_retention_days = 365
tags = {
Environment = "production"
Project = "api-security"
}
}
# Associate with Application Load Balancer
resource "aws_wafv2_web_acl_association" "alb" {
resource_arn = aws_lb.example.arn
web_acl_arn = module.regional_waf.web_acl_arn
}
# Create a KMS key for log encryption
resource "aws_kms_key" "waf_logs" {
description = "KMS key for WAF log encryption"
deletion_window_in_days = 7
tags = {
Name = "waf-logs-encryption-key"
Environment = "production"
Compliance = "NIST-800-171"
}
}
resource "aws_kms_alias" "waf_logs" {
name = "alias/waf-logs-encryption"
target_key_id = aws_kms_key.waf_logs.key_id
}
module "compliant_waf" {
source = "path/to/this/module"
scope = "REGIONAL"
mode = "active"
web_acl_name = "NIST-Compliant-WAF"
# Custom rule configuration
search_string = "/api/login"
country_codes = ["CN", "RU", "KP"]
uri_country_rule_limit = 100
uri_country_action = "block"
rate_based_rule_limit = 200
# Logging configuration with encryption for NIST 800-171 compliance
log_retention_days = 365
kms_key_id = aws_kms_key.waf_logs.arn
tags = {
Environment = "production"
Compliance = "NIST-800-171"
Project = "secure-web-app"
}
}
module "simple_waf" {
source = "path/to/this/module"
scope = "CLOUDFRONT"
country_codes = ["CN", "RU", "KP"]
search_string = "/api/login"
uri_country_rule_limit = 200
rate_based_rule_limit = 300
}
Name | Version |
---|---|
terraform | >= 1.0 |
aws | >= 5.0 |
Name | Version |
---|---|
aws | >= 5.0 |
random | n/a |
aws_wafv2_rule_group.security_baseline
- Custom rule group with rate limiting rulesaws_wafv2_web_acl.security_baseline
- Main WebACL with all rulesaws_cloudwatch_log_group.waf_log_group
- CloudWatch log group for WAF logsaws_wafv2_web_acl_logging_configuration.security_baseline
- Logging configurationrandom_id.log_suffix
- Random suffix for unique log group names
Name | Description | Type | Default | Required |
---|---|---|---|---|
scope | The scope of the WebACL. Valid values are CLOUDFRONT or REGIONAL | string |
n/a | yes |
country_codes | The country codes to match against for geo-blocking rules | list(string) |
n/a | yes |
search_string | The string to search for in the request URI path | string |
n/a | yes |
uri_country_rule_limit | The rate limit for country-based URI matching rule (requests per 5-minute window) | number |
n/a | yes |
rate_based_rule_limit | The rate limit for the login rate limiting rule (requests per 5-minute window) | number |
n/a | yes |
mode | The mode of the rule group. To Block or to Count | string |
"count" |
no |
web_acl_name | The name of the WebACL | string |
null |
no |
rule_group_name | The name of the rule group | string |
null |
no |
log_retention_days | The number of days log events are kept in CloudWatch Logs | number |
365 |
no |
uri_country_action | The action to take on the URI country rule | string |
"count" |
no |
kms_key_id | The ARN of the KMS Key to use when encrypting log data. If not provided, encryption is disabled | string |
null |
no |
tags | A map of tags to assign to the resources | map(string) |
{} |
no |
Name | Description |
---|---|
web_acl_arn | The ARN of the WAF WebACL |
web_acl_id | The ID of the WAF WebACL |
web_acl_name | The name of the WAF WebACL |
rule_group_arn | The ARN of the WAF Rule Group |
rule_group_id | The ID of the WAF Rule Group |
rule_group_name | The name of the WAF Rule Group |
log_group_arn | The ARN of the CloudWatch Log Group for WAF logs |
log_group_name | The name of the CloudWatch Log Group for WAF logs |
scope | The scope of the WAF deployment (CLOUDFRONT or REGIONAL) |
mode | The mode of the WAF rules (count or active) |
- Uses
IP
aggregate key type for rate limiting - No forwarded IP configuration needed
- Must be deployed in
us-east-1
region - Can only be associated with CloudFront distributions
- Uses
FORWARDED_IP
aggregate key type for rate limiting - Includes forwarded IP configuration for proper client IP detection
- Can be deployed in any AWS region
- Can be associated with ALB, API Gateway, and other regional resources
- Start with Count Mode: Always start with
mode = "count"
to observe traffic patterns before switching tomode = "active"
- Monitor CloudWatch Metrics: Set up CloudWatch alarms for WAF metrics to detect potential attacks
- Regular Review: Regularly review WAF logs and adjust rules based on legitimate traffic patterns
- Rate Limits: Adjust rate limits based on your application's normal traffic patterns
- Country Codes: Carefully consider which countries to block based on your user base
- WAF charges are based on the number of web ACLs, rules, and requests processed
- CloudWatch Logs incur storage costs based on retention period
- Consider log retention period based on compliance requirements vs. cost
This module provides equivalent functionality to the CDK constructs:
CloudFrontSecurityBaselineWebAcl
→ Use withscope = "CLOUDFRONT"
RegionalSecurityBaselineWebAcl
→ Use withscope = "REGIONAL"
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
This module is licensed under the MIT License. See LICENSE file for details.