Skip to content

WAF Exceptions: Configuration, Limits and Validation

This page is for the platform team. It describes how the Application Gateway addon of the shared services configures managed rule exceptions in a WAF policy, which limits apply, and which checks run when you plan. For the request process and the review, see Application Gateway and WAF policy review.

Reference design, your deployment may differ

This page describes the appgw addon of the shared services code. Whether the Application Gateway module of your hub supports the same exceptions block is not documented in the sources. Check the schema of your gateway before you copy an example.

Exclusions and exceptions

A WAF policy in prevention mode blocks requests that match its managed rules (for example the OWASP rule set). The module offers two ways to handle a legitimate request that is blocked:

Exclusion Exception
Key in the policy file managed_rules.<name>.exclusions exceptions (top level of the policy)
Matches on A request attribute (match_variable, selector, selector_match_operator) RemoteAddr, RequestHeader or RequestURI, with a list of values
Scope Rule sets and rule groups with the rules to exclude (excluded_rule_sets) One managed rule set, optionally limited to rule groups and rule IDs
Deployed by The azurerm provider An azapi update after the policy, because the azurerm provider does not support exceptions

Prefer the narrowest option: one rule ID, for one value. Do not disable a rule set because of one request.

Policy file structure

Policy files are JSON, in the folder set by waf_json_file_relative_path (default waf-definitions/) and matched with waf_json_file_pattern (default *.json). Each file has one object web_application_firewall_policy with an optional name, custom_rules, policy_settings, managed_rules and exceptions. Without name, the policy is called wafp-shared-hub-<environment>-<location_short>-001. Changing the name of an existing policy replaces it.

An exception (anonymised example):

"exceptions": [
  {
    "match_variable": "RequestHeader",
    "selector": "X-Trusted-Partner",
    "selector_match_operator": "Equals",
    "value_match_operator": "Equals",
    "values": ["true"],
    "exception_managed_rule_sets": [
      {
        "type": "OWASP",
        "version": "3.2",
        "rule_groups": [
          {
            "rule_group_name": "REQUEST-942-APPLICATION-ATTACK-SQLI",
            "rules": [942100, 942110]
          }
        ]
      }
    ]
  }
]
Field Meaning
match_variable RemoteAddr, RequestHeader or RequestURI
value_match_operator Contains, EndsWith, Equals, IPMatch or StartsWith
values The values to match. At least one.
selector, selector_match_operator Only for RequestHeader, and then both are required. The selector is the header name. The operator is Contains, EndsWith, Equals or StartsWith.
exception_managed_rule_sets Exactly one entry per exception: type, version and rule_groups
rule_groups List of rule_group_name and rules (rule IDs). The repository example for a RemoteAddr exception uses an empty list, which the validation treats as the scope of the whole rule set.

An IPMatch value must be a single IPv4 address. CIDR ranges and IPv6 are rejected.

Limits

The checks enforce the Azure limits that apply at the time of writing:

Limit Value
Exceptions per WAF policy 60
Exceptions in total across the WAF policies of one Application Gateway 60
Values for RemoteAddr exceptions 600
Values for RequestURI exceptions 10
Values for RequestHeader exceptions 10

The total counts the exceptions of all policy files in the folder, not only one. These limits are constants in the module: check them against the current Azure limits when you upgrade.

Validation at plan time

All checks are Terraform preconditions on the exception resource. A problem stops the plan, which matters: a failure during apply, after the managed rules have changed, would leave the policy without exceptions. For the same reason, any change to managed_rules of a policy re-applies its exceptions automatically (a replace trigger), because Azure removes the exceptions when the managed rules are updated.

Check Fails when
Match variable Not RemoteAddr, RequestHeader or RequestURI
Value match operator Not one of the allowed operators
IP values An IPMatch value is not a single IPv4 address
Selector A RequestHeader exception lacks selector or selector_match_operator, or another match variable sets them
Values An exception has no values
Rule set count An exception does not have exactly one exception_managed_rule_sets entry
Rule set The type and version are not one of the managed rule sets configured in the same policy
Rule group rule_group_name does not exist in that rule set
Rule ID A rule ID does not exist in that rule group
Limits One of the limits above is exceeded

The rule set, group and rule checks use the catalogue of available WAF rule sets of the subscription (the Azure resource type Microsoft.Network/applicationGatewayAvailableWafRuleSets), read during plan. The identity that runs the plan needs read access to it. The error messages list the valid values, so you can copy the right group or rule ID.

Add an exception

  1. Collect the evidence from the WAF log of the blocked request: the rule ID, the rule group, the URI and the argument or header (Application Gateway logs).
  2. Get the approval of security, and record the rationale and an example request in the change record.
  3. Add the exception to the policy file. Choose the narrowest match: a header value or a single address is better than a URI that matches many requests.
  4. Plan. Fix every precondition message.
  5. Review (WAF policy review) and apply.
  6. Test the request again, and keep a list of all exceptions with their rationale for periodic review.