Tech Racho エンジニアの「?」を「!」に。
  • 開発

[インタビュー] Aaron Patterson(後編): Rack 2、HTTP/2、セキュリティ、WebAssembly、後進へのアドバイス(翻訳)

こんにちは、hachi8833です。Aaron Pattersonインタビューの続きをお送りいたします。インタビューを音声で聞いてみると、原文でカットされている細かなやりとりやくすぐりもわかって面白いと思います。

概要

原著者の許諾を得て翻訳・公開いたします。

写真はすべて元記事からの引用です。

[インタビュー] Aaron Patterson(後編): Rack 2、HTTP/2、セキュリティ、WebAssembly、後進へのアドバイス(翻訳)

6. Rack 2とHTTP/2

技術の話題に戻りましょう。Rack 2がリリースされるので私たちも備えておきたいのですが、何か役に立ちそうなことをご存知でしたら

了解です。まずはHTTP/2についてお話しましょう。Rails ConfではHTTP/2についてお話することになると思います。HTTP/2の問題は実のところ私にとって割りとウツなんですが、お話しいたします。これまでHTTP/2へのアップグレードについて調べていたのですが、プロキシサーバーがあればHTTP/2のほとんどの部分はそこでまかなえることがわかってきました。バックエンドのRailsアプリで何も変更する必要はなく、単にRailsアプリの手前でHTTP/2を動かせばいいんです。このときに最も見落とされがちなのは、プッシュです。

しかしKazuhoという名前の人物とやりとりして、H2OはHTTP/2サーバーとして最高峰だと知りました。皆さんがH2Oをご存知かどうかはわかりませんが、KazuhoはH2Oの作者です。H2Oは素晴らしく速いうえに、本当によくできたWebサーバーです。Kazuhoは現在Fastlyで働いていますが、FastlyはKazuhoがH2Oで作業する分についてもお金を出していますし、Fastlyも自社でH2Oを使っています。

とにかく、Kazuhoは新しい標準化を提案することを思いつきました。それは新しいレスポンスコードで、私はそれが101110だと思っています。これはアーリーレスポンスと呼ばれるもので、HTTP/1の普通のレスポンスコードなのですが、本質的にプッシュ(HTTP/2プッシュ)と同じものです。使っているプロキシがこのレスポンスコードを理解し、それをHTTP/2プッシュに変換するというわけです。

この方法の良い点は、HTTP/1で動くサーバーがあり、そのサーバーの通信相手であるプロキシがHTTP/2で話せるなら、プッシュを行いたいということをプロキシが理解できるという点です。本質的にHTTP/1とHTTP/2のいいとこ取りができるので、HTTP/1サーバーにまったく影響を与えずに引き続きプッシュを行えます。

H2Oはアセットにフィンガープリントを追加できるのも嬉しい点で、そのおかげでたとえばCSSをプッシュしたい場合にもサーバーが毎回相手にプッシュする必要はありません。その機能はサーバーが行うこともできますし、実際既に(Rails)サーバーにもあるので余分な作業になってしまいます。H2Oはそこを肩代わりするよう進化できますので、アプリ側で状態を維持する必要がなくなります。

Rackについて私が考えなければならない点は、1つのリクエストに対して複数のレスポンスを送信する何らかの方法が必要だということです。しかしそれはHTTP/1のレスポンスなので、どんなアプリなどについても影響を与えずに済みます。レスポンスは従来どおりのままで、本質的にはAPIが従来のままということですが、HTTP/2を90%サポートできます。

しかしそのためにはプロキシサーバーが必要ですね?

もちろんです。プロキシサーバーがフロントに必要なのは大きなデメリットではありますが、サポートのためにアプリに影響を与えずに済むというのはメリットです。

プロキシサーバーは昨今どのぐらいのユーザーに使われているものでしょうか?95%?

Herokuがメインのユーザーでもなければ、今どきはどんな人でもプロキシサーバーを使っていると思います。その点が問題ではありますが、HerokuはHerokuで独自のプロキシを動かしていますので、アプリは事実上プロキシの向こう側にあります。

私はこの点についてHerokuのエンジニアとやりとりを重ね、「プロキシをHTTP/2に変更してプロキシでアーリーレスポンスをサポートするだけでいいから」という感じに伝えたところ、今ではHerokuに置かれるサーバーはHTTP/2を無料でサポートしてもらえるようになりました。

私が見たところ、Heroku側の主な問題のひとつは、終端がSSLプロキシなので、アプリ側からはSSLが実行されていることがわからない点でしょうか。しかしこれは実際には問題にはなりません。そのプロキシがアーリーレスポンスコードを理解するのであれば、プロキシはそれがセルであることを知る必要はないのです。

アーリーレスポンスコードが仕様に組み込まれる見通しはいかがでしょうか?

いけると思います。Kazuhoは既にIETFにプロポーザルを提出したので、後は委員会のレビューを通すだけです。きっと仕様に加えてもらえるはずと確信しています。ブラウザがアーリーレスポンスコードをサポートするようになれば状況はさらによくなるでしょう。だからサーバー側としては「ようブラウザくん、ここにあるこれを先に持っていってくれや」とやればいいわけです。これでHTTP/1サーバーがHTTP/2とだいたい同じことができるようになるわけです。何にしろ、このあたりは面白くなってきています。

Rackの方はマルチプルリクエストに対応したんでしょうか?

それについてはずっと思案中です。対応は可能だと思いますが、本質的にはがんがんハックするだけのことです。コードのハックは可能な状態ですし、要するにハッシュを取り出して別のlambdaに押し込め、そのlambdaを呼ぶようにするだけでよいのです。面倒な作業ですが、やるつもりです。

それができないとアプリの互換性が失われてしまいますね

そのとおりです。今一番気がかりなのはその点なのです。以前その点について悩んでいたとき、もっといいAPIがあればいいのではないかと考えたりもしました。しかしそれでは多くのアプリで互換性が失われてしまいますので、それは避けたい。そんな方法では誰も幸せになれませんし、そのためにアップグレードしたい人もいないでしょう。

APIの互換性が失われたバージョンのRubyなんか誰も欲しくないですよね

私はPython 3を使う気にはなれません。

7. Railsセキュリティチーム

今度はRailsのセキュリティチームについてです。チームではどんな役割を?

私の役目は、チケットを読んでバグを修正し、コードや返信などを書くことです。セキュリティチームの他のメンバーがやっていることと変わりません。役割は皆で分担していますので、それぞれがチケットを担当し、修正してリリースします。

セキュリティチームに加わった経緯を教えて下さい

まあ、こういうチームに好んで加わりたい人などいないでしょうね。仕事はとてもきついですし。普通なら加わりたくないところでしょう。私がかかわり始めたときはセキュリティのissueのバックログが山ほど積まれてて、「これリリースしないとね」「これとこれも面倒みないとまずいね」と目まぐるしくやっているうちに「おめでとう!あなたもセキュリティチームの一員です」ときて、私は「えぇええー?!」、と実際にはこんな感じの経緯でした。

元々コアチームの一員に過ぎなかったのですが、ひょんなことからセキュリティ関連に興味を持ったばかりに「セキュリティチームへようこそ」となったわけです。セキュリティチームの仕事はつらいですね。誰がやってもつらいですよ。

チームの仕事は年中無休でやらないといけないんでしょうか?

実のところ、チームではHackeroneのセキュリティレポートをすべて扱ってますし、今チームの増員を図っているところです。以前は3〜4人程度でしたが、その後10人ぐらいにはなったでしょうか。実際には、GitHubのセキュリティエンジニアたちの中にもこちらに時間を割いてくれる人がいて、今では彼らもチームの一員です。彼らはRailsコアチームのメンバーではありませんが、HackeroneのメンバーなのでHackeroneのリソースにアクセスして返信してくれます。誰かがissueを送れば、彼らが担当チームのメンバーとしてパッチ適用や返信などをやってくれるおかげで、少しは負荷を分散できています。しかし私としては、常にオンラインで年中無休で対応みたいなことをチームには要求しません。

ゼロデイ攻撃が発覚してそれを修正しなければならないときは悪夢だったでしょうか?

いいえ、悪夢でもなんでもありませんでしたし、そういう事態になったこともありません。今までで最悪だったことがあるとすれば、YAMLでのリモートコード実行が見つかったときです。もちろん、そういう事態のときはいつだってつらくなりますよ。そういうのは本当につらいです。

そのときに困ったのは、エラーの詳細について「YAMLは安全じゃないのか!」と誤解されてしまったことです。実際は、Railsの中にYAMLをevalするコードがあったのです。たとえ正しいYAMLを送信してもおそらくevalされてしまったでしょう。YAMLデコーダーは基本的にRubyを使っているので、デコーダーもRubyで実装されています。したがって、YAMLからハッシュを1つ取り出してRubyで新しいハッシュを作成すると、新しいオブジェクトが1つ割り当てられ、続いてそのHash#equalsが呼ばれます。このため、Railsの中にHash#equalsできるオブジェクトが1つ存在し、そのオブジェクトはeval可能になります。その気になれば、YAMLを送信してそこからハッシュを作成してevalし、任意のコードを実行できてしまうでしょう。

この点を皆に説明するのが最も大変でした。この問題はYAMLによるリモートコード実行(RCE)と単純化して受け取られがちです。そう見えるところもありますが、実際にはそうではありません。今でもたまにその話題になると「もう勘弁して欲しい」という気持ちになります。あのときはつらかったですね。

今のお話で、2012年にGitHubがクラックされた事件を思い出しました。あれは実際にはセキュリティ問題ではなく、今のお話のような感じでした。attr_accessibleに渡さなければならないようなパラメータのストリップは、当時面倒臭がって誰もやっていませんでした。GitHubも含めて。詳しくはわかりませんが、たぶん先ほどのYAML露出よりもこちらの方が重大だったでしょうね。あなたがGitHubに入社したのはこれが理由だったかもしれませんね。今後このような事態を繰り返さないために。

今のお話には、例のDHHによるセキュリティ関連の発言以上のものもありそうですね。たとえば、サーバーからクライアントに送信されるJavaScriptテンプレートには、バグもあればRails以外の機能もありました。CSRFトークンを奪われるなどの可能性もあったでしょう。あのときのDHHの最初の返信はたしか「フォームをJavaScriptテンプレートで送信してはならない」でしたね。

そこは何とも言えません。DHHはセキュリティ問題にはそこまで深入りしていないと思うので。だからこそセキュリティチームがあるわけです。「そうではない、実際にはこれについて対応が必要だ」と。しかしセキュリティチームの作業の多くは、説明のために費やされがちです。何が問題なのか、実際にはその機能をどのように実現するのか、などです。それからやっと、問題解決をセキュアに実行する方法を模索します。残念ながら、こうした手順を踏んでいることによって、通常のリリースに安全でない機能が含まれる可能性があります。これに限った話ではありませんが。

8. WebAssembly

次はWebAssemblyについて。どんな言語が使われるのでしょうか?

WebAssemblyは面白いですね。いずれあらゆる場面で使われるようになるでしょう。そのときになったらFirefox上でLinuxを動かすつもりです。そしてそれを自分のOS環境にします。WebAssemblyが動くFirefoxがあればいいのですから。WebAssemblyは実にクールで素晴らしいと思います。

そのあたりで何か動きはありますか?Rubyの次の目玉になったりしますでしょうか?既にRubyをJavaScriptに変換するopalもありますし、今はRubyを使っていても多くの部分をJavaScriptでプログラミングしていますが、私たちRubyistもフロントエンドに進出する機会があるでしょうか?

そうなったらきっと素晴らしいことになると思います。まだ詳しく調べたわけではありませんが、それは十分可能でしょう。RubyをさまざまなAssemblyに変換するのは面白いプロジェクトになりそうです。Assemblyがブラウザ上で動作するという点については別ですが、その点についてもよくなるでしょう。私はJavaScriptを書くのは好きではありません。こんなことを言うのは恐縮ですが、正直、最悪な言語だと思っています。

バイナリコードで書くこともたぶんないでしょうね

そのとおりです。そうなったらもっとひどくなるかもしれない。

9. mruby

最近のあなたはArduinoでいろいろ遊んでいらっしゃるそうですね。mrubyを動かしているRubyチームがあるからかなと思ったのですが、そのあたりをもう少し

遊んでいるといっても大したことはやってません。mrubyをちょっと動かしてみた程度です。しかしmrubyと組み込みハードウェアの問題は、Arduinoではmrubyプログラムも満足に保存できないほどメモリ容量が足りないという点ですね。調べてみたところ、私が家で使っているチップはメモリがたった14kぐらいしかなくて、プログラムを14k以内に収めるのは無理な話です。

この環境は残念ながら使い物になりませんでしたが、mrubyは興味をそそられます。特にコマンドラインツールなどによいのではないでしょうか。コマンドラインユーティリティのあたりではGo言語と用途がかぶるところがありますが、私はMRIの方にもっと興味があります。

私はSinatraアプリを動かしていたときにmrubyを使っていました。そのときのルーターのRAMは8MBでした。あれは面白い体験でした。まさか動くとは思ってなかったのですが、私の選んだSinatraは動きました。

おお、それはいいですね。

10. 最強の開発者になるためには

それでは最後の質問です。この会場には若い開発者も大勢集まっています。昨日のイベントでは学生もたくさん見かけました。そこで、答えにくい質問なのは承知でおたずねします。ずばり、最強の開発者になる方法とは?

修練が必要ですね。最強の開発者になるための簡単な方法はないと思っています。とにかく修練、修練、また修練です。本もどっさり読まないと。皆さんの職階やキャリアに合った本をたくさん読むことをおすすめします。

プログラミングを学習中の方なら、Chris Pineの「Learning Program Ruby」を推します。キャリアを深めたい方には、Michael Featherの「Working Effectively with Legacy Code」がよいです。この本は本当に素晴らしくて、私のプログラミング人生が変わりました。必読です。内容はJavaとC++に終始していますが、解説されている技法はあらゆる言語で通用します。

ここで重要なことがあります。ひとつの言語ばかりやるのではなく、他の言語もやる必要があると私は考えます。他の言語を学ぶことで、仕事で使っている言語でも得るものがあります。

もっと踏み込みたい人には「GC Handbook」もおすすめです。ガベージコレクションに取り組んでいるので、最近はこの本やコンパイラの本を繰り返し読んでいます。

他にも良い本はたくさんありますが、やはり修練の方が大事です。自分自身にチャレンジし、やったことのないことをやり、ひとつの言語でバグを徹底的につぶすのです。皆さんにはぜひそれをおすすめします。

オブジェクト指向言語を学びましょう。関数型言語を学びましょう。そして日々そこから最良のエッセンスを得る方法を学びましょう。

11. 本について

本の話題になりましたが、技術書以外におすすめの本はありますか?

私は技術書しか読みません。

ポッドキャストやブログも読まないんですか?

退屈するだけです。実際には料理の本を読んでますが。

料理の本ではどれが好みですか?

America’s Test Kitchen」シリーズは読破しました。Webサイトでも読んでますし、本も全部読みました。このシリーズはいいですね。

Rubyクックブックは?

(笑)あれも素晴らしい料理本ですね。あと暇ができると、よく日本語の本を読んでました。日本語の練習のために。

(日本語)ブログもですか?

(笑)ブログもです。日本語は結局ブログでしたね。

今日はこの場にお越しいただきありがとうございました。あなたに会えてよかったと思います。

こちらこそありがとうございました。


[インタビュー] Aaron Patterson(前編): GitHubとRails、日本語学習、バーベキュー(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。