Skip to main content
emnode / learn
Compliance Medium severity

AWS Security Hub · WAF

WAF.1: WAF Classic global web ACL logging

Written and reviewed by Emnode · Last reviewed

What does AWS Security Hub WAF.1 check?

WAF.1 is a periodic check on AWS WAF Classic global web ACLs (`AWS::WAF::WebACL`, the CloudFront-scoped kind). It reports FAILED when the web ACL has no logging configuration — when it isn't pointed at a Kinesis Data Firehose delivery stream to capture the requests it allows, blocks, and counts.

Why does WAF.1 matter?

A web ACL enforcing rules with no record of its decisions can't be audited. When a customer reports a legitimate request being blocked, or a security team needs to reconstruct an attack, the WAF logs are the primary evidence — and without logging every decision evaporates the moment it's made. It also maps to NIST AU-2/AU-3/AU-12 and PCI DSS 10.4.2, so an unlogged web ACL is a compliance gap on its own.

How do I fix WAF.1?

  1. Provision a Kinesis Data Firehose stream in us-east-1 whose name begins with the required `aws-waf-logs-` prefix.
  2. Identify the silent global web ACLs via the `aws waf` API (global WAF Classic is served only from the us-east-1 endpoint).
  3. Attach the logging configuration to each web ACL, redacting sensitive fields such as Authorization headers.
  4. Confirm records flow to the stream and the control flips to PASSED on the next evaluation.

Remediation script · bash

# Load balancer: enable access logs to a dedicated, log-delivery-permissioned bucket.
aws elbv2 modify-load-balancer-attributes \
  --load-balancer-arn "$LB_ARN" \
  --attributes \
      Key=access_logs.s3.enabled,Value=true \
      Key=access_logs.s3.bucket,Value=acme-elb-logs-eu-west-1 \
      Key=access_logs.s3.prefix,Value=prod-api

# WAF web ACL: attach logging (Firehose/log-group name must start with aws-waf-logs-),
# redact credentials, and keep only blocked requests to cap volume.
aws wafv2 put-logging-configuration --logging-configuration \
  ResourceArn="$WEBACL_ARN",LogDestinationConfigs="arn:aws:firehose:us-east-1:111122223333:deliverystream/aws-waf-logs-prod",RedactedFields=[{SingleHeader={Name=authorization}}]

# Network Firewall: enable ALERT logs to CloudWatch and FLOW logs to S3.
aws network-firewall update-logging-configuration --firewall-name prod-egress-fw \
  --logging-configuration 'LogDestinationConfigs=[{LogType=ALERT,LogDestinationType=CloudWatchLogs,LogDestination={logGroup=/netfw/prod-egress-fw/alert}}]'

# Route 53: log group MUST be in us-east-1, then attach the query logging config.
aws logs create-log-group --log-group-name /aws/route53/customer-portal --region us-east-1
aws route53 create-query-logging-config --hosted-zone-id Z0J1K4M2X8N9A1 \
  --cloud-watch-logs-log-group-arn arn:aws:logs:us-east-1:123456789012:log-group:/aws/route53/customer-portal

Full walkthrough (console steps, edge cases and verification) in the lesson Enable network and edge logging (LB, WAF, firewall, DNS).

Is WAF.1 a false positive?

Global WAF Classic only answers on the us-east-1 endpoint, so omitting `--region us-east-1` makes auditing commands return confusing errors that can look like a missing resource rather than a logging gap.

Part of the learning path See what's happening
  • WAF.2 WAF Classic regional rules should have a condition
  • WAF.3 WAF Classic regional rule groups should have a rule
  • WAF.4 WAF Classic regional web ACLs should have a rule
  • WAF.6 WAF Classic global rules should have a condition
  • WAF.7 WAF Classic global rule groups should have a rule
  • WAF.8 WAF Classic global web ACLs should have a rule
  • WAF.10 WAFv2 web ACLs should have a rule or rule group
  • WAF.11 WAFv2 web ACL logging should be enabled