---
layout: "fastly"
page_title: "Fastly: ngwaf_workspace_rule"
sidebar_current: "docs-fastly-resource-ngwaf-workspace-rule"
description: |-
  Provides a Fastly Next-Gen WAF Workspace Rule
---

# fastly_ngwaf_workspace_rule

Provides a Fastly Next-Gen WAF Workspace Rule, scoped to a specific NGWAF workspace.  
These rules define conditions and actions that trigger WAF enforcement at the workspace level.

## Example Usage

Basic usage:

```terraform
resource "fastly_ngwaf_workspace" "example" {
  name                            = "example"
  description                     = "Test NGWAF Workspace"
  mode                            = "block"
  ip_anonymization                = "hashed"
  client_ip_headers               = ["X-Forwarded-For", "X-Real-IP"]
  default_blocking_response_code = 429

  attack_signal_thresholds {}
}

resource "fastly_ngwaf_workspace_rule" "example" {
  workspace_id    = fastly_ngwaf_workspace.example.id
  type            = "request"
  description     = "Block requests from specific IP to login path"
  enabled         = true
  request_logging = "sampled"
  group_operator  = "all"

  action {
    type = "block"
  }

  condition {
    field    = "ip"
    operator = "equals"
    value    = "192.0.2.1"
  }

  condition {
    field    = "path"
    operator = "equals"
    value    = "/login"
  }
}
```

Using templated signals:

```terraform
resource "fastly_ngwaf_workspace" "example" {
  name                            = "example"
  description                     = "Test NGWAF Workspace"
  mode                            = "block"
  ip_anonymization                = "hashed"
  client_ip_headers               = ["X-Forwarded-For", "X-Real-IP"]
  default_blocking_response_code = 429

  attack_signal_thresholds {}
}

resource "fastly_ngwaf_workspace_rule" "example" {
  workspace_id    = fastly_ngwaf_workspace.example.id
  type            = "request"
  description     = ""
  enabled         = true
  group_operator  = "all"

  condition {
    field    = "method"
    operator = "equals"
    value    = "POST"
  }

  condition {
    field    = "path"
    operator = "equals"
    value    = "/login"
  }

  action {
    type   = "templated_signal"
    signal = "LOGINATTEMPT"
  }
}
```

Using group conditions:

```terraform
resource "fastly_ngwaf_workspace" "example" {
  name                            = "example"
  description                     = "Test NGWAF Workspace"
  mode                            = "block"
  ip_anonymization                = "hashed"
  client_ip_headers               = ["X-Forwarded-For", "X-Real-IP"]
  default_blocking_response_code = 429

  attack_signal_thresholds {}
}

resource "fastly_ngwaf_workspace_rule" "example" {
  workspace_id    = fastly_ngwaf_workspace.example.id
  type            = "request"
  description     = "Block requests with grouped conditions"
  enabled         = true
  request_logging = "sampled"
  group_operator  = "all"

  action {
    type = "block"
  }

  # This group uses "any" - matches if 'any' condition is true
  group_condition {
    group_operator = "any"

    condition {
      field    = "protocol_version"
      operator = "equals"
      value    = "HTTP/1.0"
    }

    condition {
      field    = "method"
      operator = "equals"
      value    = "HEAD"
    }

    condition {
      field    = "domain"
      operator = "equals"
      value    = "example.com"
    }
  }

  # This group uses "all" - matches only if 'all' conditions are true
  group_condition {
    group_operator = "all"

    condition {
      field    = "country"
      operator = "equals"
      value    = "AD"
    }

    condition {
      field    = "method"
      operator = "equals"
      value    = "POST"
    }
  }
}
```

Using multival conditions:

```terraform
resource "fastly_ngwaf_workspace" "example" {
  name                            = "example"
  description                     = "Test NGWAF Workspace"
  mode                            = "block"
  ip_anonymization                = "hashed"
  client_ip_headers               = ["X-Forwarded-For", "X-Real-IP"]
  default_blocking_response_code = 429

  attack_signal_thresholds {}
}

resource "fastly_ngwaf_workspace_rule" "example" {
  workspace_id    = fastly_ngwaf_workspace.example.id
  type            = "request"
  description     = "Block requests with specific header patterns"
  enabled         = true
  request_logging = "sampled"
  group_operator  = "all"

  action {
    type = "block"
  }

  multival_condition {
    field          = "request_header"
    operator       = "exists"
    group_operator = "any"

    condition {
      field    = "name"
      operator = "does_not_equal"
      value    = "Header-Sample"
    }

    condition {
      field    = "name"
      operator = "contains"
      value    = "X-API-Key"
    }
    
    condition {
      field    = "value_string"
      operator = "equals"
      value    = "application/json"
    }
  }
}
```

Using rate limits:

```terraform
resource "fastly_ngwaf_workspace" "example" {
  name                            = "example"
  description                     = "Test NGWAF Workspace"
  mode                            = "block"
  ip_anonymization                = "hashed"
  client_ip_headers               = ["X-Forwarded-For", "X-Real-IP"]
  default_blocking_response_code = 429

  attack_signal_thresholds {}
}


resource "fastly_ngwaf_workspace_signal" "demo_signal" {
  workspace_id = fastly_ngwaf_workspace.example.id
  name         = "demo"
  description  = "A description of my signal."
}

resource "fastly_ngwaf_workspace_rule" "ip_limit" {
  workspace_id    = fastly_ngwaf_workspace.example.id
  type            = "rate_limit"
  description     = "Rate limit demo rule-updated"
  enabled         = true

  condition {
    field = "ip"
    operator = "equals"
    value = "1.2.3.4"
  }

  rate_limit {
    signal    = "site.demo"
    threshold = 100
    interval  = 60
    duration  = 300

    client_identifiers {
      type = "ip"
    }
  }

  action {
    signal = "SUSPECTED-BOT"
    type = "block_signal"
  }
}
```

Using signal exclusions:

```terraform
resource "fastly_ngwaf_workspace" "example" {
  name                            = "example"
  description                     = "Test NGWAF Workspace"
  mode                            = "block"
  ip_anonymization                = "hashed"
  client_ip_headers               = ["X-Forwarded-For", "X-Real-IP"]
  default_blocking_response_code = 429

  attack_signal_thresholds {}
}

resource "fastly_ngwaf_workspace_rule" "exclude_xss_signal" {
  workspace_id    = fastly_ngwaf_workspace.example.id
  type            = "signal"
  description     = "Exclude XSS signal to address a false positive"
  enabled         = true
  group_operator  = "all"

  condition {
    field    = "path"
    operator = "like"
    value    = "/contact-form"
  }
  action {
    type   = "exclude_signal"
    signal = "XSS"
  }
}
``` 

## Import

Fastly Next-Gen WAF workspace rules can be imported using the format `<workspaceID>/<ruleID>`, e.g.:

```sh
$ terraform import fastly_ngwaf_workspace_rule.demo <workspaceID>/<ruleID>
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `action` (Block List, Min: 1) List of actions to perform when the rule matches. (see [below for nested schema](#nestedblock--action))
- `description` (String) The description of the rule.
- `enabled` (Boolean) Whether the rule is currently enabled.
- `type` (String) The type of the rule. Accepted values are `request`, `signal`, `rate_limit`, and `templated_signal`.
- `workspace_id` (String) The ID of the workspace.

### Optional

- `condition` (Block List) Flat list of individual conditions. Each must include `field`, `operator`, and `value`. (see [below for nested schema](#nestedblock--condition))
- `group_condition` (Block List) List of grouped conditions with nested logic. Each group must define a `group_operator` and at least one condition or multival_condition. (see [below for nested schema](#nestedblock--group_condition))
- `group_operator` (String) Logical operator to apply to group conditions. Accepted values are `any` and `all`.
- `multival_condition` (Block List) List of multival conditions with nested logic. Each multival list must define a `field, operator, group_operator` and at least one condition. (see [below for nested schema](#nestedblock--multival_condition))
- `rate_limit` (Block List, Max: 1) Block specifically for rate_limit rules. (see [below for nested schema](#nestedblock--rate_limit))
- `request_logging` (String) Logging behavior for matching requests. Accepted values are `sampled` and `none`.

### Read-Only

- `id` (String) The ID of this resource.

<a id="nestedblock--action"></a>
### Nested Schema for `action`

Required:

- `type` (String) The action type. One of: `add_signal`, `allow`, `block`, `browser_challenge`, `dynamic_challenge`, `exclude_signal`, `verify_token` or for rate limit rule valid values: `log_request`, `block_signal`, `browser_challenge`, `verify_token`

Optional:

- `allow_interactive` (Boolean) Specifies if interaction is allowed (used when `type = browser_challenge`).
- `deception_type` (String) specifies the type of deception (used when `type = deception`).
- `redirect_url` (String) Redirect target (used when `type = redirect`).
- `response_code` (Number) Response code used with redirect.
- `signal` (String) Signal name to exclude (used when `type = exclude_signal`).


<a id="nestedblock--condition"></a>
### Nested Schema for `condition`

Required:

- `field` (String) Field to inspect (e.g., `ip`, `path`).
- `operator` (String) Operator to apply. One of: `equals`, `does_not_equal`, `contains`, `does_not_contain`, `like`, `not_like`, `in_list`, `not_in_list`, `matches`, `does_not_match`, `greater_equal`, `lesser_equal`.
- `value` (String) The value to test the field against.


<a id="nestedblock--group_condition"></a>
### Nested Schema for `group_condition`

Required:

- `group_operator` (String) Logical operator for the group. Accepted values are `any` and `all`.

Optional:

- `condition` (Block List) A list of nested conditions in this group. (see [below for nested schema](#nestedblock--group_condition--condition))
- `multival_condition` (Block List) List of nested multival conditions in this group. Each multival list must define a `field, operator, group_operator` and at least one condition. (see [below for nested schema](#nestedblock--group_condition--multival_condition))

<a id="nestedblock--group_condition--condition"></a>
### Nested Schema for `group_condition.condition`

Required:

- `field` (String) Field to inspect (e.g., `ip`, `path`).
- `operator` (String) Operator to apply. One of: `equals`, `does_not_equal`, `contains`, `does_not_contain`, `like`, `not_like`, `in_list`, `not_in_list`, `matches`, `does_not_match`, `greater_equal`, `lesser_equal`.
- `value` (String) The value to test the field against.


<a id="nestedblock--group_condition--multival_condition"></a>
### Nested Schema for `group_condition.multival_condition`

Required:

- `condition` (Block List, Min: 1) A list of nested conditions in this multival. (see [below for nested schema](#nestedblock--group_condition--multival_condition--condition))
- `field` (String) Enums for multival condition field. Accepted values are `post_parameter`, `query_parameter`, `request_cookie`, `request_header`, `response_header`, and `signal`.
- `group_operator` (String) Logical operator for the multival condition. Accepted values are `any` and `all`.
- `operator` (String) Indicates whether the supplied conditions will check for existence or non-existence of matching field values. Accepted values are `exists` and `does_not_exist`.

<a id="nestedblock--group_condition--multival_condition--condition"></a>
### Nested Schema for `group_condition.multival_condition.condition`

Required:

- `field` (String) Field to inspect (e.g., `name`, `value`, `signal_id`).
- `operator` (String) Operator to apply (e.g., `equals`, `contains`).
- `value` (String) The value to test the field against.




<a id="nestedblock--multival_condition"></a>
### Nested Schema for `multival_condition`

Required:

- `condition` (Block List, Min: 1) A list of nested conditions in this list. (see [below for nested schema](#nestedblock--multival_condition--condition))
- `field` (String) Enums for multival condition field.. Accepted values are `post_parameter`, `query_parameter`, `request_cookie`, `request_header`, `response_header`, and `signal`.
- `group_operator` (String) Logical operator for the group. Accepted values are `any` and `all`.
- `operator` (String) Indicates whether the supplied conditions will check for existence or non-existence of matching field values. Accepted values are `exists` and `does_not_exist`.

<a id="nestedblock--multival_condition--condition"></a>
### Nested Schema for `multival_condition.condition`

Required:

- `field` (String) Field to inspect (e.g., `name`, `value`, `signal_id`).
- `operator` (String) Operator to apply. One of: `equals`, `does_not_equal`, `contains`, `does_not_contain`, `like`, `not_like`, `in_list`, `not_in_list`, `matches`, `does_not_match`, `greater_equal`, `lesser_equal`.
- `value` (String) The value to test the field against.



<a id="nestedblock--rate_limit"></a>
### Nested Schema for `rate_limit`

Required:

- `client_identifiers` (Block Set, Min: 1) List of client identifiers used for rate limiting. Can only be length 1 or 2. (see [below for nested schema](#nestedblock--rate_limit--client_identifiers))
- `duration` (Number) Duration in seconds for the rate limit.
- `interval` (Number) Time interval for the rate limit in seconds. Accepted values are 60, 600, and 3600.
- `signal` (String) Reference ID of the custom signal this rule uses to count requests.
- `threshold` (Number) Rate limit threshold. Minimum 1 and maximum 100,000.

<a id="nestedblock--rate_limit--client_identifiers"></a>
### Nested Schema for `rate_limit.client_identifiers`

Required:

- `type` (String) Type of the Client Identifier. Accepted values are `ip`, `post_parameter`, `request_cookie`, `request_header`, and `signal_payload`.

Optional:

- `key` (String) Key for the Client Identifier.
- `name` (String) Name for the Client Identifier.
