Terraform export

What you get

TFsmith generates HCL for the official Terraform providers: goauthentik/authentik, okta/okta, and auth0/auth0, against each provider's own published schema. Two ways to use it:

Per object: every row in the object list has a Terraform button showing that object as a resource block plus a matching import block, with copy and download.

Whole tenant: Export bundle... lets you pick resource types and downloads a zip with one .tf file per type, provider setup, variables, import blocks, and a coverage README.

You need Terraform 1.5 or newer (import blocks). OpenTofu works identically. Export is read-only: TFsmith never writes anything to your identity provider.

The import block

Every exported resource comes with an import block like this:

import {
  to = okta_app_saml.duo_admin_panel
  id = "0oaim59q48RDNPzik357"
}

Terraform only manages what is in its state file, and a fresh state file is empty. Without the import block, terraform plan against your tenant would try to CREATE a duplicate of every object. The import block tells Terraform "this resource is the EXISTING object with this id, adopt it into state". Your first plan then shows will be imported instead of will be created, and Terraform manages the real object from then on.

Same tenant, or a different one?

Bringing THIS tenant under Terraform management: keep the import blocks. Plan, review, apply: your existing objects are adopted, nothing is recreated.

Promoting to a DIFFERENT instance (staging to prod, a fresh tenant): remove the import blocks. Those ids only exist in the source tenant; in the target you want Terraform to create the objects. In the bundle that is one file (import.tf) to delete.

The target already has some of the objects (created by hand earlier): write import blocks using the TARGET tenant's ids.

Cross-references between objects

Provider-assigned ids are per-instance - never portable. The bundle export handles this for you: when a referenced object is part of the same export, the reference is rewritten to a Terraform expression (for example groups_included = [okta_group.slack_users.id]) that resolves at apply time to whatever id the target assigns. A single copied block keeps literal source ids: fine for self-contained objects, but anything with wiring should travel via the bundle or have its ids reviewed against the target.

Built-in objects (like Okta's Everyone group) are never exported, so references to them stay literal. Use the provider's data sources instead, for example data "okta_everyone_group" "all" {} with groups_included = [data.okta_everyone_group.all.id].

Secrets are never exported

Secret values (client secrets, private keys, passwords) are NEVER written into HCL. Every secret becomes a Terraform variable marked sensitive = true in variables.tf; you supply values at plan time (tfvars, environment, or your secret manager). Provider credentials (API URL and token) are variables too.

Commented lines

Fields the provider supports but that are unset in your tenant appear as aligned commented lines (#field = ""). Delete the single # to use one - the line is already correctly formatted.

Honest coverage

Not everything can be represented in the official providers, and TFsmith never drops anything silently: the bundle README lists every skipped object with its reason (for example Okta system apps like the Admin Console, which Terraform cannot manage), and fields with no provider argument are listed per type. Objects that cannot be represented at all are excluded from the object list rather than shown with a broken export.

Convergence check

After importing, run terraform plan again and review the remaining diffs: variable placeholders you have not filled in yet and provider defaults account for most of them. The bar to aim for is "N to import, 0 to add, 0 to destroy" on the first plan - that is the bundle working as designed.

All docs · These docs also ship inside the app under the Docs button.