Saltar al contenido
ecdsa.com
Ruby openssl (Net::HTTP, Faraday, HTTParty, RubyGems)Ruby

Mensaje de error

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

También se muestra 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)

El mensaje completo es «SSL_connect returned=1 errno=0 peeraddr=<ip>:<port> state=error: certificate verify failed (unable to get local issuer certificate)»; en nuestras pruebas, peeraddr aparecía con la gema openssl de la 3.0.1 a la 4.0.2. Faraday lo envuelve como Faraday::SSLError con el mismo mensaje; las bibliotecas que llaman directamente a Net::HTTP dejan pasar OpenSSL::SSL::SSLError tal cual.

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

Qué significa

La interfaz de OpenSSL para Ruby (en la que se basan Net::HTTP y, por tanto, la mayoría de los clientes HTTP de Ruby) no encontró el emisor de la cadena de certificados del servidor entre las CA que carga. El texto entre paréntesis es el motivo de verificación de OpenSSL; todo lo anterior describe en qué punto de SSL_connect se produjo el fallo. Normalmente, la CA es privada o está detrás de un proxy, o este Ruby consulta un bundle de CA que no la contiene.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Instalar la raíz donde la busca el OpenSSL de Ruby

    OpenSSL::X509::DEFAULT_CERT_FILE y DEFAULT_CERT_DIR muestran las rutas del archivo y del directorio; en Debian y Ubuntu, update-ca-certificates actualiza los certificados que contienen.

    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.

    Establecer SSL_CERT_FILE para el proceso

    OpenSSL respeta SSL_CERT_FILE y SSL_CERT_DIR; haz que apunten a un bundle que contenga las raíces públicas y tu 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 un cliente su propio almacén

    Un OpenSSL::X509::Store con set_default_paths más add_file conserva las raíces públicas y añade la CA privada, con verificación 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 y otros envoltorios: pasar ca_file o cert_store

    La mayoría de las bibliotecas HTTP de Ruby aceptan opciones ssl que se corresponden con ca_file, ca_path o cert_store de Net::HTTP.

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

Errores relacionados

Explorar toda la base de datos de errores de firma