cloudflare / terraform-provider-cloudflare

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

cloudflare_ruleset.zone_level_managed_waf produced an unexpected new value #2418

Closed cnk closed 1 year ago

cnk commented 1 year ago

Confirmation

Terraform and Cloudflare provider version

Terraform v1.4.6 on darwin_amd64

Affected resource(s)

Terraform configuration files

# I do not have any errors - until I add the "skip" rule

resource "cloudflare_ruleset" "zone_level_managed_waf" {
  zone_id     = cloudflare_zone.zone.id
  name        = "managed WAF"
  description = "Enable managed WAF rulesets"
  kind        = "zone"
  phase       = "http_request_firewall_managed"

  # Skip specific rules from Cloudflare OWASP Core Ruleset
  rules {
    action = "skip"
    action_parameters {
      rules = {
        "4814384a9e5d4991b9815dcfc25d2f1f" = "6179ae15870a4bb7b2d480d4843b323c"
      }
    }
    expression  = "(http.request.uri.path matches \"/admin/*\" and not http.request.uri.path matches \"/admin/login/\")"
    description = "Skip '949110: Inbound Anomaly Score Exceeded' for /admin/"
    enabled = true
  }

  # I do not have any errors 
  # Execute Cloudflare OWASP Core Ruleset - challenging at P1 level
  rules {
    action = "execute"
    action_parameters {
      id = "4814384a9e5d4991b9815dcfc25d2f1f"
      version = "latest"
      overrides {
        # By default, all PL1 to PL4 rules are enabled.
        # Set the paranoia level to PL1 by disabling rules with
        # tags "paranoia-level-2", "paranoia-level-3" and "paranoia-level-4".
        categories {
          category = "paranoia-level-2"
          enabled = false
        }
        categories {
          category = "paranoia-level-3"
          enabled = false
        }
        categories {
          category = "paranoia-level-4"
          enabled = false
        }
        rules {
          id = "6179ae15870a4bb7b2d480d4843b323c"
          action = "block"
        }
      }
    }
    expression  = "true"
    description = "Execute Cloudflare OWASP Core Ruleset on my zone-level phase entry point ruleset"
    enabled = true
  }
}

Link to debug output

https://gist.github.com/cnk/e21cece541923e0275784d6e6a9cf4a0

Panic output

No response

Expected output

I expected the general "success" message like the one below. This is what I get without the "skip" rule.

cloudflare_ruleset.zone_level_managed_waf: Modifying... [id=dba9b9a6e50841e8a751f4d8e1d62537]
cloudflare_ruleset.zone_level_managed_waf: Modifications complete after 1s [id=dba9b9a6e50841e8a751f4d8e1d62537]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

Outputs:...

Actual output

cloudflare_ruleset.zone_level_managed_waf: Modifying... [id=dba9b9a6e50841e8a751f4d8e1d62537] ╷ │ Error: Provider produced inconsistent result after apply │ │ When applying changes to cloudflare_ruleset.zone_level_managed_waf, provider │ "provider[\"registry.terraform.io/cloudflare/cloudflare\"]" produced an unexpected new value: .rules[1].logging: │ block count changed from 0 to 1. │ │ This is a bug in the provider, which should be reported in the provider's own issue tracker. ╵

Steps to reproduce

Create a TF stanza managing the OWASP managed rule set using cloudflare_ruleset Apply it .... all works fine Add a skip rule as show in the terraform config file above... rule gets created and works HOWEVER from this point forward, while all rule changes work, I always get a message "Error: Provider produced inconsistent result after apply" - even when I have not made changes in the ruleset section of my terraform file.

Additional factoids

No response

References

I think this is similar to #2408 and would like to know if the fix mentioned there will also fix my issue when it is released.

github-actions[bot] commented 1 year ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

jacobbednarz commented 1 year ago

this is unrelated to #2408 and will need to be addressed separately. i'm able to reproduce this on a fresh install so i can have a look into it.

jacobbednarz commented 1 year ago

the cause here is that for some reason, that combination of parameters is causing logging to be enabled despite never asking for it.

POST /client/v4/zones/0da42c8d2132a9ddaf714f9e7c920711/rulesets HTTP/1.1
Host: api.cloudflare.com
User-Agent: terraform/1.4.6 terraform-plugin-sdk/2.10.1 terraform-provider-cloudflare/dev
Content-Length: 933
Content-Type: application/json
X-Auth-Email: [redacted]
X-Auth-Key: [redacted]
Accept-Encoding: gzip

{
  "name": "managed WAF",
  "description": "Enable managed WAF rulesets",
  "kind": "zone",
  "phase": "http_request_firewall_managed",
  "rules": [
    {
      "action": "skip",
      "action_parameters": {
        "rules": {
          "4814384a9e5d4991b9815dcfc25d2f1f": [
            "6179ae15870a4bb7b2d480d4843b323c"
          ]
        }
      },
      "expression": "(http.request.uri.path matches \"/admin/*\" and not http.request.uri.path matches \"/admin/login/\")",
      "description": "Skip '949110: Inbound Anomaly Score Exceeded' for /admin/",
      "enabled": true
    },
    {
      "action": "execute",
      "action_parameters": {
        "id": "4814384a9e5d4991b9815dcfc25d2f1f",
        "overrides": {
          "categories": [
            {
              "category": "paranoia-level-2",
              "enabled": false
            },
            {
              "category": "paranoia-level-3",
              "enabled": false
            },
            {
              "category": "paranoia-level-4",
              "enabled": false
            }
          ],
          "rules": [
            {
              "id": "6179ae15870a4bb7b2d480d4843b323c",
              "action": "block"
            }
          ]
        },
        "version": "latest"
      },
      "expression": "true",
      "description": "Execute Cloudflare OWASP Core Ruleset on my zone-level phase entry point ruleset",
      "enabled": true
    }
  ]
}

HTTP/1.1 200 OK
Date: Wed, 10 May 2023 05:43:32 GMT
Content-Type: application/json; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
CF-Ray: 7c4fdd795a91a88e-SYD
Content-Encoding: gzip
Set-Cookie: __cflb=0H28vgHxwvgAQtjUGUFqYFDiSDreGJnUqy9bythzHbB; SameSite=Lax; path=/; expires=Wed, 10-May-23 08:13:33 GMT; HttpOnly
Vary: Accept-Encoding
CF-Cache-Status: DYNAMIC
x-envoy-upstream-service-time: 393
x-version: 7674-23eb0a9cf8bc
Set-Cookie: __cfruid=e0e9713f1fc291ce93dc0efe075ddeb6f7af2fca-1683697412; path=/; domain=.api.cloudflare.com; HttpOnly; Secure; SameSite=None
Server: cloudflare

{
  "result": {
    "id": "fae5bdd4a3f74a42b7b9542659528a12",
    "name": "managed WAF",
    "description": "Enable managed WAF rulesets",
    "source": "firewall_managed",
    "kind": "zone",
    "version": "1",
    "rules": [
      {
        "id": "1386314f149d4bc08a3792db54ad1138",
        "version": "1",
        "action": "skip",
        "expression": "(http.request.uri.path matches \"/admin/*\" and not http.request.uri.path matches \"/admin/login/\")",
        "description": "Skip '949110: Inbound Anomaly Score Exceeded' for /admin/",
        "last_updated": "2023-05-10T05:43:32.264943Z",
        "ref": "1386314f149d4bc08a3792db54ad1138",
        "enabled": true,
        "logging": {
          "enabled": true
        },
        "action_parameters": {
          "rules": {
            "4814384a9e5d4991b9815dcfc25d2f1f": [
              "6179ae15870a4bb7b2d480d4843b323c"
            ]
          }
        }
      },
      {
        "id": "180a8498dd9942478de88adf4a9061dc",
        "version": "1",
        "action": "execute",
        "expression": "true",
        "description": "Execute Cloudflare OWASP Core Ruleset on my zone-level phase entry point ruleset",
        "last_updated": "2023-05-10T05:43:32.264943Z",
        "ref": "180a8498dd9942478de88adf4a9061dc",
        "enabled": true,
        "action_parameters": {
          "id": "4814384a9e5d4991b9815dcfc25d2f1f",
          "version": "latest",
          "overrides": {
            "categories": [
              {
                "category": "paranoia-level-2",
                "enabled": false
              },
              {
                "category": "paranoia-level-3",
                "enabled": false
              },
              {
                "category": "paranoia-level-4",
                "enabled": false
              }
            ],
            "rules": [
              {
                "id": "6179ae15870a4bb7b2d480d4843b323c",
                "action": "block"
              }
            ]
          }
        }
      }
    ],
    "last_updated": "2023-05-10T05:43:32.264943Z",
    "phase": "http_request_firewall_managed"
  },
  "success": true,
  "errors": [],
  "messages": []
}

i'll ping the service team on this one for an answer as to what is going on here.

jacobbednarz commented 1 year ago

ok, so I found out why this is happening. the short version is that logging for skip rules is provided with default values irrespective of whether it is sent in the request or not. i have an ongoing discussion with the teams about this behaviour since it is pretty unintuitive however, it is working as expected.

to address the terraform specific issue, you need to add the logging property into your skip rule and it will set the correct value in the state.

cnk commented 1 year ago

Thank you so much. Adding the following section to my skip rule makes my terraform file match the Cloudflare config and then the "inconsistent result" message goes away.

logging {
  enabled = true
}
yacinehmito commented 1 year ago

Hi. I just got this error and am glad I found this issue. I reckon that it should be kept Open. Getting an error message like "Provider produced inconsistent result after apply" is still something that should be solved IMO.

yacinehmito commented 1 year ago

It's especially damning since, after having added logging { enabled = true }, I get "logging options only allowed in the skip action". So, I have to set action = "skip", even though:

This is not reassuring.

yacinehmito commented 1 year ago

On my end, the problem turned out to be with ratelimit { requests_to_origin = false } and not with logging { enabled = true }.