Rotacao de Certificados

O cert do agent emitido no enrollment tem lifetime curto (default 24h). O agent renova automaticamente antes da expiracao. Tambem da pra forcar manualmente com tatuzim-agent rotate.

Renovacao automatica

Quando dispara

A cada iteracao do run loop (poll_interval, default 30s), o agent:

  1. Le o proprio cert (identity/agent.crt)
  2. Calcula time_until_expiry
  3. Se < TATUZIM_AGENT_RENEWAL_THRESHOLD (default 6h):
    • Gera novo keypair + CSR (mesmo CN)
    • POST /v1/certs/issue via mTLS (usa cert atual)
    • Atomic swap: escreve .new + rename
    • Rebuild do mTLS client (proximas chamadas usam novo cert)
    • POST /v1/events cert_renewed

Configurar threshold

# Default
TATUZIM_AGENT_RENEWAL_THRESHOLD=6h

# Renovar mais cedo (12h antes)
TATUZIM_AGENT_RENEWAL_THRESHOLD=12h

# Conservador (1d antes)
TATUZIM_AGENT_RENEWAL_THRESHOLD=1d

Edite em /etc/tatuzim-agent/env e systemctl restart tatuzim-agent.

Garantia

Mesmo em failures transientes do server, o agent tenta de novo no proximo poll. Enquanto o cert atual ainda tem validade > 0, mTLS continua funcionando.

Se o cert expirar antes da renovacao:

  • mTLS rejeita (cert invalido)
  • Agent loga error
  • Sem recuperacao automatica — re-enroll necessario

Por isso configure RENEWAL_THRESHOLD com folga: pra cert de 24h, threshold de 6h da 4 chances de renovar antes de expirar.

Rotacao manual

sudo -u tatuzim \
    TATUZIM_SERVER_URL="https://tatuzim.dev.borlot.com.br" \
    TATUZIM_SERVER_MTLS_URL="https://tatuzim.dev.borlot.com.br:8443" \
    TATUZIM_SERVER_CA_PATH="/etc/tatuzim-agent/stepca-root.pem" \
    TATUZIM_AGENT_HOSTNAME="vps-01" \
    TATUZIM_AGENT_ROLE="mautic" \
    TATUZIM_AGENT_DATA_DIR="/var/lib/tatuzim-agent" \
    /usr/local/bin/tatuzim-agent rotate

Output:

INFO tatuzim_agent::renewal: renewing cert old_serial=0123456789abcdef0123456789abcdef
INFO tatuzim_agent::renewal: cert renewed new_serial=fedcba9876543210fedcba9876543210

Cert rotated:
  old serial: 0123456789abcdef0123456789abcdef
  new serial: fedcba9876543210fedcba9876543210

Quando usar manual

  • Compromisso suspeito da chave atual (revogue+rotacione)
  • Apos tatuzim agente revoke no server
  • Debugging do fluxo de renewal
  • Forcar troca apos mudanca de config do step-ca

Verificar rotacao

# Antes
sudo -u tatuzim tatuzim-agent identity
# cert serial: AAAA...

# Rotate (ou aguardar renewal automatico)
sudo -u tatuzim tatuzim-agent rotate

# Depois
sudo -u tatuzim tatuzim-agent identity
# cert serial: BBBB...  (diferente)

No server, audit log:

docker stop dev_tatuzim_server
docker run --rm --entrypoint /usr/local/bin/tatuzim \
    -v tatuzim_tatuzim_vault:/var/lib/tatuzim \
    -e TATUZIM_MASTER_PASSPHRASE=... \
    tatuzim-server:dev \
    evento list --root /var/lib/tatuzim --agente vps-01 --limit 5
docker start dev_tatuzim_server

# OCORRIDO_EM          TIPO           ...
# 2026-05-23T...       cert_renewed   ...
# 2026-05-23T...       cert_renewed   ...  (anterior)
# 2026-05-23T...       agent_started  ...

Atomic swap

Pra evitar janela onde cert/key estao inconsistentes:

Antes:
  identity/agent.crt    (serial AAAA)
  identity/agent.key    (par com AAAA)

Durante:
  identity/agent.crt    (serial AAAA, ainda valido)
  identity/agent.key
  identity/agent.crt.new (serial BBBB)  ← cert + key novos baixados
  identity/agent.key.new                   ← criados antes do rename

rename(agent.crt.new, agent.crt)   ← atomic no mesmo filesystem
rename(agent.key.new, agent.key)   ← atomic

Apos o swap, o codigo do agent reconstroi o mTLS client (build_mtls_client) pra usar o novo cert/key. Conexoes em vou nao sao afetadas (TLS session ja estabelecida usa as keys que ja foram trocadas).

Cert do step-ca (do server, nao do agent)

Igualmente, o server faz auto-renewal do proprio cert TLS via server_identity::ensure_server_cert() no boot. Atualmente so check na inicializacao, nao periodico. Pra rotacionar, basta restart do server (vai detectar cert quase expirado e pedir novo).

Em prod, considere um cron pra docker restart dev_tatuzim_server semanalmente, ou implementar check periodico no main loop (planejado v0.4).

Hooks tambem disparam em rotacao?

Nao no MVP. Hooks disparam apenas pro process_csr_cert (cargas), nao pra renovacao do proprio cert do agent (que e um fluxo interno).

Pra ter notificacao em renovacao, observe o evento cert_renewed:

  • No server: evento list --agente X --limit 5
  • Notify webhook (planejado v0.4)

Troubleshooting

Renovacao falha com `UnknownIssuer`

Cert do agent vence ANTES de conseguir renovar. mTLS rejeita. Solucao:

  • Reduzir RENEWAL_THRESHOLD (renovar mais cedo)
  • Aumentar lifetime do cert no step-ca (default 24h pode ser pouco)
  • Em caso de cert expirado: re-enroll o agent

`cert_renewed` evento ausente no audit

Renewal aconteceu mas evento falhou (rede flap, server reiniciando). O cert foi trocado mesmo assim. Sem impacto operacional, apenas perda de visibilidade. Proximo cert_renewed aparece normalmente.

Serial nao muda apos rotate

Erro no fluxo. Logs com RUST_LOG=debug:

sudo systemctl stop tatuzim-agent
sudo -u tatuzim RUST_LOG=debug tatuzim-agent rotate

Provavel: server retornou erro (5xx), agent abortou antes do swap. Cert antigo continua intacto.

Proximos passos

By Borlot.com.br on 23/05/2026