Pular para o conteúdo principal

Terraform Provider

O provider oficial ciphervault/ciphervault permite gerenciar vaults, secrets, policies e AppConnections como código.

Instalação

terraform {
required_version = ">= 1.5"
required_providers {
ciphervault = {
source = "ciphervault/ciphervault"
version = "~> 1.6"
}
}
}

provider "ciphervault" {
endpoint = "https://api.ciphervault.com.br"
# Auth via env CIPHERVAULT_TOKEN, ou OIDC para CI/CD:
# auth = "oidc"
# oidc_role = "terraform-prod"
}

Exemplos

Vault

resource "ciphervault_vault" "producao" {
name = "producao"
description = "Cofre de produção"
environment = "production"

encryption {
algorithm = "AES-256-GCM"
key_source = "byok"
kms_key_arn = "arn:aws:kms:sa-east-1:123:key/abc"
rotation_days = 90
}

tags = {
cost_center = "billing"
compliance = "lgpd,pci"
}
}

Policy

resource "ciphervault_policy" "billing_readers" {
name = "billing-readers"

document = jsonencode({
version = "2025-01-01"
statement = [
{
sid = "read-stripe"
effect = "allow"
action = ["secrets:read"]
resource = "vault/${ciphervault_vault.producao.name}/api/stripe/*"
principal = { group = ["billing-team"] }
condition = {
stringEquals = { "request:mfaPresent" = "true" }
}
}
]
})
}

Secret (somente para dados estáticos não sensíveis — dados sensíveis devem ser inseridos via UI/API)

resource "ciphervault_secret" "stripe_webhook" {
vault = ciphervault_vault.producao.name
path = "api/stripe/webhook_secret"
type = "api_key"

# ATENÇÃO: o valor entrará no state. Use apenas para secrets de
# baixa criticidade ou marque o state como sensível e cifrado.
value = var.stripe_webhook_secret

metadata = {
description = "Webhook signing secret"
owner = "billing-team@acme.com.br"
}
}

Database secret com rotação

resource "ciphervault_database_secret" "billing_db" {
vault = ciphervault_vault.producao.name
path = "db/postgres/billing-master"
engine = "postgresql"

connection {
host = "db-billing.internal.acme.com.br"
port = 5432
database = "billing"
admin_username = "ciphervault_admin"
admin_password_secret = "db/postgres/admin"
}

rotation {
enabled = true
interval_days = 30
grace_window_minutes = 5
rollback_on_failure = true
}
}

AppConnection

resource "ciphervault_app_connection" "billing_api" {
name = "billing-api"
vault = ciphervault_vault.producao.name
allowed_paths = ["api/stripe/*", "db/postgres/billing-master"]
ip_allowlist = ["10.0.0.0/8"]
mtls_required = true
}

output "billing_api_client_id" {
value = ciphervault_app_connection.billing_api.client_id
sensitive = false
}

output "billing_api_client_secret" {
value = ciphervault_app_connection.billing_api.client_secret
sensitive = true
}

client_secret aparece apenas na criação — após o apply, futuros plan não conseguem lê-lo. Trate o state como secret.

OIDC Provider e Role

resource "ciphervault_oidc_provider" "github" {
name = "github-acme"
issuer = "https://token.actions.githubusercontent.com"
audience = "https://ciphervault.com.br"
}

resource "ciphervault_oidc_role" "deploy_prod" {
name = "deploy-producao"
provider = ciphervault_oidc_provider.github.name

trust = {
repository = "acme-corp/billing-api"
environment = "production"
ref = "refs/heads/main"
}

policies = [ciphervault_policy.billing_readers.name]
ttl_seconds = 900
}

Boas práticas

  • State remoto criptografado. S3 + KMS, GCS + CMEK ou Terraform Cloud.
  • Workspace separado para CipherVault. Não misture com infra de aplicação.
  • OIDC para o próprio Terraform Cloud. Sem token estático no provider.
  • Use lifecycle.prevent_destroy em vaults de produção.
  • Não armazene secrets sensíveis no state se possível. Prefira inserir via API/UI e usar data "ciphervault_secret" para referenciar.