Let's Encrypt: "unable to get issuer certificate" (erro 2), reemissão forçada e limites de taxa

Uma instalação ou reconstrução do Discourse pode rejeitar um certificado Let’s Encrypt válido com:

C=US, O=Let's Encrypt, CN=YR2
error 2 at 1 depth lookup: unable to get issuer certificate
error fullchain.cer: verification failed

Reproduzi isso imediatamente após a emissão bem-sucedida de RSA. A verificação falha dispara uma solicitação desnecessária de --force, o que pode levar a HTTP 429 / rateLimited / “too many certificates”. Na minha instalação, a emissão ECDSA foi bloqueada em seguida e o HTTPS não foi iniciado.

Com as cadeias afetadas, cada reconstrução ou reinício do contêiner pode disparar uma reemissão forçada desnecessária dos certificados RSA e ECDSA, mesmo quando eles ainda são válidos. Reemissões bem-sucedidas consomem a cota do Let’s Encrypt, portanto, reconstruções ou reinícios repetidos podem atingir rapidamente o limite de taxa.

Isso pode passar despercebido enquanto o HTTPS continua funcionando com os certificados já instalados. Excluir e reinstalar uma instância com o mesmo nome de host não redefine essa cota. Se os certificados necessários estiverem ausentes na nova instalação, a emissão limitada por taxa pode impedir o início do HTTPS.

Correção

Em templates/web.letsencrypt.ssl.template.yml, dentro de cert_exists(), substitua:

- openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer
+ openssl verify -untrusted ca.cer fullchain.cer

Mantenha o restante da função inalterado. O modelo corrigido deve ser incluído na próxima reconstrução do contêiner para atualizar /usr/local/bin/letsencrypt.

Se você já estiver limitado por taxa, o patch não redefine a cota. Aplique a correção e respeite o tempo de retry after antes de tentar novas emissões.

PR: FIX: preserve the Let's Encrypt issuer chain in cert_exists - Pull Request #1136 - discourse/discourse_docker - GitHub

Confirme o problema de verificação da cadeia

A partir do diretório do certificado afetado dentro do contêiner (/shared/letsencrypt/<hostname>, ou <hostname>_ecc), compare:

openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer
openssl verify -untrusted ca.cer fullchain.cer

No caso reproduzido, o primeiro comando falha com o erro 2; o segundo retorna:

fullchain.cer: OK

Causa e validação

openssl x509 -in ca.cer lê apenas o primeiro certificado do pacote do emissor. Na cadeia YR2 observada, ele descarta o Root YR assinado cruzado necessário para alcançar ISRG Root X1.

-untrusted ca.cer fornece o pacote completo do emissor, mantendo as âncoras de confiança no armazenamento do sistema, preservando a intenção da correção de 2021 (#576).

Verifiquei as cadeias RSA e ECDSA reais dentro do contêiner. Uma reconstrução completa com o patch reutilizou ambos os certificados existentes: duas mensagens Skip, ambas as cadeias instaladas e nginx -t passou.

Relatórios relacionados

411097
413078

PR: FIX: preserve the Let's Encrypt issuer chain in cert_exists - Pull Request #1136 - discourse/discourse_docker - GitHub

1 curtida