---
name: azion-create-and-apply-a-waf-rule-set
description: >-
  Create a WAF rule set with the threat families and sensitivity you choose, then apply it to a firewall with a Set WAF behavior.
---

# Create and apply a WAF rule set

Create a [Web Application Firewall (WAF)](/en/documentation/platform/firewall/#waf) rule set, then apply it to a firewall with a Rules Engine rule. Both tasks run from Azion Console, the Azion CLI, or the API.

For a first run that ends in a blocked request, refer to [WAF quickstart](/en/documentation/platform/firewall/waf/quickstart/). That page fixes every option along the way. This page leaves them open: you choose the threat families, the sensitivity of each one, and the mode.

---

Select an interface. The prerequisites and both tasks follow that choice.

## Prerequisites

- An Azion account. To create one, refer to [How to create an account on Azion](/en/documentation/fundamentals/creating-account/).
- A firewall carrying the WAF module. WAF is the one module a firewall leaves off by default. Refer to [Set a firewall's main settings](/en/documentation/guides/application-security/firewall-and-waf/firewall-configure-main-settings/).
- A workload bound to that firewall, so the rule you create receives traffic. Refer to [Bind a firewall to a workload](/en/documentation/guides/application-security/firewall-and-waf/firewall-protect-your-domain/).

**Console**

- Access to Azion Console. To sign in, refer to [How to access Azion Console](/en/documentation/guides/platform/account-and-billing/how-to-access-azion-console/).

**CLI**

- The [Azion CLI](/en/documentation/devtools/cli/), installed and authorized.

**API**

- A personal token, and `curl` to send the requests. To create a token, refer to [Personal Tokens](/en/documentation/fundamentals/personal-tokens/).

---

## Create the rule set

A rule set carries up to eight threat families, and each family holds its own sensitivity. The sensitivity fixes the score a request has to reach before that family blocks it. Every family opens at `medium`. A higher sensitivity blocks at a lower score: it catches attacks carrying less evidence, and refuses more legitimate traffic with them. For what each family detects and what each level costs, refer to [WAF Rule Sets](/en/documentation/platform/firewall/waf/rules-set/#threat-families).

**Console**

The form lists all eight families, so every sensitivity is set in one place. To create the rule set in Azion Console:

1. **Open the WAF Rules page**

   Access [Azion Console](https://console.azion.com/) > **Edge Libraries** > **WAF Rules**.

2. **Select + WAF Rule**

3. **Name the rule set**

   In the **General** section, enter a **Name**. For example: `checkout-waf`.

4. **Set the sensitivity of each threat family**

   The **Threat Type Configuration** section lists eight families, each opening on *Sensitivity Medium*. For example, set **SQL Injection** to *Sensitivity High*.

5. **Turn on the Active switch**

6. **Save the rule set**

The rule set appears in **WAF Rules**, with its **Threat Type Configuration** and **Status**. It scores nothing until a Rules Engine rule names it.

**CLI**

`--thresholds` takes comma-separated `threat=sensitivity` pairs. A create that omits the flag carries all eight families at `medium`. To create the rule set with the Azion CLI:

1. **Run the create command**

   ```bash
   azion create waf --name "checkout-waf" --active true --rulesets 1 \
     --thresholds "sql_injection=medium,cross_site_scripting=medium,directory_traversal=medium,evading_tricks=medium,file_upload=medium,identified_attack=medium,remote_file_inclusion=medium,unwanted_access=medium"
   ```

2. **Read the output**

   The command prints the id of the rule set:

   ```text
   Created WAF with ID 12350
   ```

The rule set is active and runs on ruleset `1`. Record the id: the rule in the next section names it.

**API**

Each entry in `thresholds` names one threat family and the sensitivity it holds. To create the rule set:

1. **Send the create request**

   Replace `[TOKEN VALUE]` with your personal token:

   ```bash
   curl --request POST \
     --url https://api.azion.com/v4/workspace/wafs \
     --header 'Accept: application/json' \
     --header 'Authorization: Token [TOKEN VALUE]' \
     --header 'Content-Type: application/json' \
     --data '{
     "name": "checkout-waf",
     "active": true,
     "product_version": "1.0",
     "engine_settings": {
       "engine_version": "2021-Q3",
       "type": "score",
       "attributes": {
         "rulesets": [1],
         "thresholds": [
           { "threat": "cross_site_scripting", "sensitivity": "medium" },
           { "threat": "directory_traversal", "sensitivity": "medium" },
           { "threat": "evading_tricks", "sensitivity": "medium" },
           { "threat": "file_upload", "sensitivity": "medium" },
           { "threat": "identified_attack", "sensitivity": "medium" },
           { "threat": "remote_file_inclusion", "sensitivity": "medium" },
           { "threat": "sql_injection", "sensitivity": "medium" },
           { "threat": "unwanted_access", "sensitivity": "medium" }
         ]
       }
     }
   }'
   ```

2. **Read the response**

   The status is `202`, and `"state": "pending"` says Azion accepted the rule set and is still propagating it:

   ```json
   {
     "state": "pending",
     "data": {
       "id": 12349,
       "active": true,
       "name": "checkout-waf",
       "last_editor": "user@example.com",
       "last_modified": "2026-01-01T12:00:00.000000Z",
       "product_version": "1.0",
       "engine_settings": {
         "engine_version": "2021-Q3",
         "type": "score",
         "attributes": {
           "rulesets": [1],
           "thresholds": [
             { "threat": "cross_site_scripting", "sensitivity": "medium" },
             { "threat": "directory_traversal", "sensitivity": "medium" },
             { "threat": "evading_tricks", "sensitivity": "medium" },
             { "threat": "file_upload", "sensitivity": "medium" },
             { "threat": "identified_attack", "sensitivity": "medium" },
             { "threat": "remote_file_inclusion", "sensitivity": "medium" },
             { "threat": "sql_injection", "sensitivity": "medium" },
             { "threat": "unwanted_access", "sensitivity": "medium" }
           ]
         }
       },
       "version_id": null,
       "version_state": null,
       "is_versioned": false,
       "version": null
     }
   }
   ```

Record the `id`. The rule in the next section names it.

> **Note**
>
> A `thresholds` array with fewer than eight entries is accepted. The rule set then carries only the families you sent. A repeated `threat` is not accepted: it answers `500` with `10067 Internal Server Error`.

---

## Apply the rule set to a firewall

A [Rules Engine for Firewall](/en/documentation/platform/firewall/rules-engine/) rule selects requests with its own criteria and runs behaviors on them. The `Set WAF` behavior names one rule set and one mode. A rule carries at most one `Set WAF` behavior.

The mode belongs to the behavior rather than to the rule set, and it is required. `Logging` scores a request, records it, and serves it. `Blocking` refuses a request whose score reaches a threshold of its family. For the order to move between them, refer to [Firewall best practices](/en/documentation/platform/firewall/best-practices/#waf).

> **Caution**
>
> A criterion on `${request_args}` matches only a request that carries a query string. Every `POST` holding its payload in the body then passes unscored. Key the criterion on `${request_uri}` instead.

**Console**

To apply the rule set in Azion Console:

1. **Open the firewall**

   Access [Azion Console](https://console.azion.com/) > **Firewalls**, then select the firewall bound to your workload.

2. **Select the Rules Engine tab**

3. **Select + Rule**

4. **Name the rule**

   Enter a name for the rule. For example: `Apply checkout-waf`.

5. **Set the criterion**

   In the **Criteria** section, select the `Request Uri` variable, the *starts with* operator, and `/` as the argument.

6. **Add the Set WAF behavior**

   In the **Behaviors** section, select **Set WAF**, then select `checkout-waf` as the rule set.

7. **Set the mode to Blocking**

8. **Save the rule**

The firewall scores every request it receives against the rule set.

**CLI**

`azion create firewall-rule` takes only `--firewall-id` and `--file`, so the behavior and the mode travel in the JSON. To apply the rule set with the Azion CLI:

1. **Write the rule to a file**

   Save the following as `fw-rule.json`, with the id of your rule set in `waf_id`:

   ```json
   {
     "name": "Apply checkout-waf",
     "active": true,
     "description": "",
     "criteria": [
       [
         {
           "conditional": "if",
           "variable": "${request_uri}",
           "operator": "starts_with",
           "argument": "/"
         }
       ]
     ],
     "behaviors": [
       {
         "type": "set_waf",
         "attributes": {
           "waf_id": 12350,
           "mode": "blocking"
         }
       }
     ]
   }
   ```

2. **Create the rule**

   Replace `<firewall-id>` with the id of your firewall:

   ```bash
   azion create firewall-rule --firewall-id <firewall-id> --file fw-rule.json
   ```

3. **Read the output**

   The command prints the id of the rule:

   ```text
   Created Firewall Rule with ID 123457
   ```

The firewall scores every request it receives against the rule set.

**API**

A shell expands `${request_uri}`, so the body travels in a file rather than inline. To apply the rule set:

1. **Write the rule to a file**

   Save the following as `rule.json`, with the id of your rule set in `waf_id`:

   ```json
   {
     "name": "Apply checkout-waf",
     "active": true,
     "criteria": [
       [
         {
           "conditional": "if",
           "variable": "${request_uri}",
           "operator": "starts_with",
           "argument": "/"
         }
       ]
     ],
     "behaviors": [
       {
         "type": "set_waf",
         "attributes": {
           "waf_id": 12349,
           "mode": "blocking"
         }
       }
     ]
   }
   ```

2. **Send the create request**

   Replace `<firewall-id>` with the id of your firewall:

   ```bash
   curl --request POST \
     --url https://api.azion.com/v4/workspace/firewalls/<firewall-id>/request_rules \
     --header 'Accept: application/json' \
     --header 'Authorization: Token [TOKEN VALUE]' \
     --header 'Content-Type: application/json' \
     --data @rule.json
   ```

3. **Read the response**

   The `202` echoes the rule and adds two fields the API assigns, `description` and `order`:

   ```json
   {
     "state": "pending",
     "data": {
       "id": 123456,
       "name": "Apply checkout-waf",
       "last_editor": "user@example.com",
       "last_modified": "2026-01-01T12:00:00.000000Z",
       "created_at": "2026-01-01T12:00:00.000000Z",
       "active": true,
       "criteria": [
         [
           {
             "conditional": "if",
             "variable": "${request_uri}",
             "operator": "starts_with",
             "argument": "/"
           }
         ]
       ],
       "behaviors": [
         {
           "type": "set_waf",
           "attributes": {
             "waf_id": 12349,
             "mode": "blocking"
           }
         }
       ],
       "description": "",
       "order": 1
     }
   }
   ```

The firewall scores every request it receives against the rule set.

A body that omits `mode` is refused with `400`:

```json
{"errors":[{"code":"10059","title":"Required Field","detail":"This field is required.","status":"400","source":{"pointer":"/data/behaviors/0/attributes/mode"}}]}
```

The field takes `logging` or `blocking`. Any other value answers `400` with `10039 Invalid Choice`.

A new rule takes minutes to reach Azion's distributed infrastructure. Until it has, a request can still be answered the way it was before the rule existed.

---

## Next steps

- [WAF Rule Sets](/en/documentation/platform/firewall/waf/rules-set.md): The fields of a rule set, the eight threat families, and the five sensitivity levels.
- [Scoring and modes](/en/documentation/platform/firewall/waf/scoring-and-modes.md): How a score is built, what a sensitivity costs, and what each mode does.
- [Tune a WAF rule set](/en/documentation/guides/application-security/firewall-and-waf/tune-waf.md): Read what the rule set matched and turn a false positive into an exception.
- [Firewall best practices](/en/documentation/platform/firewall/best-practices.md#waf): When to move a rule set from Logging to Blocking, and how far to raise a family.
