2021年9月30日に発生した、Let’s Encryptのルート証明書の切り替え問題。
Amazon Linux1(OpesnSSL 1.0.2)上で稼働する弊社のRailsアプリケーションもしっかり影響を受けました。
AWSから対応方法についてアナウンスがあったのでその手順に従ってみたものの、イマイチうまくいかず、、、
そこで、ちょうどインスタンスをUbuntu20.04(OpesnSSL 1.1.1)に移行させる予定があったため、
Ubuntu上で稼働するようにアプリケーションを調整して入れ替えれば解決!
と思いきや、依然としてverify errorが発生。
以下は、Ubuntu上で奮闘した対応の記録です。
環境
- Amazon Linux1(OpesnSSL 1.0.2)
- Ubuntu 20.04(OpenSSL 1.1.1)
- Ruby 2.5.1
- Rails 6.0.3.6
OpenSSLのアップデートを試みる
OpenSSLのバージョンが低いと問題が起こるらしいので、バージョン1.1.1といえどアップデートしてみる。
$ sudo apt update && sudo apt upgrade openssl
しかしアップデートは起こらず。最新のものが入っているようです。
念のためopensslコマンドで接続してみる。
$ openssl s_client -connect XXXXX.com:443
Amazon Linux1の方ではこのコマンドでverify errorが出ましたが、Ubuntuの方では発生せず。
よって、OpenSSL 1.1.1自体は問題なさそう。
RubyがOpenSSL 1.1.1を見ていないのではないか?
1.1.1より古いバージョンのOpenSSLがシステム内に入っていて、Rubyがそちらを参照してしまっているのではないか?という仮説のもとに確認。
$ ruby -ropenssl -e "p OpenSSL::OPENSSL_VERSION"
しかし、問題なく1.1.1を参照しているようでした。
Rubyがルート証明書のリストを正常に認識できていないのではないか?
ルート証明書のリストにDST Root CA X3
が存在する、もしくはISRG Root X1
が存在しない、などの理由で問題が起こっているのではないか?と疑ったので、デフォルトのCA証明書ファイルを確認。
$ ruby -ropenssl -e "p OpenSSL::X509::DEFAULT_CERT_FILE"
しかしこちらも問題なし。
rubyコマンドではなくてプログラムファイルから実行する時に何か問題あるんじゃないか?
上記は全てrubyコマンドで実行したので、https接続確認用の簡単なプログラムを書いて実行してみる。
(参考: https://qiita.com/takano-h/items/dd10818eb7e09161bc29)
require "net/http"
uri = URI.parse("https://XXXX.com/")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme === "https"
headers = { "Content-Type" => "application/json", "Authorization" => "Basic XXXXXXX" }
response = http.get(uri.path, headers)
puts response.code # status code
puts response.body # response body
こちらもverify errorは発生しないので問題なさそう。
よくわからないが、たぶんアプリケーション側が悪いんじゃないか
- OpenSSLは問題なし
- Rubyも問題なし
- 証明書リストも問題なし
- プログラムファイルを実行しても問題なし
インフラ側でできることがもう何も無い気がしてきたので、アプリケーション側を疑うことに。
Railsは詳しくないので、最新のBundlerをインストール→Gemfile.lockを削除してbundle install
という強硬手段に出ました。
すると見事にverify errorが解消されてしまいました。
どうやらアプリケーション側で使用しているgemに問題があったようです。
問題はopenid_connect
のgemが古かったこと
改めて開発側に事情を説明し、http通信に関係するgemを洗い出してもらいました。
その中のgemを順にアップデートしてみたところ、openid_connect
をアップデートしたところで問題が解消されました。
Amazon Linux1の方でもopenid_connect
をアップデートしたところ、こちらもverify errorが解消されて問題なく稼働してくれました。
おわりに
上記はサラッと書きましたが、原因究明までにはかなり時間を要してしまいました。
OpenSSLやRuby/Railsまわりの知識があれば、もっと早く辿り着けたかもしれません。
日常的なインフラ対応は経験則でなんとかなる部分も多いですが、イレギュラーな事態へ対応していくには、基礎的な知識をもっとつけていく必要があるなと感じました。