Skip to content

Commit

Permalink
^ This is a combination of 2 commits.
Browse files Browse the repository at this point in the history
^ This is the 1st commit message:

ruleset: add support for URI header transformations

fdwfd

^ The commit message #2 will be skipped:

^ fdwfd
  • Loading branch information
jacobbednarz committed Aug 27, 2021
1 parent f052274 commit 3b49160
Show file tree
Hide file tree
Showing 3 changed files with 295 additions and 0 deletions.
26 changes: 26 additions & 0 deletions cloudflare/resource_cloudflare_ruleset.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,13 @@ func resourceCloudflareRuleset() *schema.Resource {
"uri": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"path": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"value": {
Expand All @@ -130,6 +132,7 @@ func resourceCloudflareRuleset() *schema.Resource {
"query": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"value": {
Expand Down Expand Up @@ -456,6 +459,29 @@ func buildRulesetRulesFromResource(r interface{}) ([]cloudflare.RulesetRule, err
}
}

case "uri":
for _, uriValue := range pValue.([]interface{}) {
if val, ok := uriValue.(map[string]interface{})["path"]; ok && len(val.([]interface{})) > 0 {
uriPathConfig := val.([]interface{})[0].(map[string]interface{})
rule.ActionParameters.URI = &cloudflare.RulesetRuleActionParametersURI{
Path: &cloudflare.RulesetRuleActionParametersURIPath{
Value: uriPathConfig["value"].(string),
Expression: uriPathConfig["expression"].(string),
},
}
}

if val, ok := uriValue.(map[string]interface{})["query"]; ok && len(val.([]interface{})) > 0 {
uriQueryConfig := val.([]interface{})[0].(map[string]interface{})
rule.ActionParameters.URI = &cloudflare.RulesetRuleActionParametersURI{
Query: &cloudflare.RulesetRuleActionParametersURIQuery{
Value: uriQueryConfig["value"].(string),
Expression: uriQueryConfig["expression"].(string),
},
}
}
}

default:
log.Printf("[DEBUG] unknown key encountered in buildRulesetRulesFromResource for action parameters: %s", pKey)
}
Expand Down
187 changes: 187 additions & 0 deletions cloudflare/resource_cloudflare_ruleset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,104 @@ func TestAccCloudflareRuleset_MagicTransitUpdateWithHigherPriority(t *testing.T)
})
}

func TestAccCloudflareRuleset_TransformationRuleURIPath(t *testing.T) {
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) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckCloudflareRulesetTransformationRuleURIPath(rnd, "transform rule for URI path", zoneID, zoneName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "transform rule for URI path"),
resource.TestCheckResourceAttr(resourceName, "description", rnd+" ruleset description"),
resource.TestCheckResourceAttr(resourceName, "kind", "zone"),
resource.TestCheckResourceAttr(resourceName, "phase", "http_request_transform"),

resource.TestCheckResourceAttr(resourceName, "rules.#", "1"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action", "rewrite"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.uri.#", "1"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.uri.0.path.0.value", "/static-rewrite"),
),
},
},
})
}

func TestAccCloudflareRuleset_TransformationRuleURIQuery(t *testing.T) {
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) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckCloudflareRulesetTransformationRuleURIQuery(rnd, "transform rule for URI query", zoneID, zoneName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "transform rule for URI query"),
resource.TestCheckResourceAttr(resourceName, "description", rnd+" ruleset description"),
resource.TestCheckResourceAttr(resourceName, "kind", "zone"),
resource.TestCheckResourceAttr(resourceName, "phase", "http_request_transform"),

resource.TestCheckResourceAttr(resourceName, "rules.#", "1"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action", "rewrite"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.uri.#", "1"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.uri.0.query.0.value", "a=b"),
),
},
},
})
}

func TestAccCloudflareRuleset_TransformationRuleHeaders(t *testing.T) {
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) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckCloudflareRulesetTransformationRuleHeaders(rnd, "transform rule for headers", zoneID, zoneName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "transform rule for headers"),
resource.TestCheckResourceAttr(resourceName, "description", rnd+" ruleset description"),
resource.TestCheckResourceAttr(resourceName, "kind", "zone"),
resource.TestCheckResourceAttr(resourceName, "phase", "http_request_late_transform"),

resource.TestCheckResourceAttr(resourceName, "rules.#", "1"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action", "rewrite"),

resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.headers.#", "3"),

resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.headers.0.name", "example1"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.headers.0.value", "my-http-header-value1"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.headers.0.operation", "set"),

resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.headers.1.name", "example2"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.headers.1.operation", "set"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.headers.1.expression", "cf.zone.name"),

resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.headers.2.name", "example3"),
resource.TestCheckResourceAttr(resourceName, "rules.0.action_parameters.0.headers.2.operation", "remove"),
),
},
},
})
}

func testAccCheckCloudflareRulesetMagicTransitSingle(rnd, name, accountID string) string {
return fmt.Sprintf(`
resource "cloudflare_ruleset" "%[1]s" {
Expand Down Expand Up @@ -978,3 +1076,92 @@ func testAccCheckCloudflareRulesetManagedWAFWithIDBasedOverrides(rnd, name, zone
}
}`, rnd, name, zoneID, zoneName)
}

func testAccCheckCloudflareRulesetTransformationRuleURIPath(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_request_transform"
rules {
action = "rewrite"
action_parameters {
uri {
path {
value = "/static-rewrite"
}
}
}
expression = "(http.host eq \"%[4]s\")"
description = "URI transformation path example"
enabled = false
}
}`, rnd, name, zoneID, zoneName)
}

func testAccCheckCloudflareRulesetTransformationRuleURIQuery(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_request_transform"
rules {
action = "rewrite"
action_parameters {
uri {
query {
value = "a=b"
}
}
}
expression = "(http.host eq \"%[4]s\")"
description = "URI transformation query example"
enabled = false
}
}`, rnd, name, zoneID, zoneName)
}

func testAccCheckCloudflareRulesetTransformationRuleHeaders(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_request_late_transform"
rules {
action = "rewrite"
action_parameters {
headers {
name = "example1"
operation = "set"
value = "my-http-header-value1"
}
headers {
name = "example2"
operation = "set"
expression = "cf.zone.name"
}
headers {
name = "example3"
operation = "remove"
}
}
expression = "true"
description = "example header transformation rule"
enabled = false
}
}`, rnd, name, zoneID, zoneName)
}
82 changes: 82 additions & 0 deletions website/docs/r/ruleset.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,88 @@ resource "cloudflare_ruleset" "zone_level_managed_waf_with_category_based_overri
enabled = false
}
}
# Rewrite the URI path component to a static path
resource "cloudflare_ruleset" "transform_uri_rule_path" {
zone_id = "cb029e245cfdd66dc8d2e570d5dd3322"
name = "transformation rule for URI path"
description = "change the URI path to a new static path"
kind = "zone"
phase = "http_request_transform"
rules {
action = "rewrite"
action_parameters {
uri {
path {
value = "/my-new-route"
}
}
}
expression = "(http.host eq \"example.com\" and http.uri.path eq \"/old-path\")"
description = "URI transformation path example"
enabled = true
}
}
# Rewrite the URI query component to a static query
resource "cloudflare_ruleset" "transform_uri_rule_query" {
zone_id = "cb029e245cfdd66dc8d2e570d5dd3322"
name = "transformation rule for URI query parameter"
description = "change the URI query to a new static query"
kind = "zone"
phase = "http_request_transform"
rules {
action = "rewrite"
action_parameters {
uri {
query {
value = "old=new_again"
}
}
}
expression = "true"
description = "URI transformation query example"
enabled = true
}
}
# Rewrite HTTP headers to a modified values
resource "cloudflare_ruleset" "transform_uri_http_headers" {
zone_id = "cb029e245cfdd66dc8d2e570d5dd3322"
name = "transformation rule for HTTP headers"
description = "modify HTTP headers before reaching origin"
kind = "zone"
phase = "http_request_late_transform"
rules {
action = "rewrite"
action_parameters {
headers {
name = "example-http-header-1"
operation = "set"
value = "my-http-header-value-1"
}
headers {
name = "example-http-header-2"
operation = "set"
expression = "cf.zone.name"
}
headers {
name = "example-http-header-3-to-remove"
operation = "remove"
}
expression = "true"
description = "example header transformation rule"
enabled = false
}
}
```

## Argument Reference
Expand Down

0 comments on commit 3b49160

Please sign in to comment.