Skip to content

Commit

Permalink
Merge pull request #1794 from kroosec/custom-error-responses
Browse files Browse the repository at this point in the history
Add support for rulesets custom error responses
  • Loading branch information
jacobbednarz authored Aug 8, 2022
2 parents 1ce776c + cae0c75 commit 809d353
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/1794.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/cloudflare_ruleset: add support and configuration for `serve_errors` action
```
23 changes: 23 additions & 0 deletions docs/resources/ruleset.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,26 @@ resource "cloudflare_ruleset" "redirect_from_value_example" {
enabled = true
}
}
# Serve some custom error response
resource "cloudflare_ruleset" "http_custom_error_example" {
zone_id = "0da42c8d2132a9ddaf714f9e7c920711"
name = "Serve some error response"
description = "Serve some error response"
kind = "zone"
phase = "http_custom_errors"
rules {
action = "serve_error"
action_parameters {
content = "some error html"
content_type = "text/html"
status_code = "530"
}
expression = "(http.request.uri.path matches \"^/api/\")"
description = "serve some error response"
enabled = true
}
}
```

<!-- schema generated by tfplugindocs -->
Expand Down Expand Up @@ -432,6 +452,8 @@ Optional:
- `browser_ttl` (Block List, Max: 1) List of browser TTL parameters to apply to the request. (see [below for nested schema](#nestedblock--rules--action_parameters--browser_ttl))
- `cache` (Boolean) Whether to cache if expression matches.
- `cache_key` (Block List, Max: 1) List of cache key parameters to apply to the request. (see [below for nested schema](#nestedblock--rules--action_parameters--cache_key))
- `content` (String) Content of the custom error response.
- `content_type` (String) Content-Type of the custom error response.
- `cookie_fields` (Set of String) List of cookie values to include as part of custom fields logging.
- `edge_ttl` (Block List, Max: 1) List of edge TTL parameters to apply to the request. (see [below for nested schema](#nestedblock--rules--action_parameters--edge_ttl))
- `from_list` (Block List, Max: 1) Use a list to lookup information for the action. (see [below for nested schema](#nestedblock--rules--action_parameters--from_list))
Expand All @@ -455,6 +477,7 @@ Optional:
- `rulesets` (Set of String) List of managed WAF rule IDs to target. Only valid when the `"action"` is set to skip.
- `serve_stale` (Block List, Max: 1) List of serve stale parameters to apply to the request. (see [below for nested schema](#nestedblock--rules--action_parameters--serve_stale))
- `sni` (Block List, Max: 1) List of properties to manange Server Name Indication. (see [below for nested schema](#nestedblock--rules--action_parameters--sni))
- `status_code` (Number) HTTP status code of the custom error response.
- `uri` (Block List, Max: 1) List of URI properties to configure for the ruleset rule when performing URL rewrite transformations. (see [below for nested schema](#nestedblock--rules--action_parameters--uri))
- `version` (String) Version of the ruleset to deploy.

Expand Down
20 changes: 20 additions & 0 deletions examples/resources/cloudflare_ruleset/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -343,3 +343,23 @@ resource "cloudflare_ruleset" "redirect_from_value_example" {
enabled = true
}
}

# Serve some custom error response
resource "cloudflare_ruleset" "http_custom_error_example" {
zone_id = "0da42c8d2132a9ddaf714f9e7c920711"
name = "Serve some error response"
description = "Serve some error response"
kind = "zone"
phase = "http_custom_errors"
rules {
action = "serve_error"
action_parameters {
content = "some error html"
content_type = "text/html"
status_code = "530"
}
expression = "(http.request.uri.path matches \"^/api/\")"
description = "serve some error response"
enabled = true
}
}
12 changes: 12 additions & 0 deletions internal/provider/resource_cloudflare_ruleset.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,9 @@ func buildStateFromRulesetRules(rules []cloudflare.RulesetRule) interface{} {
"origin_error_page_passthru": r.ActionParameters.OriginErrorPagePassthru,
"from_list": fromListFields,
"from_value": fromValueFields,
"content": r.ActionParameters.Content,
"content_type": r.ActionParameters.ContentType,
"status_code": r.ActionParameters.StatusCode,
})

rule["action_parameters"] = actionParameters
Expand Down Expand Up @@ -782,6 +785,15 @@ func buildRulesetRulesFromResource(d *schema.ResourceData) ([]cloudflare.Ruleset

rule.ActionParameters.Headers = headers

case "content":
rule.ActionParameters.Content = pValue.(string)

case "content_type":
rule.ActionParameters.ContentType = pValue.(string)

case "status_code":
rule.ActionParameters.StatusCode = uint16(pValue.(int))

case "host_header":
rule.ActionParameters.HostHeader = pValue.(string)

Expand Down
65 changes: 65 additions & 0 deletions internal/provider/resource_cloudflare_ruleset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,48 @@ func TestAccCloudflareRuleset_RateLimit(t *testing.T) {
})
}

func TestAccCloudflareRuleset_CustomErrors(t *testing.T) {
// Temporarily unset CLOUDFLARE_API_TOKEN if it is set as the WAF
// service does not yet support the API tokens and it results in
// misleading state error messages.
if os.Getenv("CLOUDFLARE_API_TOKEN") != "" {
defer func(apiToken string) {
os.Setenv("CLOUDFLARE_API_TOKEN", apiToken)
}(os.Getenv("CLOUDFLARE_API_TOKEN"))
os.Setenv("CLOUDFLARE_API_TOKEN", "")
}

t.Parallel()
rnd := generateRandomResourceName()
zoneID := os.Getenv("CLOUDFLARE_ZONE_ID")
zoneName := os.Getenv("CLOUDFLARE_DOMAIN")
resourceName := "cloudflare_ruleset." + rnd

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: testAccCheckCloudflareRulesetCustomErrors(rnd, "example HTTP custom error response", zoneID, zoneName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "example HTTP custom error response"),
resource.TestCheckResourceAttr(resourceName, "description", rnd+" ruleset description"),
resource.TestCheckResourceAttr(resourceName, "kind", "zone"),
resource.TestCheckResourceAttr(resourceName, "phase", "http_custom_errors"),

resource.TestCheckResourceAttr(resourceName, "rules.#", "1"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action", "serve_error"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.content", "my example error page"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.content_type", "text/plain"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.status_code", "530"),
resource.TestCheckResourceAttr(resourceName, "rules.0.expression", "(http.request.uri.path matches \"^/api/\")"),
resource.TestCheckResourceAttr(resourceName, "rules.0.description", "example http custom error response"),
),
},
},
})
}

func TestAccCloudflareRuleset_RequestOrigin(t *testing.T) {
// Temporarily unset CLOUDFLARE_API_TOKEN if it is set as the WAF
// service does not yet support the API tokens and it results in
Expand Down Expand Up @@ -2372,6 +2414,29 @@ func testAccCheckCloudflareRulesetManagedWAFPayloadLogging(rnd, name, zoneID, zo
}`, rnd, name, zoneID, zoneName)
}

func testAccCheckCloudflareRulesetCustomErrors(rnd, name, zoneID, zoneName string) string {
return fmt.Sprintf(`
resource "cloudflare_ruleset" "%[1]s" {
zone_id = "%[3]s"
name = "%[2]s"
description = "%[1]s ruleset description"
kind = "zone"
phase = "http_custom_errors"
rules {
action = "serve_error"
action_parameters {
content = "my example error page"
content_type = "text/plain"
status_code = "530"
}
expression = "(http.request.uri.path matches \"^/api/\")"
description = "example http custom error response"
enabled = true
}
}`, rnd, name, zoneID, zoneName)
}

func testAccCheckCloudflareRulesetOrigin(rnd, name, zoneID, zoneName string) string {
return fmt.Sprintf(`
resource "cloudflare_ruleset" "%[1]s" {
Expand Down
15 changes: 15 additions & 0 deletions internal/provider/schema_cloudflare_ruleset.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,21 @@ func resourceCloudflareRulesetSchema() map[string]*schema.Schema {
},
},
},
"content": {
Type: schema.TypeString,
Optional: true,
Description: "Content of the custom error response",
},
"content_type": {
Type: schema.TypeString,
Optional: true,
Description: "Content-Type of the custom error response",
},
"status_code": {
Type: schema.TypeInt,
Optional: true,
Description: "HTTP status code of the custom error response",
},
"host_header": {
Type: schema.TypeString,
Optional: true,
Expand Down

0 comments on commit 809d353

Please sign in to comment.