Terraform Provider

Identity as code.
GitOps your auth.

Manage tenants, users, roles, SSO, cloud mappings, and eBPF policies -- all from HCL. Review in PRs. Deploy with CI.

Available on Free and above. See pricing

Coming soon The Terraform provider isn't generally available yet — this is a preview of what's shipping. Get early access →

Identity as code

Your auth layer becomes a Terraform resource.

A Terraform provider is a thin adapter between HCL and a remote API. You declare the desired state — tenants, roles, SSO connections, edge policies — and Terraform's core reconciles reality to match it: read current state, diff against your config, and emit the minimum set of create / update / delete calls. The AuthFI provider maps each block to the same control-plane API the console uses, so the dashboard and your repo describe one system, not two.

  • Declarative, not imperative: you describe the end state; Terraform computes the path. No ordering scripts, no "did this already run?"
  • Dependency graph: authfi_tenant.acme.id referenced inside a role wires the apply order automatically — tenant first, then everything that needs its ID.
  • One workflow for the whole stack: the same plan/apply you already run for cloud infra now owns identity too.
main.tf
resource "authfi_tenant" "acme" {
  name   = "Acme Corp"
  slug   = "acme"
  plan   = "pro"
  region = "us"
}

resource "authfi_role" "editor" {
  tenant_id   = authfi_tenant.acme.id
  name        = "editor"
  permissions = ["read:articles",
                 "write:articles"]
}

The tenant_id = authfi_tenant.acme.id reference is the dependency edge Terraform applies in order.

Every resource in HCL

10 Terraform resources cover your entire identity stack.

From the tenant down to an eBPF agent policy, every object you can create in the console is a typed HCL block with explicit attributes. The provider validates them against the API schema at plan time — so a typo'd field or a bad enum fails in review, not in production.

authfi_tenant
resource "authfi_tenant" "acme" {
  name   = "Acme Corp"
  slug   = "acme"
  plan   = "pro"
  region = "us"
}
authfi_role
resource "authfi_role" "editor" {
  tenant_id   = authfi_tenant.acme.id
  name        = "editor"
  permissions = [
    "read:articles",
    "write:articles"
  ]
}
authfi_sso_connection
resource "authfi_sso_connection" "okta" {
  tenant_id    = authfi_tenant.acme.id
  type         = "saml"
  metadata_url = "https://..."
  domain_hint  = "acme.com"
}
authfi_agent_policy
resource "authfi_agent_policy" "api" {
  tenant_id = authfi_tenant.acme.id
  port      = 8080
  mode      = "enforce"
  rules {
    method = "GET"
    path   = "/api/patients/*"
    roles  = ["doctor"]
  }
}

Plan before apply

See exactly what changes. Then approve it.

Every Terraform run is two phases. terraform plan is read-only: the provider fetches current state for each resource and renders a precise diff — + to add, ~ to change, - to destroy. Nothing on AuthFI moves until terraform apply executes that exact plan. For a control plane that gates authentication, that pre-flight diff is the difference between a reviewed change and a 2 a.m. console click nobody can explain afterward.

  • No surprises: the diff is the contract — apply does only what plan showed, or it fails.
  • Drift detection: if someone hand-edits a connection in the console, the next plan surfaces it as a change to revert or absorb.
  • Blast radius is visible: "2 to add, 1 to change, 0 to destroy" is a number a reviewer can reason about before anything ships.
Terminal
$ terraform plan

+ authfi_tenant.acme
    name   = "Acme Corp"
    slug   = "acme"
    plan   = "pro"
    region = "us"

+ authfi_role.editor
    name        = "editor"
    permissions = ["read:articles", "write:articles"]

~ authfi_sso_connection.okta
    domain_hint: "acme.io" -> "acme.com"

Plan: 2 to add, 1 to change, 0 to destroy.

A change to domain_hint shows as a ~ in-place update — reviewable line-by-line in the PR.

GitOps the auth layer

Git is the source of truth. CI does the apply.

GitOps means the repository — not a human in a console — is the authority on what should exist. Identity config follows the same loop your infrastructure already does: change in a branch, prove it in a plan, merge to deploy. The control plane converges on whatever main says.

1

Edit HCL

Change a role, add a user, update an SSO connection.

git commit
2

Open PR

terraform plan runs in CI. Review the diff.

terraform plan
3

Merge

terraform apply runs on merge. Changes deployed.

terraform apply
4

Audit trail

Every change tracked in git history + AuthFI logs.

git + audit log
Source of truth
Git, not the console
Change review
Pull request + plan
Rollback
git revert + apply
Audit
Commit SHA per change

Full coverage

All 10 resources. One plan, then create, update, destroy.

Coverage is what separates a real provider from a toy. The AuthFI provider exposes the whole stack — tenancy, identity, authorization, and the federation / edge layer — and every one of those resources supports the standard create / read / update / delete contract that Terraform's reconciler drives. That means no object you manage in the console is stranded outside code, and no change needs an out-of-band script.

  • Import existing objects: a tenant created in the console can be brought under management with terraform import, then it's code from then on.
  • State as inventory: the state file is a machine-readable list of exactly what auth config exists — answer access-review questions from git instead of screenshots.
Resource coverage
Tenancy
authfi_tenantauthfi_projectauthfi_organization
Identity
authfi_userauthfi_group
Authorization
authfi_roleauthfi_permission
Federation & edge
authfi_sso_connectionauthfi_cloud_mappingauthfi_agent_policy
How a run touches each resource
plan Provider reads remote state for each resource and diffs it against your HCL. Pure read — nothing changes.
create New blocks become POSTs to the AuthFI API. Returned IDs land in state, so references resolve.
update Drift on a managed field becomes a PATCH. Only the changed attributes move on the wire.
destroy Removing a block deletes the resource. State is the contract — no orphaned objects left behind.
agent_policy.tf
resource "authfi_agent_policy" "api" {
  tenant_id = authfi_tenant.acme.id
  port      = 8080
  mode      = "enforce"

  rules {
    method = "GET"
    path   = "/api/patients/*"
    roles  = ["doctor"]
  }
}

The same HCL that defines a tenant also defines who can call which route at the edge.

Policy as code

Even the edge enforcement is a reviewable diff.

Authorization rules are where the highest-stakes mistakes hide — one wrong path glob or role and a protected route opens up. With authfi_agent_policy in HCL, the rule that says only a doctor may GET /api/patients/* lives in version control: it's proposed in a pull request, approved by a second engineer, and applied by CI. The eBPF agent then enforces exactly what's in state — and any change to that policy is a commit you can point an auditor at.

  • The problem it removes: ad-hoc access changes nobody reviewed, made directly against production at the edge.
  • The payoff: least-privilege rules that read like code, ship through review, and roll back with git revert — provable in a SOC 2 / access review without a war room.

Get started

Ready to get started?

Free for 5,000 monthly active users. No credit card required.