Fehlermeldung
state=error: certificate verify failed (unable to get local issuer certificate)
Auch ausgegeben als
- 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)
Die vollständige Meldung lautet „SSL_connect returned=1 errno=0 peeraddr=<ip>:<port> state=error: certificate verify failed (unable to get local issuer certificate)“; peeraddr war in unseren Tests mit dem openssl-Gem 3.0.1 bis 4.0.2 enthalten. Faraday verpackt sie als Faraday::SSLError mit derselben Meldung; Bibliotheken, die Net::HTTP direkt aufrufen, reichen OpenSSL::SSL::SSLError durch.
Ruby openssl (Net::HTTP, Faraday, HTTParty, RubyGems) — OpenSSL::SSL::SSLError from SSL_connect
Was der Fehler bedeutet
Das OpenSSL-Binding von Ruby (von Net::HTTP und damit von den meisten Ruby-HTTP-Clients verwendet) konnte den Aussteller der Zertifikatskette des Servers nicht unter den CAs finden, die es lädt. Der Text in Klammern ist der Grund aus der OpenSSL-Prüfung; alles davor beschreibt, an welcher Stelle in SSL_connect der Fehler aufgetreten ist. Meist ist die CA privat oder steckt hinter einem Proxy, oder dieses Ruby schaut in ein CA-Bundle, das sie nicht enthält.
Warum der Fehler auftritt
Eine private CA oder ein Proxy mit TLS-Inspektion
häufigDie Kette endet bei einem Root-Zertifikat, das der von Ruby verwendete OpenSSL-Zertifikatsspeicher nicht enthält.
Ein gegen ein eigenes OpenSSL gebautes Ruby (rbenv, asdf, rvm unter macOS)
häufigSolche Ruby-Versionen verwenden das CA-Bundle des OpenSSL von Homebrew oder des mitgelieferten OpenSSL, nicht den macOS-Schlüsselbund; von der IT zum Schlüsselbund hinzugefügte Root-Zertifikate greifen nicht.
Der Server sendet sein Zwischenzertifikat nicht
gelegentlichOpenSSL lädt fehlende Zwischenzertifikate nicht nach, deshalb scheitert hier ein Server, der nur sein Leaf-Zertifikat sendet, obwohl Browser ihn akzeptieren.
RubyInstaller unter Windows
gelegentlichRuby unter Windows bringt ein eigenes CA-Bundle mit; Root-Zertifikate der Firma im Windows-Zertifikatsspeicher sind nicht automatisch darin enthalten.
So behebst du den Fehler
- 1.
Root-Zertifikat dort installieren, wo das OpenSSL von Ruby sucht
OpenSSL::X509::DEFAULT_CERT_FILE und DEFAULT_CERT_DIR zeigen die Pfade; unter Debian und Ubuntu aktualisiert update-ca-certificates diese.
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.
SSL_CERT_FILE für den Prozess setzen
OpenSSL berücksichtigt SSL_CERT_FILE und SSL_CERT_DIR; lass sie auf ein Bundle zeigen, das die öffentlichen Root-Zertifikate und deine CA enthält.
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.
Einem Client einen eigenen Zertifikatsspeicher geben
Ein OpenSSL::X509::Store mit set_default_paths plus add_file behält die öffentlichen Root-Zertifikate und fügt die private CA hinzu, ohne die Prüfung einzuschränken.
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 und andere Wrapper: ca_file oder cert_store übergeben
Die meisten Ruby-HTTP-Bibliotheken akzeptieren ssl-Optionen, die auf ca_file, ca_path oder cert_store von Net::HTTP abgebildet werden.
ruby conn = Faraday.new("https://api.example.com", ssl: { ca_file: "/etc/ssl/private-ca/corp-root-ca.pem" })
Verwandte Fehler
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)