古いRubyを使うためOpenSSL 1.1.1をXubuntu 22.04に入れる
rbenvにOpenSSL 1.1を入れてもらう
ruby-build 20220710からrbenvがOpenSSL 1.1を入れてくれるようになったようです。これで下記の作業は必要なくなりそう。
$ cd ~/.rbenv/plugins/ruby-build/
$ git pull
$ rbenv install 3.0.2
Downloading openssl-1.1.1q.tar.gz...
:
OpenSSL 1.1.1をインストールする
https://www.openssl.org/source/ より、メンテナンス用のユーザーとして作業する
ダウンロード。電子署名の検証に使ったsqコマンドについてはこちら。
$ mkdir -p ~/c/src/local/packages
$ cd ~/c/src/local/packages
$ curl -sO https://www.openssl.org/source/openssl-1.1.1o.tar.gz
$ curl -sO https://www.openssl.org/source/openssl-1.1.1o.tar.gz.asc
$ curl -sO https://keys.openpgp.org/vks/v1/by-fingerprint/8657ABB260F056B1E5190839D9C4D26D0E604491
$ sq verify --signer-cert 8657ABB260F056B1E5190839D9C4D26D0E604491 --detached openssl-1.1.1o.tar.gz.asc openssl-1.1.1o.tar.gz
Good signature from D9C4D26D0E604491
1 good signature.
展開、設定、ビルド、テスト
$ tar zvxf packages/openssl-1.1.1o.tar.gz
$ cd openssl-1.1.1o/
$ ./config --prefix=/opt/openssl-1.1.1
$ make
$ make test
インストール
$ sudo make install
システムのルートCAストアを利用する (詳細は下記)
$ sudo mv /opt/openssl-1.1.1/ssl/certs /opt/openssl-1.1.1/ssl/certs.installed
$ sudo ln -s /etc/ssl/certs /opt/openssl-1.1.1/ssl/certs
rbenvでRubyをインストールする
3.1未満のRubyはXubuntu 22.04のOpenSSL 3ではビルドできない。
$ rbenv uninstall 3.0.4
$ rbenv install 3.0.4
:
BUILD FAILED (Ubuntu 22.04 using ruby-build 20220412-1-g5c814ed)
:
The Ruby openssl extension was not compiled.
ERROR: Ruby install aborted due to missing extensions
Try running `apt-get install -y libssl-dev` to fetch missing dependencies.
:
上記でインストールしたOpenSSL 1.1.1を利用する。
$ RUBY_CONFIGURE_OPTS='--with-openssl-dir=/opt/openssl-1.1.1' rbenv install 3.0.4
rbenvでインストールされたRubyを利用する
C拡張ライブラリがOpenSSL 1.1.1を利用している場合には、実行時に共有オブジェクトの位置を教えてあげる必要があるようです。
$ export LD_LIBRARY_PATH=/opt/openssl-1.1.1/lib:$LD_LIBRARY_PATH
$ bundle exec ruby …
この項は、インストールしたOpenSSLでシステムのルートCAストアを利用するようにすることで不要になりました。bundlerは証明書をピンしているのではなく提供されていない環境でも利用できるようにしているようです。
古いbundlerのピンしているルートCA証明書に新しいものを加える
bundle install
が、rubygems.orgのSSL証明書を検証できずに止まりました。
$ rbenv install 2.6.6
$ rbenv local 2.6.6
$ bundle install --path=vendor/bundle
:
Retrying fetcher due to error (2/4): Bundler::Fetcher::CertificateFailureError Could not verify the SSL certificate for https://rubygems.org/.
:
bundlerがルートCA証明書をピンしているようです。
$ for p in `find ~/.rbenv/versions/2.6.6/ -name *CA*`; do dirname $p; done | grep rubygems.org | sort -u
/home/zunda/.rbenv/versions/2.6.6/lib/ruby/2.6.0/bundler/ssl_certs/index.rubygems.org
/home/zunda/.rbenv/versions/2.6.6/lib/ruby/2.6.0/bundler/ssl_certs/rubygems.org
/home/zunda/.rbenv/versions/2.6.6/lib/ruby/2.6.0/rubygems/ssl_certs/index.rubygems.org
/home/zunda/.rbenv/versions/2.6.6/lib/ruby/2.6.0/rubygems/ssl_certs/rubygems.org
rubygems.orgのSSL証明書のルートはGlobalSign Root CA - R3のようです。
$ :| openssl s_client -connect rubygems.org:443 2>/dev/null
CONNECTED(00000003)
---
Certificate chain
0 s:CN = rubygems.org
i:C = BE, O = GlobalSign nv-sa, CN = GlobalSign Atlas R3 DV TLS CA 2022 Q1
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Jan 22 16:45:18 2022 GMT; NotAfter: Feb 23 16:45:17 2023 GMT
1 s:C = BE, O = GlobalSign nv-sa, CN = GlobalSign Atlas R3 DV TLS CA 2022 Q1
i:OU = GlobalSign Root CA - R3, O = GlobalSign, CN = GlobalSign
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Oct 20 12:00:00 2021 GMT; NotAfter: Oct 20 00:00:00 2024 GMT
---
:
システムの持ってるルート証明書をコピーしてきちゃおう。
$ for p in `find ~/.rbenv/versions/2.6.6/ -name *CA*`; do dirname $p; done | grep rubygems.org | sort -u | xargs -i cp /etc/ssl/certs/GlobalSign_Root_CA_-_R3.pem {}
これで、bundle install
が完走するようになりました。
ルートCAの管理
opensslコマンド
./config --prefix=/opt/openssl-1.1.1
で設定したopensslはそのままではシステムのルートCAを参照しない。
/opt/openssl-1.1.1/ssl/certs/
にはファイルがない。Ubuntuが管理していると思われる/etc/ssl/certs
にはUbuntuが管理しているルートCAが含まれているようだ。システムが管理しているopensslの参照先にもUbuntuが管理しているルートCAが含まれているようだ。少なくともISRG Root X1の提供元はca-certificates
のようだ。
$ LD_LIBRARY_PATH=/opt/openssl-1.1.1/lib:$LD_LIBRARY_PATH /opt/openssl-1.1.1/bin/openssl version -d
OPENSSLDIR: "/opt/openssl-1.1.1/ssl"
$ ls -l /opt/openssl-1.1.1/ssl/certs/ISRG_Root_X1.pem
ls: cannot access '/opt/openssl-1.1.1/ssl/certs/ISRG_Root_X1.pem': No such file or directory
$ ls -l /etc/ssl/certs/ISRG_Root_X1.pem
lrwxrwxrwx 1 root root 51 May 16 2021 /etc/ssl/certs/ISRG_Root_X1.pem -> /usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt
$ openssl version -d
OPENSSLDIR: "/usr/lib/ssl"
$ ls -l /usr/lib/ssl/certs/ISRG_Root_X1.pem
lrwxrwxrwx 1 root root 51 May 16 2021 /usr/lib/ssl/certs/ISRG_Root_X1.pem -> /usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt
$ dpkg -S /usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt
ca-certificates: /usr/share/ca-certificates/mozilla/ISRG_Root_X1.crt
システムのopensslはLet's Encryptの証明書を検証できる。
$ :| openssl s_client -connect mastodon.zunda.ninja:443 > /dev/null
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = mastodon.zunda.ninja
verify return:1
DONE
この記事でインストールしたopensslはLet's Encryptの証明書を検証できない。
$ :| LD_LIBRARY_PATH=/opt/openssl-1.1.1/lib:$LD_LIBRARY_PATH /opt/openssl-1.1.1/bin/openssl s_client -connect mastodon.zunda.ninja:443 > /dev/null
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = mastodon.zunda.ninja
verify return:1
DONE
Ruby
$ ruby -ropen-uri -e "p URI.open('https://mastodon.zunda.ninja/')"
#<Tempfile:/tmp/open-uri20220625-7148-d4cj1t>
$ rbenv local 2.6.6
$ ruby -ropen-uri -e "p URI.open('https://mastodon.zunda.ninja/')"
Traceback (most recent call last):
:
1: from /home/zunda/.rbenv/versions/2.6.6/lib/ruby/2.6.0/net/protocol.rb:44:in `ssl_socket_connect'
/home/zunda/.rbenv/versions/2.6.6/lib/ruby/2.6.0/net/protocol.rb:44:in `connect_nonblock': SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate) (OpenSSL::SSL::SSLError)
この記事でインストールしたopensslにシステムのルートCAを見せる
$ sudo mv /opt/openssl-1.1.1/ssl/certs /opt/openssl-1.1.1/ssl/certs.installed
$ sudo ln -s /etc/ssl/certs /opt/openssl-1.1.1/ssl/certs
これでこの記事でインストールしたopensslでもルートCAを参照することができるようになる。
$ :| LD_LIBRARY_PATH=/opt/openssl-1.1.1/lib:$LD_LIBRARY_PATH /opt/openssl-1.1.1/bin/openssl s_client -connect mastodon.zunda.ninja:443 > /dev/null
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = mastodon.zunda.ninja
verify return:1
DONE
$ rbenv local 2.6.6
$ ruby -ropen-uri -e "p URI.open('https://mastodon.zunda.ninja/')"
#<Tempfile:/tmp/open-uri20220625-7484-20nmko>