Terraform Automation for AWS WAF: Security Automations and Web ACL Management

AWS WAF is a web application firewall that helps protect applications from common exploits by using customizable rules, which you define and deploy in web access control lists (ACLs). Configuring AWS WAF rules can be challenging, especially for organizations that do not have dedicated security teams. To simplify this process, Amazon Web Services (AWS) offers the Security Automations for AWS WAF. The Security Automations for AWS WAF solution can be deployed by using AWS CloudFormation according to the instructions in the Security Automations for AWS WAF Implementation Guide. This pattern provides an alternative deployment option for organizations that use HashiCorp Terraform as their preferred infrastructure as code (IaC) tool to provision and manage their cloud infrastructure. When you deploy this solution, Terraform automatically applies the changes in the cloud and deploys and configures the AWS WAF settings and protective features.

AWS WAF lets you control HTTP and HTTPS traffic that reaches your web applications. You can block SQL injection attempts, cross-site scripting, bad bots, and other common attack patterns. Managing WAF rules with Terraform means your web application firewall configuration is version-controlled, reviewed, and applied consistently across all your endpoints.

Prerequisites and Deployment Requirements

The Security Automations for AWS WAF solution by using Terraform has explicit prerequisites and limitations.

Prerequisites

Requirement Minimum Version / Condition
AWS account An active AWS account
AWS CLI version 2.4.25 or later, installed and configured with necessary permissions
Terraform version 1.1.9 or later, installed and configured

The WAF Automation on AWS solution is developed using Terraform which automatically deploys a set of AWS WAF rules that filter common web-based attacks. Users can select from preconfigured protective features that define the rules included in an AWS WAF web access control list (web ACL). Once deployed, AWS WAF protects your Amazon CloudFront distributions or Application Load Balancers by inspecting web requests.

Prerequisites for the automation sample are:

  • An active AWS account.
  • AWS Command Line Interface (AWS CLI) installed and configured with necessary permissions.
  • Terraform installed and configured.

Common deployment commands used with the sample:

bash terraform init terraform plan -var-file="testing.tfvars" terraform apply -var-file="testing.tfvars"

Core Terraform Constructs for WAFv2

Web ACL Container

The Web ACL is the container for all your WAF rules. The base resource starts with a default action and adds rules.

hcl resource "aws_wafv2_web_acl" "main" { name = "${var.project}-waf" description = "WAF rules for ${var.project}" scope = "REGIONAL" # Use CLOUDFRONT for CloudFront distributions with a us-east-1 provider default_action { allow {} } visibility_config { cloudwatch_metrics_enabled = true metric_name = "${var.project}-waf-metrics" sampled_requests_enabled = true } tags = { Name = "${var.project}-waf" Environment = var.environment } }

For API Gateway fronting, a regional ACL is defined as:

hcl resource "aws_wafv2_web_acl" "api_gateway_waf" { name = "api-gateway-waf" description = "Managed rule WAF" scope = "REGIONAL" default_action { allow {} } }

Scope selection determines where the Web ACL can be attached:

Scope Use Case
REGIONAL Application Load Balancers, API Gateway, Amazon AppSync
CLOUDFRONT CloudFront distributions, us-east-1 provider required

AWS Managed Rule Groups

AWS provides managed rule groups that cover the most common attack patterns. Adding managed rule groups is a primary method for baseline protection.

An example rule referencing a managed rule group with an override:

hcl rule { name = "AWS-AWSManagedRulesCommonRuleSet" priority = 0 override_action { none {} } statement { managed_rule_group_statement { name = "AWSManagedRulesCommonRuleSet" vendor_name = "AWS" rule_action_override { action_to_use { allow {} } name = "SizeRestrictions_BODY" } } } visibility_config { cloudwatch_metrics_enabled = true metric_name = "AWS-AWSManagedRulesCommonRuleSet" sampled_requests_enabled = true } }

A second managed rule group example:

hcl rule { name = "AWS-AWSManagedRulesAmazonIpReputationList" priority = 1 override_action { none {} } statement { managed_rule_group_statement { name = "AWSManagedRulesAmazonIpReputationList" vendor_name = "AWS" } } visibility_config

Benefits of implementing AWS WAF with Terraform include:

  • It can protect web applications from common web attacks.
  • It allows for the efficient application of security rules using AWS-managed rule sets.
  • It offers flexible security measures by allowing specific rules to be overridden.

Logging and Monitoring Configuration

Enable WAF Logging for security analysis:

hcl resource "aws_wafv2_web_acl_logging_configuration" "main" { log_destination_configs = [aws_cloudwatch_log_group.waf.arn] resource_arn = aws_wafv2_web_acl.main.arn logging_filter { default_behavior = "DROP" filter { behavior = "KEEP" requirement = "MEETS_ANY" condition { action_condition { action = "BLOCK" } } condition { action_condition { action = "COUNT" } } } } }

Log group naming must start with aws-waf-logs-:

hcl resource "aws_cloudwatch_log_group" "waf" { name = "aws-waf-logs-${var.project}" retention_in_days = 90 }

Visibility config for the entire Web ACL can enable CloudWatch metrics and sampled requests.

Security Automations Parameters

The Security Automations for AWS WAF solution by Terraform exposes parameters for protective features.

Key parameters referenced in the automation:

  • ActivateHttpFloodProtectionParam = yes - AWS Lambda log parser, yes - Amazon Athena log parser, yes - AWS WAF rate based rule
  • ActivateScannersProbesProtectionParam = yes - AWS Lambda log parser, yes - Amazon Athena log parser
  • ENDPOINT = ALB , cloudfront

These parameters drive conditional deployment of Lambda log parsers, Athena log parsers, and rate-based rules.

Modular Terraform Project Structure

To enhance the security of our application, we have implemented AWS WAF in front of API Gateway. During the implementation, we configured WAF, IAM roles, and CloudWatch Logs using Terraform, and this article serves as a memorandum of the process.

The directory structure of Terraform is modularized, with configurations separated for each environment (dev, stg, prod)

The modules directory contains Terraform modules (waf, iamroles, cloudwatchlogs, etc.) used in the project.

-- terraform-project/ -- environments/ -- dev/ -- backend.tf -- main.tf -- stg/ -- backend.tf -- main.tf -- prod/ -- backend.tf -- main.tf -- modules/ -- waf/ -- main.tf -- variables.tf -- outputs.tf -- provider.tf -- README.md -- iam_roles/ -- main.tf -- variables.tf -- outputs.tf -- provider.tf -- README.md -- cloudwatch_logs/ -- main.tf -- variables.tf -- outputs.tf -- provider.tf -- README.md -- ...other… -- docs/ -- architecrture.drowio -- architecrture.png

This modular approach separates environment-specific backend configuration from reusable modules for WAF, IAM roles, and CloudWatch Logs.

Reusable WAF Module Patterns

This terraform module creates two type of WAFv2 Web ACL rules. Follow a commum list of Web ACL rules that can be used by this module and how to setup it, also a link of the documentation with a full list of AWS WAF Rules, you need to use the “Name” of the Rule Groups and take care with WCUs, it’s why Web ACL rules can’t exceed 1500 WCUs.

Example module invocation:

hcl module "terraform_aws_wafv2_global" { source = "git::https://github.com/DNXLabs/terraform-aws-waf.git?ref=1.1.0" for_each = { for rule in try(local.workspace.wafv2_global.rules, []) : rule.global_rule => rule } waf_cloudfront_enable = try(each.value.waf_cloudfront_enable, false) web_acl_id = try(each.value.web_acl_id, "") # Optional WEB ACLs (WAF) to attach to CloudFront global_rule = try(each.value.global_rule, []) scope = each.value.scope default_action = try(each.value.default_action, "block") ### Log Configuration logs_enable = try(each.value.logs_enable, false) logs_retension = try(each.value.logs_retension, 90) logging_redacted_fields = try(each.value.logging_redacted_fields, []) logging_filter = try(each.value.logging_filter, []) ### Statement Rules byte_match_statement_rules = try(each.value.byte_match_statement_rules, []) geo_match_statement_rules = try(each.value.geo_match_statement_rules, []) ip_set_reference_statement_rules = try(each.value.ip_set_reference_statement_rules, []) managed_rule_group_statement_rules = try(each.value.managed_rule_group_statement_rules, []) rate_based_statement_rules = }

The module supports configuration for log retention, redacted fields, logging filter, and multiple statement rule types including byte match, geo match, IP set reference, managed rule group, and rate based statements.

Common Operations and Troubleshooting

When destroying resources, optimistic locking errors can occur.

Error message:
Error: Error deleting WAFv2 IPSet: WAFOptimisticLockException: AWS WAF couldn’t save your changes because someone changed the resource after you started to edit it. Re-apply your changes.

Resolution guidance from the sample: Delete the IPsets manually and retry the terraform destroy command.

Existing required distribution configuration example for CloudFront attachment:

hcl web_acl_id = aws_wafv2_web_acl.main.arn

Operational Guidance

AWS WAF with Terraform gives you a layered defense for your web applications. Start with the AWS managed rule groups to cover the most common attack patterns, add rate limiting for abuse prevention, and build custom rules for your specific application needs. The key is to start in count mode (monitoring only) so you can tune rules before blocking traffic. Once you are confident in your rules, switch to block mode and enable logging for ongoing security monitoring.

For related security topics, see how to implement DDoS protection with Terraform and how to implement security groups best practices with Terraform.

Conclusion

Terraform automation for AWS WAF centralizes web application firewall configuration in version-controlled infrastructure code. The Security Automations for AWS WAF solution by using Terraform provides a pre-built pattern that deploys Lambda log parsers, Athena log parsers, and rate-based rules alongside Web ACLs, with parameters such as ActivateHttpFloodProtectionParam and ActivateScannersProbesProtectionParam controlling protective feature activation. Core WAFv2 implementation relies on awswafv2webacl with regional or CloudFront scope, defaultaction, visibilityconfig, and modular rule definitions referencing AWSManagedRulesCommonRuleSet and AWSManagedRulesAmazonIpReputationList with override actions for fine-tuning. Logging is completed via awswafv2webaclloggingconfiguration targeting a CloudWatch log group named aws-waf-logs-${var.project} with retention and filtering for BLOCK and COUNT actions. Modular project layouts separate environments dev, stg, prod from reusable modules for waf, iamroles, and cloudwatchlogs, enabling consistent deployment to ALB or CloudFront endpoints. WCU limits of 1500 per Web ACL must be respected when composing managed rule groups and custom statements, and operational issues such as WAFOptimisticLockException on IPSet deletion require manual cleanup before terraform destroy can succeed. Together these patterns deliver a layered, observable, and maintainable WAF posture through Terraform.

Sources

  1. Deploy the Security Automations for AWS WAF solution by using Terraform
  2. How to implement WAF rules with Terraform
  3. AWS WAF Automation Terraform Samples
  4. AWS WAF implementation guide setting up with Terraform for enhanced security
  5. Terraform AWS WAF

Related Posts