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
Uma CA privada ou um proxy com inspeção de TLS
comumA cadeia termina em uma raiz que não está no repositório do OpenSSL usado pelo Ruby.
Um Ruby compilado com o próprio OpenSSL (rbenv, asdf, rvm no macOS)
comumEssas instalações do Ruby usam o bundle de CAs do OpenSSL do Homebrew ou do OpenSSL embutido, e não o chaveiro do macOS (Keychain); raízes adicionadas ao chaveiro pela TI não valem para elas.
O servidor não envia o intermediário
ocasionalO OpenSSL não busca intermediários ausentes, por isso um servidor que envia só o certificado folha falha aqui, embora os navegadores o aceitem.
RubyInstaller no Windows
ocasionalO Ruby no Windows traz o próprio bundle de CAs; as raízes da empresa no repositório do Windows não entram nele automaticamente.
Como corrigir
- 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.
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.
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.
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
state=error: certificate verify failed (self-signed certificate in certificate…Ruby openssl (Net::HTTP, Faraday, RubyGems)Could not verify the SSL certificate for https://gems.example.com/.Bundlercurl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local…Python ssl module (OpenSSL)