← Blog

openssl-win-root: Den Windows-Zertifikatsspeicher mit Ruby nutzen

Wer Ruby unter Windows einsetzt, sieht früher oder später eine HTTPS-Anfrage mit einem Fehler bei der Zertifikatsprüfung scheitern, obwohl sich dieselbe Seite im Browser problemlos öffnen lässt. openssl-win-root ist ein kleines Gem, das genau hier hilft.

Zuerst die Ehre, wem sie gebührt: Geschrieben hat das Gem Stas Ukolov, das ursprüngliche Repository ist github.com/ukoloff/openssl-win-root. Die erste Version erschien 2015. Mein Anteil ist klein, ich beschreibe ihn weiter unten.

Das Problem

OpenSSL in Ruby schaut nicht in den Windows-Zertifikatsspeicher, sondern braucht eigene CA-Zertifikate. RubyInstaller liefert zwar eine Datei cacert.pem mit, aber wie das README des Gems erwähnt, wird diese Datei nicht automatisch aktualisiert. Sie entspricht dem Stand, als Ihre Ruby-Version gebaut wurde. Neuere Stammzertifikate können also fehlen.

Windows hingegen hält seinen eigenen Speicher für vertrauenswürdige Stammzertifikate aktuell. Dort liegen auch Zertifikate, die Ihre Firma installiert, zum Beispiel per Gruppenrichtlinie. Ruby sieht sie schlicht nicht.

Was das Gem macht

Wenn Sie es unter Windows laden, macht openssl-win-root Folgendes:

  1. Es liest die vertrauenswürdigen Stammzertifikate aus dem Windows-Systemspeicher (über die crypt32-API, mit Hilfe von Fiddle).
  2. Es schreibt sie als PEM-Dateien in einen Ordner pem im Verzeichnis des Gems, mit den Dateinamen, die OpenSSL für ein Zertifikatsverzeichnis erwartet.
  3. Es fügt diesen Ordner dem Standard-Zertifikatsspeicher von OpenSSL hinzu und setzt die Umgebungsvariable SSL_CERT_DIR darauf.

Ein Netzwerkzugriff ist dafür nicht nötig. Auf anderen Betriebssystemen tut das Gem nichts, es kann also problemlos in einem plattformübergreifenden Projekt stehen.

So verwenden Sie es

Fügen Sie es dem Gemfile hinzu, nur für Windows:

gem 'openssl-win-root' if Gem.win_platform?

Führen Sie danach bundle aus oder installieren Sie es direkt:

gem install openssl-win-root

Laden Sie es, bevor Sie HTTPS-Anfragen machen:

require 'openssl/win/root'
require 'net/http'

Net::HTTP.get(URI('https://www.ruby-lang.org/')).length

Verwendet Ihr Projekt Bundler.require, wie etwa Rails, brauchen Sie das explizite require nicht.

Die exportierten Zertifikate lassen sich auch ausserhalb von Ruby nutzen. Setzen Sie SSL_CERT_DIR oder die Option -CApath des Befehls openssl auf den Ordner, den diese Methode liefert:

OpenSSL::Win::Root.path

Worauf Sie achten sollten

Meine Rolle

Als Ruby 3.2 erschien, funktionierte das Gem nicht mehr: Es rief File.exists? auf, und diese Methode wurde in Ruby 3.2 entfernt. Das ist dasselbe Problem, über das ich in meinem Beitrag zum Gem file_exists schreibe. Ich habe dafür einen Pull Request mit der Ein-Wort-Korrektur eröffnet.

Ich bin einer der beiden Inhaber des Gems auf RubyGems und habe im Januar 2023 die Version 1.1.2 aus meinem Fork veröffentlicht. Diese Version hat sehr wenig geändert:

Alles andere, also die eigentliche Idee und die Umsetzung, ist die Arbeit von Stas.