imperva / terraform-provider-incapsula

This package is a plugin for Terraform, and is designed to be used to auto-provision sites in Incapsula via Incapsula’s API from the terraform cli/yaml configurations.
Mozilla Public License 2.0
44 stars 71 forks source link

Whitespace changes always being reported for incapsula_policy resources #425

Open uduncanu opened 3 months ago

uduncanu commented 3 months ago

Confirmation

Terraform and Imperva provider version

Terraform 1.8.3 Imperva provider 3.25.0

Affected resource(s)

incapsula_policy

Terraform configuration files

resource "incapsula_policy" "policy" {
    name        = "WAF Policy"
    enabled     = true 
    policy_type = "WAF_RULES"
    description = "WAF Policy"
    policy_settings = jsonencode(
      [
        {
          policySettingType = "REMOTE_FILE_INCLUSION"
          settingsAction    = "BLOCK" : "ALERT"
          data              = {}
        },
        {
          policySettingType = "SQL_INJECTION"
          settingsAction    = "ALERT"
          data              = {}
        },
        {
          policySettingType = "ILLEGAL_RESOURCE_ACCESS"
          settingsAction    = "ALERT"
          data              = {}
        },
        {
          policySettingType = "CROSS_SITE_SCRIPTING"
          settingsAction    = "ALERT"
          data              = {}
        },
      ]
    )
}

Debug output

I've skipped the debug output as it's too verbose and may contain sensitive information, but I found this in the trace output:

policy_settings: was cty.StringVal("[{\"data\":{},\"policySettingType\":\"REMOTE_FILE_INCLUSION\",\"settingsAction\":\"ALERT\"},{\"data\":{},\"policySettingType\":\"SQL_INJECTION\",\"settingsAction\":\"ALERT\"},{\"data\":{},\"policySettingType\":\"ILLEGAL_RESOURCE_ACCESS\",\"settingsAction\":\"ALERT\"},{\"data\":{},\"policySettingType\":\"CROSS_SITE_SCRIPTING\",\"settingsAction\":\"ALERT\"}]"), but now cty.StringVal("[\n    {\n        \"settingsAction\": \"ALERT\",\n        \"policySettingType\": \"REMOTE_FILE_INCLUSION\",\n        \"data\": {}\n    },\n    {\n        \"settingsAction\": \"ALERT\",\n        \"policySettingType\": \"SQL_INJECTION\",\n        \"data\": {}\n    },\n    {\n        \"settingsAction\": \"ALERT\",\n        \"policySettingType\": \"ILLEGAL_RESOURCE_ACCESS\",\n        \"data\": {}\n    },\n    {\n        \"settingsAction\": \"ALERT\",\n        \"policySettingType\": \"CROSS_SITE_SCRIPTING\",\n        \"data\": {}\n    }\n]")

### Panic output

_No response_

### Expected output

No changes

### Actual output

Whitespace changes found

module.pinot_decanter_com_imperva.incapsula_policy.policy will be updated in-place

~ resource "incapsula_policy" "policy" { id = "REDACTED" name = "WAF Policy" ~ policy_settings = jsonencode( # whitespace changes [ { data = {} policySettingType = "REMOTE_FILE_INCLUSION" settingsAction = "ALERT" }, { data = {} policySettingType = "SQL_INJECTION" settingsAction = "ALERT" }, { data = {} policySettingType = "ILLEGAL_RESOURCE_ACCESS" settingsAction = "ALERT" }, { data = {} policySettingType = "CROSS_SITE_SCRIPTING" settingsAction = "ALERT" }, ] )

(4 unchanged attributes hidden)

}

Steps to reproduce

  1. Apply the included incapsula_policy resource, with an empty data block
  2. Run terraform plan. There should be no changes but there are.

Additional factoids

I've done a bit of digging into this, and I believe what's happening is that Terraform is reordering the items in the JSON object so that they're in alphabetical order, and then the code to filter out whitespace changes in resource_policy.go isn't correctly removing the empty data block. It will be the first item in the object, but the code to remove it looks for a comma before it which won't be there when it's the first item in the object.

I'm not sure if it's oldValue or newValue in this block of code causing the issue and my knowledge of how this all works is limited so I may be wrong, but I think this change to move the comma may fix the problem:

oldValue = strings.ReplaceAll(oldValue, ",\"data\":{}", "")
...
newValue = strings.ReplaceAll(newValue, ",\"data\":{}", "")

to

oldValue = strings.ReplaceAll(oldValue, "\"data\":{},", "")
...
newValue = strings.ReplaceAll(newValue, "\"data\":{},", "")

A workaround for this is to just remove the empty data block entirely, which then doesn't need replacing and so doesn't show pending whitespace changes.

References

No response

Vizzyy commented 3 months ago

I'm having this same issue. Thank you, @uduncanu, for reporting it, and for providing a workaround at the bottom!