SSH Certificate Authentication: Substitua Senhas de Uma Vez por Todas
SSH Certificate Authentication: O Método Que Substitui Senhas e Funciona de Verdade
Eu perdi três dias debugging um problema de SSH. Três dias. Tinha um script de deploy que funcionava perfeito em produção, mas no servidor de staging? “Permission denied (publickey)”. Mudei a chave, depois mudei de novo, verifiquei o authorized_keys, conferi as permissões do .ssh/, reiniciei o sshd, lí o /var/log/auth.log mais vezes do que eu gostaria de admitir.
O problema? Uma chave SSH com 2048 bits que tinha expirado silenciosamente. Sem aviso. Sem erro claro. Só o famigerado “Permission denied” que não diz nada útil.
Depois disso, eu decidi que nunca mais queria depender de senhas SSH — e definitivamente nunca mais queria descobrir que uma chave expirou só quando o deploy falhasse às 2h da manhã. A solução que encontrei se chama SSH Certificate Authentication, e é o assunto desse post.
O Que É SSH Certificate Authentication?
É um método de autenticação SSH onde, em vez de confiar diretamente na chave pública do usuário (o modelo tradicional de “aqui está minha chave, me deixa entrar”), você assina digitalmente essa chave com um Certificate Authority (CA) privado. O servidor SSH confia na CA — não na chave individual.
Traduzindo: você tem uma autoridade certificadora que assina as chaves dos usuários. Quando alguém tenta fazer login, o servidor verifica a assinatura da CA, não a chave do usuário diretamente.
A grande sacada? Você pode definir uma data de expiração no certificado. Depois disso, ele simplesmente para de funcionar. Sem drama, sem surpresas às 2h da manhã.
Por Que Não Usar Só Chave Pública Tradicional?
O modelo tradicional funciona, mas tem três problemas chatos:
- Sem expiração: Uma chave SSH nunca expira por padrão. Se alguém Roubar essa chave, tem acesso vitalício ao seu servidor.
- Revogação manual: Precisa remover a chave pública do authorized_keys de todos os servidores quando alguém sai da equipe ou perde um laptop. Em 50 servidores, isso é um inferno.
- Escalabilidade horrível: Adicionar um novo desenvolvedor significa copiar a chave para N servidores. Com certificados, você só assina o certificado — todos os servidores que confiam na CA já estão prontos.
Arquitetura: Entendendo as Peças
A autenticação por certificado SSH funciona com dois componentes principais:
1. User Certificate
É a chave pública do usuário assinada pela sua CA. Contém:
- Chave pública do usuário
- ID do usuário (quem é)
- ID da CA que assinou
- Tipo de chave (ssh-rsa, ecdsa-sha2-nistp256, etc.)
- Serial (único por certificado)
- Período de validade (timestamps de início e expiração)
- Permissões críticas (opções como permit-pty, permit-X11-forwarding)
- Assinatura da CA sobre tudo isso
2. Host Certificate
Similar ao user certificate, mas para o servidor. Garante que você está se conectando ao servidor real, não a um ataque man-in-the-middle. O cliente SSH verifica a assinatura do host certificate contra a CA pública configurada.
O Perrengue Real: Quando a CA Venceu
Passo a Passo: Implementando SSH Certificate Authentication
Passo 1: Gerar a CA do Servidor
# Gere a chave privada da CA (NUNCA copie essa chave pra nenhum server)
ssh-keygen -t ed25519 -f ~/ca_user -C "CA Usuario - AutoMente"
# Gere a CA de host (essa também fica só no seu CA server)
ssh-keygen -t ed25519 -f ~/ca_host -C "CA Host - AutoMente"
# Configure permissões mínimas na chave privada
chmod 600 ~/ca_user ~/ca_host
Passo 2: Configurar o Servidor SSH para Confiar na CA
# No servidor, edite /etc/ssh/sshd_config:
# Caminho para a chave pública da CA de usuários
TrustedUserCAKeys /etc/ssh/ca_user.pub
# Caminho para o certificado de host (auto-assinado pela sua CA de host)
HostCertificate /etc/ssh/ssh_host_ecdsa_key-cert.pub
# Desabilite autenticação por senha (opcional, mas recomendado)
PasswordAuthentication no
# Recarregue o sshd
sudo systemctl reload sshd
Passo 3: Assinar a Chave do Usuário
# Assinar a chave pública do usuário com a CA
ssh-keygen -s ~/ca_user \
-I "usuario-devops@empresa.com" \
-n devops \
-V '+1d' \
-z 1001 \
~/.ssh/id_ed25519.pub
# Flags explicadas:
# -s: chave privada da CA para assinar
# -I: ID do certificado (identificação)
# -n: principal(s) — usuário(s) unix que pode usar esse cert
# -V: validade (+1d = 1 dia, +52w = 52 semanas, -5m = -5 minutos)
# -z: número de série (único por certificado na CA)
Isso gera um arquivo id_ed25519-cert.pub ao lado da sua chave pública. Esse é o certificado que você distribui junto com a chave.
Passo 4: Distribuir e Testar
# No cliente, configure ~/.ssh/config para usar certificado:
Host *.example.com
IdentityFile ~/.ssh/id_ed25519
CertificateFile ~/.ssh/id_ed25519-cert.pub
# Teste a conexão
ssh -v usuario@servidor01.example.com
No debug output, procure por Server accepts key e Certificate.
Revogação: O Problema Que Atrapalha Muita Gente
Uma dúvida comum: “OK, mas se o cara sair, como eu revogo o acesso na hora?”
Existem duas estratégias:
Estratégia 1: RevokedKeys (legacy mas funcional)
# No servidor, edite sshd_config:
RevokedKeys /etc/ssh/revoked_keys
# Para revogar um certificado, adicione a linha ao arquivo:
ssh-ed25519 AAAA... revoked
Estratégia 2: Principals (mais elegante)
Se você usa o campo -n ao assinar, o certificado só é válido para Principals específicos. Remover alguém é questão de não incluir mais esse principal na hora de assinar.
# Assinar sem o principal do usuário que saiu
ssh-keygen -s ~/ca_user \
-I "novo-devops@empresa.com" \
-n devops,deploy \
-V '+30d' \
~/.ssh/id_ed25519.pub
Cronograma de Validade: Quanto Tempo Colocar?
Essa é uma decisão de segurança vs. conveniência:
- +1h a +8h: Para pipelines de CI/CD automatizados. Curto, mas você precisa de automação pra assinar.
- +1d a +7d: Para workstations de devs. Curto o bastante pra limitar dano se perder laptop.
- +30d a +1y: Para service accounts que precisam de acesso confiável e estável.
Minha recomendação: Use +7d como padrão para humanos e +1d para pipelines. Crie rotação automática de certificados via script ou ferramenta como Cloudflare’s ssh-ca.
Integrando Com Infraestrutura Real
Com Ansible
# roles/ssh-ca/tasks/main.yml
- name: Deploy CA public key
copy:
dest: /etc/ssh/ca_user.pub
content: "{{ ssh_ca_public_key }}"
owner: root
group: root
mode: '0644'
- name: Configure sshd to trust CA
lineinfile:
path: /etc/ssh/sshd_config
line: "TrustedUserCAKeys /etc/ssh/ca_user.pub"
state: present
notify: reload sshd
Com Terraform (AWS EC2)
resource "aws_instance" "server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.micro"
# User data para configurar SSH CA no primeiro boot
user_data = <<-EOF
#!/bin/bash
echo "${tls_self_signed_cert.ca_public_key}" > /etc/ssh/ca_user.pub
echo "TrustedUserCAKeys /etc/ssh/ca_user.pub" >> /etc/ssh/sshd_config
systemctl reload sshd
EOF
}
Comparando: Senhas vs Chave Tradicional vs Certificates
| Aspecto | Senhas | Chave Tradicional | Certificate Auth |
|---|---|---|---|
| Expiração | Manual | Nunca | Automática |
| Revogação | Mudar senha | Remover de todos servers | Parar de assinar |
| Escalabilidade | Péssima | Razoável | Excelente |
| Proteção contra MITM | Nenhuma | Parcial | Completa (c/ host cert) |
| Setup inicial | Trivial | Fácil | Médio |
Erro Comum: O Principals Mismatch
Se você assinar com -n devops mas tentar fazer login como root, vai tomar um Permission denied (publickey) silencioso. O SSH não diz “principals mismatch” — ele só nega.
Debug:
# Verifique o que tem no certificado
ssh-keygen -L -f ~/.ssh/id_ed25519-cert.pub
Isso mostra todos os principals permitidos. Se não aparecer o usuário que você está tentando usar, é esse o problema.
Automação: Assinando Certificados Via Script
#!/bin/bash
# sign_ssh_key.sh - Assina chaves SSH automaticamente
CA_KEY="/opt/ca/keys/ca_user"
DAYS_VALID="${1:-7}"
PRINCIPALS="${2:-devops}"
PUB_KEY="${3:-/dev/stdin}"
serial=$(date +%s)
ssh-keygen -s "$CA_KEY" \
-I "cert-$(whoami)-$(hostname)" \
-n "$PRINCIPALS" \
-V "+${DAYS_VALID}d" \
-z "$serial" \
"$PUB_KEY"
Conclusão: É Mais Trabalho, Mas Compensa
Sim, configurar SSH Certificate Authentication toma tempo. Você precisa de um servidor de CA, rotação de chaves, scripts de assinatura, talvez até uma dashboard pra gerenciar tudo.
Mas a alternativa — ficar gerenciando authorized_keys em 50 servidores, descobrir que alguém saiu três meses depois porque ainda tinha acesso, perder uma manhã debugando um “Permission denied” — é pior.
Eu implementei isso num projeto com 12 servidores e 8 desenvolvedores. O setup inicial levou um dia. Depois disso, adicionar um novo desenvolvedor leva 5 minutos: gerar chave, assinar, entregar o certificado. Zero configuração em qualquer servidor.
Se você trabalha com infraestrutura, deploy automation ou qualquer coisa que envolva SSH em múltiplas máquinas, dá uma chance. Eu não voltei pra modelo tradicional depois que experimentei.
🔧 E você? Qual automação relacionado a servidores, deploy ou segurança você gostaria de ver aqui no AutoMente? Me conta nos comentários — pode ser que o próximo post resolva exatamente o seu problema. Se já usa Certificate Authentication, compartilha o perrengue que você enfrentou na implementação. Ajuda mais gente do que você imagina.
Categoria: Fortaleza Digital
