Skip to content

WAF Logging Configurations

Input map: wafv2_web_acl_logging_configuration

Configure WAF logging to CloudWatch with filtering and sensitive field redaction.

Key Fields

Field Type Default Description
web_acl string required Key reference to wafv2_web_acl
log_destinations list required Array of log destinations (ARNs or key references)
logging_filter object null Filter which requests to log
redacted_fields list null Fields to redact from logs

Log Destination Object

Field Type Default Description
destination string required Direct ARN or key reference to CloudWatch/S3
destination_type string "arn" "arn", "cloudwatch_log_group", or "s3_bucket"

Basic Example

wafv2_web_acl_logging_configuration = {
  waf-logging = {
    web_acl = "EpicManagedRulesWebACL"
    log_destinations = [
      {
        destination      = "WAFLogGroup"
        destination_type = "cloudwatch_log_group"
      }
    ]
  }
}

Note: Currently AWS WAF only supports a single log destination, but the configuration accepts an array for future compatibility.

Logging Filters

Filter logs to reduce noise and costs by only logging specific request types.

Log Only Blocked Requests

wafv2_web_acl_logging_configuration = {
  api-waf-logging = {
    web_acl = "api-waf"
    log_destinations = [
      {
        destination      = "WAFLogGroup"
        destination_type = "cloudwatch_log_group"
      }
    ]

    logging_filter = {
      default_behavior = "DROP"
      filter = [{
        behavior    = "KEEP"
        requirement = "MEETS_ANY"
        condition = [{
          action_condition = {
            action = "BLOCK"
          }
        }]
      }]
    }
  }
}

Log Blocked and Counted Requests

wafv2_web_acl_logging_configuration = {
  api-waf-logging = {
    web_acl = "api-waf"
    log_destinations = [
      {
        destination      = "WAFLogGroup"
        destination_type = "cloudwatch_log_group"
      }
    ]

    logging_filter = {
      default_behavior = "DROP"
      filter = [{
        behavior    = "KEEP"
        requirement = "MEETS_ANY"
        condition = [
          {
            action_condition = { action = "BLOCK" }
          },
          {
            action_condition = { action = "COUNT" }
          }
        ]
      }]
    }
  }
}

Field Redaction

Redact sensitive data from WAF logs to comply with privacy requirements.

Redact Authorization Headers

wafv2_web_acl_logging_configuration = {
  api-waf-logging = {
    web_acl = "api-waf"
    log_destinations = [
      {
        destination      = "WAFLogGroup"
        destination_type = "cloudwatch_log_group"
      }
    ]

    redacted_fields = [
      {
        single_header = {
          name = "authorization"
        }
      }
    ]
  }
}

Redact Multiple Fields

wafv2_web_acl_logging_configuration = {
  api-waf-logging = {
    web_acl = "api-waf"
    log_destinations = [
      {
        destination      = "WAFLogGroup"
        destination_type = "cloudwatch_log_group"
      }
    ]

    redacted_fields = [
      {
        single_header = {
          name = "authorization"
        }
      },
      {
        single_header = {
          name = "cookie"
        }
      },
      {
        query_string = true
      },
      {
        uri_path = true
      }
    ]
  }
}

Available Redacted Field Types

Type Description Example
single_header Specific HTTP header { single_header = { name = "authorization" } }
query_string Entire query string { query_string = true }
uri_path Request URI path { uri_path = true }
method HTTP method { method = true }

Logging Filter Options

Filter Behavior

  • KEEP – Include matching requests in logs
  • DROP – Exclude matching requests from logs

Filter Requirement

  • MEETS_ALL – All conditions must match
  • MEETS_ANY – Any condition can match

Action Conditions

Available actions for filtering:

  • ALLOW – Requests allowed by rules
  • BLOCK – Requests blocked by rules
  • COUNT – Requests counted but not blocked
  • CAPTCHA – Requests challenged with CAPTCHA
  • CHALLENGE – Requests challenged
  • EXCLUDED_AS_COUNT – Requests excluded from rule groups

Complete Example

wafv2_web_acl_logging_configuration = {
  waf-logging = {
    web_acl = "EpicManagedRulesWebACL"
    log_destinations = [
      {
        destination      = "WAFLogGroup"
        destination_type = "cloudwatch_log_group"
      }
    ]

    # Only log blocked and counted requests
    logging_filter = {
      default_behavior = "DROP"
      filter = [{
        behavior    = "KEEP"
        requirement = "MEETS_ANY"
        condition = [
          {
            action_condition = { action = "BLOCK" }
          },
          {
            action_condition = { action = "COUNT" }
          }
        ]
      }]
    }

    # Redact sensitive data
    redacted_fields = [
      {
        single_header = { name = "authorization" }
      },
      {
        single_header = { name = "cookie" }
      },
      {
        single_header = { name = "x-api-key" }
      },
      {
        query_string = true
      }
    ]
  }
}

CloudWatch Log Groups

When using destination_type = "cloudwatch_log_group", reference existing CloudWatch log groups by key:

loggroups = {
  WAFLogGroup = {
    name              = "aws-waf-logs-WAFLogGroup"
    retention_in_days = 30
  }

  ProdWAFLogGroup = {
    name              = "aws-waf-logs-ProdWAFLogGroup"
    retention_in_days = 90
  }
}

wafv2_web_acl_logging_configuration = {
  waf-logging = {
    web_acl = "waf"
    log_destinations = [
      {
        destination      = "WAFLogGroup"
        destination_type = "cloudwatch_log_group"
      }
    ]
  }
}

Note: WAF log group names must start with aws-waf-logs- (enforced by AWS). Note: S3 bucket names for WAF logs must start with aws-waf-logs- (enforced by AWS).