terraform-provider-cloudflare icon indicating copy to clipboard operation
terraform-provider-cloudflare copied to clipboard

cloudflare_access_policy always detects changes when both group and email are included

Open bootswithdefer opened this issue 3 years ago • 8 comments

Confirmation

  • [X] My issue isn't already found on the issue tracker.
  • [X] I have replicated my issue using the latest version of the provider and it is still present.

Terraform and Cloudflare provider version

Terraform v1.1.2
on linux_amd64
+ provider registry.terraform.io/cloudflare/cloudflare v3.5.0

Affected resource(s)

cloudflare_access_policy

Terraform configuration files

resource "cloudflare_access_policy" "users" {
  application_id = cloudflare_access_application.application.id
  zone_id        = data.vault_generic_secret.cloudflare.data["zone_id"]
  name           = "Allowed Users"
  precedence     = "2"
  decision       = "allow"

  include {
    group = ["uuid-of-group"]
    email = ["email@local"]
  }
}

Debug output

Not including

Panic output

No response

Expected output

No changes on second apply.

Actual output

  ~ resource "cloudflare_access_policy" "users" {
        id                             = "uuid"
        name                           = "Allowed Users"
        # (6 unchanged attributes hidden)

      ~ include {
          ~ group                   = [
              + "uuid-of-group",
            ]
            # (10 unchanged attributes hidden)
        }
      - include {
          - any_valid_service_token = false -> null
          - certificate             = false -> null
          - device_posture          = [] -> null
          - email                   = [] -> null
          - email_domain            = [] -> null
          - everyone                = false -> null
          - geo                     = [] -> null
          - group                   = [
              - "uuid-of-group",
            ] -> null
          - ip                      = [] -> null
          - login_method            = [] -> null
          - service_token           = [] -> null
        }
    }

Steps to reproduce

Apply, approve changes Apply again, changes detected

Additional factoids

The policy is created correct and the terraform state show the following. Adding two include{} blocks in the resource also causes changes to be detected on every run and does not create the policy correctly.

resource "cloudflare_access_policy" "users" {
    application_id                 = "uuid"
    decision                       = "allow"
    id                             = "uuid"
    name                           = "Allowed Users"
    precedence                     = 2
    purpose_justification_prompt   = ""
    purpose_justification_required = false
    zone_id                        = (sensitive)

    include {
        any_valid_service_token = false
        certificate             = false
        device_posture          = []
        email                   = [
            "email@local",
        ]
        email_domain            = []
        everyone                = false
        geo                     = []
        group                   = []
        ip                      = []
        login_method            = []
        service_token           = []
    }
    include {
        any_valid_service_token = false
        certificate             = false
        device_posture          = []
        email                   = []
        email_domain            = []
        everyone                = false
        geo                     = []
        group                   = [
            "uuid-of-group",
        ]
        ip                      = []
        login_method            = []
        service_token           = []
    }
}

References

No response

bootswithdefer avatar Sep 22 '21 18:09 bootswithdefer

I'm experiencing the same issue when trying to include Azure.

      ~ include {
            # (11 unchanged attributes hidden)

          + azure {
              + id                   = ["$grp_uuid"]
              + identity_provider_id = "$idp_uuid"
            }
        }

It doesn't matter if the Azure block is added to a cloudflare_access_policy resource or to a cloudflare_access_group resourced and referenced, both ways always show a change.

danie1sullivan avatar Sep 23 '21 12:09 danie1sullivan

I have the same problem

  ~ resource "cloudflare_access_policy" "main" {
        id                             = "d647dd11-130b-4670-a560-90498e465ec0"
        name                           = "allow"
        # (6 unchanged attributes hidden)

      ~ include {
          ~ ip                      = [
              + "1.1.1.1/32",
              + "2.2.2.2/32",
            ]
            # (10 unchanged attributes hidden)
        }
      - include {
          - any_valid_service_token = false -> null
          - certificate             = false -> null
          - device_posture          = [] -> null
          - email                   = [] -> null
          - email_domain            = [] -> null
          - everyone                = false -> null
          - geo                     = [] -> null
          - group                   = [] -> null
          - ip                      = [
              - "1.1.1.1/32",
              - "2.2.2.2/32",
            ] -> null
          - login_method            = [] -> null
          - service_token           = [] -> null
        }
    }

ondrejsika avatar Nov 11 '21 21:11 ondrejsika

I am having the same issue, when both email and email_domain are set.

 ~ resource "cloudflare_access_group" "this" {
        id         = "dd8a4299-ad4d-410b-b4ae-14d621a92694"
        name       = "allow-me"
        # (1 unchanged attribute hidden)

      ~ include {
          ~ email                   = [
              + "[email protected]",
              + "[email protected]",
            ]
          ~ email_domain            = [
              - "example.com",
            ]
            # (9 unchanged attributes hidden)
        }
      + include {
          + email_domain = [
              + "example.com",
            ]
        }
    }

eidam avatar Nov 13 '21 23:11 eidam

I'm still seeing this in 3.8.0

Any chance this can get fixed?

rogersd avatar Feb 09 '22 16:02 rogersd

Still seeing this in 3.9.1 :broken_heart:

rnt avatar Feb 17 '22 18:02 rnt

I've spent some time looking into this issue and this seems to be due to the way the require, include and exclude blocks are handled internally in the provider.

There seem to be a couple of different bugs interacting here leading to the unwanted behaviour:

  1. When reading data back from the API, the provider reads each field (or set of related fields in the case of e.g. Azure config) and puts it in its own entry in the slice, effectively representing multiple blocks, regardless of how many blocks were defined in Terraform. Terraform emits a warning to this effect:
Provider "provider[\"registry.terraform.io/cloudflare/cloudflare\"]" produced an unexpected new value for cloudflare_access_policy.example, but we are tolerating it because it is using the legacy plugin SDK.
   The following problems may be the cause of any confusing errors from downstream operations:
     - .require: block count changed from 1 to 2

See https://github.com/cloudflare/terraform-provider-cloudflare/blob/199efbcb8259d9449e81d868980abf905b8d897c/cloudflare/resource_cloudflare_access_group.go#L445-L449 where each entry in the data slice effectively represents a block of require, include or exclude.

  1. When writing data to the API, if multiple blocks are configured, only the last one takes effect. See: https://github.com/cloudflare/terraform-provider-cloudflare/blob/199efbcb8259d9449e81d868980abf905b8d897c/cloudflare/resource_cloudflare_access_group.go#L180-L184

These 2 bugs means that you're currently stuck with config that applies outright incorrectly or diffs perpetually.

I've attempted to fix this with a local version of the provider by replacing the code in the latter sample with

for _, value := range exclude {
	if value != nil {
		policy.Exclude = append(policy.Exclude, BuildAccessGroupCondition(value.(map[string]interface{})))
	}
}

but this leads to the following error response from the API when configuring multiple blocks error creating Access Policy for ID "": HTTP status 400: access.api.error.failed_to_load_group (11020), I've yet to find the time to investigate this further.

Hopefully this can be of some help. I'm hesitant to raise a PR for potential fixes because it seems like the most "correct" solution based on Cloudflare's API would require breaking changes to the provider.

bas-papegaaij avatar Mar 18 '22 05:03 bas-papegaaij

This seem to be not just for email but other things as well.

It doesn't really matter if I specify as:

  include {
    group = var.dev_groups_allow
  }
  include {
    any_valid_service_token = true
  }

which always comes back as:

  ~ resource "cloudflare_access_policy" "allow" {
        id             = "80c1...e629"
        name           = "rule-dev"
        # (4 unchanged attributes hidden)

      ~ include {
          - any_valid_service_token = true -> null
          ~ group                   = [
              + "9310...454",
            ]
            # (9 unchanged attributes hidden)
        }
      + include {
          + any_valid_service_token = true
        }
    }

or

  include {
    group = var.dev_groups_allow
    any_valid_service_token = true
  }

which always comes back as:

  ~ resource "cloudflare_access_policy" "allow" {
        id             = "80c199...f6de629"
        name           = "rule-dev"
        # (4 unchanged attributes hidden)

      ~ include {
          ~ group                   = [
              + "9310e...5a454",
            ]
            # (10 unchanged attributes hidden)
        }
      - include {
          - any_valid_service_token = false -> null
          - certificate             = false -> null
          - device_posture          = [] -> null
          - email                   = [] -> null
          - email_domain            = [] -> null
          - everyone                = false -> null
          - geo                     = [] -> null
          - group                   = [
              - "9310e...a454",
            ] -> null
          - ip                      = [] -> null
          - login_method            = [] -> null
          - service_token           = [] -> null
        }
    }

perosb avatar Jun 01 '22 09:06 perosb

I have the same problem, does it make sense to wait for a fix?

dhalturin avatar Aug 30 '22 02:08 dhalturin

We're running into this when both email and email_domain are specified. We're interested in a fix.

esalter avatar Sep 30 '22 14:09 esalter