WAF Managed Rules configuration using Terraform (2)

Last updated Apr 29, 2026 This page provides examples of deploying and configuring WAF Managed Rules in your zone or account using Terraform. It covers the following configurations:

If you are using the Cloudflare API, refer to the following resources:

For more information on deploying and configuring managed rulesets using the Rulesets API, refer to Work with managed rulesets in the Ruleset Engine documentation.

Before you start

Obtain the necessary account, zone, and managed ruleset IDs

The Terraform configurations provided in this page need the zone ID (or account ID) of the zone/account where you will deploy the managed rulesets.

  • To retrieve the list of accounts you have access to, including their IDs, use the List accounts operation.
  • To retrieve the list of zones you have access to, including their IDs, use the List zones operation.

The deployment of managed rulesets via Terraform requires that you use the ruleset IDs. To find the IDs of managed rulesets, use the List account rulesets operation. The response will include the description and IDs of existing managed rulesets.

The IDs of WAF managed rulesets are also available in the WAF Managed Rules page.

Import or delete existing rulesets

Terraform assumes that it has complete control over account and zone rulesets. If you already have rulesets configured in your account or zone, do one of the following:

  • Import existing rulesets to Terraform using the cf-terraforming tool. Recent versions of the tool can generate resource definitions for existing rulesets and import their configuration to Terraform state.
  • Start from scratch by deleting existing rulesets (account and zone rulesets with "kind": "root" and "kind": "zone", respectively) and then defining your rulesets configuration in Terraform.

Deploy managed rulesets at the zone level

The following example deploys two managed rulesets to the zone with ID <ZONE_ID> using Terraform, using a cloudflare_ruleset resource with two rules that execute the managed rulesets.

<details>

<summary>

Required API token permissions

</summary>

At least one of the following <a href="https://developers.cloudflare.com/fundamentals/api/reference/permissions/">token permissions</a> is required:

  • <code>Zone WAF Write</code>

</details>

Configure the cloudflare_ruleset ↗︎ resource:

# Configure a ruleset at the zone level for the "http_request_firewall_managed" phase
resource "cloudflare_ruleset" "zone_level_managed_waf" {
  zone_id     = var.cloudflare_zone_id
  name        = "Managed WAF entry point ruleset"
  description = "Zone-level WAF Managed Rules config"
  kind        = "zone"
  phase       = "http_request_firewall_managed"

rules = [
    {
      # Execute Cloudflare Managed Ruleset
      ref         = "execute_cloudflare_managed_ruleset"
      description = "Execute Cloudflare Managed Ruleset on my zone-level phase entry point ruleset"
      expression  = "true"
      action      = "execute"
      action_parameters = {
        id = "efb7b8c949ac4650a09736fc376e9aee"
      }
    },
    {
      # Execute Cloudflare OWASP Core Ruleset
      ref         = "execute_cloudflare_owasp_core_ruleset"
      description = "Execute Cloudflare OWASP Core Ruleset on my zone-level phase entry point ruleset"
      expression  = "true"
      action      = "execute"
      action_parameters = {
        id = "4814384a9e5d4991b9815dcfc25d2f1f"
      }
    },
  ]
}
# Configure a ruleset at the zone level for the "http_request_firewall_managed" phase
resource "cloudflare_ruleset" "zone_level_managed_waf" {
  zone_id     = "<ZONE_ID>"
  name        = "Managed WAF entry point ruleset"
  description = "Zone-level WAF Managed Rules config"
  kind        = "zone"
  phase       = "http_request_firewall_managed"

# Execute Cloudflare Managed Ruleset
  rules {
    ref         = "execute_cloudflare_managed_ruleset"
    description = "Execute Cloudflare Managed Ruleset on my zone-level phase entry point ruleset"
    expression  = "true"
    action      = "execute"
    action_parameters {
      id = "efb7b8c949ac4650a09736fc376e9aee"
    }
  }

# Execute Cloudflare OWASP Core Ruleset
  rules {
    ref         = "execute_cloudflare_owasp_core_ruleset"
    description = "Execute Cloudflare OWASP Core Ruleset on my zone-level phase entry point ruleset"
    expression  = "true"
    action      = "execute"
    action_parameters {
      id = "4814384a9e5d4991b9815dcfc25d2f1f"
    }
  }
}

Deploy managed rulesets at the account level

Notes

  • Account-level WAF configuration requires an Enterprise plan with a paid add-on.
  • Managed rulesets deployed at the account level will only apply to incoming traffic of zones on an Enterprise plan. The expression of your execute rule must end with and cf.zone.plan eq "ENT".

The following example deploys two managed rulesets to the account with ID <ACCOUNT_ID> using Terraform, using a cloudflare_ruleset resource with two rules that execute the managed rulesets for two hostnames belonging to Enterprise zones.

<details>

<summary>

Required API token permissions

</summary>

All of the following <a href="https://developers.cloudflare.com/fundamentals/api/reference/permissions/">token permissions</a> are required:

  • <code>Account WAF Write</code>
  • <code>Account Rulesets Write</code>

</details>

Configure the cloudflare_ruleset ↗︎ resource:

resource "cloudflare_ruleset" "account_level_managed_waf" {
  account_id  = var.cloudflare_account_id
  name        = "Managed WAF entry point ruleset"
  description = "Account-level WAF Managed Rules config"
  kind        = "root"
  phase       = "http_request_firewall_managed"

rules = [
    {
      # Execute Cloudflare Managed Ruleset
      ref         = "execute_cloudflare_managed_ruleset_api_store"
      description = "Execute Cloudflare Managed Ruleset on my account-level phase entry point ruleset"
      expression  = "http.host in {\"api.example.com\" \"store.example.com\"} and cf.zone.plan eq \"ENT\""
      action      = "execute"
      action_parameters = {
        id = "efb7b8c949ac4650a09736fc376e9aee"
      }
    },
    {
      # Execute Cloudflare OWASP Core Ruleset
      ref         = "execute_owasp_core_ruleset_api_store"
      description = "Execute Cloudflare OWASP Core Ruleset on my account-level phase entry point ruleset"
      expression  = "http.host in {\"api.example.com\" \"store.example.com\"} and cf.zone.plan eq \"ENT\""
      action      = "execute"
      action_parameters = {
        id = "4814384a9e5d4991b9815dcfc25d2f1f"
      }
    },
  ]
}
resource "cloudflare_ruleset" "account_level_managed_waf" {
  account_id  = "<ACCOUNT_ID>"
  name        = "Managed WAF entry point ruleset"
  description = "Account-level WAF Managed Rules config"
  kind        = "root"
  phase       = "http_request_firewall_managed"

# Execute Cloudflare Managed Ruleset
  rules {
    ref         = "execute_cloudflare_managed_ruleset_api_store"
    description = "Execute Cloudflare Managed Ruleset on my account-level phase entry point ruleset"
    expression  = "http.host in {\"api.example.com\" \"store.example.com\"} and cf.zone.plan eq \"ENT\""
    action      = "execute"
    action_parameters {
      id = "efb7b8c949ac4650a09736fc376e9aee"
    }
  }

# Execute Cloudflare OWASP Core Ruleset
  rules {
    ref         = "execute_owasp_core_ruleset_api_store"
    description = "Execute Cloudflare OWASP Core Ruleset on my account-level phase entry point ruleset"
    expression  = "http.host in {\"api.example.com\" \"store.example.com\"} and cf.zone.plan eq \"ENT\""
    action      = "execute"
    action_parameters {
      id = "4814384a9e5d4991b9815dcfc25d2f1f"
    }
  }
}

Configure exceptions

The following example adds two exceptions for the Cloudflare Managed Ruleset:

  • The first rule will skip the execution of the entire Cloudflare Managed Ruleset (with ID ...376e9aee) for specific URLs, according to the rule expression.
  • The second rule will skip the execution of two rules belonging to the Cloudflare Managed Ruleset for specific URLs, according to the rule expression.

Add the two exceptions to the cloudflare_ruleset resource before the rule that deploys the Cloudflare Managed Ruleset:

resource "cloudflare_ruleset" "zone_level_managed_waf" {
  # (...)

rules = [
    {
      # Skip execution of the entire Cloudflare Managed Ruleset for specific URLs
      ref         = "skip_cloudflare_managed_ruleset_example_com"
      description = "Skip Cloudflare Managed Ruleset"
      expression  = "(http.request.uri.path eq \"/status\" and http.request.uri.query contains \"skip=rulesets\")"
      action      = "skip"
      action_parameters = {
        rulesets = ["efb7b8c949ac4650a09736fc376e9aee"]
      }
    },
    {
      # Skip execution of two rules in the Cloudflare Managed Ruleset for specific URLs
      ref         = "skip_wordpress_sqli_rules_example_com"
      description = "Skip WordPress and SQLi rules"
      expression  = "(http.request.uri.path eq \"/status\" and http.request.uri.query contains \"skip=rules\")"
      action      = "skip"
      action_parameters = {
        rules = {
          # Format: "<RULESET_ID>" = ["<RULE_ID_1>", "<RULE_ID_2>"]
          "efb7b8c949ac4650a09736fc376e9aee" = ["5de7edfa648c4d6891dc3e7f84534ffa", "e3a567afc347477d9702d9047e97d760"]
        }
      }
    },
    {
      # Execute Cloudflare Managed Ruleset
      ref         = "execute_cloudflare_managed_ruleset"
      description = "Execute Cloudflare Managed Ruleset on my zone-level phase entry point ruleset"
      expression  = "true"
      action      = "execute"
      action_parameters = {
        id = "efb7b8c949ac4650a09736fc376e9aee"
      }
    },
    # (...)
  ]
}