Know More About Web Application Firewalls: Decision-Making and Implementation in AWS

Table of contents
- Introduction
- What is a Web Application Firewall?
- Why AWS WAF?
- Types of Threats Handled by WAF
- Real-World Case Study: Protecting Kubernetes (EKS) Applications with AWS WAF
- Terraform Implementation Guide:
- Architecture Overview
- 1. Creating Web ACLs in Terraform
- 2. Attaching WAF to ALBs Dynamically
- 3. Writing Custom Rules (Regex, IP Set, Geo, Rate-Based)
- 4. Environment-Specific Rule Control (dev, stage, prod)
- 5. Dynamic Ruleset Template (Terraform for_each + Rule Groups)
- 6. Logging and Analytics (Optional but Recommended)
- Performance & Cost Considerations
- Conclusion

Introduction
Web Application Firewalls (WAFs) are like the secret service agents of your web infrastructure. While many developers and DevOps engineers think of WAFs as plug-and-play tools, seasoned professionals understand that the decision to implement a WAF, especially in cloud environments like AWS must be strategic, context-driven, and deeply integrated into the security lifecycle of your applications.
In this comprehensive guide, we're not just going to talk about what WAF is. We're going to dive deep into the anatomy of WAFs, why they matter, how they work in the AWS ecosystem, and most importantly — how to take informed decisions about implementing WAF in real-world, enterprise-grade architectures using Terraform.
This blog is structured in a narrative, story-driven format peppered with professional insights, real-world experiences, and step-by-step infrastructure code examples.
What is a Web Application Firewall?
A Web Application Firewall sits between your users and your application. Its job is to inspect HTTP/S traffic and block malicious requests before they reach your web servers. Think of it as a bouncer at a high-end club: it evaluates every request before letting it through the velvet rope.
Traditional firewalls inspect network-level traffic (IP/TCP), but WAFs focus on the application layer (Layer 7), protecting against:
SQL injection
Cross-site scripting (XSS)
Remote file inclusion
OWASP Top 10
Bot attacks
Rate limiting
Why AWS WAF?
AWS WAF stands out as a cloud-native, fully managed Layer 7 firewall designed specifically for modern applications running within the AWS ecosystem. While traditional WAFs may require on-prem appliances or heavy custom setup, AWS WAF simplifies everything by integrating directly into your existing cloud architecture.
Key Benefits of WAF in AWS:
Global Deployment via CloudFront or Regional via ALB/API Gateway
Depending on your architecture, AWS WAF can be deployed globally through Amazon CloudFront, which is ideal for static websites and CDN-backed applications with global reach. Alternatively, for more backend or containerized apps, it can be regionally deployed on Application Load Balancers (ALB) or Amazon API Gateway, ensuring low latency and tight coupling with microservices or REST APIs.
CloudFront deployment is optimal for latency-sensitive apps with distributed global users.
ALB-based WAFs are perfect for applications hosted in EKS, ECS, or EC2 behind regional load balancers.
API Gateway integration helps protect serverless apps (like those on Lambda).
This flexibility gives enterprises the freedom to align security enforcement points with their application topology.
Real-time Metrics and Detailed Logging
Monitoring isn’t an afterthought. AWS WAF integrates with Amazon CloudWatch, Kinesis Firehose, and S3, providing real-time visibility into what is being blocked, allowed, or counted.
This enables:
Alerting on unusual request patterns (e.g., brute force attacks)
Detailed audits and investigations using WAF logs
Dashboarding for security posture via CloudWatch or third-party tools like Datadog
Rule Customization: Managed and Custom rules
AWS WAF supports both:
AWS Managed Rule Groups: Maintained by AWS, covering OWASP Top 10, bad bots, account takeover, etc.
Custom Rule Groups: Tailored to your application logic, with regex match, geo blocking, size constraints, header validation, and more.
You can combine multiple rule types to build fine-grained security layers. For example:
Allow only requests with valid session tokens
Block specific countries from accessing sensitive paths
Enforce CAPTCHA on login endpoints
Cost-Effective Pay-As-You-Go Model
Unlike legacy WAF vendors with heavy licensing models, AWS WAF is billed per Web ACL, per rule, and per million requests processed.
This allows you to:
Scale security based on usage
Apply granular rules only where necessary
Predict and optimize costs by using consolidated or scoped ACLs
You pay only for what you configure and inspect, without fixed commitments or upfront fees
Summary: AWS WAF is not just a firewall; it's a scalable security layer that can be embedded intelligently within your app stack using modern IaC tools like Terraform. It empowers you to write security policies as code, monitor with precision, and act with agility — without the complexity of managing physical devices or third-party integrations.
Types of Threats Handled by WAF
Injection attacks (SQL, NoSQL, etc.)
Cross-site scripting (XSS)
Broken authentication abuse
DDoS attacks (rate-based rule)
Bad bots (e.g., scrapers, credential stuffers)
Zero-day exploits (via managed rule updates)
Make decisions to use WAF, When to use WAF :-
1. Application Sensitivity: Understanding What You're Really Protecting
Before deploying a Web Application Firewall (WAF), you must first understand the sensitivity of the application you’re protecting. Not all applications are created equal, and neither should your security strategy be.
Public-Facing APIs
Public APIs are the digital front doors to your application and like any front door, they’re often the first target for attackers.
Why they’re risky:
They expose business logic directly over HTTP/S.
They are often over-permissive, undocumented, or lack throttling.
Attackers use automated tools to fuzz endpoints and discover vulnerable patterns.
WAF Role:
Bot protection to detect scraping or credential stuffing attempts.
Rate limiting to prevent abuse of open endpoints.
Geo-restrictions to block access from regions where you don't operate.
Custom header validation to enforce strict client contracts.
Example:
You expose a /payments/initiate
API to partners. If this isn’t secured properly, attackers can simulate payment flows or overwhelm your backend with crafted payloads. A WAF with strict regex and rate rules can neutralize this threat.
Login Portals
Login pages are gold mines for malicious actors. They serve as the first point of access for authorized users and potentially for attackers running brute-force or credential-stuffing campaigns.
Why they’re risky:
They are prone to brute-force login attempts.
Attackers may use leaked credentials from previous breaches.
Bots can simulate user login behavior to test authentication controls.
WAF Role:
IP reputation filtering to block known malicious networks.
Captcha enforcement using AWS WAF CAPTCHA or AWS Managed Challenge.
Account lockout logic based on repeated failed login attempts.
Inspection of user-agent patterns to block known automation tools.
Example:
An EKS-based micro-service hosts an internal dashboard with login at myprotiene.kart/login
. You notice 10,000 failed logins every Sunday night from IP ranges in foreign countries. With WAF rules, you can block those geos, enforce challenge/response, and monitor anomaly patterns in real-time.
Financial Transactions
Applications dealing with payment processing, user funds, or any form of monetary value are subject to the most stringent threat vectors. This is especially true for FinTech, E-Commerce, or SaaS billing systems.
Why they’re risky:
Attackers attempt business logic manipulation (e.g., zero-cost transactions).
APIs may lack validation on server-side amounts, rates, or transaction limits.
Fraudsters might attempt to exploit race conditions (e.g., double-spending).
WAF Role:
Custom regex pattern matching to filter malformed or unauthorized input patterns.
Rule chaining to allow only valid request parameter structures.
Blocking unusual country/currency combinations dynamically.
Logging every request field for audit and anomaly detection via Athena/S3.
Example:
A discount endpoint allows POST /apply-coupon
. Without validation, someone could pass coupon=50_OFF_ALL
and modify the request payload client-side. With a WAF in place, you can block tampered payloads or validate parameter length/encoding patterns.
2. Traffic Volume & Source: Understanding what traffic should be blocked.
Your application's exposure level and user base significantly influence the necessity and complexity of a WAF setup.
Global Audience?
If your application serves users from across the globe especially in markets with known high bot activity or untrusted origins your surface area for attack increases exponentially. Public SaaS platforms, ecommerce sites, and social networking apps commonly face a barrage of automated probes and reconnaissance attempts simply because they're always online and accessible from anywhere.
By deploying WAF with geo-blocking rules, you can restrict or challenge traffic from countries where your business has no market presence. This not only improves security but can also reduce cost and latency.
Example: An ALB integrated with WAF that blocks traffic from regions like North Korea, Iran, or anonymous VPN proxies.
Susceptible to Scraping?
Apps with public content — like pricing data, product listings, or news feeds — are magnets for scrapers and bots that seek to clone or undercut your service. Left unchecked, scraping can:
Drive up infrastructure and bandwidth costs
Skew analytics and business metrics
Lead to competitive data theft
AWS WAF lets you identify and rate-limit or block such traffic by analyzing patterns such as:
Abnormal request frequency (rate-based rules)
User agents associated with known scraping tools
Absence of session cookies or headers (commonly missing in bots)
In environments like EKS, where services are exposed via a shared ALB, you can apply scraping protection selectively at the path or host level using Terraform rulesets scoped to individual applications.
Real-World Case Study: Protecting Kubernetes (EKS) Applications with AWS WAF
Per say; You run a financial services platform deployed in EKS behind an Application Load Balancer (ALB). Your security team raises an alert: unauthorized login attempts spike during weekends. Some scraping activity is also noticed.
Solution:
Deploy AWS WAF with custom rules on ALB
Enforce CAPTCHA on login page
Block IPs from blacklisted geographies
Rate-limit requests from suspicious user agents
Challenges when hosting applications on Kubernetes:
Multi-tenant microservices using single ALB
Different WAF needs per domain/service
Terraform-controlled IaC enforcement
Terraform Implementation Guide:
Now that we’ve understood the why and where of WAF usage in AWS, let’s move into the how and nothing aligns better with DevSecOps best practices than managing your WAF using Terraform.
This section outlines a modular, scalable, and environment-aware Terraform implementation that integrates AWS WAF with ALBs, specifically for Kubernetes workloads running in Amazon EKS. But this approach is equally effective for ECS, Lambda with API Gateway, or CloudFront-backed applications.
Architecture Overview
We will create:
Web ACLs (per environment and per ALB)
Custom rule groups (regex, IP match, rate limiting)
Attachments to ALBs using
aws_wafv2_web_acl_association
Terraform-driven rule variations for
dev
,stage
, andprod
Logging setup to send WAF logs to S3 (and optionally to CloudWatch)
We’ll use Terraform modules with for_each
to selectively enable or disable WAF at the app level, keeping performance and cost in check.
Here’s how the implementation is logically split:
terraform/
├── modules/
│ └── waf/
│ ├── waf.tf
│ ├── waf-rules.tf
│ ├── waf-logging.tf
│ ├── variables.tf
│ └── outputs.tf
├── envs/
│ ├── dev/
│ │ └── terraform.tfvars
│ ├── stage/
│ │ └── terraform.tfvars
│ └── prod/
│ └── terraform.tfvars
└── main.tf
1. Creating Web ACLs in Terraform
In waf.tf
:
resource "aws_wafv2_web_acl" "this" {
name = var.name
description = "Web ACL for ${var.environment} environment"
scope = var.scope # "REGIONAL" for ALB, "CLOUDFRONT" for CF
default_action {
allow {}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "${var.name}-metrics"
sampled_requests_enabled = true
}
rule {
name = "AWS-AWSManagedRulesCommonRuleSet"
priority = 1
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "aws-common-rules"
sampled_requests_enabled = true
}
}
tags = var.tags
}
2. Attaching WAF to ALBs Dynamically
In main.tf
:
resource "aws_wafv2_web_acl_association" "this" {
for_each = var.enable_waf ? var.alb_map : {}
resource_arn = each.value.alb_arn
web_acl_arn = module.waf.web_acl_arn
}
In terraform.tfvars
:
enable_waf = true
alb_map = {
app1 = {
alb_arn = "arn:aws:elasticloadbalancing:eu-west-1:111111111111:loadbalancer/app/app1"
}
app2 = {
alb_arn = "arn:aws:elasticloadbalancing:eu-west-1:111111111111:loadbalancer/app/app2"
}
}
3. Writing Custom Rules (Regex, IP Set, Geo, Rate-Based)
In waf-rules.tf
:
resource "aws_wafv2_ip_set" "allowed_ips" {
name = "allowed-ips-${var.environment}"
scope = var.scope
ip_address_version = "IPV4"
addresses = var.allowed_ips
}
locals {
rules = [
{
name = "LimitByIP"
priority = 2
action = "block"
statement = {
not_statement = {
statement = {
ip_set_reference_statement = {
arn = aws_wafv2_ip_set.allowed_ips.arn
}
}
}
}
},
{
name = "RegexBlocker"
priority = 3
action = "block"
statement = {
regex_pattern_set_reference_statement = {
arn = aws_wafv2_regex_pattern_set.blocked_patterns.arn
field_to_match = { body = {} }
text_transformation = [{
priority = 0
type = "LOWERCASE"
}]
}
}
}
]
}
4. Environment-Specific Rule Control (dev, stage, prod)
You can inject different rule sets per environment using conditionals in your Terraform variables:
variable "environment" {}
locals {
enable_rate_limit = var.environment == "prod"
}
resource "aws_wafv2_web_acl" "this" {
...
dynamic "rule" {
for_each = local.enable_rate_limit ? [1] : []
content {
name = "RateLimit1000"
priority = 5
action {
block {}
}
statement {
rate_based_statement {
limit = 1000
aggregate_key_type = "IP"
}
}
...
}
}
}
5. Dynamic Ruleset Template (Terraform for_each + Rule Groups)
You can fully modularize custom rules using maps/lists in your terraform.tfvars
:
custom_rules = {
block_user_agents = {
priority = 1
action = "block"
field = "headers"
match = "User-Agent"
patterns = ["curl", "wget", "python"]
}
block_countries = {
priority = 2
action = "block"
field = "geo"
countries = ["RU", "CN", "IR"]
}
}
Loop through in waf-rules.tf
:
dynamic "rule" {
for_each = var.custom_rules
content {
name = rule.value.name
priority = rule.value.priority
action {
"${rule.value.action}" = {}
}
statement {
# Build regex, geo or IP match depending on rule.value.field
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "${rule.value.name}-metric"
sampled_requests_enabled = true
}
}
}
6. Logging and Analytics (Optional but Recommended)
In waf-logging.tf
:
resource "aws_wafv2_web_acl_logging_configuration" "this" {
log_destination_configs = [aws_kinesis_firehose.waf_logs.arn]
resource_arn = aws_wafv2_web_acl.this.arn
logging_filter {
default_behavior = "KEEP"
filters {
behavior = "DROP"
requirement = "MUST_MEET_ALL"
conditions {
action_condition {
action = "ALLOW"
}
}
}
}
}
Performance & Cost Considerations
AWS WAF charges:
Per Web ACL
Per rule
Per million requests
Tip: Don't blindly enable WAF on every ALB use domain-level scoping via Terraform and for_each
to optimize cost.
Conclusion
Web Application Firewalls aren't silver bullets — but when thoughtfully deployed and continuously tuned, they’re indispensable for modern, cloud-native application security.
By deeply integrating AWS WAF with your architecture using Terraform, you not only enforce strong perimeter defenses but also future-proof your security posture.
Subscribe to my newsletter
Read articles from aditya narra directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
