Defines a set of Web Application Firewall configuration options that can be used to populate a service WAF. This resource will configure rules, thresholds and other settings for a WAF.
Basic usage:
resource "fastly_service_vcl" "demo" {
name = "demofastly"
domain {
name = "example.com"
comment = "demo"
}
backend {
address = "127.0.0.1"
name = "origin1"
port = 80
}
condition {
name = "WAF_Prefetch"
type = "PREFETCH"
statement = "req.backend.is_origin"
}
# This condition will always be false
# adding it to the response object created below
# prevents Fastly from returning a 403 on all of your traffic.
condition {
name = "WAF_always_false"
statement = "false"
type = "REQUEST"
}
response_object {
name = "WAF_Response"
status = "403"
response = "Forbidden"
content_type = "text/html"
content = "<html><body>Forbidden</body></html>"
request_condition = "WAF_always_false"
}
waf {
prefetch_condition = "WAF_Prefetch"
response_object = "WAF_Response"
}
force_destroy = true
}
resource "fastly_service_waf_configuration" "waf" {
waf_id = fastly_service_vcl.demo.waf[0].waf_id
http_violation_score_threshold = 100
}
Usage with rules:
resource "fastly_service_vcl" "demo" {
name = "demofastly"
domain {
name = "example.com"
comment = "demo"
}
backend {
address = "127.0.0.1"
name = "origin1"
port = 80
}
condition {
name = "WAF_Prefetch"
type = "PREFETCH"
statement = "req.backend.is_origin"
}
# This condition will always be false
# adding it to the response object created below
# prevents Fastly from returning a 403 on all of your traffic.
condition {
name = "WAF_always_false"
statement = "false"
type = "REQUEST"
}
response_object {
name = "WAF_Response"
status = "403"
response = "Forbidden"
content_type = "text/html"
content = "<html><body>Forbidden</body></html>"
request_condition = "WAF_always_false"
}
waf {
prefetch_condition = "WAF_Prefetch"
response_object = "WAF_Response"
}
force_destroy = true
}
resource "fastly_service_waf_configuration" "waf" {
waf_id = fastly_service_vcl.demo.waf[0].waf_id
http_violation_score_threshold = 100
rule {
modsec_rule_id = 1010090
revision = 1
status = "log"
}
}
Usage with rule exclusions:
resource "fastly_service_vcl" "demo" {
name = "demofastly"
domain {
name = "example.com"
comment = "demo"
}
backend {
address = "127.0.0.1"
name = "origin1"
port = 80
}
condition {
name = "WAF_Prefetch"
type = "PREFETCH"
statement = "req.backend.is_origin"
}
# This condition will always be false
# adding it to the response object created below
# prevents Fastly from returning a 403 on all of your traffic.
condition {
name = "WAF_always_false"
statement = "false"
type = "REQUEST"
}
response_object {
name = "WAF_Response"
status = "403"
response = "Forbidden"
content_type = "text/html"
content = "<html><body>Forbidden</body></html>"
request_condition = "WAF_always_false"
}
waf {
prefetch_condition = "WAF_Prefetch"
response_object = "WAF_Response"
}
force_destroy = true
}
resource "fastly_service_waf_configuration" "waf" {
waf_id = fastly_service_vcl.demo.waf[0].waf_id
http_violation_score_threshold = 100
rule {
modsec_rule_id = 2029718
revision = 1
status = "log"
}
rule_exclusion {
name = "index page"
exclusion_type = "rule"
condition = "req.url.basename == \"index.html\""
modsec_rule_ids = [2029718]
}
}
Usage with rules from data source:
variable "type_status" {
type = map(string)
default = {
score = "score"
threshold = "log"
strict = "log"
}
}
resource "fastly_service_vcl" "demo" {
name = "demofastly"
domain {
name = "example.com"
comment = "demo"
}
backend {
address = "127.0.0.1"
name = "origin1"
port = 80
}
condition {
name = "WAF_Prefetch"
type = "PREFETCH"
statement = "req.backend.is_origin"
}
# This condition will always be false
# adding it to the response object created below
# prevents Fastly from returning a 403 on all of your traffic.
condition {
name = "WAF_always_false"
statement = "false"
type = "REQUEST"
}
response_object {
name = "WAF_Response"
status = "403"
response = "Forbidden"
content_type = "text/html"
content = "<html><body>Forbidden</body></html>"
request_condition = "WAF_always_false"
}
waf {
prefetch_condition = "WAF_Prefetch"
response_object = "WAF_Response"
}
force_destroy = true
}
data "fastly_waf_rules" "owasp" {
publishers = ["owasp"]
}
resource "fastly_service_waf_configuration" "waf" {
waf_id = fastly_service_vcl.demo.waf[0].waf_id
http_violation_score_threshold = 100
dynamic "rule" {
for_each = data.fastly_waf_rules.owasp.rules
content {
modsec_rule_id = rule.value.modsec_rule_id
revision = rule.value.latest_revision_number
status = lookup(var.type_status, rule.value.type, "log")
}
}
}
Usage with support for individual rule configuration (this is the suggested pattern):
# this variable is used for rule configuration in bulk
variable "type_status" {
type = map(string)
default = {
score = "score"
threshold = "log"
strict = "log"
}
}
# this variable is used for individual rule configuration
variable "individual_rules" {
type = map(string)
default = {
1010020 = "block"
}
}
resource "fastly_service_vcl" "demo" {
name = "demofastly"
domain {
name = "example.com"
comment = "demo"
}
backend {
address = "127.0.0.1"
name = "origin1"
port = 80
}
condition {
name = "WAF_Prefetch"
type = "PREFETCH"
statement = "req.backend.is_origin"
}
# This condition will always be false
# adding it to the response object created below
# prevents Fastly from returning a 403 on all of your traffic.
condition {
name = "WAF_always_false"
statement = "false"
type = "REQUEST"
}
response_object {
name = "WAF_Response"
status = "403"
response = "Forbidden"
content_type = "text/html"
content = "<html><body>Forbidden</body></html>"
request_condition = "WAF_always_false"
}
waf {
prefetch_condition = "WAF_Prefetch"
response_object = "WAF_Response"
}
force_destroy = true
}
data "fastly_waf_rules" "owasp" {
publishers = ["owasp"]
}
resource "fastly_service_waf_configuration" "waf" {
waf_id = fastly_service_vcl.demo.waf[0].waf_id
http_violation_score_threshold = 202
dynamic "rule" {
for_each = data.fastly_waf_rules.owasp.rules
content {
modsec_rule_id = rule.value.modsec_rule_id
revision = rule.value.latest_revision_number
# Nested lookups in order to apply a combination of in bulk and individual rule configuration.
status = lookup(var.individual_rules, rule.value.modsec_rule_id, lookup(var.type_status, rule.value.type, "log"))
}
}
}
Usage with support for specific rule revision configuration:
# this variable is used for rule configuration in bulk
variable "type_status" {
type = map(string)
default = {
score = "score"
threshold = "log"
strict = "log"
}
}
# This variable is used for individual rule revision configuration.
variable "specific_rule_revisions" {
type = map(string)
default = {
# If the revision requested is not found, the server will return a 404 response code.
1010020 = 1
}
}
resource "fastly_service_vcl" "demo" {
name = "demofastly"
domain {
name = "example.com"
comment = "demo"
}
backend {
address = "127.0.0.1"
name = "origin1"
port = 80
}
condition {
name = "WAF_Prefetch"
type = "PREFETCH"
statement = "req.backend.is_origin"
}
# This condition will always be false
# adding it to the response object created below
# prevents Fastly from returning a 403 on all of your traffic.
condition {
name = "WAF_always_false"
statement = "false"
type = "REQUEST"
}
response_object {
name = "WAF_Response"
status = "403"
response = "Forbidden"
content_type = "text/html"
content = "<html><body>Forbidden</body></html>"
request_condition = "WAF_always_false"
}
waf {
prefetch_condition = "WAF_Prefetch"
response_object = "WAF_Response"
}
force_destroy = true
}
data "fastly_waf_rules" "owasp" {
publishers = ["owasp"]
}
resource "fastly_service_waf_configuration" "waf" {
waf_id = fastly_service_vcl.demo.waf[0].waf_id
http_violation_score_threshold = 202
dynamic "rule" {
for_each = data.fastly_waf_rules.owasp.rules
content {
modsec_rule_id = rule.value.modsec_rule_id
revision = lookup(var.specific_rule_revisions, rule.value.modsec_rule_id, rule.value.latest_revision_number)
status = lookup(var.type_status, rule.value.type, "log")
}
}
}
Usage omitting rule revision field. The first time Terraform is applied, the latest rule revisions are associated with the WAF. Any subsequent apply would not alter the rule revisions.
# This variable is used for rule configuration in bulk.
variable "type_status" {
type = map(string)
default = {
score = "score"
threshold = "log"
strict = "log"
}
}
# This variable is used for individual rule configuration.
variable "individual_rules" {
type = map(string)
default = {
1010020 = "block"
}
}
resource "fastly_service_vcl" "demo" {
name = "demofastly"
domain {
name = "example.com"
comment = "demo"
}
backend {
address = "127.0.0.1"
name = "origin1"
port = 80
}
condition {
name = "WAF_Prefetch"
type = "PREFETCH"
statement = "req.backend.is_origin"
}
# This condition will always be false
# adding it to the response object created below
# prevents Fastly from returning a 403 on all of your traffic.
condition {
name = "WAF_always_false"
statement = "false"
type = "REQUEST"
}
response_object {
name = "WAF_Response"
status = "403"
response = "Forbidden"
content_type = "text/html"
content = "<html><body>Forbidden</body></html>"
request_condition = "WAF_always_false"
}
waf {
prefetch_condition = "WAF_Prefetch"
response_object = "WAF_Response"
}
force_destroy = true
}
data "fastly_waf_rules" "owasp" {
publishers = ["owasp"]
}
resource "fastly_service_waf_configuration" "waf" {
waf_id = fastly_service_vcl.demo.waf[0].waf_id
http_violation_score_threshold = 202
dynamic "rule" {
for_each = data.fastly_waf_rules.owasp.rules
content {
modsec_rule_id = rule.value.modsec_rule_id
# Rule revision field ommitted.
status = lookup(var.individual_rules, rule.value.modsec_rule_id, lookup(var.type_status, rule.value.type, "log"))
}
}
}
# This output contains the WAF's active rules set. This can be useful for identifying which revision is active for each WAF rule.
output "rules" {
value = fastly_service_waf_configuration.waf.rule
}
When adding a waf
to an existing fastly_service_vcl
and at the same time adding a fastly_service_waf_configuration
resource with waf_id = fastly_service_vcl.demo.waf[0].waf_id
might result with the in the following error:
fastly_service_vcl.demo.waf is empty list of object
For this scenario, it's recommended to split the changes into two distinct steps:
waf
block to the fastly_service_vcl
and apply the changesfastly_service_waf_configuration
to the HCL and apply the changesThis is an example of the import command being applied to the resource named fastly_service_waf_configuration.waf
The resource ID should be the WAF ID.
$ terraform import fastly_service_waf_configuration.waf xxxxxxxxxxxxxxxxxxxx
If Terraform is already managing a remote WAF configurations against a resource being imported then the user will be asked to remove it from the existing Terraform state.
The following is an example of the Terraform state command to remove the resource named fastly_service_waf_configuration.waf
from the Terraform state file.
$ terraform state rm fastly_service_waf_configuration.waf
waf_id
(String) The ID of the Web Application Firewall that the configuration belongs toactivate
(Boolean) Conditionally prevents a new firewall version from being activated. The apply step will continue to create a new draft version but will not activate it if this is set to false
. Default true
allowed_http_versions
(String) Allowed HTTP versionsallowed_methods
(String) A space-separated list of HTTP method namesallowed_request_content_type
(String) Allowed request content typesallowed_request_content_type_charset
(String) Allowed request content type charsetarg_length
(Number) The maximum number of arguments allowedarg_name_length
(Number) The maximum allowed argument name lengthcombined_file_sizes
(Number) The maximum allowed size of all filescritical_anomaly_score
(Number) Score value to add for critical anomaliescrs_validate_utf8_encoding
(Boolean) CRS validate UTF8 encodingerror_anomaly_score
(Number) Score value to add for error anomalieshigh_risk_country_codes
(String) A space-separated list of country codes in ISO 3166-1 (two-letter) formathttp_violation_score_threshold
(Number) HTTP violation thresholdinbound_anomaly_score_threshold
(Number) Inbound anomaly thresholdlfi_score_threshold
(Number) Local file inclusion attack thresholdmax_file_size
(Number) The maximum allowed file size, in bytesmax_num_args
(Number) The maximum number of arguments allowednotice_anomaly_score
(Number) Score value to add for notice anomaliesparanoia_level
(Number) The configured paranoia levelphp_injection_score_threshold
(Number) PHP injection thresholdrce_score_threshold
(Number) Remote code execution thresholdrestricted_extensions
(String) A space-separated list of allowed file extensionsrestricted_headers
(String) A space-separated list of allowed header namesrfi_score_threshold
(Number) Remote file inclusion attack thresholdrule
(Block Set) (see below for nested schema)rule_exclusion
(Block Set) (see below for nested schema)session_fixation_score_threshold
(Number) Session fixation attack thresholdsql_injection_score_threshold
(Number) SQL injection attack thresholdtotal_arg_length
(Number) The maximum size of argument names and valueswarning_anomaly_score
(Number) Score value to add for warning anomaliesxss_score_threshold
(Number) XSS attack thresholdactive
(Boolean) Whether a specific firewall version is currently deployedcloned_version
(Number) The latest cloned firewall version by the providerid
(String) The ID of this resource.number
(Number) The WAF firewall versionrule
Required:
modsec_rule_id
(Number) The Web Application Firewall rule's modsecurity IDstatus
(String) The Web Application Firewall rule's status. Allowed values are (log
, block
and score
)Optional:
revision
(Number) The Web Application Firewall rule's revision. The latest revision will be used if this is not providedrule_exclusion
Required:
condition
(String) A conditional expression in VCL used to determine if the condition is metexclusion_type
(String) The type of rule exclusion. Values are rule
to exclude the specified rule(s), or waf
to disable the Web Application Firewallname
(String) The name of rule exclusionOptional:
modsec_rule_ids
(Set of Number) Set of modsecurity IDs to be excluded. No rules should be provided when exclusion_type
is waf
. The rules need to be configured on the Web Application Firewall to be excludedRead-Only:
number
(Number) The numeric ID assigned to the WAF Rule Exclusion