okta / terraform-provider-okta

A Terraform provider to manage Okta resources, enabling infrastructure-as-code provisioning and management of users, groups, applications, and other Okta objects.
https://registry.terraform.io/providers/okta/okta
Mozilla Public License 2.0
257 stars 208 forks source link

Terraform plan showing changes when no changed being made #2052

Open mikeally99 opened 2 months ago

mikeally99 commented 2 months ago

Community Note

Terraform Version

Terraform Version: v1.7.5

Initializing provider plugins...

Terraform Configuration Files

# Copy-paste your Terraform configurations here - for large Terraform configs,
# please use a service like Dropbox and share a link to the ZIP file. For
# security, you can also encrypt the files using our GPG public key: https://keybase.io/hashicorp

Debug Output

~ update in-place Terraform will perform the following actions:

module.okta.okta_app_signon_policy_rule.app_polrul_10_03 will be updated in-place

  ~ resource "okta_app_signon_policy_rule" "app_polrul_10_03" {
      ~ constraints                 = [
          - jsonencode(
                {
                  - possession = {}
                }
            ),
          + jsonencode(
                {
                  + possession = {
                      + excludedAuthenticationMethods = [
                          + {
                              + key    = "okta_email"
                              + method = "email"
                            },
                          + {
                              + key    = "phone_number"
                              + method = "sms"
                            },
                          + {
                              + key    = "phone_number"
                              + method = "voice"
                            },
                        ]
                      + required                      = "false"
                    }
                }
            ),
        ]
        id                          = "rulfjznakbqu5jhpk1d7"
        name                        = "Custom Catch-all Rule intextMFA"
        # (15 unchanged attributes hidden)
    }

module.okta.okta_app_signon_policy_rule.app_polrul_14_01 will be updated in-place

  ~ resource "okta_app_signon_policy_rule" "app_polrul_14_01" {
        id                          = "rulfjziw5fc5PlIBO1d7"
        name                        = "SFDC-GlobalResponseVpn-AllowDesktop"
        # (17 unchanged attributes hidden)
      - platform_include {
          - os_type = "CHROMEOS" -> null
          - type    = "DESKTOP" -> null
        }
      - platform_include {
          - os_type = "MACOS" -> null
          - type    = "DESKTOP" -> null
        }
      - platform_include {
          - os_type = "OTHER" -> null
          - type    = "DESKTOP" -> null
        }
      - platform_include {
          - os_type = "OTHER" -> null
          - type    = "MOBILE" -> null
        }
      - platform_include {
          - os_type = "WINDOWS" -> null
          - type    = "DESKTOP" -> null
        }
      + platform_include {
          + os_expression = "\"\""
          + os_type       = "OTHER"
          + type          = "DESKTOP"
        }
      + platform_include {
          + os_expression = "\"\""
          + os_type       = "OTHER"
          + type          = "MOBILE"
        }
      + platform_include {
          + os_type = "CHROMEOS"
          + type    = "DESKTOP"
        }
      + platform_include {
          + os_type = "MACOS"
          + type    = "DESKTOP"
        }
      + platform_include {
          + os_type = "WINDOWS"
          + type    = "DESKTOP"
        }
    }
  # module.okta.okta_app_signon_policy_rule.app_polrul_14_02 will be updated in-place
  ~ resource "okta_app_signon_policy_rule" "app_polrul_14_02" {
        id                          = "rulfjzsxtnqE77tDH1d7"
        name                        = "SFDC - intranet"
        # (17 unchanged attributes hidden)
      - platform_include {
          - os_type = "CHROMEOS" -> null
          - type    = "DESKTOP" -> null
        }
      - platform_include {
          - os_type = "MACOS" -> null
          - type    = "DESKTOP" -> null
        }
      - platform_include {
          - os_type = "OTHER" -> null
          - type    = "DESKTOP" -> null
        }
      - platform_include {
          - os_type = "OTHER" -> null
          - type    = "MOBILE" -> null
        }
      - platform_include {
          - os_type = "WINDOWS" -> null
          - type    = "DESKTOP" -> null
        }
      + platform_include {
          + os_expression = "\"\""
          + os_type       = "OTHER"
          + type          = "DESKTOP"
        }
      + platform_include {
          + os_expression = "\"\""
          + os_type       = "OTHER"
          + type          = "MOBILE"
        }
      + platform_include {
          + os_type = "CHROMEOS"
          + type    = "DESKTOP"
        }
      + platform_include {
          + os_type = "MACOS"
          + type    = "DESKTOP"
        }
      + platform_include {
          + os_type = "WINDOWS"
          + type    = "DESKTOP"
        }
    }
  # module.okta.okta_app_signon_policy_rule.app_polrul_15_01 will be updated in-place
  ~ resource "okta_app_signon_policy_rule" "app_polrul_15_01" {
        id                          = "rulfjzt27pZDW5Qvn1d7"
        name                        = "SFDC - intranet"
        # (17 unchanged attributes hidden)
      - platform_include {
          - os_type = "CHROMEOS" -> null
          - type    = "DESKTOP" -> null
        }
      - platform_include {
          - os_type = "MACOS" -> null
          - type    = "DESKTOP" -> null
        }
      - platform_include {
          - os_type = "OTHER" -> null
          - type    = "DESKTOP" -> null
        }
      - platform_include {
          - os_type = "OTHER" -> null
          - type    = "MOBILE" -> null
        }
      - platform_include {
          - os_type = "WINDOWS" -> null
          - type    = "DESKTOP" -> null
        }
      + platform_include {
          + os_expression = "\"\""
          + os_type       = "OTHER"
          + type          = "DESKTOP"
        }
      + platform_include {
          + os_expression = "\"\""
          + os_type       = "OTHER"
          + type          = "MOBILE"
        }
      + platform_include {
          + os_type = "CHROMEOS"
          + type    = "DESKTOP"
        }
      + platform_include {
          + os_type = "MACOS"
          + type    = "DESKTOP"
        }
      + platform_include {
          + os_type = "WINDOWS"
          + type    = "DESKTOP"
        }
    }
  # module.okta.okta_app_signon_policy_rule.app_polrul_17_02 will be updated in-place
  ~ resource "okta_app_signon_policy_rule" "app_polrul_17_02" {
      ~ constraints                 = [
          - jsonencode(
                {
                  - knowledge  = {
                      - reauthenticateIn = "xxxxx"
                      - types            = [
                          - "password",
                        ]
                    }
                  - possession = {
                      - userPresence = "OPTIONAL"
                    }
                }
            ),
          + jsonencode(
                {
                  + knowledge  = {
                      + reauthenticateIn = "PT43800H"
                      + types            = [
                          + "password",
                        ]
                    }
                  + possession = {
                      + authenticationMethods = [
                          + {
                              + key    = "okta_verify"
                              + method = "signed_nonce"
                            },
                          + {
                              + key    = "okta_verify"
                              + method = "push"
                            },
                          + {
                              + key    = "webauthn"
                              + method = "webauthn"
                            },
                          + {
                              + key    = "yubikey_token"
                              + method = "otp"
                            },
                        ]
                      + userPresence          = "OPTIONAL"
                    }
                }
            ),
        ]
        id                          = "rulfjzgfhr0rI8PUB1d7"
        name                        = "Delinea HighPriv"
        # (16 unchanged attributes hidden)
    }
```diff
  # module.okta.okta_authenticator.okta_verify will be updated in-place
  ~ resource "okta_authenticator" "okta_verify" {
        id                          = "autb7gs0lkpEZSLCm1d7"
        name                        = "Okta Verify"
      ~ settings                    = jsonencode(
          ~ {
              + appInstanceId           = ""
              + enrollmentSecurityLevel = "ANY"
              + userVerificationMethods = [
                  + "BIOMETRICS",
                  + "PIN",
                ]
                # (3 unchanged attributes hidden)
            }
        )
        # (6 unchanged attributes hidden)
    }
  # module.okta.okta_network_zone.AWSNetworkZone-Mastercard will be updated in-place
  ~ resource "okta_network_zone" "AWSNetworkZone-Mastercard" {
      ~ gateways = [
          - "xxxxx",
          - "xxxx",
          - xxxx",
          - "xxxxx",
          + "xxxxx",
          + "xxxxx",
          + "xxxxx",
          + "xxxxx",
          + "xxxxx",
          + "xxxxx",
          + "xxxxx",
          + "xxxxx",
          + "xxxxx,
        ]
        id       = "nzofjyokiovvyiDHJ1d7"
      ~ name     = "Fairsquare ZPA Zone" -> "AWSNetworkZone-Mastercard"
        # (4 unchanged attributes hidden)
    }
  # module.okta.okta_policy_signon.signon_pol07 will be updated in-place
  ~ resource "okta_policy_signon" "signon_pol07" {
      ~ groups_included = [
          - "00gb7gpmsrPRuwIvl1d7",
        ]
        id              = "00pf7gp9g7YpaVh6U1d7"
        name            = "GP MaxSession"
        # (3 unchanged attributes hidden)
    }

terraform apply -input=false -auto-approve plan.tfplan module.okta.okta_network_zone.AWSNetworkZone-Mastercard: Modifying... [id=nzofjyokiovvyiDHJ1d7] module.okta.okta_authenticator.okta_verify: Modifying... [id=autb7gs0lkpEZSLCm1d7] module.okta.okta_app_signon_policy_rule.app_polrul_17_02: Modifying... [id=rulfjzgfhr0rI8PUB1d7] module.okta.okta_policy_signon.signon_pol07: Modifying... [id=00pf7gp9g7YpaVh6U1d7] module.okta.okta_app_signon_policy_rule.app_polrul_10_03: Modifying... [id=rulfjznakbqu5jhpk1d7] module.okta.okta_app_signon_policy_rule.app_polrul_14_01: Modifying... [id=rulfjziw5fc5PlIBO1d7] module.okta.okta_app_signon_policy_rule.app_polrul_15_01: Modifying... [id=rulfjzt27pZDW5Qvn1d7] module.okta.okta_network_zone.AWSNetworkZone-Mastercard: Modifications complete after 0s [id=nzofjyokiovvyiDHJ1d7] module.okta.okta_app_signon_policy_rule.app_polrul_17_02: Modifications complete after 0s [id=rulfjzgfhr0rI8PUB1d7] module.okta.okta_app_signon_policy_rule.app_polrul_14_01: Modifications complete after 0s [id=rulfjziw5fc5PlIBO1d7] module.okta.okta_app_signon_policy_rule.app_polrul_10_03: Modifications complete after 0s [id=rulfjznakbqu5jhpk1d7] module.okta.okta_app_signon_policy_rule.app_polrul_14_02: Modifying... [id=rulfjzsxtnqE77tDH1d7] module.okta.okta_app_signon_policy_rule.app_polrul_15_01: Modifications complete after 0s [id=rulfjzt27pZDW5Qvn1d7] module.okta.okta_policy_signon.signon_pol07: Modifications complete after 1s [id=00pf7gp9g7YpaVh6U1d7] module.okta.okta_authenticator.okta_verify: Modifications complete after 1s [id=autb7gs0lkpEZSLCm1d7] module.okta.okta_app_signon_policy_rule.app_polrul_14_02: Modifications complete after 1s [id=rulfjzsxtnqE77tDH1d7] Apply complete! Resources: 0 added, 8 changed, 0 destroyed.

Panic Output

none

Expected Behavior

No changes should have showed up in the terraform plan and there shouldn't of been any modifications, all we did was rerun the same config again.

Can this be done in the Admin UI?

No

Can this be done in the actual API call?

I don't know - When we call the API it shows the proper data.

Actual Behavior

Its making changes when the code is static. Just rerunning the same commit.

Steps to Reproduce

  1. terraform apply
  2. watch logs

Important Factoids

no

References

exitcode0 commented 2 months ago

( I'm not from Okta ) While this config is quite hard to read without any formatting

Is this newly created configuration, or a modification of existing configuration? when you applied this configuration for the first time, did terraform successfully apply your requested configuration?

If terraform updates a resource and a part of that update is successful, the Okta API will sometimes return a HTTP 200 Terraform therefor believes that the update was successful, but on the next terraform run it will see that the config doesn't match the desired state and will attempt to apply the same config again then the cycle repeats

If i'm correct about what is going on here, this behavior is a result of design decisions in the upstream Okta API

mikeally99 commented 2 months ago

We ran terraform once to build the items in okta. Then ran it again (same commit) and it showed changes to be made. Ok I’ll check to make sure the change was made.

Thanks 😊

From: Robert Mcgregor @.> Date: Tuesday, August 6, 2024 at 7:16 AM To: okta/terraform-provider-okta @.> Cc: Fisher, Michael @.>, Author @.> Subject: EXTERNAL Re: [okta/terraform-provider-okta] Terraform plan showing changes when no changed being made (Issue #2052) ( I'm not from Okta ) While this config is quite hard to read without any formatting Is this newly created configuration, or a modification of existing configuration? when you applied this configuration for the first time, did terraform successfully

( I'm not from Okta ) While this config is quite hard to read without any formatting

Is this newly created configuration, or a modification of existing configuration? when you applied this configuration for the first time, did terraform successfully apply your requested configuration?

If terraform updates a resource and a part of that update is successful, the Okta API will sometimes return a HTTP 200 Terraform therefor believes that the update was successful, but on the next terraform run it will see that the config doesn't match the desired state and will attempt to apply the same config again then the cycle repeats

If i'm correct about what is going on here, this behavior is a result of design decisions in the upstream Okta API

— Reply to this email directly, view it on GitHubhttps://urldefense.com/v3/__https:/github.com/okta/terraform-provider-okta/issues/2052*issuecomment-2271042306__;Iw!!OvkwO7jMGv3YbLsL!5kSqfTT1AVopvvJjuXPfVarfgQk0_X-6Klq7mtUPBlwWquPx0asB0j3lllVPvqQ12EzV10rjjt_yBAikJF1XzIrty48$, or unsubscribehttps://urldefense.com/v3/__https:/github.com/notifications/unsubscribe-auth/AOXEGGLJ6DSHCHCNQHKMGUTZQCWCBAVCNFSM6AAAAABLZGKW32VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENZRGA2DEMZQGY__;!!OvkwO7jMGv3YbLsL!5kSqfTT1AVopvvJjuXPfVarfgQk0_X-6Klq7mtUPBlwWquPx0asB0j3lllVPvqQ12EzV10rjjt_yBAikJF1Xc_TXTbU$. You are receiving this because you authored the thread.Message ID: @.***>

duytiennguyen-okta commented 2 months ago

Thank you @exitcode0. Hi @mikeally99, the situation is as @exitcode0 describe. It is the result from the upstream API. If there is something that does not apply correctly, then I will create a bug ticket, but if not then we can just close this one out

joecarterbooking commented 2 months ago

We observed similar behaviour with our existing 'okta_app_signon_policy_rule' resources after moving to provide 4.10.0. The root cause seems to be a bug in the way that rules are created (either by UI or TF). When we create a rule, it defaults to adding the phone (SMS and call) and e-mail authenticators to the list of excluded authenticators. This in effect sets the possession required flag to false. When Terraform then runs, it tries to remove this flag because if you don't explicitly exclude authenticators, it should be true. However, TF does not clear the excluded authenticators, so this will happen on each run.

The bug comes when you then change the rule to something like any 2 factors. This then removes the excluded authenticators. They even remain removed if you revert the rule back the original IDP+factor. This to me seems to be a bug with the way policies rules are created.

pro4tlzz commented 2 months ago

Okta changed some things without releasing notes about them, that's why you see PLATFORM_INCLUDE changes for example. In the admin console in a production org try to manually edit an auth policy rule that uses device assurances for desktop platforms and you won't be able to specify the device platform separately anymore, however you can still do this for Okta mobile.

duytiennguyen-okta commented 2 months ago

OKTA internal reference https://oktainc.atlassian.net/browse/OKTA-793222

rjthomas02 commented 2 months ago

So is this also related to the output I see for my Terraform plan. The logic is opposite that the required=true is being removed for the assigned authenticators?

pro4tlzz commented 2 months ago

So is this also related to the output I see for my Terraform plan. The logic is opposite that the required=true is being removed for the assigned authenticators? - jsonencode( { - knowledge = { - reauthenticateIn = "PT2H" - required = true - types = [ - "password", ] } - possession = { - deviceBound = "REQUIRED" - hardwareProtection = "REQUIRED" - phishingResistant = "REQUIRED" - required = true } } ), + jsonencode( { + knowledge = { + reauthenticateIn = "PT2H" + types = [ + "password", ] } + possession = { + deviceBound = "REQUIRED" + hardwareProtection = "REQUIRED" + phishingResistant = "REQUIRED"

If you check the actual Okta Policy API for that rule you'll see that the required key isn't present anymore. This isn't really a terraform bug, just upstream Okta API changes with no announcements being made...

MichalMMac commented 2 weeks ago

Problem with os_expression in okta_app_signon_policy_rule is quite annoying (Reproducible with 4.11).

We use this code to select all other desktop platforms:

 platform_include {
          + os_expression = ".*"
          + os_type       = "OTHER"
          + type          = "DESKTOP"
        }

Keeping .* in os_expression results in terraform plan / terraform plan to suggest these changes on every run:

 platform_include {
          - os_type       = "MACOS" -> null
          - type          = "DESKTOP" -> null
            # (1 unchanged attribute hidden)
        }
      - platform_include {
          - os_type       = "OTHER" -> null
          - type          = "DESKTOP" -> null
            # (1 unchanged attribute hidden)
        }
      - platform_include {
          - os_type       = "WINDOWS" -> null
          - type          = "DESKTOP" -> null
            # (1 unchanged attribute hidden)
        }
      + platform_include {
          + os_expression = ".*"
          + os_type       = "OTHER"
          + type          = "DESKTOP"
        }
      + platform_include {
          + os_type = "MACOS"
          + type    = "DESKTOP"
        }
      + platform_include {
          + os_type = "WINDOWS"
          + type    = "DESKTOP"
        }

The workaround is to change os_expression value to an empty string "". Terraform won't then try to make any changes to the object. The downside is that you have to remember to put back .* any time you do some other change to the object. Otherwise the API call fails.