Skip to main content
On this page

Coverage by target cloud

How the backends compare

Each row compares a capability of WAFv2 with its adaptation on each backend. A dash means this row is not stated for that backend.

Infrastructure-only adaptation

On Azure

How it works

On AWS, an aws_wafv2_web_acl holds rules that AWS WAF evaluates in front of an ALB or a CloudFront distribution: IP-set allow and block lists, rate-based rules, byte-match and geo-match conditions, and AWS managed rule groups. On Azure, the equivalent is the Application Gateway WAF, whose rules live in an azurerm_web_application_firewall_policy. When the stack is built, the web ACL becomes one Azure WAF policy. IP-set, rate-based, byte-match and geo-match statements become custom rules, and AWS managed rule groups map to the OWASP Core Rule Set. You attach the policy to your Application Gateway, and Azure’s WAF evaluates every request; Tensor9 is not in the request path. Statements with no Azure equivalent are not translated, and the build names each one in a warning.
On AWS, AWS WAF enforces the aws_wafv2_web_acl rules at an ALB or CloudFront. On Azure, the build turns the same rules into an azurerm_web_application_firewall_policy that the Application Gateway WAF evaluates.On AWS, AWS WAF enforces the aws_wafv2_web_acl rules at an ALB or CloudFront. On Azure, the build turns the same rules into an azurerm_web_application_firewall_policy that the Application Gateway WAF evaluates.

The build turns your web ACL into an Azure WAF policy that the Application Gateway WAF evaluates.

What the build creates

Each web ACL becomes one WAF policy in the same resource group and region as the rest of the stack. The rules keep their AWS priorities. Each translated statement becomes one entry in custom_rules, and the policy’s managed_rules block always includes OWASP Core Rule Set 3.2, because Azure requires a managed rule set. Policy and rule names keep only their letters and digits. The policy runs in Prevention mode, so a matching block rule stops the request rather than only logging it. AWS allow and block actions stay allow and block; a count action becomes Log. The build does not attach the policy to a gateway, even if the stack had an aws_wafv2_web_acl_association; you attach it, as you attached the web ACL on AWS.
The web ACL's rules become two parts of one WAF policy: custom_rules, with one entry per translated statement, and managed_rules, holding the OWASP Core Rule Set. The policy is created in the stack's resource group, and you attach it to the Application Gateway.The web ACL's rules become two parts of one WAF policy: custom_rules, with one entry per translated statement, and managed_rules, holding the OWASP Core Rule Set. The policy is created in the stack's resource group, and you attach it to the Application Gateway.

One web ACL becomes one WAF policy: custom rules plus the OWASP managed rule set.

How the rule statements translate

A byte_match_statement becomes a match condition. The AWS field becomes the match variable: URI path becomes RequestUri, query string becomes QueryString, method becomes RequestMethod, body becomes RequestBody, and a single header becomes RequestHeaders. The positional constraint becomes the operator: exactly becomes Equal, starts with becomes BeginsWith, ends with becomes EndsWith, and contains or contains word becomes Contains. The lowercase, URL-decode and HTML-entity-decode text transformations are kept. A geo_match_statement becomes a GeoMatch rule on the client address with the same two-letter country codes. IP sets and rate-based rules are covered in the next section.
Each AWS WAFv2 statement type maps to an Azure construct: ip_set_reference to a RemoteAddr IPMatch custom rule with the CIDRs inline; rate_based to a RateLimitRule; byte_match to a match_condition with a typed variable; geo_match to a GeoMatch rule; managed_rule_group to the OWASP managed rule set.Each AWS WAFv2 statement type maps to an Azure construct: ip_set_reference to a RemoteAddr IPMatch custom rule with the CIDRs inline; rate_based to a RateLimitRule; byte_match to a match_condition with a typed variable; geo_match to a GeoMatch rule; managed_rule_group to the OWASP managed rule set.

Four statement types become custom rules; AWS managed rule groups map to the OWASP Core Rule Set.

IP sets and rate limits

Azure custom rules cannot refer to a separate IP list, so an IP set’s CIDRs are copied into the rule’s match_values with the RemoteAddr variable and the IPMatch operator. An IP set shared by several web ACLs is copied into each policy, so a change to the list must be made in each one. A rate_based_statement becomes a RateLimitRule on the client address, with the AWS request limit as its threshold. Azure accepts only two windows, one minute and five minutes. A 60-second or 300-second window maps exactly; any other window of 60 seconds or less becomes one minute, and anything longer becomes five minutes. The build warns when it rounds.
An aws_wafv2_ip_set with three CIDRs becomes a custom rule with the RemoteAddr variable and the IPMatch operator, whose match_values list holds the same three CIDRs.An aws_wafv2_ip_set with three CIDRs becomes a custom rule with the RemoteAddr variable and the IPMatch operator, whose match_values list holds the same three CIDRs.

The IP set’s CIDRs are written into the custom rule itself; there is no separate list resource.

Managed rules, scope and the default action

Managed rule groups. AWS managed rule groups map to the OWASP Core Rule Set that Microsoft ships with the Application Gateway WAF, so injection, cross-site scripting and protocol-violation coverage is kept. The individual rule IDs differ; see Limitations. Scope. A REGIONAL web ACL maps directly. A CLOUDFRONT web ACL is also created as an Application Gateway policy; for a global edge, Azure’s equivalent is Front Door, which the build names in a warning. Default action. A default action of allow maps exactly. A default of block does not, because Azure has no policy-wide default deny; see Limitations.

Limitations

Where AWS WAF and the Azure WAF policy differ
  • Regex, SQLi, XSS, size, label and composite statements are not supported. Regex, size-constraint, SQL-injection and XSS match statements, label matches and and / or / not composites create no rule; the build names each one. You can cover injection and cross-site checks with the OWASP rules, and re-create a regex check as an Azure custom rule with the Regex operator.
  • A default block action behaves differently: unmatched requests are allowed. The allow rules are created, but a request that matches no rule still passes. Add an explicit lowest-priority block rule to restore deny-by-default.
  • Rate windows behave differently: they round to one or five minutes. A window other than 60 or 300 seconds is rounded, which changes the effective rate.
  • Rate-limit scope-down statements are not supported. A scope_down_statement is dropped, so the limit applies to all traffic the rule matches. Add a match condition to narrow it again.
  • AWS managed rule IDs are not supported. Managed groups map to OWASP Core Rule Set 3.2 as a whole. Per-rule action overrides and excluded rules are dropped; re-create them as OWASP exclusions.
  • An OWASP baseline is added when you had no managed group. Azure requires a managed rule set, so a web ACL with only custom rules gains OWASP Core Rule Set 3.2. It can block traffic your web ACL allowed; check it before taking traffic.
  • The compress-whitespace transformation is not supported. Azure has no equivalent, so a byte match that used it compares the raw value. Lowercase, URL-decode and HTML-entity-decode are kept.
  • Rules the build cannot read behave differently: they never become allows. A rule whose action comes from a variable is created as Block. An IP set whose addresses come from a variable creates no rule. Rules generated by a dynamic "rule" block are not translated. The build warns about each.

Other considerations

  • Attach the policy to your gateway. Associate the WAF policy with the Application Gateway in front of the workload. Until then it protects nothing.
  • Enforcement starts immediately. The policy runs in Prevention mode. If you want a trial period, switch it to Detection mode in the Azure portal first.
  • Logging is on the gateway. WAF request logs are a diagnostic setting on the Application Gateway, not part of the policy. Enable them there.
  • References to the web ACL. References to its id or name now point to the WAF policy. A policy has no ARN, so an output that reads the ARN is removed with a warning, and any other ARN reference stops the build with an error.
  • Keep the WAF resources in one module. If the aws_wafv2_* resources span more than one module, the build stops with an error.
  • Azure limits differ. The Application Gateway WAF limits the number of custom rules and the size of match values differently from AWS. Check a very large IP set or rule set against the Azure limits.

On OCI

How it works

On AWS, an aws_wafv2_web_acl holds rules that AWS WAF evaluates in front of an ALB or a CloudFront distribution: IP-set lists, rate-based rules, byte-match and geo-match conditions, and AWS managed rule groups. On OCI, the equivalent is the OCI Web Application Firewall, whose rules live in an oci_waf_web_app_firewall_policy. When the stack is built, the web ACL becomes one OCI WAF policy, and each IP set becomes an oci_waf_network_address_list. Request conditions are written in OCI’s JMESPATH condition language, and AWS managed rule groups map to OCI’s OWASP-based protection. You attach the policy to a load balancer or gateway, and OCI’s WAF evaluates every request; Tensor9 is not in the request path. Several conditions are approximations, described below, and the build warns about each one so you can check it.
On AWS, AWS WAF enforces the aws_wafv2_web_acl rules. On OCI, the build turns the same rules into an oci_waf_web_app_firewall_policy, plus a network address list for each IP set, and OCI's WAF evaluates the policy.On AWS, AWS WAF enforces the aws_wafv2_web_acl rules. On OCI, the build turns the same rules into an oci_waf_web_app_firewall_policy, plus a network address list for each IP set, and OCI's WAF evaluates the policy.

The build turns your web ACL into an OCI WAF policy, plus an address list for each IP set.

What the build creates

OCI names a policy’s actions once and has each rule refer to one by name. The build creates three: an allow action, a block action that returns HTTP 403, and a check action that logs the match and lets the request continue. AWS allow, block and count map to allow, block and check. Rules are grouped by what they inspect: access-control rules (IP-set, byte-match and geo-match), rate-limiting rules, and protection rules (the managed OWASP capabilities). The policy and its address lists are created in the stack’s compartment. The build does not attach the policy, even if the stack had an aws_wafv2_web_acl_association; you attach it, as you attached the web ACL on AWS.
The policy declares three named actions (allowAction, blockAction, checkAction) and three rule modules: request access control for IP, byte and geo rules; request rate limiting for rate rules; request protection for managed groups. Each ip-set is a separate network address list. The policy is created in the stack's compartment.The policy declares three named actions (allowAction, blockAction, checkAction) and three rule modules: request access control for IP, byte and geo rules; request rate limiting for rate rules; request protection for managed groups. Each ip-set is a separate network address list. The policy is created in the stack's compartment.

The policy names three actions once, and groups rules into access control, rate limiting and protection.

How the rule statements translate

A rate_based_statement becomes a rate-limiting rule with the AWS limit as requests_limit and the AWS window as period_in_seconds, unchanged. A request over the limit gets the block action’s HTTP 403. A byte_match_statement becomes an access-control rule whose condition checks whether the URL path contains the search string. That is the condition for every byte match, whatever field and positional constraint the AWS rule used. A geo_match_statement becomes an access-control rule that compares the request’s x-country header with the country codes. Check both kinds of condition before the policy takes traffic.
ip_set_reference becomes a network address list plus an access-control rule; rate_based becomes a rate-limiting rule with the same window; byte_match becomes an access-control rule that checks the URL path; geo_match becomes an access-control rule on the x-country header; managed_rule_group becomes an OWASP protection rule.ip_set_reference becomes a network address list plus an access-control rule; rate_based becomes a rate-limiting rule with the same window; byte_match becomes an access-control rule that checks the URL path; geo_match becomes an access-control rule on the x-country header; managed_rule_group becomes an OWASP protection rule.

IP-set and rate rules map closely; byte-match and geo-match conditions are approximations to check.

IP sets and address lists

Each IP set becomes an oci_waf_network_address_list of type ADDRESSES holding the same CIDRs. The access-control rule for an IP-set statement does not refer to that list: its JMESPATH condition lists the CIDRs itself and compares them with the client address. A change to the IP set therefore has to be made in the rule’s condition, not only in the address list. This condition is an approximation of the AWS IP-set match, and the build warns about it. Confirm that it matches the addresses you expect before the policy enforces.
An aws_wafv2_ip_set becomes an oci_waf_network_address_list of type ADDRESSES holding the same CIDRs. The access-control rule does not refer to the list; its JMESPATH condition lists the CIDRs itself and compares them with the client address.An aws_wafv2_ip_set becomes an oci_waf_network_address_list of type ADDRESSES holding the same CIDRs. The access-control rule does not refer to the list; its JMESPATH condition lists the CIDRs itself and compares them with the client address.

Each IP set becomes an address list, and the access-control rule lists the same CIDRs in its own condition.

Managed protection and the default action

Managed rule groups. Each AWS managed rule group becomes a protection rule using OCI’s OWASP Core Rule Set capability, with the block action. Injection, cross-site scripting and protocol-violation coverage is kept. AWS rule IDs do not correspond one to one with OCI capabilities, so alerts and exclusions written for a specific AWS rule must be re-created. You can tune OCI’s protection capabilities in the console after the build to remove false positives. Default action. OCI’s access-control rules have their own default action, so both AWS defaults map: allow becomes the allow action, and block becomes the block action. A deny-by-default web ACL keeps denying requests that match no rule, with no extra catch-all rule needed.

Limitations

Where AWS WAF and the OCI WAF policy differ
  • Regex, SQLi, XSS, size, label and composite statements are not supported. Regex, size-constraint, SQL-injection and XSS match statements, label matches and and / or / not composites create no rule; the build names each one. You can cover injection and cross-site checks with the OWASP protection, and write other checks as JMESPATH access-control conditions.
  • Byte-match conditions behave differently: they always check the URL path. Every byte match becomes “the URL path contains the search string”, whatever field (header, query string, body) and positional constraint the AWS rule used. Rewrite conditions that matched anything else.
  • Geo-match conditions behave differently: they read an x-country header. The condition compares that request header with the country codes, so it works only if the header is present in your traffic. Verify it against your setup.
  • IP-set conditions behave differently: the rule lists the CIDRs itself. The address list holds the exact CIDRs, but the rule’s condition does not use it and is an approximation. Verify it before enforcing.
  • Text transformations are not supported. OCI conditions match the raw request value, so lowercase, URL-decode, HTML-entity-decode and compress-whitespace transformations are dropped.
  • Rate-limit scope-down statements are not supported. A scope_down_statement is dropped, so the limit applies to all traffic the rule matches.
  • AWS managed rule IDs are not supported. Managed groups map to the OWASP capability as a whole. Per-rule action overrides and excluded rules are dropped; re-create them in OCI.
  • Rules the build cannot read behave differently: they never become allows. A rule action or web ACL default action that comes from a variable becomes the block action. An IP set whose addresses come from a variable creates no rule. Rules generated by a dynamic "rule" block are not translated. The build warns about each.

Other considerations

  • Attach the policy. Associate the WAF policy with the load balancer or gateway in front of the workload. Until then it protects nothing.
  • Enforcement starts immediately. The block action returns HTTP 403 on a match. For a trial period, switch rules to the check action first.
  • Check conditions before taking traffic. Review the IP-set, byte-match and geo-match conditions in the OCI console once; they are where the translation is approximate.
  • References to the web ACL. References to its id or name now point to the WAF policy. A policy has no ARN, so an output that reads the ARN is removed with a warning, and any other ARN reference stops the build with an error.
  • Keep the WAF resources in one module. If the aws_wafv2_* resources span more than one module, the build stops with an error.

Debug this service

For requests through a service adapter, use Explain and request diagnostics to investigate the selected mapping. Follow the BYOC service-adapter debugging runbook to capture and interpret the diagnostic evidence. Service Catalog.