Terraform Provider for MazeVault¶
The MazeVault Terraform Provider allows you to manage your MazeVault organization, projects, secrets, certificates, rotations, integrations, and access control entirely as code. The provider is built on the Terraform Plugin Framework and targets Terraform 1.5+.
Installation¶
terraform {
required_version = ">= 1.5"
required_providers {
mazevault = {
source = "MazeVault/mazevault"
version = "~> 1.0"
}
}
}
Provider Configuration¶
provider "mazevault" {
server_url = "https://vault.example.com"
api_token = var.mazevault_api_token # recommended: use a variable, never hardcode
# Optional: service account credentials (alternative to api_token)
# client_id = var.mazevault_client_id
# client_secret = var.mazevault_client_secret
timeout = "30s"
skip_tls_verify = false # set true only in development environments
}
Provider Arguments¶
| Argument | Type | Required | Description |
|---|---|---|---|
server_url |
string | No | MazeVault server URL. Defaults to MAZEVAULT_SERVER_URL environment variable. |
api_token |
string | No | API token for authentication. Sensitive. Defaults to MAZEVAULT_API_TOKEN. |
client_id |
string | No | Service account client ID. Alternative to api_token. |
client_secret |
string | No | Service account client secret. Sensitive. |
timeout |
string | No | API request timeout (e.g. 30s, 1m). Default: 30s. |
skip_tls_verify |
bool | No | Skip TLS verification. Development only — never enable in production. |
Secret handling
Never put credentials directly in .tf files. Use environment variables (MAZEVAULT_API_TOKEN) or a secrets backend such as Vault or Azure Key Vault to inject sensitive values at plan/apply time.
Authentication Methods¶
API Token (recommended for automation)¶
Generate tokens in Admin → API Tokens or via the mazevault_api_token resource.
Service Account (CI/CD pipelines)¶
provider "mazevault" {
server_url = var.server_url
client_id = var.client_id
client_secret = var.client_secret
}
Resources¶
mazevault_organization¶
Manages the top-level organization configuration.
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Organization UUID. |
name |
string | Yes | Organization name. |
created_at |
string | Computed | Creation timestamp (ISO 8601). |
mazevault_project¶
Groups secrets and certificates under a logical boundary with its own RBAC.
resource "mazevault_project" "backend" {
organization_id = mazevault_organization.main.id
name = "Backend Services"
environment = "production"
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Project UUID. |
organization_id |
string | Yes | Parent organization ID. |
name |
string | Yes | Project name. |
environment |
string | No | Primary environment label. |
created_at |
string | Computed | Creation timestamp. |
mazevault_secret¶
Manages an encrypted secret inside a project. The secret value is stored as an AES-256-GCM encrypted blob in MazeVault and is marked sensitive in Terraform state.
resource "mazevault_secret" "db_password" {
project_id = mazevault_project.backend.id
key = "DB_PASSWORD"
value = var.db_password
environment = "production"
ttl_hours = 8760 # 1 year
metadata = {
owner = "backend-team"
tier = "critical"
}
rotation {
enabled = true
interval_days = 90
notification_emails = ["ops@example.com"]
}
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Secret UUID. |
project_id |
string | Yes | Parent project ID. |
key |
string | Yes | Secret name/key (e.g. DB_PASSWORD). |
value |
string | Yes | Secret value. Sensitive. |
environment |
string | Yes | Environment (dev, staging, production, …). |
ttl_hours |
number | No | Time-to-live in hours. Omit for no expiry. |
metadata |
map(string) | No | Arbitrary key/value labels. |
version |
number | Computed | Current version counter. |
status |
string | Computed | Secret lifecycle status. |
created_at |
string | Computed | Creation timestamp. |
rotation block
| Attribute | Type | Required | Description |
|---|---|---|---|
enabled |
bool | Yes | Activate automatic rotation. |
schedule |
string | No | Cron expression for rotation schedule. |
interval_days |
number | No | Rotation interval in days (alternative to cron). |
notification_emails |
list(string) | No | Notify these addresses on rotation failure. |
Orchestrator Mode
When MazeVault is configured in Orchestrator Mode, the value field is forwarded directly to the configured external secrets manager (Azure Key Vault, AWS Secrets Manager, or HashiCorp Vault). The value is not stored locally.
mazevault_secret_link¶
Links a secret to an integration so that rotation writes the new value into an external system (database, Kubernetes secret, DevOps pipeline variable, etc.).
resource "mazevault_secret_link" "db_link" {
secret_id = mazevault_secret.db_password.id
integration_id = mazevault_integration.azure_kv.id
link_type = "database"
metadata = {
db_user = "app_user"
db_host = "db.prod.example.com"
}
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Link UUID. |
secret_id |
string | Yes | Secret to link. |
integration_id |
string | Yes | Target integration. |
link_type |
string | No | database, agent, devops, or generic. |
metadata |
map(string) | No | Integration-specific configuration. |
mazevault_rotation_config¶
Defines a full rotation pipeline for a secret, including reconciler inputs, grace periods, and write-back targeting.
resource "mazevault_rotation_config" "db_rotation" {
secret_id = mazevault_secret.db_password.id
environment = "production"
ttl_hours = 720 # 30 days
rotation_strategy = "rolling"
grace_period_minutes = 60
workflow_steps_json = jsonencode([
{
type = "postgres_rotation"
config = {
host = "db.prod.example.com"
port = 5432
database = "appdb"
username = "app_user"
}
}
])
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Rotation config UUID. |
secret_id |
string | Yes | Secret to rotate. |
environment |
string | Yes | Environment this config applies to. |
ttl_hours |
number | Yes | Rotation interval in hours. |
rotation_strategy |
string | No | rolling, immediate, or blue-green. |
target_environment |
string | No | Override write-back environment. Defaults to environment. |
scope |
string | No | project (default) or organization. |
grace_period_minutes |
number | No | Minutes the old credential stays valid after rotation (0 = hard cutover). |
workflow_steps_json |
string | No | JSON array of rotation step configurations. |
mazevault_rotation_workflow¶
Creates a rotation workflow directly for a secret (simpler alternative to mazevault_rotation_config when only one workflow is needed).
resource "mazevault_rotation_workflow" "api_key" {
secret_id = mazevault_secret.api_key.id
environment = "production"
schedule = "0 2 * * 1" # Every Monday at 02:00
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Workflow UUID. |
secret_id |
string | Yes | Secret this workflow rotates. |
environment |
string | Yes | Target environment. |
schedule |
string | No | Cron schedule for automatic rotation. |
mazevault_certificate¶
Manages a certificate issued by or tracked in MazeVault. The private key is computed (generated by MazeVault) and exposed as a sensitive Terraform output.
resource "mazevault_certificate" "tls" {
common_name = "api.example.com"
ttl = "8760h" # 1 year
key_size = 4096
organization_ca_account_id = var.ca_account_id
}
output "tls_cert_pem" {
value = mazevault_certificate.tls.certificate_pem
sensitive = false
}
output "tls_key_pem" {
value = mazevault_certificate.tls.private_key_pem
sensitive = true
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Certificate UUID. |
common_name |
string | Yes | Certificate CN (e.g. api.example.com). |
ttl |
string | No | Validity duration (Go duration string: 8760h, 365d). |
key_size |
number | No | RSA key size in bits (default: 2048). |
organization_ca_account_id |
string | No | CA account for automatic issuance and rotation. |
serial_number |
string | Computed | Certificate serial number. |
certificate_pem |
string | Computed | PEM-encoded certificate. |
private_key_pem |
string | Computed | PEM-encoded private key. Sensitive. |
status |
string | Computed | pending, issued, expired, revoked. |
expires_at |
string | Computed | Expiry timestamp. |
mazevault_certificate_template¶
Defines a reusable certificate issuance policy: key usage, extended key usage, SANs, validity, and CA account binding.
resource "mazevault_certificate_template" "web_tls" {
project_id = mazevault_project.backend.id
name = "Web TLS 1Y"
ca_account_id = var.ca_account_id
ttl_hours = 8760
key_type = "RSA"
key_size = 2048
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Template UUID. |
project_id |
string | Yes | Owning project. |
name |
string | Yes | Template name. |
ca_account_id |
string | No | Bound CA account ID. |
ttl_hours |
number | No | Default certificate validity in hours. |
key_type |
string | No | RSA or EC. |
key_size |
number | No | Key size (bits for RSA, curve size for EC). |
mazevault_ca¶
Registers a CA account (DigiCert, Venafi, ADCS, ACME, Vault PKI, etc.) within a project.
resource "mazevault_ca" "digicert" {
project_id = mazevault_project.backend.id
name = "DigiCert Production"
provider_type = "digicert"
config = {
api_key = var.digicert_api_key
organization_id = "12345"
}
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | CA account UUID. |
project_id |
string | Yes | Owning project. |
name |
string | Yes | Descriptive name. |
provider_type |
string | Yes | digicert, venafi, adcs, acme, vault, step, est, psd2. |
config |
map(string) | No | Provider-specific configuration (API keys, URLs). Sensitive. |
mazevault_integration¶
Connects MazeVault to an external secrets store or deployment target (Azure Key Vault, AWS Secrets Manager, Kubernetes, GCP Secret Manager, etc.).
resource "mazevault_integration" "azure_kv" {
project_id = mazevault_project.backend.id
name = "Production Azure Key Vault"
type = "azure_key_vault"
config = {
vault_url = "https://prod-vault.vault.azure.net"
tenant_id = var.tenant_id
client_id = var.client_id
use_managed_identity = "true"
}
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Integration UUID. |
project_id |
string | Yes | Owning project. |
name |
string | Yes | Integration name. |
type |
string | Yes | azure_key_vault, aws_secrets_manager, kubernetes, gcp_secret_manager, hashicorp_vault. |
config |
map(string) | No | Provider-specific configuration. |
mazevault_integration_group¶
Groups multiple integrations mapped to different environments. Useful for multi-region or multi-KeyVault scenarios where the same logical secret must be written to different backends depending on environment.
resource "mazevault_integration_group" "multi_env_kv" {
project_id = mazevault_project.backend.id
name = "Multi-Region Key Vaults"
description = "Routes secrets to the correct regional Azure Key Vault"
mappings {
integration_id = mazevault_integration.azure_kv_eu.id
environment = "production-eu"
priority = 1
}
mappings {
integration_id = mazevault_integration.azure_kv_us.id
environment = "production-us"
priority = 1
}
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Group UUID. |
project_id |
string | Yes | Owning project. |
name |
string | Yes | Group name. |
description |
string | No | Optional description. |
mappings block
| Attribute | Type | Required | Description |
|---|---|---|---|
integration_id |
string | Yes | Integration to assign to this environment slot. |
environment |
string | Yes | Environment label (dev, staging, production-eu, …). |
priority |
number | No | Priority for failover. Lower = higher priority. |
mazevault_consistency_group¶
Validates that a set of secret keys exist with matching values across multiple environments. MazeVault continuously monitors the group and raises alerts when inconsistencies are detected.
resource "mazevault_consistency_group" "db_creds" {
project_id = mazevault_project.backend.id
name = "Database Credentials Parity"
description = "Ensure DB creds are consistent across staging and production"
secret_keys = ["DB_HOST", "DB_PORT", "DB_NAME"]
environments = ["staging", "production"]
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Group UUID. |
project_id |
string | Yes | Owning project. |
name |
string | Yes | Group name. |
description |
string | No | Description. |
secret_keys |
list(string) | Yes | Secret keys to monitor for consistency. |
environments |
list(string) | Yes | Environments to compare. |
mazevault_role¶
Creates a custom RBAC role with a specific permission set.
resource "mazevault_role" "deploy_bot" {
name = "deploy-bot"
description = "Read-only access for deployment pipelines"
permissions = ["secrets:read", "certificates:read", "projects:read"]
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Role UUID. |
name |
string | Yes | Role name (unique within organization). |
description |
string | No | Description. |
permissions |
list(string) | Yes | Permission strings (e.g. secrets:read, certificates:write). |
mazevault_group_mapping¶
Maps an external identity provider group (Entra ID, LDAP, SCIM) to a MazeVault RBAC role.
resource "mazevault_group_mapping" "ops_team" {
external_group_id = "sg-ops-production"
role_id = mazevault_role.deploy_bot.id
provider_type = "entra"
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Mapping UUID. |
external_group_id |
string | Yes | External group identifier (Entra object ID, LDAP DN, SCIM group name). |
role_id |
string | Yes | Target MazeVault role. |
provider_type |
string | No | entra, ldap, scim. |
mazevault_service_identity¶
Creates a service account (machine identity) with its own client_id and client_secret for non-human CI/CD access.
resource "mazevault_service_identity" "ci_pipeline" {
display_name = "GitHub Actions CI"
description = "Read-only service account for deployment pipeline"
owner_email = "platform-team@example.com"
}
output "ci_client_id" {
value = mazevault_service_identity.ci_pipeline.client_id
}
output "ci_client_secret" {
value = mazevault_service_identity.ci_pipeline.client_secret
sensitive = true
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Service identity UUID. |
display_name |
string | Yes | Human-readable name. |
description |
string | No | Description. |
owner_email |
string | Yes | Contact email for the owning team. |
client_id |
string | Computed | OAuth2 client ID. |
client_secret |
string | Computed | OAuth2 client secret. Sensitive. |
mazevault_api_token¶
Creates a personal or service API token with granular scope.
resource "mazevault_api_token" "automation" {
name = "terraform-automation"
scopes = ["secrets:read", "certificates:read", "rotation:write"]
}
| Attribute | Type | Required | Description |
|---|---|---|---|
id |
string | Computed | Token UUID. |
name |
string | Yes | Token name. |
scopes |
list(string) | Yes | Permission scopes. |
token |
string | Computed | The raw token value. Sensitive. Only available at creation. |
Data Sources¶
mazevault_consistency_status¶
Reads the current consistency status of a project's consistency groups.
data "mazevault_consistency_status" "check" {
project_id = mazevault_project.backend.id
}
output "consistency_ok" {
value = data.mazevault_consistency_status.check.status == "healthy"
}
| Attribute | Type | Description |
|---|---|---|
project_id |
string | Project to query. |
status |
string | healthy, warning, or error. |
missing_count |
number | Number of missing secrets detected. |
issues |
list(string) | Human-readable list of consistency issues. |
mazevault_project_certificates¶
Lists all certificates in a project.
| Attribute | Type | Description |
|---|---|---|
project_id |
string | Project to query. |
certificates |
list(object) | List of certificate summaries (id, common_name, status, expires_at). |
mazevault_project_cas¶
Lists CA accounts registered in a project.
mazevault_project_certificate_templates¶
Lists certificate templates available in a project.
data "mazevault_project_certificate_templates" "templates" {
project_id = mazevault_project.backend.id
}
mazevault_project_csrs¶
Lists pending Certificate Signing Requests in a project.
Complete Example¶
The following example provisions a fully automated secret rotation pipeline for a PostgreSQL password in production.
terraform {
required_providers {
mazevault = {
source = "MazeVault/mazevault"
version = "~> 1.0"
}
}
}
provider "mazevault" {
server_url = var.mazevault_url
api_token = var.mazevault_token
}
resource "mazevault_organization" "acme" {
name = "Acme Corp"
}
resource "mazevault_project" "backend" {
organization_id = mazevault_organization.acme.id
name = "Backend Services"
environment = "production"
}
resource "mazevault_integration" "azure_kv" {
project_id = mazevault_project.backend.id
name = "Production Key Vault"
type = "azure_key_vault"
config = {
vault_url = var.keyvault_url
use_managed_identity = "true"
}
}
resource "mazevault_secret" "db_password" {
project_id = mazevault_project.backend.id
key = "POSTGRES_PASSWORD"
value = var.initial_db_password
environment = "production"
rotation {
enabled = true
interval_days = 30
notification_emails = ["dba@example.com"]
}
}
resource "mazevault_secret_link" "db_link" {
secret_id = mazevault_secret.db_password.id
integration_id = mazevault_integration.azure_kv.id
link_type = "database"
metadata = {
db_user = "app_user"
db_host = "db.prod.example.com"
db_name = "appdb"
}
}
resource "mazevault_rotation_config" "db" {
secret_id = mazevault_secret.db_password.id
environment = "production"
ttl_hours = 720
rotation_strategy = "rolling"
grace_period_minutes = 60
workflow_steps_json = jsonencode([
{
type = "connection_validation"
config = { integration_id = mazevault_integration.azure_kv.id }
},
{
type = "postgres_rotation"
config = {
host = "db.prod.example.com"
port = 5432
database = "appdb"
username = "app_user"
}
}
])
}
resource "mazevault_consistency_group" "prod_creds" {
project_id = mazevault_project.backend.id
name = "Production DB Credentials"
secret_keys = ["POSTGRES_PASSWORD", "POSTGRES_HOST", "POSTGRES_PORT"]
environments = ["staging", "production"]
}
Importing Existing Resources¶
Use terraform import to bring existing MazeVault resources under Terraform management:
# Import a secret
terraform import mazevault_secret.db_password <secret-uuid>
# Import a project
terraform import mazevault_project.backend <project-uuid>
# Import a certificate
terraform import mazevault_certificate.tls <certificate-uuid>
# Import an integration group
terraform import mazevault_integration_group.multi_env_kv <group-uuid>
Resource UUIDs are visible in the MazeVault UI (URL path) or via the REST API (GET /api/v1/...).
Best Practices¶
- Store state remotely — use Terraform Cloud, Azure Blob Storage, or AWS S3 with state locking enabled.
- Mark sensitive outputs — always add
sensitive = trueon any output that exposes secret values or private keys. - Use variables for credentials — inject
api_token,client_secret, and CA credentials viaTF_VAR_environment variables or a CI/CD secrets store, never in.tfvarsfiles committed to source control. - Pin provider versions — use
~> 1.0to allow patch updates while preventing unexpected major-version changes. - Use consistency groups for drift detection — after provisioning, add a
mazevault_consistency_groupto catch environment drift before it becomes an incident. - Rotation grace periods — always set
grace_period_minutes > 0for database rotations to allow in-flight connections to finish before the old credential is invalidated. - Separate workspaces per environment — use Terraform workspaces or separate state files per environment (dev/staging/production) to prevent accidental cross-environment resource writes.