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

cloudflare_zero_trust_access_application changes on every apply

Open per-lind opened this issue 7 months ago • 25 comments

Confirmation

  • [x] This is a bug with an existing resource and is not a feature request or enhancement. Feature requests should be submitted with Cloudflare Support or your account team.
  • [x] I have searched the issue tracker and my issue isn't already found.
  • [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.11.2 on linux_amd64

  • provider registry.terraform.io/cloudflare/cloudflare v5.3.0

Affected resource(s)

cloudflare_zero_trust_access_application

Terraform configuration files

terraform {
  required_providers {
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "~> 5.3.0"
    }
  }
}

resource "cloudflare_zero_trust_access_policy" "app" {
  account_id = "xxx"
  decision   = "allow"
  include = [{
    saml = {
      attribute_name = "group"
      attribute_value = "test"
      identity_provider_id = "xxx"
    }
  }]


  name = "APP-test"

  require = [{
    group = {
      id = "cde0fd42-4c40-4216-a6ab-884e6d435eba"
    } }
  ]
}

resource "cloudflare_zero_trust_access_application" "app" {
  account_id                  = "xxx"
  type                        = "self_hosted"
  allow_authenticate_via_warp = true
  allowed_idps                = ["xxx"]
  app_launcher_visible        = true
  auto_redirect_to_identity   = true
  destinations = [
    {
      type       = "private"
      uri        = "192.168.1.200:3389"
      cidr       = "192.168.1.200"
      port_range = "3389"
    },
  ]
  name                     = "test"
  options_preflight_bypass = false
  policies = [{
    id         = cloudflare_zero_trust_access_policy.app.id
    precedence = 0
    decision   = "allow"
  }, ]
  session_duration = "24h"
}

Link to debug output

https://gist.github.com/per-lind/52f4b57820c16096c0f2187a21021205

Panic output

No response

Expected output

No changes on 2nd apply

Actual output

cloudflare_zero_trust_access_application.app will be updated in-place

~ resource "cloudflare_zero_trust_access_application" "app" { ~ aud = "xxx" -> (known after apply) + cors_headers = (known after apply) ~ created_at = "2025-04-10T08:51:27Z" -> (known after apply) ~ destinations = [ ~ { ~ cidr = "192.168.1.200/32" -> "192.168.1.200" + uri = "192.168.1.200:3389" # (2 unchanged attributes hidden) }, ] + footer_links = (known after apply) id = "8fcffbc5-f3af-406a-8941-2f1ad66a82fb" + landing_page_design = (known after apply) name = "test" + path_cookie_attribute = false ~ policies = [ ~ { + connection_rules = (known after apply) ~ exclude = [] -> (known after apply) id = "ce3de7bb-eb8c-49ab-a570-5e2dd6758b34" ~ include = [ - { - saml = { - attribute_name = "group" -> null - attribute_value = "test" -> null - identity_provider_id = "xxx" -> null } -> null }, ] -> (known after apply) - name = "APP-test" -> null ~ precedence = 1 -> 0 ~ require = [ - { - group = { - id = "cde0fd42-4c40-4216-a6ab-884e6d435eba" -> null } -> null }, ] -> (known after apply) # (1 unchanged attribute hidden) }, ] + saas_app = (known after apply) + scim_config = (known after apply) + skip_app_launcher_login_page = false - tags = [] -> null + target_criteria = (known after apply) ~ updated_at = "2025-04-10T08:52:34Z" -> (known after apply) # (10 unchanged attributes hidden) }

Plan: 0 to add, 1 to change, 0 to destroy.

Steps to reproduce

Create an application with a policy to it terraform apply run a 2nd terraform apply

Additional factoids

This does not happen with version 5.1.0

References

https://github.com/cloudflare/terraform-provider-cloudflare/issues/5370

per-lind avatar Apr 10 '25 09:04 per-lind

the reproduction case here is invalid for saml. in terraform are separated with equals signs while saml uses colons. can you confirm the reproduction case here?

jacobbednarz avatar Apr 11 '25 00:04 jacobbednarz

I ran into a similar issue with the following resource:

resource "cloudflare_zero_trust_access_application" "test-application" {
  account_id = var.primary_account_id
  allowed_idps = []
  app_launcher_visible = true
  destinations = [{
    type = "public"
    uri = "test-application.${var.primary_zone_name}"
  }]
  domain = "test-application.${var.primary_zone_name}"
  http_only_cookie_attribute = true
  logo_url = "https://www.cloudflare.com/img/logo-web-badges/cf-logo-on-white-bg.svg"
  name = "Test Application"
  policies = [{
    # For some reason, passing id or id/precedence doesn't work and triggers {"code":12130,"message":"access.api.error.invalid_request: unrecognized policy decision"}
    # id = cloudflare_zero_trust_access_policy.test-policy.id
    # precedence = 1

    # Pull in policy info manually
    decision = cloudflare_zero_trust_access_policy.test-policy.decision
    exclude  = cloudflare_zero_trust_access_policy.test-policy.exclude
    include  = cloudflare_zero_trust_access_policy.test-policy.include
    name     = "${cloudflare_zero_trust_access_policy.test-policy.name} (Non-reusable)"
    require  = cloudflare_zero_trust_access_policy.test-policy.require

    # Attempted to add these to fix the resource update, didn't work:
    id = "00000000-1111-4222-3333-444444444444"
    precedence = 1
  }]
  type = "self_hosted"

  # Attempted to add these to fix the resource update, didn't work:
  options_preflight_bypass = false
  self_hosted_domains = ["test-application.${var.primary_zone_name}"]
  tags = []
}

There are two issues I ran into: first, I can't find a way to pass an existing policy ID to policies. And then, when passing a per-application policy, I get the update on every apply issue that @per-lind is running into.

Output:

# cloudflare_zero_trust_access_application.test-application will be updated in-place
~ resource "cloudflare_zero_trust_access_application" "test-application" {
    ~ aud                          = "000111222moremoremore" -> (known after apply)
    + cors_headers                 = (known after apply)
    ~ created_at                   = "2025-04-11T16:09:46Z" -> (known after apply)
    + footer_links                 = (known after apply)
      id                           = "00000000-1111-4222-3333-444444444444"
    + landing_page_design          = (known after apply)
      name                         = "Test Application"
    + path_cookie_attribute        = false
    ~ policies                     = [
        ~ {
            + connection_rules = (known after apply)
              id               = "00000000-1111-4222-3333-444444444444"
            ~ include          = [
                ~ {
                    + auth_context        = (known after apply)
                    + auth_method         = (known after apply)
                    + azure_ad            = (known after apply)
                    + common_name         = (known after apply)
                    + device_posture      = (known after apply)
                    + email_domain        = (known after apply)
                    + email_list          = (known after apply)
                    + external_evaluation = (known after apply)
                    + geo                 = (known after apply)
                    + github_organization = (known after apply)
                    + group               = (known after apply)
                    + gsuite              = (known after apply)
                    + ip                  = (known after apply)
                    + ip_list             = (known after apply)
                    + login_method        = (known after apply)
                    + okta                = (known after apply)
                    + saml                = (known after apply)
                    + service_token       = (known after apply)
                      # (1 unchanged attribute hidden)
                  },
                ~ {
                    + auth_context        = (known after apply)
                    + auth_method         = (known after apply)
                    + azure_ad            = (known after apply)
                    + common_name         = (known after apply)
                    + device_posture      = (known after apply)
                    + email_domain        = (known after apply)
                    + email_list          = (known after apply)
                    + external_evaluation = (known after apply)
                    + geo                 = (known after apply)
                    + github_organization = (known after apply)
                    + group               = (known after apply)
                    + gsuite              = (known after apply)
                    + ip                  = (known after apply)
                    + ip_list             = (known after apply)
                    + login_method        = (known after apply)
                    + okta                = (known after apply)
                    + saml                = (known after apply)
                    + service_token       = (known after apply)
                      # (1 unchanged attribute hidden)
                  },
              ]
              name             = "Test Policy (Non-reusable)"
              # (4 unchanged attributes hidden)
          },
      ]
    + saas_app                     = (known after apply)
    + scim_config                  = (known after apply)
    + skip_app_launcher_login_page = false
      tags                         = []
    + target_criteria              = (known after apply)
    ~ updated_at                   = "2025-04-11T16:09:46Z" -> (known after apply)
      # (13 unchanged attributes hidden)
  }

Some IDs/names updated to be more generic.

benmanns avatar Apr 11 '25 16:04 benmanns

@jacobbednarz oh sorry about that (the code does however work). I will update the post

per-lind avatar Apr 11 '25 16:04 per-lind

I can't find a way to pass an existing policy ID to policies

@benmanns Same here, I filed a separate bug for that issue: #5499

chris-pinola-rf avatar Apr 11 '25 17:04 chris-pinola-rf

I will not re-open the issue but it is same as https://github.com/cloudflare/terraform-provider-cloudflare/issues/5370 and the issue WAS NOT FIXED. Also, the problem in NOT only with cloudflare_zero_trust_access_application but with:

  1. cloudflare_zero_trust_access_application
  2. cloudflare_zero_trust_access_policy
  3. cloudflare_zero_trust_access_identity_provider
  4. cloudflare_zero_trust_access_group
  5. cloudflare_zero_trust_list

and maybe more.

 octav@MacBook-Pro-m  ~/cloudflare   main ●  tf apply -auto-approve
cloudflare_zero_trust_access_identity_provider.provider["OpenID Connect"]: Refreshing state... [id=f26b2aeb-2b29-41de-cf3be7392ead]
cloudflare_zero_trust_access_group.group["Everyone"]: Refreshing state... [id=587dd4d1-4b7b-4e12-9f07aaa43952]
cloudflare_zero_trust_access_group.group["Developers"]: Refreshing state... [id=771359e1-fb1d-43d8-797a255e78b3]
cloudflare_zero_trust_access_group.group["Admins emails"]: Refreshing state... [id=975f4846-5832-8c21-0c69333a209f]
cloudflare_zero_trust_access_group.group["Nifi operators emails"]: Refreshing state... [id=6f6127e4-499a-8bac-5e21bb580820]
cloudflare_zero_trust_access_group.group["Admins ips"]: Refreshing state... [id=8723aad0-8b14-4f39-c293233fbb6d]
cloudflare_zero_trust_access_policy.policy["Everyone"]: Refreshing state... [id=94a93801-209c-4c36-e8a6cac51d89]
cloudflare_zero_trust_access_policy.policy["Filter by email"]: Refreshing state... [id=6bebb1b4-0da3-a77e-e617d31bde08]
cloudflare_zero_trust_access_policy.policy["Filter by email nifi"]: Refreshing state... [id=47efe264-4c3f-a883-2663da932e70]
cloudflare_zero_trust_access_policy.policy["Filter by ip"]: Refreshing state... [id=ceda7e11-5421-4d49-1e9da73fa590]
cloudflare_zero_trust_access_application.application["Nifi"]: Refreshing state... [id=89153a71-9624-4547-9c984dca96bc]
cloudflare_zero_trust_access_application.application["Name"]: Refreshing state... [id=a14da0c5-b2e2-a396-53a3ccf46684]

OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

OpenTofu will perform the following actions:

  # cloudflare_zero_trust_access_application.application["Name"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_application" "application" {
      - allowed_idps                 = [] -> null
      ~ aud                          = "d82d033e988ef82e45f2e1ba752c5b95e01ffbf80e0ec" -> (known after apply)
      + cors_headers                 = (known after apply)
      ~ created_at                   = "2025-03-25T14:01:01Z" -> (known after apply)
      + footer_links                 = (known after apply)
        id                           = "a14da0c5-b2e2-a396-53a3ccf46684"
      + landing_page_design          = (known after apply)
        name                         = "Name"
      + path_cookie_attribute        = false
      ~ policies                     = [
          ~ {
              + connection_rules = (known after apply)
              ~ exclude          = [] -> (known after apply)
                id               = "ceda7e11-5421-4d49-1e9da73fa590"
              ~ include          = [
                  - {
                      - group = {
                          - id = "8723aad0-8b14-4f39-c293233fbb6d" -> null
                        } -> null
                    },
                  - {
                      - group = {
                          - id = "771359e1-fb1d-43d8-797a255e78b3" -> null
                        } -> null
                    },
                ] -> (known after apply)
              - name             = "Filter by ip" -> null
              ~ require          = [] -> (known after apply)
                # (2 unchanged attributes hidden)
            },
          ~ {
              + connection_rules = (known after apply)
              ~ exclude          = [] -> (known after apply)
                id               = "6bebb1b4-0da3-a77e-e617d31bde08"
              ~ include          = [
                  - {
                      - group = {
                          - id = "975f4846-5832-8c21-0c69333a209f" -> null
                        } -> null
                    },
                ] -> (known after apply)
              - name             = "Filter by email" -> null
              ~ require          = [] -> (known after apply)
                # (2 unchanged attributes hidden)
            },
        ]
      + saas_app                     = (known after apply)
      + scim_config                  = (known after apply)
      - self_hosted_domains          = [
          - "*.example.com",
        ] -> null
      + skip_app_launcher_login_page = false
      - tags                         = [] -> null
      + target_criteria              = (known after apply)
      ~ updated_at                   = "2025-04-18T09:47:52Z" -> (known after apply)
        # (11 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_application.application["Nifi"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_application" "application" {
      - allowed_idps                 = [] -> null
      ~ aud                          = "235cc2411ba8b022f70353d1f79cb28edf2e80aa220db077d1b8b5f6d3cee1cf" -> (known after apply)
      + cors_headers                 = (known after apply)
      ~ created_at                   = "2025-03-25T14:01:01Z" -> (known after apply)
      + footer_links                 = (known after apply)
        id                           = "89153a71-9624-4547-9c984dca96bc"
      + landing_page_design          = (known after apply)
        name                         = "Nifi"
      + path_cookie_attribute        = false
      ~ policies                     = [
          ~ {
              + connection_rules = (known after apply)
              ~ exclude          = [] -> (known after apply)
                id               = "ceda7e11-5421-4d49-1e9da73fa590"
              ~ include          = [
                  - {
                      - group = {
                          - id = "8723aad0-8b14-4f39-c293233fbb6d" -> null
                        } -> null
                    },
                  - {
                      - group = {
                          - id = "771359e1-fb1d-43d8-797a255e78b3" -> null
                        } -> null
                    },
                ] -> (known after apply)
              - name             = "Filter by ip" -> null
              ~ require          = [] -> (known after apply)
                # (2 unchanged attributes hidden)
            },
          ~ {
              + connection_rules = (known after apply)
              ~ exclude          = [] -> (known after apply)
                id               = "47efe264-4c3f-a883-2663da932e70"
              ~ include          = [
                  - {
                      - group = {
                          - id = "6f6127e4-499a-8bac-5e21bb580820" -> null
                        } -> null
                    },
                ] -> (known after apply)
              - name             = "Filter by email nifi" -> null
              ~ require          = [] -> (known after apply)
                # (2 unchanged attributes hidden)
            },
        ]
      + saas_app                     = (known after apply)
      + scim_config                  = (known after apply)
      - self_hosted_domains          = [
          - "example.com",
        ] -> null
      + skip_app_launcher_login_page = false
      - tags                         = [] -> null
      + target_criteria              = (known after apply)
      ~ updated_at                   = "2025-04-18T09:47:52Z" -> (known after apply)
        # (11 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_group.group["Admins ips"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_group" "group" {
      ~ created_at = "2025-03-25T13:30:58Z" -> (known after apply)
        id         = "8723aad0-8b14-4f39-c293233fbb6d"
      ~ include    = [
          ~ {
              ~ ip = {
                  ~ ip = "2a02:2f0f:c00::/64" -> "2a02:2f0f:c00:d4a9:d159:548e:6bbd/64"
                }
            },
            # (5 unchanged elements hidden)
        ]
        name       = "Admins ips"
      ~ require    = [] -> (known after apply)
      ~ updated_at = "2025-04-18T09:47:50Z" -> (known after apply)
        # (2 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_identity_provider.provider["OpenID Connect"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_identity_provider" "provider" {
      ~ config      = {
          + client_secret = (sensitive value)
          ~ redirect_url  = "https://example.cloudflareaccess.com/cdn-cgi/access/callback" -> (known after apply)
            # (5 unchanged attributes hidden)
        }
        id          = "f26b2aeb-2b29-41de-cf3be7392ead"
        name        = "Name SSO"
      ~ scim_config = {
          + scim_base_url    = (known after apply)
          - seat_deprovision = false -> null
          + secret           = (sensitive value)
          - user_deprovision = false -> null
            # (1 unchanged attribute hidden)
        }
        # (2 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_policy.policy["Everyone"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_policy" "policy" {
      ~ app_count                      = 0 -> (known after apply)
      + approval_groups                = (known after apply)
      + approval_required              = false
      ~ created_at                     = "2025-03-25T13:31:04Z" -> (known after apply)
        id                             = "94a93801-209c-4c36-e8a6cac51d89"
      + isolation_required             = false
        name                           = "Everyone"
      + purpose_justification_required = false
      ~ reusable                       = true -> (known after apply)
      ~ updated_at                     = "2025-04-18T09:47:51Z" -> (known after apply)
        # (6 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_policy.policy["Filter by email"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_policy" "policy" {
      ~ app_count                      = 1 -> (known after apply)
      + approval_groups                = (known after apply)
      + approval_required              = false
      ~ created_at                     = "2025-03-25T13:31:04Z" -> (known after apply)
        id                             = "6bebb1b4-0da3-a77e-e617d31bde08"
      + isolation_required             = false
        name                           = "Filter by email"
      + purpose_justification_required = false
      ~ reusable                       = true -> (known after apply)
      ~ updated_at                     = "2025-04-18T09:47:51Z" -> (known after apply)
        # (6 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_policy.policy["Filter by email nifi"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_policy" "policy" {
      ~ app_count                      = 1 -> (known after apply)
      + approval_groups                = (known after apply)
      + approval_required              = false
      ~ created_at                     = "2025-03-25T13:31:04Z" -> (known after apply)
        id                             = "47efe264-4c3f-a883-2663da932e70"
      + isolation_required             = false
        name                           = "Filter by email nifi"
      + purpose_justification_required = false
      ~ reusable                       = true -> (known after apply)
      ~ updated_at                     = "2025-04-18T09:47:51Z" -> (known after apply)
        # (6 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_policy.policy["Filter by ip"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_policy" "policy" {
      ~ app_count                      = 2 -> (known after apply)
      + approval_groups                = (known after apply)
      + approval_required              = false
      ~ created_at                     = "2025-03-25T13:31:04Z" -> (known after apply)
        id                             = "ceda7e11-5421-4d49-1e9da73fa590"
      + isolation_required             = false
        name                           = "Filter by ip"
      + purpose_justification_required = false
      ~ reusable                       = true -> (known after apply)
      ~ updated_at                     = "2025-04-18T09:47:51Z" -> (known after apply)
        # (6 unchanged attributes hidden)
    }

Plan: 0 to add, 8 to change, 0 to destroy.
cloudflare_zero_trust_access_identity_provider.provider["OpenID Connect"]: Modifying... [id=f26b2aeb-2b29-41de-cf3be7392ead]
cloudflare_zero_trust_access_group.group["Admins ips"]: Modifying... [id=8723aad0-8b14-4f39-c293233fbb6d]
cloudflare_zero_trust_access_identity_provider.provider["OpenID Connect"]: Modifications complete after 1s [id=f26b2aeb-2b29-41de-cf3be7392ead]
cloudflare_zero_trust_access_group.group["Admins ips"]: Modifications complete after 1s [id=8723aad0-8b14-4f39-c293233fbb6d]
cloudflare_zero_trust_access_policy.policy["Filter by email"]: Modifying... [id=6bebb1b4-0da3-a77e-e617d31bde08]
cloudflare_zero_trust_access_policy.policy["Everyone"]: Modifying... [id=94a93801-209c-4c36-e8a6cac51d89]
cloudflare_zero_trust_access_policy.policy["Filter by email nifi"]: Modifying... [id=47efe264-4c3f-a883-2663da932e70]
cloudflare_zero_trust_access_policy.policy["Filter by ip"]: Modifying... [id=ceda7e11-5421-4d49-1e9da73fa590]
cloudflare_zero_trust_access_policy.policy["Everyone"]: Modifications complete after 1s [id=94a93801-209c-4c36-e8a6cac51d89]
cloudflare_zero_trust_access_policy.policy["Filter by ip"]: Modifications complete after 1s [id=ceda7e11-5421-4d49-1e9da73fa590]
cloudflare_zero_trust_access_policy.policy["Filter by email nifi"]: Modifications complete after 1s [id=47efe264-4c3f-a883-2663da932e70]
cloudflare_zero_trust_access_policy.policy["Filter by email"]: Modifications complete after 1s [id=6bebb1b4-0da3-a77e-e617d31bde08]
cloudflare_zero_trust_access_application.application["Nifi"]: Modifying... [id=89153a71-9624-4547-9c984dca96bc]
cloudflare_zero_trust_access_application.application["Name"]: Modifying... [id=a14da0c5-b2e2-a396-53a3ccf46684]
cloudflare_zero_trust_access_application.application["Nifi"]: Modifications complete after 1s [id=89153a71-9624-4547-9c984dca96bc]
cloudflare_zero_trust_access_application.application["Name"]: Modifications complete after 1s [id=a14da0c5-b2e2-a396-53a3ccf46684]
Releasing state lock. This may take a few moments...

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


###################################################################



 octav@MacBook-Pro-m  ~/cloudflare   main ●  tf plan
Acquiring state lock. This may take a few moments...
cloudflare_zero_trust_access_identity_provider.provider["OpenID Connect"]: Refreshing state... [id=f26b2aeb-2b29-41de-cf3be7392ead]
cloudflare_zero_trust_access_group.group["Everyone"]: Refreshing state... [id=587dd4d1-4b7b-4e12-9f07aaa43952]
cloudflare_zero_trust_access_group.group["Admins emails"]: Refreshing state... [id=975f4846-5832-8c21-0c69333a209f]
cloudflare_zero_trust_access_group.group["Nifi operators emails"]: Refreshing state... [id=6f6127e4-499a-8bac-5e21bb580820]
cloudflare_zero_trust_access_group.group["Developers"]: Refreshing state... [id=771359e1-fb1d-43d8-797a255e78b3]
cloudflare_zero_trust_access_group.group["Admins ips"]: Refreshing state... [id=8723aad0-8b14-4f39-c293233fbb6d]
cloudflare_zero_trust_access_policy.policy["Everyone"]: Refreshing state... [id=94a93801-209c-4c36-e8a6cac51d89]
cloudflare_zero_trust_access_policy.policy["Filter by email"]: Refreshing state... [id=6bebb1b4-0da3-a77e-e617d31bde08]
cloudflare_zero_trust_access_policy.policy["Filter by email nifi"]: Refreshing state... [id=47efe264-4c3f-a883-2663da932e70]
cloudflare_zero_trust_access_policy.policy["Filter by ip"]: Refreshing state... [id=ceda7e11-5421-4d49-1e9da73fa590]
cloudflare_zero_trust_access_application.application["Name"]: Refreshing state... [id=a14da0c5-b2e2-a396-53a3ccf46684]
cloudflare_zero_trust_access_application.application["Nifi"]: Refreshing state... [id=89153a71-9624-4547-9c984dca96bc]

OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

OpenTofu will perform the following actions:

  # cloudflare_zero_trust_access_application.application["Name"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_application" "application" {
      - allowed_idps                 = [] -> null
      ~ aud                          = "d82d033e988ef82e45f2e17729469889d5f95e01ffbf80e0ec" -> (known after apply)
      + cors_headers                 = (known after apply)
      ~ created_at                   = "2025-03-25T14:01:01Z" -> (known after apply)
      + footer_links                 = (known after apply)
        id                           = "a14da0c5-b2e2-a396-53a3ccf46684"
      + landing_page_design          = (known after apply)
        name                         = "Name"
      + path_cookie_attribute        = false
      ~ policies                     = [
          ~ {
              + connection_rules = (known after apply)
              ~ exclude          = [] -> (known after apply)
                id               = "ceda7e11-5421-4d49-1e9da73fa590"
              ~ include          = [
                  - {
                      - group = {
                          - id = "8723aad0-8b14-4f39-c293233fbb6d" -> null
                        } -> null
                    },
                  - {
                      - group = {
                          - id = "771359e1-fb1d-43d8-797a255e78b3" -> null
                        } -> null
                    },
                ] -> (known after apply)
              - name             = "Filter by ip" -> null
              ~ require          = [] -> (known after apply)
                # (2 unchanged attributes hidden)
            },
          ~ {
              + connection_rules = (known after apply)
              ~ exclude          = [] -> (known after apply)
                id               = "6bebb1b4-0da3-a77e-e617d31bde08"
              ~ include          = [
                  - {
                      - group = {
                          - id = "975f4846-5832-8c21-0c69333a209f" -> null
                        } -> null
                    },
                ] -> (known after apply)
              - name             = "Filter by email" -> null
              ~ require          = [] -> (known after apply)
                # (2 unchanged attributes hidden)
            },
        ]
      + saas_app                     = (known after apply)
      + scim_config                  = (known after apply)
      - self_hosted_domains          = [
          - "*.example.com",
        ] -> null
      + skip_app_launcher_login_page = false
      - tags                         = [] -> null
      + target_criteria              = (known after apply)
      ~ updated_at                   = "2025-04-18T09:52:57Z" -> (known after apply)
        # (11 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_application.application["Nifi"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_application" "application" {
      - allowed_idps                 = [] -> null
      ~ aud                          = "235cc2411ba8b022f70353d80aa220db077d1b8b5f6d3cee1cf" -> (known after apply)
      + cors_headers                 = (known after apply)
      ~ created_at                   = "2025-03-25T14:01:01Z" -> (known after apply)
      + footer_links                 = (known after apply)
        id                           = "89153a71-9624-4547-9c984dca96bc"
      + landing_page_design          = (known after apply)
        name                         = "Nifi"
      + path_cookie_attribute        = false
      ~ policies                     = [
          ~ {
              + connection_rules = (known after apply)
              ~ exclude          = [] -> (known after apply)
                id               = "ceda7e11-5421-4d49-1e9da73fa590"
              ~ include          = [
                  - {
                      - group = {
                          - id = "8723aad0-8b14-4f39-c293233fbb6d" -> null
                        } -> null
                    },
                  - {
                      - group = {
                          - id = "771359e1-fb1d-43d8-797a255e78b3" -> null
                        } -> null
                    },
                ] -> (known after apply)
              - name             = "Filter by ip" -> null
              ~ require          = [] -> (known after apply)
                # (2 unchanged attributes hidden)
            },
          ~ {
              + connection_rules = (known after apply)
              ~ exclude          = [] -> (known after apply)
                id               = "47efe264-4c3f-a883-2663da932e70"
              ~ include          = [
                  - {
                      - group = {
                          - id = "6f6127e4-499a-8bac-5e21bb580820" -> null
                        } -> null
                    },
                ] -> (known after apply)
              - name             = "Filter by email nifi" -> null
              ~ require          = [] -> (known after apply)
                # (2 unchanged attributes hidden)
            },
        ]
      + saas_app                     = (known after apply)
      + scim_config                  = (known after apply)
      - self_hosted_domains          = [
          - "example.com",
        ] -> null
      + skip_app_launcher_login_page = false
      - tags                         = [] -> null
      + target_criteria              = (known after apply)
      ~ updated_at                   = "2025-04-18T09:52:57Z" -> (known after apply)
        # (11 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_group.group["Admins ips"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_group" "group" {
      ~ created_at = "2025-03-25T13:30:58Z" -> (known after apply)
        id         = "8723aad0-8b14-4f39-c293233fbb6d"
      ~ include    = [
          ~ {
              ~ ip = {
                  ~ ip = "2a02:2f0f:c00::/64" -> "2a02:2f0f:c00:d159:548e:6bbd/64"
                }
            },
            # (5 unchanged elements hidden)
        ]
        name       = "Admins ips"
      ~ require    = [] -> (known after apply)
      ~ updated_at = "2025-04-18T09:52:55Z" -> (known after apply)
        # (2 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_identity_provider.provider["OpenID Connect"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_identity_provider" "provider" {
      ~ config      = {
          + client_secret = (sensitive value)
          ~ redirect_url  = "https://example.cloudflareaccess.com/cdn-cgi/access/callback" -> (known after apply)
            # (5 unchanged attributes hidden)
        }
        id          = "f26b2aeb-2b29-41de-cf3be7392ead"
        name        = "Name SSO"
      ~ scim_config = {
          + scim_base_url    = (known after apply)
          - seat_deprovision = false -> null
          + secret           = (sensitive value)
          - user_deprovision = false -> null
            # (1 unchanged attribute hidden)
        }
        # (2 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_policy.policy["Everyone"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_policy" "policy" {
      ~ app_count                      = 0 -> (known after apply)
      + approval_groups                = (known after apply)
      + approval_required              = false
      ~ created_at                     = "2025-03-25T13:31:04Z" -> (known after apply)
        id                             = "94a93801-209c-4c36-e8a6cac51d89"
      + isolation_required             = false
        name                           = "Everyone"
      + purpose_justification_required = false
      ~ reusable                       = true -> (known after apply)
      ~ updated_at                     = "2025-04-18T09:52:56Z" -> (known after apply)
        # (6 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_policy.policy["Filter by email"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_policy" "policy" {
      ~ app_count                      = 1 -> (known after apply)
      + approval_groups                = (known after apply)
      + approval_required              = false
      ~ created_at                     = "2025-03-25T13:31:04Z" -> (known after apply)
        id                             = "6bebb1b4-0da3-a77e-e617d31bde08"
      + isolation_required             = false
        name                           = "Filter by email"
      + purpose_justification_required = false
      ~ reusable                       = true -> (known after apply)
      ~ updated_at                     = "2025-04-18T09:52:56Z" -> (known after apply)
        # (6 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_policy.policy["Filter by email nifi"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_policy" "policy" {
      ~ app_count                      = 1 -> (known after apply)
      + approval_groups                = (known after apply)
      + approval_required              = false
      ~ created_at                     = "2025-03-25T13:31:04Z" -> (known after apply)
        id                             = "47efe264-4c3f-a883-2663da932e70"
      + isolation_required             = false
        name                           = "Filter by email nifi"
      + purpose_justification_required = false
      ~ reusable                       = true -> (known after apply)
      ~ updated_at                     = "2025-04-18T09:52:56Z" -> (known after apply)
        # (6 unchanged attributes hidden)
    }

  # cloudflare_zero_trust_access_policy.policy["Filter by ip"] will be updated in-place
  ~ resource "cloudflare_zero_trust_access_policy" "policy" {
      ~ app_count                      = 2 -> (known after apply)
      + approval_groups                = (known after apply)
      + approval_required              = false
      ~ created_at                     = "2025-03-25T13:31:04Z" -> (known after apply)
        id                             = "ceda7e11-5421-4d49-1e9da73fa590"
      + isolation_required             = false
        name                           = "Filter by ip"
      + purpose_justification_required = false
      ~ reusable                       = true -> (known after apply)
      ~ updated_at                     = "2025-04-18T09:52:56Z" -> (known after apply)
        # (6 unchanged attributes hidden)
    }

Plan: 0 to add, 8 to change, 0 to destroy.

octavian2204 avatar Apr 18 '25 10:04 octavian2204

Clearly this is a consequence of doing the fully automatic generation. The api will return a full object on a GET, even if the terraform object has not set the properties. This is especially obvious when setting policies on an application:

Image

(Notice how the ID have not changed but simply the properties on the policy object that is managed somewhere else.

All properties on the policies objects are retrieved on GET from the API, and since technically it is possible to set these properties on the terraform object (because it is autogenerated) it would be wholly redundant to set the name of a policy that I am referencing by ID.

HOWEVER, even with full on ignore_changes on every change the provider suggests for an access application, it will still want to make an apply with all of it simply updates from the API:

Image

(and yes I have added ignore changes for footer_links, and path_cookie_attribute etc, but either it complains that it is a redundant ignore or it simply ignores the ignore.

petero-dk avatar Apr 24 '25 20:04 petero-dk

And for anyone who cares about minimizing the output (but not removing the constant apply) this is my ignore in Terraform:


  lifecycle {
    ignore_changes = [
      destinations, self_hosted_domains, path_cookie_attribute, skip_app_launcher_login_page,
      policies.0.name, policies.0.decision, policies.0.exclude, policies.0.include, policies.0.connection_rules, policies.0.require,
      policies.1.name, policies.1.decision, policies.1.exclude, policies.1.include, policies.1.connection_rules, policies.1.require
   ]
  }

It gives a warning The attribute "self_hosted_domains" is deprecated. but without it, it wants to change the property

Sidenote:

Adding this, will STILL make the resource wanting to update

  lifecycle {
    ignore_changes = all
  }

petero-dk avatar Apr 24 '25 20:04 petero-dk

FWIW, cloudflare_zero_trust_organization seems to be affected as well.

lavaturtle avatar Apr 29 '25 20:04 lavaturtle

has there been any word from cloudflare team on a fix for this? obviously it's not mission critical but man is this bug annoying

brizzbuzz avatar May 03 '25 11:05 brizzbuzz

Discussed during the triage today, and wanted to confirm that this one is not fixed in the upcoming 5.4.0, but we're still looking.

jhutchings1 avatar May 05 '25 21:05 jhutchings1

This resource has been giving me hell. it's simply impossible to use.

bluemalkin avatar May 09 '25 17:05 bluemalkin

+1 this is an issue for us too

pdeva avatar May 10 '25 05:05 pdeva

Unfortunately, we are also running into this issue regarding the cloudflare_zero_trust_access_application resource. It seems like this was open about a month ago and is impacting our now updated terraform repo and confusing users. Has anyone got a workaround or is there a possible fix for this?

ronballesteros avatar May 22 '25 03:05 ronballesteros

@ronballesteros Not to my knowledge. I've just been holding off on upgrading my modules to 5.x because of all the bugs with Zero Trust resources. 🙁

chris-pinola-rf avatar May 22 '25 14:05 chris-pinola-rf

@ronballesteros version 5.1.0 works for us

per-lind avatar May 23 '25 18:05 per-lind

@ronballesteros version 5.1.0 works for us

its strange, can you confirm? Try another resources like cloudflare_access_rule or anything else in cloudflare provider

octavian2204 avatar May 24 '25 11:05 octavian2204

On the latest version 5.5 we are now seeing an error that completely fails the apply :

 Error: Provider produced inconsistent result after apply
│ 
│ When applying changes to
│ cloudflare_zero_trust_access_policy.cloudflare_bypass, provider
│ "provider[\"registry.terraform.io/cloudflare/cloudflare\"]" produced an
│ unexpected new value: .app_count: was cty.NumberIntVal(0), but now
│ cty.NumberIntVal(2).
│ 
│ This is a bug in the provider, which should be reported in the provider's
│ own issue tracker.

Edit, can see this is reported in #5608

petero-dk avatar May 27 '25 01:05 petero-dk

yea we had the same, had to pin to v5.4.

I understand why CF team wants to go with the auto generated approach for the provider, but so far the result has been a disaster.

Wish I had shipped our new codebase on the v4 provider.

brizzbuzz avatar May 27 '25 07:05 brizzbuzz

yea we had the same, had to pin to v5.4.

I understand why CF team wants to go with the auto generated approach for the provider, but so far the result has been a disaster.

Wish I had shipped our new codebase on the v4 provider.

We implemented a workaround for the issue in 5.5 which works:

  lifecycle {
    ignore_changes = [app_count, reusable]
  }

petero-dk avatar May 27 '25 18:05 petero-dk

I'm having the same issues where the fields pulled from the cloudflare_zero_trust_access_policy resources referenced in the policies list apparently ignored/reset when Terraform proposes the plan. This is with v5.5.0. I don't want to have to set temporary lifecycle ignore policies on a bunch of resources throughout the code to avoid clobbering our infrastructure.

knightsg avatar May 30 '25 23:05 knightsg

After adding ignore to all

lifecycle {
  ignore_changes = all
}

the diff is shown as below:

  ~ resource "cloudflare_zero_trust_access_application" "test" {
      ~ aud                          = "dc7b25bfc7d0aa7dbc06406a910a3dc3b17b270025a66d9fa37c9115d9c040af" -> (known after apply)
      ~ created_at                   = "2025-06-02T12:43:46Z" -> (known after apply)
        id                           = "355886c2-d2bf-4514-93b6-5748227d3111"
      + landing_page_design          = (known after apply)
        name                         = "test"
      + path_cookie_attribute        = false
      + saas_app                     = (known after apply)
      + skip_app_launcher_login_page = false
        tags                         = []
      ~ updated_at                   = "2025-06-02T13:37:18Z" -> (known after apply)
        # (13 unchanged attributes hidden)
    }

It seems like the issue is that the provider doesn't see the current state for some of the fields above, values from the state file.

"aud": "dc7b25bfc7d0aa7dbc06406a910a3dc3b17b270025a66d9fa37c9115d9c040af", (matches)
"created_at": "0001-01-01T00:00:00Z",
"landing_page_design": null,
"path_cookie_attribute": false,
"saas_app": null,
"skip_app_launcher_login_page": false,

I'd bet that issue is with bugged created_at or one of the attributes that already match value but still show as diff path_cookie_attribute or skip_app_launcher_login_page

provider v5.5.0

jkotiuk avatar Jun 02 '25 13:06 jkotiuk

Is there a known work-around?

paaloeye avatar Jun 06 '25 02:06 paaloeye

@per-lind @octavian2204 - can confirm that I don't see the changes for cloudflare_zero_trust_access_application on version 5.1.0, however, we got other application changes for other resources such as cloudflare_zero_trust_access_policy.

Terraform will perform the following actions:

  # cloudflare_zero_trust_access_policy.<redacted> will be updated in-place
  ~ resource "cloudflare_zero_trust_access_policy" "<redacted>" {
      ~ app_count                      = 8 -> (known after apply)
      ~ approval_groups                = [] -> (known after apply)
      + approval_required              = false
      ~ created_at                     = "2024-06-19T16:56:14Z" -> (known after apply)
        id                             = "<redacted>"
      + isolation_required             = false
        name                           = "<redacted>"
      + purpose_justification_required = false
      ~ reusable                       = true -> (known after apply)
      ~ updated_at                     = "2025-05-21T20:45:39Z" -> (known after apply)
        # (6 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

ronballesteros avatar Jun 06 '25 10:06 ronballesteros

I downgraded to 5.1.0 but still have loads of changes for cloudflare_zero_trust_access_application.

paaloeye avatar Jun 10 '25 07:06 paaloeye

I ended up with following workaround:

variable "cf_zero_trust_workaround" {
  type    = bool
  default = true
}

resource "cloudflare_zero_trust_access_application" "apps" {
  for_each = var.name == "live" ? {} : (var.cf_zero_trust_workaround == true ? {} : local.domains_apex_only)
}

It hides all cloudflare_zero_trust_access_application after creation via cf_zero_trust_workaround flag.

Here is a script in Nushell to delete them from the state:

tf plan -- -out .tmp/plan.out
tf show -- -json .tmp/plan.out | from json | get
(tf show -- -json .tmp/plan.out | from json
  | get resource_changes
  | select address change
  | where { ($in | get change | get actions | first) == "delete" }
  | get address
  | each { terraform state rm $in })

paaloeye avatar Jun 10 '25 09:06 paaloeye

Has anyone tested on this with version 5.6.0?

cpapad avatar Jun 23 '25 13:06 cpapad

Has anyone tested on this with version 5.6.0?

@cpapad I recently reran our migration workflow with 5.6.0 and it's still doing the same thing.

knightsg avatar Jun 23 '25 18:06 knightsg

Has anyone tested on this with version 5.6.0?

@cpapad I recently reran our migration workflow with 5.6.0 and it's still doing the same thing.

Thank you! I'll stick with 5.1.0 until this is resolved

cpapad avatar Jun 24 '25 08:06 cpapad

I'm seeing the same issues as others. Has a root cause been found at least?

MScottBlake avatar Jun 27 '25 19:06 MScottBlake

I have the bug with these attributes in 5.6.0: landing_page_design, path_cookie_attribute, saas_app, skip_app_launcher_login_page. And of course I defined everything, but still I have to ignore policies if I don't want 20 more lines of change for each app. Anyone knows how can we put someone from cloudflare on it ?

RoyLDD avatar Jul 04 '25 12:07 RoyLDD