Skip to main content

Enable CloudWatch Metrics for AWS WAFv2 Web ACL Rules

Overview

This check verifies that every rule and rule group in your AWS WAFv2 Web ACL has CloudWatch metrics enabled. CloudWatch metrics provide visibility into how your WAF rules are evaluating and handling web traffic.

Risk

Without CloudWatch metrics enabled on your WAF rules:

  • You lose visibility into which rules are blocking or allowing traffic
  • Attack patterns like SQL injection, cross-site scripting (XSS), and bot activity may go undetected
  • Troubleshooting misconfigured rules becomes difficult
  • You cannot set up alarms for unusual traffic patterns or rule matches

This gap in monitoring can delay detection of security threats, potentially compromising your application's security.

Remediation Steps

Prerequisites

  • AWS Console access with permissions to modify WAFv2 resources
  • The Web ACL name or ID you want to update

AWS Console Method

  1. Sign in to the AWS WAF Console
  2. In the navigation pane, choose Web ACLs
  3. Select your Web ACL from the list
  4. Go to the Rules tab
  5. For each rule listed:
    • Click Edit
    • Scroll to the Visibility configuration section
    • Enable CloudWatch metrics
    • Enter a Metric name (use a descriptive name like the rule name)
    • Click Save rule
  6. Repeat for all rules in the Web ACL

For Rule Groups:

  1. In the navigation pane, choose Rule groups
  2. Select the rule group you want to update
  3. Click Edit
  4. In the Visibility configuration section, enable CloudWatch metrics
  5. Enter a Metric name
  6. Click Save
AWS CLI (optional)

Updating WAFv2 Web ACLs via CLI requires retrieving the current configuration, modifying it, and updating with the new configuration. The update-web-acl command replaces the entire Web ACL specification.

Step 1: List your Web ACLs

# For regional resources (ALB, API Gateway, etc.)
aws wafv2 list-web-acls \
--scope REGIONAL \
--region us-east-1

# For CloudFront distributions
aws wafv2 list-web-acls \
--scope CLOUDFRONT \
--region us-east-1

Step 2: Get the current Web ACL configuration

aws wafv2 get-web-acl \
--name <your-web-acl-name> \
--scope REGIONAL \
--id <your-web-acl-id> \
--region us-east-1

Note the LockToken in the response; you will need it for the update.

Step 3: Update the Web ACL

Modify the JSON to ensure each rule has CloudWatchMetricsEnabled: true in its VisibilityConfig, then update:

aws wafv2 update-web-acl \
--name <your-web-acl-name> \
--scope REGIONAL \
--id <your-web-acl-id> \
--lock-token <lock-token-from-get-web-acl> \
--default-action '{"Allow": {}}' \
--visibility-config '{"CloudWatchMetricsEnabled": true, "MetricName": "my-webacl-metric", "SampledRequestsEnabled": true}' \
--rules '[
{
"Name": "MyRule",
"Priority": 1,
"Statement": {"RateBasedStatement": {"Limit": 2000, "AggregateKeyType": "IP"}},
"Action": {"Block": {}},
"VisibilityConfig": {
"CloudWatchMetricsEnabled": true,
"MetricName": "MyRule-metric",
"SampledRequestsEnabled": true
}
}
]' \
--region us-east-1

Important: The update-web-acl command replaces the entire configuration. Make sure to include all existing rules with their updated visibility configurations.

CloudFormation (optional)

When defining a WAFv2 Web ACL in CloudFormation, ensure CloudWatchMetricsEnabled: true is set in both the Web ACL's VisibilityConfig and each rule's VisibilityConfig.

AWSTemplateFormatVersion: '2010-09-09'
Description: WAFv2 Web ACL with CloudWatch Metrics Enabled

Parameters:
WebACLName:
Type: String
Description: Name for the Web ACL
Default: my-web-acl

Resources:
WebACL:
Type: AWS::WAFv2::WebACL
Properties:
Name: !Ref WebACLName
Scope: REGIONAL
DefaultAction:
Allow: {}
# Web ACL-level visibility config
VisibilityConfig:
CloudWatchMetricsEnabled: true
MetricName: !Sub "${WebACLName}-metric"
SampledRequestsEnabled: true
Rules:
- Name: RateLimitRule
Priority: 1
Statement:
RateBasedStatement:
Limit: 2000
AggregateKeyType: IP
Action:
Block: {}
# Rule-level visibility config
VisibilityConfig:
CloudWatchMetricsEnabled: true
MetricName: RateLimitRule-metric
SampledRequestsEnabled: true

Outputs:
WebACLArn:
Description: ARN of the Web ACL
Value: !GetAtt WebACL.Arn
WebACLId:
Description: ID of the Web ACL
Value: !GetAtt WebACL.Id

Key points:

  • Each rule must have its own VisibilityConfig block with CloudWatchMetricsEnabled: true
  • The MetricName must be unique within the Web ACL
  • SampledRequestsEnabled allows you to view sample requests in the AWS console
Terraform (optional)

In Terraform, ensure every visibility_config block has cloudwatch_metrics_enabled = true.

terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}

provider "aws" {
region = "us-east-1"
}

variable "web_acl_name" {
description = "Name for the Web ACL"
type = string
default = "my-web-acl"
}

resource "aws_wafv2_web_acl" "example" {
name = var.web_acl_name
description = "Web ACL with CloudWatch metrics enabled"
scope = "REGIONAL"

default_action {
allow {}
}

# Web ACL-level visibility config with CloudWatch metrics enabled
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "${var.web_acl_name}-metric"
sampled_requests_enabled = true
}

# Example rule with CloudWatch metrics enabled
rule {
name = "RateLimitRule"
priority = 1

action {
block {}
}

statement {
rate_based_statement {
limit = 2000
aggregate_key_type = "IP"
}
}

# Rule-level visibility config - this is the key setting
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "RateLimitRule-metric"
sampled_requests_enabled = true
}
}
}

output "web_acl_arn" {
description = "ARN of the Web ACL"
value = aws_wafv2_web_acl.example.arn
}

output "web_acl_id" {
description = "ID of the Web ACL"
value = aws_wafv2_web_acl.example.id
}

Key points:

  • Every rule block must include a visibility_config with cloudwatch_metrics_enabled = true
  • The Web ACL itself also needs a top-level visibility_config
  • Each metric_name should be unique and descriptive

Verification

After enabling CloudWatch metrics:

  1. Go to the AWS WAF Console
  2. Select your Web ACL
  3. Review each rule and confirm CloudWatch metrics is enabled in the visibility configuration
  4. Check the CloudWatch metrics tab to see metrics appearing (may take a few minutes)
CLI Verification
aws wafv2 get-web-acl \
--name <your-web-acl-name> \
--scope REGIONAL \
--id <your-web-acl-id> \
--region us-east-1 \
--query 'WebACL.Rules[*].{Name:Name,MetricsEnabled:VisibilityConfig.CloudWatchMetricsEnabled}'

All rules should show MetricsEnabled: true.

To re-run the Prowler check:

prowler aws --checks wafv2_webacl_rule_logging_enabled

Additional Resources

Notes

  • Scope matters: Use REGIONAL for resources like Application Load Balancers and API Gateway. Use CLOUDFRONT for CloudFront distributions (and you must use the us-east-1 region).
  • Metric naming: Each metric name must be unique within the Web ACL. Use descriptive names that match your rule names for easier troubleshooting.
  • Cost consideration: CloudWatch metrics incur standard CloudWatch pricing. The cost is typically minimal but scales with the number of rules and request volume.
  • Propagation time: Changes to WAF configurations may take a few minutes to propagate across all edge locations.