Pular para o conteúdo principal

Plugin SDK — secret engines customizados

A partir da v4.5, o CipherVault aceita secret engines customizados da comunidade sem fork do backend. Implemente em JavaScript/Node.js, deixe no diretório CV_PLUGINS_DIR, reinicie. File-based discovery

  • contrato bem definido.

Casos de uso

  • Engine para banco proprietário (Teradata, SAP HANA, Snowflake)
  • Engine para sistema interno (LDAP customizado, API de mainframe)
  • Engine que combina N steps em um lease (multi-DB, transaction-like)

Configuração

# Backend env var
CV_PLUGINS_DIR=/etc/ciphervault/plugins

CV escaneia o diretório no boot. Cada subdiretório com plugin.json é tratado como engine.

Estrutura de plugin

/etc/ciphervault/plugins/
└── my-custom-engine/
├── plugin.json
├── index.js
└── package.json (opcional, com deps)

plugin.json

{
"name": "my-custom-engine",
"version": "1.0.0",
"type": "dynamic_secret_engine",
"engine_id": "my_custom",
"description": "Engine para sistema interno X",
"license_min_plan": "professional",
"main": "index.js"
}

index.js

module.exports = {
// Identifier usado em backend.engine
id: 'my_custom',

// Validar config no momento de criar o backend (POST /dynamic-secrets/backends)
validateBackendConfig(config) {
if (!config.host) throw new Error('host obrigatório');
return true;
},

// Testar conectividade (POST /dynamic-secrets/backends/:id/test)
async testConnection(backend) {
// Conecta com creds admin, faz ping
return { ok: true, latency_ms: 42 };
},

// Criar lease (POST /dynamic-secrets/leases)
async createLease({ backend, role, ttl }) {
const username = `cv_${role.name}_${Date.now()}`;
const password = generatePassword();

// Executa o que precisar no sistema externo
await provisionUser(backend, username, password, ttl);

return {
username,
password,
expires_at: new Date(Date.now() + ttl * 1000).toISOString(),
// metadata opcional
metadata: { backend_user_id: 'abc123' },
};
},

// Revogar lease (DELETE /dynamic-secrets/leases/:id ou expiração automática)
async revokeLease({ backend, lease }) {
await deprovisionUser(backend, lease.username);
},
};

Reference plugin

backend/plugins-example/dummy-engine/ no repo do produto é o reference implementation completo. Use como template — cobre todos os hooks + testes unitários.

Discovery

# CV log no boot:
[plugin-loader] Found 2 plugins in /etc/ciphervault/plugins
[plugin-loader] Loaded my-custom-engine (engine_id=my_custom)
[plugin-loader] Loaded sap-hana-engine (engine_id=sap_hana)

# Verificar via API
curl https://cv.acme.com.br/dynamic-secrets/engines \
-H "Authorization: Bearer $CV_TOKEN"
# → { "engines": ["postgres", "mysql", ..., "my_custom", "sap_hana"] }

Validação de plugin

Quando você POST cria backend com engine: "my_custom":

  1. CV verifica se há plugin registrado para my_custom
  2. Chama validateBackendConfig(config) do plugin
  3. Persiste backend
  4. testConnection chamado se ?test=true na query

Segurança e isolamento

⚠️ Plugins rodam in-process no backend Node.js. Não há sandbox.

  • Confie apenas em plugins auditados. Code review antes de instalar
  • NetworkPolicy restritiva — plugin egress só pra hosts esperados
  • license_min_plan no plugin.json honrado por lib/license.js — plugin pode ser premium-only
  • Logs sanitizados — não logar valores de secret em código do plugin

Limitações atuais

  • JavaScript/Node.js apenas — Go/Python/etc. exigem subprocess wrapper (planejado v5)
  • Sem hot reload — adicionar plugin requer restart do backend
  • Sem signing/verification do plugin — segurança 100% via filesystem permissions
  • Plugin é singleton — uma instância por backend; sem isolamento por tenant

Roadmap

  • v5: plugin signing via Sigstore + auto-verification
  • v5: hot reload (file watcher)
  • v5: WASM runtime para isolamento + linguagem-agnóstico
  • v5: plugin registry oficial (cv plugin install my-org/sap-hana)

Boas práticas

  • Versione semver no plugin.json — facilita debugging
  • Teste em staging primeiro — plugins têm acesso ao banco interno do CV
  • Use metadata no lease para guardar IDs externos (úteis em revoke)
  • generatePassword com 32+ chars [A-Za-z0-9!@#$%^&*]
  • Idempotência em revokerevokeLease pode ser chamado 2× (reconcile)