Skip to content

Terraform provider

Manage EvalGuard projects, API keys, firewall rules, eval schedules and gateway policies as code. Published on the Terraform Registry as EvalGuardAi/evalguard.

v1.1.0 — five resources with real CRUD against the EvalGuard /api/v1 surface, pinned by contract tests.

Security posture

base_url is https-only — the API key is a Bearer token, so a plaintext endpoint is a hard error. Credential fields (api_key, the created key) are marked sensitive. Retries are bounded and idempotency-safe: 429 is always retried; 5xx is retried only on idempotent verbs — never a double-create. Releases are signed, multi-platform GoReleaser builds; CI runs gosec (SAST), govulncheck, and terraform validate on every example.

Provider setup

Pin the provider and configure auth. The API key is read from the EVALGUARD_API_KEY environment variable by default — keep it out of version control.

versions.tf
terraform {
  required_providers {
    evalguard = {
      source  = "EvalGuardAi/evalguard"
      version = "~> 1.1"
    }
  }
}

provider "evalguard" {
  # api_key defaults to $EVALGUARD_API_KEY.
  # base_url defaults to https://evalguard.ai (self-hosters override — https only).
}

Resources

Five resources, each backed by real HTTP against /api/v1 (schema-only stubs were removed in v1.1.0).

evalguard_projectPOST /api/v1/projects + GET|PATCH|DELETE /api/v1/projects/{id}

A project — the tenancy boundary evals, scans, traces and firewall rules attach to.

evalguard_api_keyPOST /api/v1/api-keys, GET ?orgId, DELETE /api/v1/api-keys/{id} (soft revoke)

A scoped API key. The plaintext `key` is returned once, on create, as a sensitive attribute — capture it in an output or a secret store.

evalguard_firewall_rulePOST /api/v1/firewall/rules (upsert), GET ?projectId, DELETE ?ruleId&projectId

A runtime firewall rule (regex / classifier / policy) with a priority and a block/allow/flag action.

evalguard_eval_schedulePOST /api/v1/eval-schedules, GET ?projectId, PATCH, DELETE ?id

A cron-scheduled regression eval — model + scorers run on a schedule so quality doesn't silently drift.

evalguard_gateway_policy/api/v1/gateway/policies (create-rule + list + delete; update = delete+create)

An agent-gateway egress policy (allow/deny tools, endpoints) enforced at proxy time.

Complete example

A project with a CI-scoped key, a prompt-injection firewall rule, a nightly regression eval, and a gateway egress policy. This is the config CI runs terraform validate against.

main.tf
variable "evalguard_org_id" {
  type        = string
  description = "Organization that owns these resources."
}

resource "evalguard_project" "example" {
  org_id = var.evalguard_org_id
  name   = "checkout-assistant"
  slug   = "checkout-assistant"

  settings = jsonencode({
    retention_days = 30
  })
}

resource "evalguard_api_key" "ci" {
  org_id = var.evalguard_org_id
  name   = "ci-firewall-check"
  scopes = ["firewall:check"]
}

resource "evalguard_firewall_rule" "block_injection" {
  project_id = evalguard_project.example.id
  name       = "block-prompt-injection"
  type       = "regex"
  priority   = 10

  condition = jsonencode({
    pattern = "(?i)ignore (all )?previous instructions"
  })

  action = jsonencode({
    type = "block"
  })
}

resource "evalguard_eval_schedule" "nightly" {
  project_id      = evalguard_project.example.id
  name            = "nightly-regression"
  cron_expression = "0 3 * * *"

  config = jsonencode({
    model   = "gpt-4"
    scorers = ["exact-match"]
  })
}

resource "evalguard_gateway_policy" "deny_external_http" {
  project_id = evalguard_project.example.id
  name       = "deny-external-http"
  effect     = "deny"
  priority   = 50

  conditions = jsonencode({
    tools = ["http.get"]
  })
}

# The plaintext key is returned once, on create.
output "ci_api_key" {
  value     = evalguard_api_key.ci.key
  sensitive = true
}

Apply it

export EVALGUARD_API_KEY="eg_live_..."

terraform init
terraform plan  -var "evalguard_org_id=$ORG_ID"
terraform apply -var "evalguard_org_id=$ORG_ID"

# Read the CI key back out (sensitive):
terraform output -raw ci_api_key

Notes

  • evalguard_gateway_policy has no in-place update path on the API (create + delete only), so a change to an existing policy is a replace (delete-then-create) — expect -/+ in the plan.
  • Deleting an evalguard_api_key is a soft revoke — the key stops authenticating but the audit row is retained.
  • Self-hosters set base_url on the provider block to their instance (https only).