← Articoli

openssl-win-root: usare l’archivio certificati di Windows con Ruby

Se usate Ruby su Windows, prima o poi vedrete una richiesta HTTPS fallire con un errore di verifica del certificato, anche se lo stesso sito si apre senza problemi nel browser. openssl-win-root è una piccola gem che aiuta proprio in questo caso.

Innanzitutto, il merito a chi spetta: la gem è stata scritta da Stas Ukolov e il repository originale è github.com/ukoloff/openssl-win-root. La prima release risale al 2015. Il mio contributo è piccolo e lo descrivo più avanti.

Il problema

L’OpenSSL di Ruby non consulta l’archivio certificati di Windows: ha bisogno di propri certificati CA. RubyInstaller include un file cacert.pem, ma come fa notare il README della gem, questo file non viene aggiornato automaticamente. È il bundle del momento in cui è stata compilata la vostra versione di Ruby, quindi possono mancare certificati radice più recenti.

Windows invece mantiene aggiornato il proprio archivio di certificati radice attendibili. Questo archivio contiene anche i certificati installati dalla vostra azienda, ad esempio tramite Group Policy. Ruby semplicemente non li vede.

Cosa fa la gem

Quando la caricate su Windows, openssl-win-root:

  1. legge i certificati radice attendibili dall’archivio di sistema di Windows (tramite l’API crypt32, usando Fiddle),
  2. li scrive come file PEM in una cartella pem all’interno della directory della gem, con i nomi che OpenSSL si aspetta per una directory di certificati,
  3. aggiunge quella cartella all’archivio certificati predefinito di OpenSSL e imposta su di essa la variabile d’ambiente SSL_CERT_DIR.

Non serve alcun accesso alla rete. Sugli altri sistemi operativi la gem non fa nulla, quindi la si può tenere senza problemi in un progetto multipiattaforma.

Come usarla

Aggiungetela al Gemfile, solo per Windows:

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

Poi eseguite bundle, oppure installatela direttamente:

gem install openssl-win-root

Caricatela prima di effettuare richieste HTTPS:

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

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

Se il vostro progetto usa Bundler.require, come fa Rails, il require esplicito non serve.

I certificati esportati si possono usare anche al di fuori di Ruby. Puntate SSL_CERT_DIR, o l’opzione -CApath del comando openssl, alla cartella restituita da:

OpenSSL::Win::Root.path

Cose da tenere presenti

Il mio ruolo

Con l’arrivo di Ruby 3.2 la gem ha smesso di funzionare: chiamava File.exists?, rimosso in Ruby 3.2. È lo stesso problema di cui ho scritto nel mio articolo sulla gem file_exists. Ho aperto una pull request con la correzione di una sola parola.

Sono uno dei due proprietari della gem su RubyGems e a gennaio 2023 ho pubblicato la versione 1.1.2 dal mio fork. Quella release ha cambiato molto poco:

Tutto il resto, l’idea e l’implementazione vere e proprie, è opera di Stas.