こんにちは! CTO 室所属エンジニアの id:hogelog です。
もういくつ寝るとクリスマスというわけで毎年クリスマスのお楽しみ、新バージョンの Ruby がリリースされます。次バージョンの Ruby 3.1 では { foo:, bar: }
のようなハッシュのショートハンドや改善されたエラーハイライトが導入されるなど、Ruby の使い心地を改善する機能がいくつも組み込まれておりとても楽しみですね!
そんな Ruby 3.1 がもうすぐリリースされるというタイミングですが、ここでは先日リリースされた Ruby 3.0.3, 2.7.5, 2.6.9 に関連して hey 社内で進めたちょっとした業務とそこで出会った不具合について紹介します。
Ruby 3.0.3, 2.7.5, 2.6.9 のリリースと CVE-2021-41817, CVE-2021-41816, CVE-2021-41819
2021/11/24 にリリースされた Ruby 3.0.3, 2.7.5, 2.6.9 のリリースは CVE-2021-41817, CVE-2021-41816, CVE-2021-41819 の脆弱性に対応するためのセキュリティリリースです。
脆弱性対応のセキュリティリリースというものは速やかにアップグレードすることが望ましいです。リリースがされた時点で STORES のサービス (https://stores.jp/ec) は Ruby 2.7.4 を利用していました。 STORES も速やかに Ruby 2.7.5 にアップグレードすることが望ましいのですが、 STORES は現在 EC2 インスタンス上で Rails アプリを動かす構成となっており、Ruby のアップグレードをするにも「ソースコードを一行書き換えるだけ」では済みません。
しかし Ruby 2.7.4 -> 2.7.5 で対応している CVE-2021-41817, CVE-2021-41816, CVE-2021-41819 は date gem, cgi gem という2つの default gem のアップグレードでも対応可能となっています。*1 gem のアップグレードだけならば普段のデプロイフローの中でしていることなので対応は非常に容易です。gem のアップデートだけでも標準ライブラリの更新をできるようにしていっている Ruby 処理系改善の成果ですね。
rubygems < 3.2.0 ✕ bundler --path の不具合
そんなわけで Gemfile, Gemfile.lock を更新し date gem, cgi gem を脆弱性対応版に更新しデプロイ作業を進めたところ、bundle install
後の bundle exec …
実行ステップで以下のようなエラーを出力して終了してしまいました。
Bundler::GemNotFound: Could not find date-3.2.2 in any of the sources /path/to/ruby/lib/ruby/2.7.0/bundler/spec_set.rb:86:in `block in materialize' /path/to/ruby/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `map!' /path/to/ruby/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `materialize' /path/to/ruby/lib/ruby/2.7.0/bundler/definition.rb:170:in `specs' /path/to/ruby/lib/ruby/2.7.0/bundler/definition.rb:237:in `specs_for' /path/to/ruby/lib/ruby/2.7.0/bundler/definition.rb:226:in `requested_specs' /path/to/ruby/lib/ruby/2.7.0/bundler/runtime.rb:101:in `block in definition_method' /path/to/ruby/lib/ruby/2.7.0/bundler/runtime.rb:20:in `setup' /path/to/ruby/lib/ruby/2.7.0/bundler.rb:149:in `setup' /path/to/ruby/lib/ruby/2.7.0/bundler/setup.rb:20:in `block in <top (required)>' /path/to/ruby/lib/ruby/2.7.0/bundler/ui/shell.rb:136:in `with_level' /path/to/ruby/lib/ruby/2.7.0/bundler/ui/shell.rb:88:in `silence' /path/to/ruby/lib/ruby/2.7.0/bundler/setup.rb:20:in `<top (required)>'
非常に不可解なエラーだったので一旦 date gem, cgi gem のアップグレードはリバートし調査を進めたのですが、以下の条件下において bundler の実行に不具合が発生していることがわかりました。
- rubygems < 3.2.0
- 他 gem への依存性のない default gem を gem install でインストールした後、 BUNDLE_PATH 設定した bundler でインストール
一行で示すと以下のコマンドラインがエラーとなってしまいます。
gem install date:3.2.2 && bundle init && echo 'gem "date", "3.2.2"' >> Gemfile && bundle config set --local path gems && bundle install && bundle check
$ ruby -v ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [arm64-darwin20] $ gem -v 3.1.6 $ gem install date:3.2.2 Fetching date-3.2.2.gem Building native extensions. This could take a while... Successfully installed date-3.2.2 Parsing documentation for date-3.2.2 Installing ri documentation for date-3.2.2 Done installing documentation for date after 0 seconds 1 gem installed $ bundle init Writing new Gemfile to /Users/hogelog/repos/hey/tmp/blog/Gemfile $ echo 'gem "date", "3.2.2"' >> Gemfile $ bundle config set --local path gems $ bundle install # gems/ 以下にインストールされるはずがインストール済とされる Fetching gem metadata from https://rubygems.org/. Resolving dependencies... Using bundler 2.1.4 Using date 3.2.2 Bundle complete! 1 Gemfile dependency, 2 gems now installed. Bundled gems are installed into `./gems` $ bundle check # bundle install 済なので本来はインストール済とされるはず The following gems are missing * date (3.2.2) Install missing gems with `bundle install` $ echo $? 1
状況としては非常に限定的ですがサーバーへのデプロイなどではしばしばあり得る条件です。
デプロイできないのは困るのですが、こちらの不具合は rubygems をアップグレードすることで回避可能でした。rubygems のアップグレードは以下のように gem update --system
コマンドで実施できます。
$ gem update --system 3.2.33 Updating rubygems-update Fetching rubygems-update-3.2.33.gem Successfully installed rubygems-update-3.2.33 … $ bundle install Fetching gem metadata from https://rubygems.org/. Using bundler 2.2.33 Fetching date 3.2.2 Installing date 3.2.2 with native extensions Bundle complete! 1 Gemfile dependency, 2 gems now installed. Bundled gems are installed into `./gems` $ bundle check The Gemfile's dependencies are satisfied
というわけで STORES ではアップグレードした rubygems を利用して date gem 3.2.2, cgi gem 0.3.1 を導入し、速やかに脆弱性対応を済ませることができました。
Ruby 3.0 はデフォルトの rubygems バージョンが 3.2.3 なのでこの不具合に当たるアクティブな Ruby は 2.6, 2.7 のみです。*2 あまり大きな仕事ではなく、最新バージョンの Ruby の話でもなく、非常に限定的な状況でしか踏まない不具合対応の話です。しかしおそらくあまり広く知られた不具合ではなく、とても困っている人もいるかもしれませんし、ブログの形で周知してみました。どこかの誰かの参考になれば幸いです。
hey では不具合の原因を丁寧に調査し着実に業務を前に進めるエンジニアを募集しています。少しでも興味を持ってくれた方は以下のウェブサイトからオンライン会社説明会やカジュアル面談への応募、エントリーなどお待ちしております。
この記事は hey アドベントカレンダー21日目の記事として書かれました。heyの色々なポジションな人が様々なことについて記事を書いているので、ぜひ一度眺めにきてみてください。 tech.hey.jp