Resources

Each section shows an example, the attributes worth knowing about and the import command. The provider repository has the full schema of every resource.

An attribute marked replaces cannot be changed in place: changing it destroys the object and creates a new one, with a new UUID. For a user or a client, that also drops what hangs off the old one, such as credentials, sessions and role assignments.

ferriskey_realm

resource "ferriskey_realm" "acme" {
  name = "acme"
}
AttributeDescription
nameRealm name. Renamed in place, but every URL and issuer of the realm changes with it
realm_idUUID, read-only
settingsRead-only copy of the realm settings. Manage them with ferriskey_realm_settings

Destroying the resource deletes the realm and everything in it. The master realm cannot be deleted, so do not manage it with this resource: read it with the ferriskey_realm data source.

terraform import ferriskey_realm.acme acme

ferriskey_realm_settings

resource "ferriskey_realm_settings" "acme" {
  realm                     = ferriskey_realm.acme.name
  access_token_lifetime     = 600
  refresh_token_lifetime    = 43200
  user_registration_enabled = true
  forgot_password_enabled   = true
  passkey_enabled           = true
}

Manages the realm settings: token lifetimes, default_signing_algorithm, registration, forgotten password, remember me, magic links, passkeys, email verification and compass_enabled. Lifetimes are in seconds, email_verification_ttl_hours in hours and magic_link_ttl in minutes.

An update is a partial merge, like the API: a setting you leave out keeps its current value, it is not reset to the default. Destroying the resource stops managing the settings and changes nothing on the server.

require_mfa, login_aliases, the lockout, consent, locale and branding settings are not in the resource yet. Set them in the console or with PUT /realms/{realm_name}/settings.

terraform import ferriskey_realm_settings.acme acme

ferriskey_client

resource "ferriskey_client" "web" {
  realm         = ferriskey_realm.acme.name
  client_id     = "acme-web"
  name          = "Acme Web App"
  client_type   = "confidential"
  redirect_uris = [
    "https://app.acme.example/callback",
    "https://app.acme.example/silent-renew",
  ]
  access_token_lifetime = 300
}

resource "ferriskey_client" "spa" {
  realm                        = ferriskey_realm.acme.name
  client_id                    = "acme-spa"
  name                         = "Acme SPA"
  client_type                  = "public"
  public_client                = true
  direct_access_grants_enabled = false
  redirect_uris                = ["https://spa.acme.example/callback"]
}
AttributeDescription
client_idThe client_id applications send
client_typeconfidential, public or system. Replaces
public_clientNo secret, PKCE carries the protection. Replaces
service_account_enabledAllows the client_credentials grant. Replaces
direct_access_grants_enabledAllows the deprecated password grant
redirect_urisA set, so order does not matter. Leave it out to leave the client’s redirect URIs alone, set [] to remove them all. See redirect URIs
access_token_lifetime, refresh_token_lifetime, id_token_lifetime, temporary_token_lifetimePer-client overrides, in seconds. The realm value applies when unset
secretGenerated by the server, read-only and sensitive. Stored in the state
service_account_user_idThe service account user, when service_account_enabled is on. Give it roles with ferriskey_user_role

The other client properties, such as require_pkce, token_exchange_enabled, consent_required, back-channel logout, post-logout redirects and web origins, are not in the resource yet. A client created by the provider gets the server defaults for them.

terraform import ferriskey_client.web acme/3a8c6128-1111-2222-3333-444455556666

ferriskey_user

resource "ferriskey_user" "alice" {
  realm            = ferriskey_realm.acme.name
  username         = "alice"
  email            = "alice@acme.example"
  email_verified   = true
  firstname        = "Alice"
  lastname         = "Liddell"
  required_actions = ["update_password"]
}
AttributeDescription
usernameReplaces
emailOnce set, it can be changed but not cleared: removing it from the configuration leaves the server value
email_verifiedfalse by default
enabledtrue by default
required_actionsverify_email, update_password, configure_passkey. See required actions
user_uuidUUID, read-only. Use it in ferriskey_user_role and ferriskey_organization_member

The resource sets no password and no credential. Set them in the console, with the API, or let the user sign in another way, such as a magic link or an identity provider.

Leave configure_otp out of required_actions. FerrisKey works it out at each sign-in from the realm and the user’s roles and never stores it, so Terraform would plan to add it on every run.

The user removes verify_email and update_password from their account by completing them. Terraform then plans to add them back. Add lifecycle { ignore_changes = [required_actions] } when the actions are set once at creation.

terraform import ferriskey_user.alice acme/9f1c0e2a-aaaa-bbbb-cccc-ddddeeeeffff

ferriskey_role

resource "ferriskey_role" "support" {
  realm       = ferriskey_realm.acme.name
  name        = "support"
  description = "Read-only support staff"
  permissions = ["view_users", "query_users", "view_clients"]
}

permissions takes the snake_case names of the permissions reference, and replaces the whole set on update. realm replaces. The resource manages realm roles only: client_id is read-only.

A name that matches no permission is dropped silently when the provider’s account holds manage_realm, and refused with a 403 otherwise. In the first case, the server never stores it, so every plan shows it again. Check the names when a role keeps showing a change.

terraform import ferriskey_role.support acme/4b2d7f90-1111-2222-3333-444455556666

ferriskey_user_role

resource "ferriskey_user_role" "alice_support" {
  realm   = ferriskey_realm.acme.name
  user_id = ferriskey_user.alice.user_uuid
  role_id = ferriskey_role.support.role_uuid
}

Assigns a realm role to a user, or to a client’s service account through service_account_user_id. It is a link with no attributes of its own: every change replaces it. Destroying it removes the assignment, not the user or the role.

terraform import ferriskey_user_role.alice_support acme/USER_UUID/ROLE_UUID

ferriskey_organization

resource "ferriskey_organization" "globex" {
  realm       = ferriskey_realm.acme.name
  name        = "Globex"
  alias       = "globex"
  description = "Globex Corporation tenant"
  domain      = "globex.example"
}

alias is the stable, URL-safe identifier of the organization within the realm. enabled is true by default, redirect_url is optional, and realm replaces.

terraform import ferriskey_organization.globex acme/7c3e9a14-1111-2222-3333-444455556666

ferriskey_organization_member

resource "ferriskey_organization_member" "alice_globex" {
  realm           = ferriskey_realm.acme.name
  organization_id = ferriskey_organization.globex.organization_uuid
  user_id         = ferriskey_user.alice.user_uuid
}

Adds a user to an organization. Like ferriskey_user_role, it is a link and every change replaces it.

terraform import ferriskey_organization_member.alice_globex acme/ORG_UUID/USER_UUID

ferriskey_password_policy

resource "ferriskey_password_policy" "acme" {
  realm             = ferriskey_realm.acme.name
  min_length        = 14
  require_uppercase = true
  require_lowercase = true
  require_number    = true
  require_special   = true
  max_age_days      = 365
}

Manages the realm’s password policy. Leave max_age_days unset for passwords that never expire. A realm always has a policy, so destroying the resource stops managing it and leaves the policy as it is.

terraform import ferriskey_password_policy.acme acme

ferriskey_smtp_config

resource "ferriskey_smtp_config" "acme" {
  realm      = ferriskey_realm.acme.name
  host       = "smtp.example.com"
  port       = 587
  username   = "mailer"
  password   = var.smtp_password
  from_email = "no-reply@acme.example"
  from_name  = "Acme"
  encryption = "tls"
}

Manages the realm’s SMTP settings, described in the email guide. All attributes are required. encryption is tls, ssl or none.

The API never returns password. Terraform keeps the value from the configuration, so a password changed in the console is not seen as drift, and after an import the password has to be set in the configuration before the next apply. Destroying the resource deletes the realm’s SMTP configuration.

terraform import ferriskey_smtp_config.acme acme

ferriskey_identity_provider

resource "ferriskey_identity_provider" "google" {
  realm        = ferriskey_realm.acme.name
  alias        = "google"
  provider_id  = "oidc"
  display_name = "Google"

  config = {
    clientId     = var.google_client_id
    clientSecret = var.google_client_secret
  }
}
AttributeDescription
aliasUnique within the realm. Replaces
provider_idoidc or saml. Replaces
configProvider-specific keys, such as clientId, clientSecret or authorizationUrl. Only the keys you set are managed: keys the server adds are ignored
enabledtrue by default
trust_email, link_only, store_token, add_read_token_role_on_createBooleans, server default when unset
first_broker_login_flow_alias, post_broker_login_flow_aliasFlow aliases

The import ID uses the alias, not a UUID:

terraform import ferriskey_identity_provider.google acme/google