Terraform Resources Reference¶
justiam_user¶
Creates or manages a user account.
resource "justiam_user" "example" {
email = "user@example.com"
first_name = "First"
last_name = "Last"
password = "InitialPass123!" # only used at creation
is_active = true
is_admin = false
is_service_account = false
}
| Argument | Required | Description |
|---|---|---|
email |
Yes | Unique email address |
username |
No (computed) | Auto-derived from the email local-part. Read-only. |
first_name |
No | First name |
last_name |
No | Last name |
password |
No | Initial password (local accounts only) |
is_active |
No | Default true |
is_admin |
No | Full admin access, default false |
is_service_account |
No | API-only account, default false |
justiam_group¶
| Argument | Required | Description |
|---|---|---|
name |
Yes | Unique group name |
description |
No | Description |
justiam_group_member¶
Adds a user to a group.
resource "justiam_group_member" "example" {
group_id = justiam_group.engineering.id
user_id = justiam_user.alice.id
}
justiam_admin_role¶
Creates an IDP administrative role with a specific set of permissions.
resource "justiam_admin_role" "helpdesk" {
name = "Help Desk"
description = "Can view users and groups"
permissions = ["users.view", "groups.view"]
}
| Argument | Required | Description |
|---|---|---|
name |
Yes | Unique role name |
description |
No | Description |
permissions |
Yes | List of permission strings |
See Admin Roles for the full list of permissions.
justiam_group_admin_role¶
Assigns an Admin role to a group.
resource "justiam_group_admin_role" "example" {
group_id = justiam_group.admins.id
role_id = justiam_admin_role.helpdesk.id
}
justiam_application¶
Creates an OIDC or SAML application.
resource "justiam_application" "example" {
name = "My App"
description = "Optional description"
type = "oidc" # oidc | spa | saml | external
redirect_uris = ["https://app.example.com/callback"]
allowed_scopes = ["openid", "profile", "email"]
grant_types = ["authorization_code", "refresh_token"]
access_restricted = false
show_in_dashboard = true
launch_url = "https://app.example.com"
icon_url = "https://app.example.com/icon.png"
token_expiry = 3600
mfa_policy = "inherit"
claim_mappings = [
{
claim = "groups"
value = "$${groups}"
},
{
claim = "app_roles"
value = "$${appRoles}"
required_scope = "roles"
}
]
}
| Argument | Required | Description |
|---|---|---|
name |
Yes | Application name |
type |
Yes | oidc, spa, saml, or external |
redirect_uris |
No | List of allowed callback URLs. Supports exact strings or regex: prefixed patterns. |
allowed_scopes |
No | Scopes the client may request |
grant_types |
No | authorization_code, refresh_token |
access_restricted |
No | Require explicit access grants |
show_in_dashboard |
No | Show in My Apps portal |
launch_url |
No | Launch link in portal |
icon_url |
No | Icon shown in portal |
app_group |
No | Grouping label in portal |
token_expiry |
No | Access/ID token lifetime (seconds) |
mfa_policy |
No | Per-app MFA override |
client_id |
No | Override auto-generated client ID |
claim_mappings |
No | List of { claim, value, required_scope } |
Computed outputs: id, client_id, client_secret (sensitive)
claim_mappings block¶
| Argument | Required | Description |
|---|---|---|
claim |
Yes | JWT claim name |
value |
Yes | Template or literal value |
required_scope |
No | Only emit when this scope is granted |
justiam_application_group_access¶
Grants a group access to an access_restricted application.
resource "justiam_application_group_access" "example" {
application_id = justiam_application.example.id
group_id = justiam_group.engineering.id
}
justiam_app_role¶
Creates an App Mapping entry for an application.
resource "justiam_app_role" "developer" {
application_id = justiam_application.example.id
name = "developer" # variable_name
description = "Developer access"
value = "developer"
}
justiam_federated_provider¶
Configures a federated login provider (OAuth2, OIDC, SAML 2.0, or LDAP).
# Google OAuth2
resource "justiam_federated_provider" "google" {
name = "Google"
provider_type = "google"
client_id = "1234.apps.googleusercontent.com"
client_secret = var.google_client_secret
enabled = true
allowed_domains = ["example.com"]
}
# Microsoft Entra ID
resource "justiam_federated_provider" "microsoft" {
name = "Microsoft"
provider_type = "microsoft"
client_id = var.ms_client_id
client_secret = var.ms_client_secret
issuer_url = "https://login.microsoftonline.com/${var.tenant_id}/v2.0"
enabled = true
}
# SAML 2.0 SP-initiated
resource "justiam_federated_provider" "saml_corporate" {
name = "Corporate SSO"
provider_type = "saml"
client_id = "https://justiam.example.com" # SP Entity ID
client_secret = var.idp_signing_certificate_pem
enabled = true
metadata = {
idp_entity_id = "https://idp.example.com/saml"
idp_sso_url = "https://idp.example.com/saml/sso"
}
}
# LDAP / Active Directory
resource "justiam_federated_provider" "ldap" {
name = "Corporate LDAP"
provider_type = "ldap"
client_id = "cn=service,dc=example,dc=com" # Bind DN
client_secret = var.ldap_bind_password
enabled = true
metadata = {
ldap_url = "ldap://ldap.example.com:389"
base_dn = "dc=example,dc=com"
user_filter = "(uid={username})"
}
}
| Argument | Required | Description |
|---|---|---|
name |
Yes | Display name shown on the login page |
provider_type |
Yes | google, github, microsoft, apple, oidc, saml, or ldap |
client_id |
No | OAuth2 client ID / SAML SP Entity ID / LDAP Bind DN. Optional for LDAP (anonymous bind) |
client_secret |
No | OAuth2 secret / Apple .p8 key / SAML IdP cert PEM / LDAP Bind password |
issuer_url |
No | Required for microsoft and oidc. OIDC discovery base URL |
scopes |
No | Space-separated OIDC scopes. Default: openid profile email |
enabled |
No | Show on login page. Default true |
allowed_domains |
No | Restrict to users from these email domains |
allowed_emails |
No | Restrict to these specific email addresses |
metadata |
No | Provider-specific key-value pairs. See table below |
metadata keys by provider type:
| Provider | Key | Required | Description |
|---|---|---|---|
apple |
team_id |
Yes | Apple Team ID |
apple |
key_id |
Yes | Apple Key ID |
saml |
idp_entity_id |
Yes | IdP Entity ID |
saml |
idp_sso_url |
Yes | IdP SSO endpoint URL |
saml |
attr_email |
No | SAML attribute for email (auto-detected if omitted) |
saml |
attr_first_name |
No | SAML attribute for given name (auto-detected if omitted) |
saml |
attr_last_name |
No | SAML attribute for surname (auto-detected if omitted) |
ldap |
ldap_url |
Yes | LDAP server URL (ldap:// or ldaps://) |
ldap |
base_dn |
Yes | Base DN for user search |
ldap |
user_filter |
Yes | Search filter with {username} placeholder |
ldap |
start_tls |
No | "true" to upgrade plain LDAP to TLS via StartTLS |
ldap |
attr_email |
No | LDAP attribute for email (default: mail) |
ldap |
attr_first_name |
No | LDAP attribute for given name (default: givenname) |
ldap |
attr_last_name |
No | LDAP attribute for surname (default: sn) |
justiam_integration¶
Creates an event-driven integration.
resource "justiam_integration" "notify_slack" {
name = "Notify Slack on user creation"
description = "Posts to #idp-events when a new user is created"
enabled = true
triggers = ["user.created"]
conditions = jsonencode([
{ field = "user.email", operator = "contains", value = "@example.com", order = 1 }
])
actions = jsonencode([
{
action_type = "slack"
order = 1
config = {
webhook_url = "https://hooks.slack.com/services/XXX/YYY/ZZZ"
message = "New user {{.Data.user_email}} was created"
}
}
])
}
| Argument | Required | Description |
|---|---|---|
name |
Yes | Unique display name |
description |
No | Optional description |
enabled |
No | Default true |
triggers |
Yes | List of event types, e.g. ["user.created"] |
conditions |
No | JSON array of condition objects (see Integrations docs) |
actions |
Yes | JSON array of action objects (see Integrations docs) |
justiam_access_request_template¶
Manages a temporary-access request template. See Access Requests for a full walkthrough.
resource "justiam_access_request_template" "vpn_access" {
name = "VPN access"
description = "Grants VPN group membership for up to 8 hours."
app_id = justiam_application.infra.id
mapping_ids = [justiam_app_mapping.vpn_role.id]
allowed_durations = [60, 480]
approver_group_ids = [justiam_group.network_ops.id]
require_justification = true
notification_policy = "round_robin"
escalation_after_mins = 60
escalation_group_id = justiam_group.engineering_managers.id
}
| Argument | Required | Description |
|---|---|---|
name |
Yes | Display name |
description |
No | Shown to requesters |
app_id |
Yes | Target application UUID |
mapping_ids |
No | App-mapping UUIDs to grant |
allowed_durations |
No | Allowed durations in minutes |
approver_group_ids |
No | Approver group UUIDs |
require_justification |
No | Default true |
auto_approve |
No | Default false |
notification_policy |
No | all / first_n / random_n / round_robin |
notification_count |
No | N for first_n / random_n / round_robin policies |
escalation_after_mins |
No | Escalation timeout; omit to disable |
escalation_group_id |
No | Escalation group UUID |
justiam_settings¶
Manages global JustIAM settings. This is a singleton resource — create only one instance per provider configuration. Settings always exist on the server; creating this resource reads and optionally updates them, while destroying it is a no-op.
resource "justiam_settings" "main" {
mfa_policy = "any"
mfa_enforce_enrollment = true
mfa_reauth_interval_minutes = 0
mfa_allowed_methods = "totp,passkey"
trusted_device_duration_days = 30
session_duration_days = 7
}
| Argument | Required | Description |
|---|---|---|
mfa_policy |
No | Global MFA policy: disabled, any, otp, passkey. Default disabled. |
mfa_enforce_enrollment |
No | Block logins until the user has enrolled at least one MFA method. Default false. |
mfa_reauth_interval_minutes |
No | Re-prompt MFA every N minutes. 0 = once per session (default). |
mfa_allowed_methods |
No | Comma-separated list of enrollable MFA methods. Default totp,passkey. |
trusted_device_duration_days |
No | Days a trusted device skips MFA. 0 = disabled (default). |
session_duration_days |
No | SSO session lifetime in days. Default 7. |
allow_local_login |
No | Allow email/password login. Default true. |
allow_forgot_password |
No | Show the "Forgot password?" link. Default true. |
allow_email_otp |
No | Allow passwordless sign-in via email OTP or magic link. Default false. Requires SMTP. |
allow_password_login |
No | Allow users to sign in with email and password. Default true. Disable to force passwordless (OTP / magic-link) only. |
Computed outputs: id (always "settings")
justiam_certificate¶
Creates and manages a managed signing certificate (RSA or ECDSA key pair). The private key is stored encrypted server-side and is never returned by the API.
resource "justiam_certificate" "saml" {
name = "SAML Signing Cert"
key_algorithm = "ecdsa-p256"
validity_days = 730
}
| Argument | Required | Description |
|---|---|---|
name |
Yes | Human-readable certificate name |
common_name |
No | X.509 Common Name (CN). Defaults to name. |
key_algorithm |
No | rsa2048, rsa4096 (default), ecdsa-p256, ecdsa-p384 |
validity_days |
No | Certificate validity in days. Default 365. |
Computed outputs: id, cert_pem, expires_at
Data sources¶
data.justiam_user¶
Look up a user by email:
data "justiam_user" "alice" {
email = "alice@example.com"
}
output "alice_id" {
value = data.justiam_user.alice.id
}
justiam_scheduled_task¶
Creates a custom script task. The script runs on the specified cron schedule (or manually
when schedule_type = "once"). For preset-based tasks see justiam_preset_task.
resource "justiam_scheduled_task" "hourly_sync" {
name = "Hourly LDAP Sync"
task_type = "script"
schedule_type = "cron"
cron_expr = "0 * * * *"
enabled = true
script = <<-EOT
package task
import "fmt"
func Run() (string, error) {
return fmt.Sprintf("sync complete"), nil
}
EOT
task_config = {
ldap_base_dn = "dc=example,dc=com"
}
secrets = {
ldap_bind_password = var.ldap_password
}
}
| Argument | Required | Description |
|---|---|---|
name |
Yes | Display name |
task_type |
Yes | "script" |
schedule_type |
Yes | "cron" (automatic) or "once" (manual/event trigger only) |
cron_expr |
When schedule_type = "cron" |
5-field cron expression. next_run_at is computed automatically on create/update. |
script |
When task_type = "script" |
Go source; must declare package task and export func Run() (string, error) |
enabled |
No | Default true. Re-enabling a cron task recomputes next_run_at immediately. |
timeout_secs |
No | Max execution time in seconds. Default 30. |
pending_timeout_secs |
No | Cancel the run if it stays pending this many seconds. Default 1800. |
overlap_policy |
No | "allow" (default), "skip", "queue", "replace" |
agent_labels |
No | Required capability labels. Empty = any agent. |
label_match |
No | "any" (default) or "all" |
task_config |
No | Key-value config passed to config.Get() in scripts |
secrets |
No | Key-value secrets passed to secrets.Get(). Write-only — never returned by API. |
Computed outputs: id
Cron scheduling: when
schedule_type = "cron", JustIAM computesnext_run_atautomatically on save. A background poller (every 30 s, multi-replica safe) fires due tasks. See Cron scheduling.
justiam_preset_source¶
Registers a GitHub catalog repository as a preset source. Preset sources host versioned task script manifests that can be instantiated as Preset Tasks.
resource "justiam_preset_source" "internal" {
name = "Internal Catalog"
url = "https://raw.githubusercontent.com/acme/idp-presets/main"
auth_type = "github_token"
public_key = "untrusted comment: minisign public key\nRWSxxxxxxxxx..."
secrets = {
token = var.github_pat
}
}
| Argument | Required | Description |
|---|---|---|
name |
Yes | Human-readable source name |
url |
Yes | Raw GitHub URL prefix (e.g. https://raw.githubusercontent.com/org/repo/main). Changing this forces re-creation. |
auth_type |
No | Authentication type: none (default), github_token, or github_app |
public_key |
No | Minisign public key used to verify catalog and manifest file checksums. Leave empty to disable signature verification (not recommended for 3rd-party sources). |
secrets |
No | Credentials map. For github_token: token. For github_app: installation_token. Values are write-only and never returned by the API. |
Computed outputs: id, is_official, auth_type
justiam_preset_task¶
Instantiates a versioned task from a catalog preset. The manifest (script + schedule) is snapshotted on creation. Change version to upgrade the script in-place.
resource "justiam_preset_task" "dd_teams_sync" {
name = "acme-datadog-teams-sync"
source_id = justiam_preset_source.internal.id
preset_id = "datadog-teams-sync"
version = "v1.2.0"
cron_expr = "0 * * * *"
enabled = true
config = {
dd_endpoint = "https://api.datadoghq.eu"
justiam_app_id = justiam_application.datadog.id
variable_name = "teams"
}
secrets = {
dd_api_key = var.dd_api_key
dd_app_key = var.dd_app_key
}
}
| Argument | Required | Description |
|---|---|---|
name |
Yes | Display name for the scheduled task |
source_id |
Yes | ID of the preset source. Changing forces re-creation. |
preset_id |
Yes | Preset identifier in the catalog (e.g. datadog-teams-sync). Changing forces re-creation. |
version |
Yes | Version tag to pin. Change this value to upgrade the script in-place. |
cron_expr |
No | Override the preset's default cron expression. next_run_at is computed automatically. |
config |
No | Key-value config fields as defined by the preset manifest. |
secrets |
No | Key-value secret fields as defined by the preset manifest. Values are write-only and never returned by the API. |
enabled |
No | Whether the task is active. Default true. |
Computed outputs: id, task_id
justiam_agent_token¶
Creates an agent token used to authenticate an external agent connecting via gRPC. The raw token value is only available immediately after creation — it is never returned by subsequent API calls. Store it in a secret manager or Terraform sensitive output immediately.
See External Agents for full deployment instructions.
resource "justiam_agent_token" "on_prem" {
name = "on-prem-agent"
}
output "agent_token" {
value = justiam_agent_token.on_prem.token
sensitive = true
}
| Argument | Required | Description |
|---|---|---|
name |
Yes | Human-readable label. Changing forces re-creation. |
Computed outputs: id, token (sensitive, write-once), created_at