Pular para o conteúdo
ecdsa.com
Ruby openssl (Net::HTTP, Faraday, HTTParty, RubyGems)Ruby

Mensagem de erro

state=error: certificate verify failed (unable to get local issuer certificate)

Também aparece como

  • OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 peeraddr=127.0.0.1:8443 state=error: certificate verify failed (unable to get local issuer certificate)

A mensagem completa é “SSL_connect returned=1 errno=0 peeraddr=<ip>:<port> state=error: certificate verify failed (unable to get local issuer certificate)”; nos nossos testes, o peeraddr apareceu da gem openssl 3.0.1 até a 4.0.2. O Faraday encapsula o erro em Faraday::SSLError com a mesma mensagem; bibliotecas que chamam o Net::HTTP diretamente repassam o OpenSSL::SSL::SSLError sem alteração.

Ruby openssl (Net::HTTP, Faraday, HTTParty, RubyGems) — OpenSSL::SSL::SSLError from SSL_connect

O que significa

O binding do OpenSSL para Ruby (usado pelo Net::HTTP e, portanto, pela maioria dos clientes HTTP do Ruby) não encontrou o emissor da cadeia de certificados do servidor entre as CAs que carrega. O texto entre parênteses é o motivo da verificação informado pelo OpenSSL; tudo o que vem antes descreve em que ponto do SSL_connect a falha aconteceu. Normalmente, a CA é privada ou fica atrás de um proxy, ou este Ruby consulta um bundle de CAs que não a contém.

Por que acontece

Como corrigir

  1. 1.

    Instalar a raiz onde o OpenSSL do Ruby procura

    OpenSSL::X509::DEFAULT_CERT_FILE e DEFAULT_CERT_DIR mostram os caminhos; no Debian e no Ubuntu, o update-ca-certificates atualiza esses locais.

    bash
    # Ruby's OpenSSL reads the system bundle (see its default paths)
    ruby -ropenssl -e 'p OpenSSL::X509::DEFAULT_CERT_FILE, OpenSSL::X509::DEFAULT_CERT_DIR'
    sudo cp corp-root-ca.pem /usr/local/share/ca-certificates/corp-root-ca.crt && sudo update-ca-certificates
  2. 2.

    Definir SSL_CERT_FILE para o processo

    O OpenSSL respeita SSL_CERT_FILE e SSL_CERT_DIR; aponte essas variáveis para um bundle que contenha as raízes públicas e sua CA.

    bash
    # One process / environment: point OpenSSL at a bundle with the needed roots
    export SSL_CERT_FILE=/etc/ssl/private-ca/corp-ca-bundle.pem
    ruby app.rb
  3. 3.

    Dar a um único cliente o próprio repositório

    Um OpenSSL::X509::Store com set_default_paths mais add_file mantém as raízes públicas e adiciona a CA privada, com verificação completa.

    ruby
    # One client: default roots plus a private CA
    store = OpenSSL::X509::Store.new
    store.set_default_paths
    store.add_file("/etc/ssl/private-ca/corp-root-ca.pem")
    
    http = Net::HTTP.new("api.example.com", 443)
    http.use_ssl = true
    http.cert_store = store
  4. 4.

    Faraday e outros wrappers: passar ca_file ou cert_store

    A maioria das bibliotecas HTTP do Ruby aceita opções ssl que correspondem a ca_file, ca_path ou cert_store do Net::HTTP.

    ruby
    conn = Faraday.new("https://api.example.com", ssl: { ca_file: "/etc/ssl/private-ca/corp-root-ca.pem" })

Erros relacionados

Ver toda a base de erros de assinatura