cloudflare / terraform-provider-cloudflare

Cloudflare Terraform Provider
https://registry.terraform.io/providers/cloudflare/cloudflare
Mozilla Public License 2.0
796 stars 616 forks source link

cloudflare_ruleset causing crash #4560

Open arunesh90 opened 1 week ago

arunesh90 commented 1 week ago

Confirmation

Terraform and Cloudflare provider version

Terraform v1.9.8
on darwin_arm64
+ provider registry.terraform.io/cloudflare/cloudflare v4.45.0
+ provider registry.terraform.io/hashicorp/aws v5.75.1
+ provider registry.terraform.io/integrations/github v6.3.1

Affected resource(s)

Terraform configuration files

resource "cloudflare_ruleset" "http_request_cache_settings" {
  count = var.environment == "production" ? 1 : 0

  zone_id = lookup(data.cloudflare_zones._.zones[0], "id")
  name    = "default"
  kind    = "zone"
  phase   = "http_request_cache_settings"

  rules {
    action      = "set_cache_settings"
    description = "caching"
    enabled     = true
    expression  = "(http.request.full_uri eq \"https://example.com/path1\")"
    action_parameters {
      cache = false
    }
  }

  rules {
    action      = "set_cache_settings"
    description = "caching2"
    enabled     = true
    expression  = "(http.host eq \"example.com\" and starts_with(http.request.uri.path, \"/path1\"))"
    action_parameters {
      cache = false
    }
  }

  rules {
    action      = "set_cache_settings"
    description = "caching3"
    enabled     = true
    expression  = "(http.host eq \"example.com\" and http.request.uri.path eq \"/path1\")"
    action_parameters {
      cache = false
    }
  }

  rules {
    action      = "set_cache_settings"
    description = "caching4"
    enabled     = true
    expression  = "(http.host eq \"example.com\" and http.request.uri.path eq \"/path1/path2\") or (http.host eq \"example.com\" and http.request.uri.path eq \"/path1/path2\")"
    action_parameters {
      cache = false
    }
  }

  rules {
    action      = "set_cache_settings"
    description = "Disable cache for tunneled instances used for testing/dev"
    enabled     = true
    expression  = "(http.host in {\"example.com\" \"example.com\"})"
    action_parameters {
      cache = false
      browser_ttl {
        mode = "bypass"
      }
    }
  }

  rules {
    action      = "set_cache_settings"
    description = "API cache"
    enabled     = true
    expression  = "(http.host in {\"example.com\" \"example.com\"} and http.request.uri.path matches \"^/path1/path2/path3\") or (http.host in {\"example.com\" \"example.com\"} and http.request.uri.path in {\"/path1/path2\"})"
    action_parameters {
      edge_ttl {
        mode = "respect_origin"
      }
      browser_ttl {
        mode = "respect_origin"
      }
    }
  }

  rules {
    action      = "set_cache_settings"
    description = "Homepage cache"
    enabled     = true
    expression  = "(http.host in {\"example1.com\" \"example2.com\"} and http.request.uri.path eq \"/\")"
    action_parameters {
      cache = true
    }
  }
}

Link to debug output

https://gist.github.com/arunesh90/63af12b26e8546d5f783fa24442ef7dc

Panic output

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xf65cb2]

goroutine 142 [running]:
github.com/cloudflare/terraform-provider-cloudflare/internal/framework/service/rulesets.toRulesetResourceModel({0x21060d8, 0xc000f68e70}, {0x70?, {0xc00060a680?, 0xc00060a160?}}, {0x20?, {0x0?, 0x0?}}, {{0xc000e85932, 0x20}, ...})
    github.com/cloudflare/terraform-provider-cloudflare/internal/framework/service/rulesets/resource.go:644 +0x3e32
github.com/cloudflare/terraform-provider-cloudflare/internal/framework/service/rulesets.(*RulesetResource).Read(0xc00103c000, {0x21060d8, 0xc000f68e70}, {{{{0x210e310, 0xc0012cfbc0}, {0x18d5c20, 0xc001b4b9b0}}, {0x2112df0, 0xc00155d540}}, 0xc001376018, ...}, ...)
    github.com/cloudflare/terraform-provider-cloudflare/internal/framework/service/rulesets/resource.go:209 +0x519
github.com/hashicorp/terraform-plugin-framework/internal/fwserver.(*Server).ReadResource(0xc000870000, {0x21060d8, 0xc000f68e70}, 0xc000f68ed0, 0xc000d8f578)
    github.com/hashicorp/terraform-plugin-framework@v1.12.0/internal/fwserver/server_readresource.go:117 +0x84e
github.com/hashicorp/terraform-plugin-framework/internal/proto6server.(*Server).ReadResource(0xc000870000, {0x21060d8?, 0xc000f68d80?}, 0xc0005cc2c0)
    github.com/hashicorp/terraform-plugin-framework@v1.12.0/internal/proto6server/server_readresource.go:55 +0x38e
github.com/hashicorp/terraform-plugin-mux/tf6muxserver.(*muxServer).ReadResource(0xc000ba24d0, {0x21060d8?, 0xc000f68a20?}, 0xc0005cc2c0)
    github.com/hashicorp/terraform-plugin-mux@v0.16.0/tf6muxserver/mux_server_ReadResource.go:35 +0x193
github.com/hashicorp/terraform-plugin-go/tfprotov6/tf6server.(*server).ReadResource(0xc000bdc320, {0x21060d8?, 0xc000f68210?}, 0xc00086a1c0)
    github.com/hashicorp/terraform-plugin-go@v0.24.0/tfprotov6/tf6server/server.go:784 +0x309
github.com/hashicorp/terraform-plugin-go/tfprotov6/internal/tfplugin6._Provider_ReadResource_Handler({0x1db9ca0, 0xc000bdc320}, {0x21060d8, 0xc000f68210}, 0xc000ccc000, 0x0)
    github.com/hashicorp/terraform-plugin-go@v0.24.0/tfprotov6/internal/tfplugin6/tfplugin6_grpc.pb.go:509 +0x1a6
google.golang.org/grpc.(*Server).processUnaryRPC(0xc0005e0200, {0x21060d8, 0xc000f68180}, {0x210f580, 0xc0009d2b60}, 0xc001554000, 0xc00085acf0, 0x2f1f248, 0x0)
    google.golang.org/grpc@v1.66.2/server.go:1394 +0xe49
google.golang.org/grpc.(*Server).handleStream(0xc0005e0200, {0x210f580, 0xc0009d2b60}, 0xc001554000)
    google.golang.org/grpc@v1.66.2/server.go:1805 +0xe8b
google.golang.org/grpc.(*Server).serveStreams.func2.1()
    google.golang.org/grpc@v1.66.2/server.go:1029 +0x8b
created by google.golang.org/grpc.(*Server).serveStreams.func2 in goroutine 70
    google.golang.org/grpc@v1.66.2/server.go:1040 +0x125

Expected output

One of our cache rules got recently manually changed on the dashboard while it's managed by the config above, so the expectation from this new plan would be to sync it back up or at least give some kind of error/warning about it - Instead it appears that something inside the ruleset code of the provider crashed. The exact rule that got changed is the Homepage cache one from my config. On the dashboard we simply added another hostname, so it's now:

(http.host in {"example1.com" "example2.com" "example3.com"} and http.request.uri.path eq "/")

versus what's in the config:

(http.host in {"example1.com" "example2.com"} and http.request.uri.path eq "/")

Seems as if the ruleset code had issues handling that manual change and couldn't generate a change for that and proceeded to crash.

Actual output

Provider should've created a change for my ruleset that got manually edited, but instead it crashed.

Steps to reproduce

  1. Create cache rule like the Homepage cache one from my config, via Terraform
  2. Manually edit it in the dashboard
  3. Trigger another Terraform plan
  4. Crash

Additional factoids

No response

References

No response

github-actions[bot] commented 1 week ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

github-actions[bot] commented 1 week ago

Thank you for opening this issue and sorry to hear you're hitting issues. Unfortunately, the reproduction case provided contains HCL dynamic expressions. Examples of these are:

Maintainers don't accept these as reproduction cases since using these constructs and expressions can hold their own logic bugs which are outside of the provider and not able to be diagnosed.

For maintainers to triage this issue, we recommend providing a minimal reproduction test case that is only contains the impacted resources and can be easily reproduced in an isolated environment. Without providing this, maintainers are limited in what support they can provide.

arunesh90 commented 3 days ago

Sorry for the delay, but I can confirm this is happening for me without the conditional as well.