Pular para o conteúdo
ecdsa.com
curl (OpenSSL backend)curl

Mensagem de erro

curl: (60) SSL certificate problem: unable to get local issuer certificate

Também aparece como

  • curl: (60) SSL certificate OpenSSL verify result: unable to get local issuer certificate (20)
  • SSL certificate problem: unable to get local issuer certificate

O curl baseado em OpenSSL (Linux, Homebrew no macOS, Git for Windows) imprime este texto; versões mais novas (8.22.0 no nosso teste, enquanto a 8.14.1 ainda usava o texto acima) formulam assim: “SSL certificate OpenSSL verify result: unable to get local issuer certificate (20)”, acrescentando o código de verificação do OpenSSL. O curl compilado com Schannel no Windows relata a mesma situação como “schannel: SEC_E_UNTRUSTED_ROOT (0x80090325)”, e a libcurl baseada em GnuTLS (usada pelo git no Debian e no Ubuntu), como “server verification failed: certificate signer not trusted”. Ferramentas baseadas na libcurl, como PHP e git, imprimem a parte depois de “(60) ” com o próprio prefixo.

curl (OpenSSL backend) — CURLE_PEER_FAILED_VERIFICATION, X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY (20)

O que significa

O curl recebeu os certificados do servidor, mas não encontrou, no próprio bundle de CAs, o certificado que emitiu o último da cadeia. O certificado pode ser perfeitamente válido; o curl simplesmente não consegue ligá-lo a nenhuma raiz em que confia, por isso recusa a conexão (código de saída 60). A peça que falta é um intermediário que o servidor esqueceu de enviar ou uma CA raiz que sua máquina não tem.

Por que acontece

Como corrigir

  1. 1.

    Ver o que o servidor envia de fato

    Liste os certificados do handshake. Se aparecer só um (profundidade 0) e o emissor dele for uma CA intermediária, a configuração do servidor está incompleta e precisa ser corrigida no servidor. Se a cadeia terminar em uma raiz da empresa ou criada por conta própria, é o cliente que não tem essa raiz.

    bash
    # Which certificates does the server send, and who issued the last one?
    openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \
      | grep -E '^ *[0-9]+ s:|^ *i:'
    #  0 s:CN=api.example.com
    #    i:C=US, O=Example Trust Services, CN=Example TLS Issuing CA   <- leaf only: intermediate missing
  2. 2.

    Corrigir o servidor: servir a cadeia completa

    Configure o servidor web com um bundle que contenha o certificado folha seguido de todos os intermediários. Isso corrige o erro para todos os clientes de uma vez, inclusive aplicativos móveis e clientes de API que você não controla.

    bash
    # Leaf first, then each intermediate in order; the root itself is optional
    cat api.example.com.crt intermediate.crt > fullchain.pem
    
    # nginx:   ssl_certificate     /etc/nginx/tls/fullchain.pem;
    # Apache:  SSLCertificateFile  /etc/apache2/tls/fullchain.pem
    # certbot: use live/<name>/fullchain.pem, never cert.pem
  3. 3.

    Instalar uma CA raiz privada no repositório do sistema

    Quando a cadeia termina legitimamente em uma raiz da empresa ou interna, adicione essa raiz ao bundle do sistema operacional. Obtenha a raiz com a equipe de TI ou de plataforma, ou com a própria CA; nunca a partir do certificado que a conexão com falha apresentou, já que é exatamente nele que você ainda não pode confiar.

    bash
    # Debian, Ubuntu, Alpine (the file must end in .crt)
    sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt
    sudo update-ca-certificates
    
    # RHEL, Fedora, Amazon Linux
    sudo cp corp-root-ca.pem /etc/pki/ca-trust/source/anchors/
    sudo update-ca-trust
  4. 4.

    Apontar o curl para um bundle em um comando ou em um shell

    A opção --cacert adiciona confiança para uma única chamada sem mexer no sistema; a variável CURL_CA_BUNDLE define o bundle para todas as chamadas do curl no ambiente. O arquivo pode conter vários certificados PEM.

    bash
    curl --cacert corp-root-ca.pem https://api.example.com/
    
    # or for every curl command in this shell (a file may hold several PEM certificates)
    export CURL_CA_BUNDLE=/opt/certs/corp-and-public-roots.pem
  5. 5.

    Instalar o bundle de CAs em contêineres mínimos

    Se até sites públicos falham dentro de um contêiner, a imagem não tem bundle. Instale ca-certificates na imagem (ou copie /etc/ssl/certs/ca-certificates.crt de um estágio de build) em vez de desligar a verificação.

    bash
    # Debian/Ubuntu-based images
    apt-get update && apt-get install -y --no-install-recommends ca-certificates
    # Alpine
    apk add --no-cache ca-certificates
  6. 6.

    Diagnóstico temporário: confirmar que é um problema de confiança

    A opção -k (--insecure) desativa a verificação de certificados, então uma resposta bem-sucedida só prova que o caminho de rede funciona e que a falha é de confiança. Nunca a deixe em scripts: com -k, qualquer um no caminho pode ler e alterar o tráfego, inclusive credenciais e código baixado.

    bash
    # Diagnostic only: if this works, the problem is trust, not the network.
    curl -sS -k -o /dev/null -w '%{http_code}\n' https://api.example.com/

Erros relacionados

Ver toda a base de erros de assinatura