Skip to content

saif-resources / external-identity

Resolves Okta (external tenant) OAuth/OIDC app settings for a consuming service.

Native Okta lookups, zero remote state (#845)

This module has no tfe_outputs reads. All okta_app fields — including the front-end/Web app's OpenIdConnectClientId/OpenIdConnectClientSecret, previously a residual remote-state read — are now native Okta data-source lookups:

  • API app (data.okta_apps.api_app + data.okta_app_oauth.api_app) — label derived from project_id (lower(project_id) prod, lower("${project_id}-np") non-prod), mirroring the producer module's own naming. Resolved in two steps: search with q, filter the results down to an exact label match, then look the app up by id. A single okta_app_oauth { label = ... } lookup is not safe here — see Label collisions below.
  • Front-end/Web app (data.okta_apps.front_end + data.okta_app_oauth.front_end) — only a minority of consuming services provision one, so a direct okta_app_oauth lookup (which hard-fails on no match) can't gate on existence. The plural data.okta_apps data source fixes that: it returns an empty list (no error) when its exact label match finds nothing, giving a genuine existence signal. Its project_id is derived from this module's project_id by replacing the -api-<type>- segment with -web- (e.g. pol-api-exp-policyportal → pol-web-policyportal — confirmed against every real front-end pairing in production). See the comments on data "okta_apps" "front_end" in main.tf for the full rationale.

Label collisions

The singular okta_app_oauth data source's label argument is unsafe when any other app's label starts with the one being looked up. The provider implements it as a limit=1 query against Okta's List Apps API, where q is a case-insensitive startsWith match over label and name and results are sorted by creation date. If a prefix-overlapping app was created first, it takes the single slot and the lookup fails with:

Error: no OAuth application found with the provided label: <label>

even though the requested app exists and is ACTIVE. clm-api-proc-claim hit this against clm-api-proc-claimintake. The failure depends on app creation order in the org, not on configuration, so it can appear on a workspace that previously planned cleanly.

This is tracked upstream as okta/terraform-provider-okta#2847. The generic okta_app data source was fixed for the same bug in #1111/#1115, but the fix was never propagated to okta_app_oauth or okta_app_saml, and it is still unfixed as of provider 6.11.0. Both app lookups in this module therefore go through the plural okta_apps data source, which paginates the full result set, and filter it for an exact label match in a local.

A lifecycle.precondition asserts that exactly one app matched. This is load bearing, not cosmetic: with zero matches the id argument would be null, which makes the provider list applications with no search filter at all and bind whichever app comes back first. That app's client_secret would then be written to Key Vault under this service's name and its client_id published as OAuthClientId_ext.

Coverage lives in tests/validate.tftest.hcl.

Providers

Name Version
azurerm.shared-services >= 4.0, < 5.0
okta >= 4.18.0, < 5.0.0

Inputs

Name Description Type Default Required
context Platform context from the environment module any n/a yes
enable_oidc Whether to emit OpenIdConnectClientId_ext / OpenIdConnectClientSecret_ext app settings bool false no
identity Identity bundle from the identity module (needs uami_principal_id for KV RBAC) any n/a yes
project_id The project identifier, used for KV secret naming string n/a yes

Outputs

Name Description
app_settings Map of Okta (ext) credential app settings. Merge into webapp app_settings.
auth_server_audience The Okta authorization server audience (for APIM policies)
auth_server_url The Okta authorization server URL (for APIM policies)
has_open_id_connect Whether the Okta workspace has OpenID Connect configured
token_lifetime Token lifetime configuration from Okta data module. Contains ExternalAccess, ExternalRefresh, CorpAccess, CorpRefresh keys.

Resources

  • resource.azurerm_key_vault_secret.oidc_client_secret (/terraform-docs/modules/external-identity/main.tf#190)
  • resource.azurerm_key_vault_secret.okta_client_secret (/terraform-docs/modules/external-identity/main.tf#180)
  • resource.azurerm_role_assignment.oidc_secret_reader (/terraform-docs/modules/external-identity/main.tf#213)
  • resource.azurerm_role_assignment.okta_secret_reader (/terraform-docs/modules/external-identity/main.tf#200)
  • data source.okta_app_oauth.api_app (/terraform-docs/modules/external-identity/main.tf#65)
  • data source.okta_app_oauth.front_end (/terraform-docs/modules/external-identity/main.tf#116)
  • data source.okta_apps.api_app (/terraform-docs/modules/external-identity/main.tf#60)
  • data source.okta_apps.front_end (/terraform-docs/modules/external-identity/main.tf#111)
  • data source.okta_auth_server.api_app (/terraform-docs/modules/external-identity/main.tf#81)

View source on GitHub