Modos de Carga
O Tatuzim implementa tres modos de entrega, cada um otimizado pra um nivel de confianca e tipo de conteudo. Apenas csr_cert esta implementado no MVP; selado e push estao no roadmap.
Visao Geral
| Modo | Confianca | Quem inicia | Quem cifra | Uso tipico |
|---|---|---|---|---|
| csr_cert | Alta | Agent (pull) | step-ca (sem segredo cifrado) | Cert TLS — chave privada gerada localmente |
| selado | Alta | Agent (pull) | Publisher (envelope) | Plugins, secrets — confidencial por destinatario |
| push | Media | Server (push) | Publisher (assinatura) | Listas de bloqueio, configs publicas |
Modo `csr_cert` (implementado)
Quando usar: o agente precisa de um certificado e a chave privada NUNCA pode trafegar (ex: cert TLS pra Traefik servindo HTTPS no proprio VPS).
Fluxo
1. Admin: tatuzim carga create --tipo csr_cert --nome traefik-cert --destino vps-01
(registra a carga + entrega pendente)
2. Agent (loop run):
GET /v1/manifest → ve [{ id=E1, tipo=csr_cert, nome=traefik-cert }]
Para E1:
- Gera keypair ECDSA P-256 LOCAL
- Cria CSR com CN=vps-01
- POST /v1/certs/issue { csr_pem } via mTLS
- Server orquestra step-ca → cert
- Recebe { cert_pem, ca_pem }
- Escreve out/traefik-cert.crt + out/traefik-cert.key
- POST /v1/events entrega_instalada
- Executa hook post-csr-certGarantias
- Chave privada nunca sai do agent — server jamais ve nem armazena
- Server e step-ca veem apenas o CSR (publico)
- Idempotente: agent marca entrega em
processed.jsonapos sucesso - Audit: cada passo gera evento
Limitacao MVP
O CN do CSR e sempre o hostname do agent. Pra emitir cert com outro CN (dev.cdn.borlot.com.br), precisa de mecanismo dedicado (sub-fase futura ou direto via step-ca + outro provisioner).
Modo `selado` (roadmap v0.2)
Quando usar: voce quer entregar conteudo confidencial criado fora do agent (ex: plugin compilado, secret estatico).
Conceito: Envelope Encryption
Voce (publisher):
1. Gera DEK (Data Encryption Key) random
2. Cifra plaintext com DEK → ciphertext_blob
3. Para cada destinatario:
- Pega pubkey_X25519 do agent (do enroll)
- ECDH(DEK, agent_pubkey) → wrapped_dek_per_recipient
4. Sobe { ciphertext_blob, [wrapped_dek_per_agent...] } pro server
Server:
- Armazena o blob (no Cofre, planejado)
- Marca entregas pendentes por destinatario
Agent (loop):
- Ve carga selado no manifest
- GET /v1/blobs/<id> → recebe seu wrapped_dek + ciphertext
- X25519 ECDH com sua privkey → DEK
- ChaCha20-Poly1305 decrypt(DEK, ciphertext) → plaintext
- InstalaGarantias
- Confidencialidade per-destinatario: agent comprometido nao decripta carga dos outros
- Authenticity: publisher assina pacote inteiro
- No-trust-server: server nao tem como decriptar (so move blobs)
Pre-requisitos pra implementacao
- Agent envia pubkey X25519 no enroll (alem do cert)
- Server precisa de storage adequado pros blobs (Cofre)
- Tabela
cargasja temcofre_blob_prefixreservado pra isso - Crate
chacha20poly1305ja no workspace
Modo `push` (roadmap v0.3)
Quando usar: dados nao confidenciais que voce quer distribuir rapido pra todos os agentes (listas de bloqueio, regras de WAF, datasets compartilhados).
Conceito
Server inicia a entrega em vez de esperar o agent puxar:
Admin: tatuzim carga create --tipo push --nome block-list --destino agents-com-role-web
Server:
- Identifica destinatarios (todos com role=web)
- Pra cada agent ativo:
- Long-polling open OR proximo poll dele
- Server entrega payload assinado (sem cifra por dest, pq nao e confidencial)
Agent:
- Recebe payload (via response do long-poll OU push da pubsub futura)
- Valida assinatura do publisher
- Aplica/instala
- Reporta eventoPor que existir push se voce pode pull frequente?
Pull frequente (cada 5s) consome banda e CPU pra checks que retornam vazio. Push:
- Latency baixa pra distribuicao urgente (lista de bloqueio que precisa propagar AGORA)
- Banda otima (so trafega quando ha conteudo)
Trade-off: complexidade — conexao persistente ou polling rapido continuo.
Comparacao das garantias
| Garantia | csr_cert | selado | push |
|---|---|---|---|
| Confidencialidade end-to-end | ✓ (key local) | ✓ (envelope) | ✗ (publico) |
| Autenticidade do conteudo | ✓ (cert do step-ca) | ✓ (assinatura publisher) | ✓ (assinatura publisher) |
| Server pode ler conteudo | N/A (e cert publico) | ✗ | ✓ (mas e publico mesmo) |
| Idempotencia | ✓ | ✓ | ✓ |
| Audit log | ✓ | ✓ | ✓ |
Quando usar qual
Tem chave privada/secret?
│
├─ Sim, e cliente quer gerar local (cert TLS, ECDSA pra signing)
│ → csr_cert
│
├─ Sim, e voce quer DISTRIBUIR (plugin com secret embed, .env)
│ → selado
│
└─ Nao, e conteudo publico
├─ Atualizacao frequente, baixa latencia desejada (block-list)
│ → push
└─ Atualizacao esparsa, ok esperar proximo poll
→ selado (sem confidencialidade efetiva, mas usa infra existente)Implementacao por modo
| Camada | csr_cert | selado | push |
|---|---|---|---|
tatuzim_core::types::TipoCarga |
CsrCert |
Selado |
Push |
| Schema (cargas/entregas) | ✓ | ✓ (campos ja reservados) | ✓ |
| API endpoints | /v1/manifest, /v1/certs/issue |
/v1/blobs/<id> (pendente) |
/v1/push/<agent_id> (pendente) |
| Agent processor | process_csr_cert ✓ |
process_selado (pendente) |
process_push (pendente) |
| Crypto | step-ca (CSR) | ChaCha20-Poly1305 + X25519 ECDH | Ed25519 signature |
Referencias
- Arquitetura
- Criando uma Carga (csr_cert)
- Changelog (status de cada modo)