Перейти к содержимому
ecdsa.com
Ruby openssl (Net::HTTP, Faraday, HTTParty, RubyGems)Ruby

Сообщение об ошибке

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

Также выводится как

  • 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)

Полное сообщение: «SSL_connect returned=1 errno=0 peeraddr=<ip>:<port> state=error: certificate verify failed (unable to get local issuer certificate)»; в наших проверках peeraddr присутствовал в версиях гема openssl от 3.0.1 до 4.0.2. Faraday оборачивает эту ошибку в Faraday::SSLError с тем же сообщением; библиотеки, которые вызывают Net::HTTP напрямую, пробрасывают OpenSSL::SSL::SSLError как есть.

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

Что это означает

Привязка Ruby к OpenSSL (её использует Net::HTTP, а значит, и большинство HTTP-клиентов на Ruby) не нашла издателя цепочки сертификатов сервера среди загруженных CA. Текст в скобках — причина, которую указывает проверка OpenSSL; всё, что перед ним, описывает, на каком этапе SSL_connect произошёл сбой. Обычно CA частный или принадлежит прокси, либо этот Ruby смотрит в пакет сертификатов CA, в котором этого CA нет.

Почему это происходит

Как исправить

  1. 1.

    Установите корневой сертификат туда, где его ищет OpenSSL в Ruby

    Пути показывают OpenSSL::X509::DEFAULT_CERT_FILE и DEFAULT_CERT_DIR; в Debian и Ubuntu файлы сертификатов по этим путям обновляет update-ca-certificates.

    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.

    Задайте SSL_CERT_FILE для процесса

    OpenSSL учитывает SSL_CERT_FILE и SSL_CERT_DIR; укажите в них пакет сертификатов, в котором есть и публичные корневые сертификаты, и ваш 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.

    Создайте собственное хранилище для одного клиента

    OpenSSL::X509::Store с set_default_paths и add_file сохраняет публичные корневые сертификаты и добавляет частный CA, при этом проверка выполняется полностью.

    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 и другие обёртки: передайте ca_file или cert_store

    Большинство HTTP-библиотек для Ruby принимают параметры ssl, которые соответствуют параметрам ca_file, ca_path или cert_store в Net::HTTP.

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

Связанные ошибки

Открыть всю базу ошибок подписей