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 fromproject_id(lower(project_id)prod,lower("${project_id}-np")non-prod), mirroring the producer module's own naming. Resolved in two steps: search withq, filter the results down to an exact label match, then look the app up byid. A singleokta_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 directokta_app_oauthlookup (which hard-fails on no match) can't gate on existence. The pluraldata.okta_appsdata source fixes that: it returns an empty list (no error) when its exactlabelmatch finds nothing, giving a genuine existence signal. Itsproject_idis derived from this module'sproject_idby 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 ondata "okta_apps" "front_end"inmain.tffor 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:
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)