[和訳] 「install.sh の Curl パイプ Bash」問題を解決する 5つの方法 #getchef
この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。
本稿は 5 Ways to Deal With the install.sh Curl Pipe Bash problem (2015/07/16) の和訳です。
あなたは chef-client をインストールするのに、次のようなコマンドを実行するように書いてあるドキュメントを見たことがあると思います。
curl -L https://www.chef.io/chef/install.sh | bash -s -- -v 12
次のようにもできます。
curl -L https://chef.sh | bash
ChefDK では次のようにします。
curl -L https://www.chef.io/chef/install.sh | bash -s -- -v 12 -P chefdk
これらのコマンドが行うことは omnitruck と呼んでいるサービスと通信し、実行しているのはどの種類のディストリビューションなのかを判断するロジックを持つ 600 行くらいの短さのシェルスクリプトをダウンロードし、正しい s3 パッケージをダウンロードします(また、バージョン番号、ナイトリー、chefdk をインストールするコマンドラインオプションなどを取り扱っています)。
これらのコマンドすべては、インターネットからインストーラスクリプトをダウンロードして、bash シェルを通してローカルのマシンで実行するという形式に従っています。この方法は、多くの理由で非難されています。
この方法についてあなたが感じている心配の度合いと実際の危険性について、私はどう考えているかを整理し、それから代替策について説明しようと思います。これまで Chef をインストールするのに curl | bash を使ってはいけないと言った人は一人もいなかったでしょう? 同時に、このインストール方法を提供している理由と、新規ユーザにはこのインストール方法を最初に提示し続ける理由も説明しようと思います。
では、curl | bash に対して行える 5つの方法について説明しましょう。
気にしない
そう、install.sh を取り扱う最初の方法は、気にしない、ということです。もう少し説明しますが、これから説明する理由も気にしないのなら、1〜2節飛ばしてください。
はじめに、どうして気にしないのかという多くの根拠について書きました。curl | bash が悪いという議論を行う人々はさらに悪い議論を作り出すからです。私達が構築できる最高の curl | bash を作ったと言えることに満足しています。SSL を使っているし、すべてのバイナリのチェックサムを計算しているし、チェックサムは製品とは分離しているし、アカウントは異なる証明書を持っているし、すべてのスクリプトは git の履歴で確認できるし、PR を送ることでアクセスすることもできます。もし 600行の install.sh スクリプトをレビューしていないことが心配なら、10,000行の ruby コードの chef-client だってそれ以上に心配しないとおかしいでしょう? (アップグレードする前に RC 版をテストしていただけると嬉しいです。リモートからは十分でないと知っていますので)
しかしながら、install.sh による唯一の危険は、omnitruck サーバが侵入されて install.sh が改竄されるということです。そしてあなたはこのファイルをサーバにダウンロードし、root で実行することになります。もし install.sh の使用が自動化プロビジョニング手順の一部だったり、install.sh を実行する自動アップデートスクリプトならば、改竄を検知するまでの長い間、攻撃者はあなたのサーバに root で実行するコードを注入し放題になってしまうでしょう。RPM や Deb レポジトリの場合、root で実行するコードはあなたのディストリビューションの yum や apt-get バイナリで、ダウンロードしたパッケージは署名されていて、バイナリの検証はたいてい有効なので、改竄されたパッケージは検出されるため、この問題はありません (ダウンロードした公開鍵による署名が改竄されていないこと、私達が署名に使っている秘密鍵が誰かに盗まれていないこと、これらを信用しなければいけませんが)。
これが install.sh の弱点で、パッケージマネージャ経由でのインストールがよりよい方法であるということを隠さずに認めます。しかし、これについて心配する人々や私達のサーバが侵入されることを心配する人々は、パッケージマネージャのディストリビューションの経路の改竄についてはもちろん、私達の署名用の鍵も改竄されていることについてはおそらく心配していないということを述べました。ただし、omnitruck ruby アプリが壊れる可能性があることと、インターネットに直結したサーバに私達の秘密鍵を保存しないという追加的な予防手段があることは正しいです。
install.sh スクリプトをどこかにキャッシュする
install.sh 問題のもっとも単純な解決策は、スクリプトをキャッシュすることです。一旦キャッシュしてしまえば、誰かが私達のサーバに侵入しても、あなたのスクリプトまでは改竄できません。これで、あなたのディストリビューションで動作させている apt-get が「任意のバイナリ」であるのに比べれば、あなたがインターネットからダウンロードするような「任意のスクリプト」ではありません。誰かがディストリビューションのミラーサイトの 1つに侵入することと、おおよそ同レベルの攻撃があなたに対して行われるという危険に晒されています。もちろんスクリプトが古くなることがありますが、長い間とても安定していて API も安定しており、github の履歴を精査できるし、必要ならば必要なときにバグ修正を取り込むこともできます。
スクリプトはダウンロードする製品のチェックサムを計算しており、そして製品とチェックサムは別々のレポジトリに内部的には別々の証明書で格納されているので、すべてが SSL で行われるため、ダウンロードした情報が改竄されるようなほとんどの方法は事前に軽減されています。製品の署名の頂点で行われるので (MacOSX と Windows で修正されています)、パッケージマネージャのパッケージ検証を有効にしていれば、パッケージレポジトリを使っていて私達の公開鍵をインポートしているなら、改竄されたパッケージも拒絶します。
packagecloud.io レポジトリを使用する
オーケー、install.sh が単に嫌いなら、私達が packagecloud.io に持っている RPM や deb ファイルレポジトリを使うという次の解決策を聞いて嬉しくなるでしょう。packagecloud サイトに packagecloud レポジトリをインストールする方法のドキュメントがあります。しかし、デフォルトではおそらくやりたくないであろう(笑)、「Bash Scripts」タブに困惑するでしょう。まあ、「Chef」タブを叩いてみてください。Chef の packagecloud Cookbook が行う作業をとても短く親切に説明しています。
Chef の Recipe の metadata.rb に次のように記載します。
depends "packagecloud"
そして、omnibus_update Cookbook からちょっと借りてきた、多少複雑な Recipe を提案します。
packagecloud_repo "chef/stable" do
type "deb" # or "rpm"
end
package "chef" do
version node['myorg']['chef-client-version']
action :install
notifies :run, 'ruby_block[omnibus chef killer]', :immediately
end
# Continuing with a chef client run after the client has been upgraded will give undetermined results
ruby_block 'omnibus chef killer' do
block do
raise 'New omnibus chef version installed. Killing Chef run!'
end
action :nothing
end
しかし、これは Chef をインストールするのに Chef が動作していることを要求するので、初期ブートストラップの問題は解決していません。なので、次の 2つの方法のうちの 1つを組み合わせて使う必要があります。このコードは、(皆が deb/rpm を使っているなら) omnibus_update Cookbook の最も一般的なベストプラクティスであるユースケースの置き換えだと思います。
Knife Bootstrap の独自テンプレート
これは文字通り、ブートストラップする Node 上で knife bootstrap が実行するコードを、お好みのシェルスクリプトコードを置き換えます。デフォルトで Chef が使うテンプレートは「chef-full」(「フルスタック omnibus インストーラ」の略)と呼ばれており、Chef のソースコード内にあります。Chef 12.4.1 での chef-client をインストールするコードブロックはここにあり、好きなように変更できます。
<% if knife_config