Gerenciamento de segredos

Como guardar senhas, tokens e chaves fora do spec do job, com criptografia em repouso e rotação versionada.

Segurança·8 min·

Senha de banco, chave de API, token OAuth, credencial de provedor. Tudo isso é segredo e nada disso pode estar no spec do job.

Por dois motivos. Primeiro, specs costumam ser versionados em algum repositório. Qualquer pessoa com acesso de leitura ao repositório passa a ter acesso ao segredo. Segundo, specs trafegam em logs, em terminais compartilhados, em screenshots de revisão. Cada um desses pontos é um vazamento esperando para acontecer.

O HeroCtl traz um cofre de segredos integrado. Você não monta nada por fora.

Criando um segredo

Pela CLI, três formas:

# valor literal direto na linha de comando
heroctl secret create db_password --from-literal="s3nh4-l0nga-e-aleatoria"

# de um arquivo
heroctl secret create tls_key --from-file=./privkey.pem

# stdin (não fica no histórico do shell)
echo -n "valor-secreto" | heroctl secret create api_token --from-stdin

Pelo painel web, há um formulário equivalente.

Listando e inspecionando

# lista todos os segredos visíveis pelo seu token
heroctl secret list

# mostra metadados (versão, autor, data de criação) — nunca o valor
heroctl secret describe db_password

# mostra o valor (exige permissão explícita)
heroctl secret get db_password

heroctl secret get é a operação mais sensível do sistema. Ela aparece no log de auditoria com nome de quem leu, quando, e de qual IP.

Atenção: Em produção, restrinja secret:read ao mínimo de papéis. Para a maioria dos times, ninguém precisa ler valores manualmente — o cluster injeta direto no job.

Criptografia em repouso

Cada segredo é criptografado com AES-256 antes de ser persistido. A chave de criptografia do cluster fica protegida e nunca é armazenada junto com os dados criptografados.

Operacionalmente isso significa que um backup do estado do cluster, sem a chave, é inútil para um atacante. Você pode subir um snapshot em disco rígido externo sem se preocupar.

A chave em si é gerada na inicialização do cluster e fica em arquivo protegido por permissão de filesystem (0600, owner root) em cada nó servidor. Para rotacionar:

heroctl cluster rekey

Esse comando re-criptografa todos os segredos com uma chave nova e invalida a antiga. Faça em janela de manutenção — a operação pode demorar minutos em clusters com milhares de segredos.

Injetando no job

A injeção é feita no momento em que a alocação inicia. O valor descriptografado existe apenas na memória do processo, nunca em disco.

job: api-pagamentos
env:
  DATABASE_URL: ${secret.database_url}
  STRIPE_KEY: ${secret.stripe_secret}
  REDIS_PASSWORD: ${secret.redis_password}

O processo dentro do contêiner enxerga as variáveis como qualquer outra. Nenhuma alteração no código da aplicação.

Para injetar como arquivo (útil para chaves TLS, certificados, JSON de service account):

job: webhook-handler
files:
  - path: /etc/app/credentials.json
    content: ${secret.gcp_service_account}
    mode: "0400"

O arquivo é criado em tmpfs (não toca disco), com a permissão indicada, antes do processo principal subir.

Versionamento e rotação

Toda atualização de um segredo cria uma versão nova. A versão antiga fica disponível por uma janela de tempo configurável (default 7 dias) para casos de rollback.

# atualiza, mantendo histórico
heroctl secret update db_password --from-literal="senha-nova"

# lista versões
heroctl secret history db_password

# faz rollback para versão anterior
heroctl secret rollback db_password --to-version 3

Por padrão, jobs em execução continuam usando a versão que estava ativa quando subiram. Para forçar releitura, redeploye o job:

heroctl job redeploy api-pagamentos

Para um job que precisa sempre da versão mais recente sem redeploy, declare:

env:
  DATABASE_URL: ${secret.database_url:latest}

Nesse modo, o cluster reinicia a alocação automaticamente quando o segredo muda.

Permissões por papel (Business+)

No plano Business, você ganha controle granular sobre quem pode fazer o quê com qual segredo. O modelo trabalha com escopos hierárquicos:

policy "deploy-prod-secrets":
  secret:
    path: "prod/*"
    capabilities: ["read", "list"]
  secret:
    path: "prod/admin/*"
    capabilities: []  # nem listar

Atribua a política a um token ou a um papel e pronto. Ver o documento de RBAC para o modelo completo.

Auditoria (Business+)

Todo acesso é registrado:

heroctl audit secret --name db_password --since 30d

Saída tabular com timestamp, usuário, ação (read, update, delete), origem (IP), e resultado. Exporte para análise externa:

heroctl audit secret --since 30d --format json > audit.jsonl

Configure alertas para padrões anômalos: leitura fora de horário comercial, mesmo segredo lido por usuários diferentes em janela curta, falhas de permissão repetidas.

Backup criptografado

Backups dos segredos saem cifrados, prontos para mandar para storage S3-compatível:

# config do cluster
backup:
  secrets:
    enabled: true
    schedule: "0 3 * * *"  # 3h da manhã todo dia
    destination:
      type: s3
      bucket: heroctl-backups
      region: us-east-1
      prefix: secrets/
      credentials: ${secret.backup_s3_creds}
    retention_days: 90

O snapshot é cifrado com a chave do cluster antes de ser enviado. O bucket pode estar acessível para outros propósitos sem risco — quem tiver acesso de leitura não consegue descriptografar nada.

Para restaurar em um cluster novo, você precisa do snapshot e da chave do cluster original. Guarde a chave separada do storage de backup.

Cofres externos

Para times com requisitos de conformidade que exigem uso de cofre corporativo já existente, há integração opcional:

secret_backend:
  type: aws_kms
  region: us-east-1
  key_id: alias/heroctl-prod

Suportado de fábrica: AWS KMS, GCP KMS, HashiCorp Vault. Nesse modo, o HeroCtl delega operações de criptografia ao cofre externo. Os segredos continuam acessíveis pela mesma sintaxe ${secret.nome}.

Use isso se você já tem o cofre operando e auditado. Para a maioria dos times, o backend nativo é suficiente e mais simples.

Boas práticas

Em ordem de importância:

  1. Sem hardcode em spec. Nem em commit, nem temporariamente, nem "só para teste". O hábito vaza.
  2. Separação dev / staging / prod. Use prefixos no nome (dev/db_password, prod/db_password) ou clusters separados. Nunca compartilhe credencial de produção com ambiente de desenvolvimento.
  3. Rotação periódica. Mínimo a cada 90 dias para credenciais de banco e provedores. Mais frequente para tokens de API que vazam fácil.
  4. Least privilege na leitura. Quase ninguém precisa de secret:read. A injeção automática no job não exige que a pessoa que fez deploy tenha acesso ao valor.
  5. Revisão de auditoria mensal. Olhe quem leu o quê. Anomalias aparecem se você procura.
  6. Não loga segredo. Configure a aplicação para mascarar variáveis sensíveis em logs. O cluster cifra em repouso, mas se sua aplicação imprime print(os.environ) no startup, acabou.

Próximos passos

#secrets#seguranca#criptografia#rotacao