大規模なユーザーコンテンツのHTTPS化 Let's Encryptも活用した「はてなブログ」のこだわり

国内外を問わず、多くのWebサービスで「HTTPS化」が進んでいます。暗号化通信によってユーザーの情報を盗聴から保護し、データの改ざんやなりすましを防ぐことでセキュリティを強化できる上、HTTPSを前提とした新たな技術が活用できることがメリットです。

HTTPSでない通信をWebブラウザが注意喚起する対応も進んでいます。Google Chromeでは、2018年7月に正式リリースされたバージョン68から、HTTPで配信されるページコンテンツに対して、アドレスバーに「保護されていない通信」と表示されるようになりました。今後は、さらに厳しく警告されることになるようです。

こうした動向を踏まえて、株式会社はてなが提供するブログサービス「はてなブログ」でも、HTTPS化への準備が2017年9月に告知され、2018年6月にかけて移行が順次行われました。その実現には、ブログサービスならではのさまざまな工夫が必要だったといいます。

はてなブログへの接続をすべてHTTPSにできる機能の実装予定と、利用を検討するユーザー様に準備いただきたいこと - はてなブログ開発ブログ

今回は、株式会社はてなでアプリケーションエンジニアを務め、今回のHTTPS化プロジェクトを進めた中澤亮太@aereal、写真・右)さんと福本貴之@__papix__、写真・左)さんに、開発にあたって意識した点やその内幕を聞いてみました。

hatenablog engineers

ブログならではの特殊な背景:たくさんの独自ドメインとMixed Content

── はてなブログでは、いつごろからHTTPS化への取り組みが始まったのでしょうか?

中澤 HTTPS化に取り組み始めたのは、告知の少し前で2017年8月のことです。業界全体の動向を見据えて、はてなブログではHTTPS化をその期*1で最も優先順位の高い取り組みと位置付け、私と福本がアサインされる形でスタートしました。

福本 HTTPS化は3つのフェーズに分けて進めました。第1フェーズでは、はてなブログの管理画面。第2フェーズは、はてなが提供するドメインを使ったブログ*.hatenablog.comなど)のHTTPS化。そして最後の第3フェーズは、有料プラン「はてなブログPro」の機能の1つとして提供している独自ドメインを利用したブログのHTTPS化です。

はてなブログHTTPS化の進め方
第1フェーズ
はてなブログ管理画面のHTTPS化
第2フェーズ
はてな提供ドメイン(hatenablog.comなど)を使ったブログのHTTPS化
第3フェーズ
はてなブログProで提供する独自ドメインのHTTPS化

第1フェーズと第2フェーズは、通常のサーバーをHTTPS化するのと同じでやるべきことはだいたい決まっていましたから、それを着実にやっていこうという気持ちで臨みました。とは言え、実際に手を動かしてから分かることも多く、想定以上に大変だったのが実感です。

── 大規模なユーザー向けサービスのHTTPS化ということで、他のWebサイトにはない問題もあったかと思いますが……。

中澤 当初から考慮しないといけないことが多そうだと覚悟していたのは、第3フェーズの独自ドメインにおけるSSLサーバー証明書の扱いです。

最初は、はてなブログがAWS上で動いていることもあり、AWSがマネージドサービスとして提供している証明書発行サービスを利用することも検討しました。

ですが、はてなの独自ドメインの利用数は万単位のオーダーという他にあまり見ないような規模です。似たような仕組みを採用したシステムも確かにあり、オーダーの桁が少ないならば、多少ナイーブなシステムでも大丈夫ですが、はてなブログの場合はとにかくスケールが違う。

そこを踏まえて、どう証明書を発行し、継続的に更新し、コンテンツ配信時に選択して使うかという難しい課題がありました。

福本 もうひとつ、UGC(User Generated Content)なブログサービスならではの課題もありました。通常のサービスならば、ある程度コンテンツの内容を事業者側で制御できます。しかし、ブログはユーザーさん自身がコンテンツを作り、それを多くの読者が見に来ることでサービスが成り立っています。

はてなブログでは、ページ中に画像だけでなく、JavaScriptやCSSといった外部のさまざまなコンテンツを埋め込めるのですが、それがHTTPだと、Mixed Content(混合コンテンツ)という問題が発生します。ユーザーさんが過去に貼り付けたコンテンツをすべて修正するのは難しいにせよ、少なくとも公式が提供する機能で貼り付けたときは、これから発生しないようにしたい。そうでないとブラウザが検知して警告を出すため、読者やユーザーさんを不安がらせてしまいます。

中澤 ブラウザによっては画像が見えなくなったり、JavaScriptが動作せずにコンテンツが正しく動作しなかったり、ユーザーさんの意図した通りに表示されなくなるという問題もありました。

aereal

NginxとAWSマネージドサービスを組み合わせて実現した動的な証明書配信

── 実際にどのように解決していったかをお聞きしたいのですが、まず「独自ドメイン」についてはどのように対応したのでしょうか?

中澤 独自ドメインのHTTPS化では、無償で電子証明書を発行できる「Let's Encrypt」を認証局に採用しました*2。コスト面での利点に加え、APIを介してプロセスを自動化できる証明書発行サービスとなると、選択肢はほぼLet's Encryptのみでした。

Let's Encrypt - Free SSL/TLS Certificates

そして、Nginxの拡張モジュール「ngx_mruby」のフックポイントを活用して、リクエストが来たら証明書を動的に読み込むようにしました。

証明書配信時の遅延を減らすことも重要です。ローカルのファイルシステム上に証明書を持つとスケーラビリティ上、スジがよくありません。かといって、データストアを置いて相対的に遠い距離にあるものを読み込みにいくペナルティも避けたいと考え、プロキシごとにmemcachedによるキャッシュも併用することにしました。

証明書配信用に開発したゲートウェイにmrubyからリクエストがあると、まずmemcachedに問い合わせを行います。そこに証明書があればそれを返して終わり。なければ、マスターデータベースとなるAmazon DynamoDBにリクエストして証明書を取得し、mrubyに返答しつつmemcachedのキャッシュに書き込む形です(下記資料の25ページ目からを参照)

これって「ピタゴラスイッチみたいだな」と思って、自分の中ではそう呼んでいました。

ブログサービスのHTTPS化を支えたAWSで作るピタゴラスイッチ - builderscon tokyo 2018

キャッシュデータの生存期間は、キャッシュを生かしたパフォーマンスと、古い証明書が返されてしまうリスクとのバランスを取って、1時間程度にしています。特定のブログにバースト流入が発生しても、1時間程度のタイムウィンドウがあれば収まりますし、その間はキャッシュが効きます。

福本 証明書の更新は、Let's Encryptで発行した証明書の有効期限である3カ月より短い間隔で、ある程度の余裕を持たせながら定期的に実行しています。その更新も集中しないよう、再発行には1時間程度でランダム化する仕組みも持たせました。

── ゲートウェイなど必要な仕組みの実装で工夫したことを教えてください。

中澤 ゲートウェイをはじめとする一連のサービスは、はてなブログで主に使っているPerlではなく、Goで書いています。

Let's Encryptとの連携には、AWSのStep FunctionsLambdaを活用することを決めていたため、Lambdaがサポートするランタイムの中から、静的に型を付けることができ、コンパイラの力を借りることができるもの……と考えていくと、ほぼ全会一致でGoに決まりました。Perlが好きな人には、意外とGoは書きやすいと思います。

福本 今回の仕組みではAWSのマネージドサービスをかなり活用していますが、もし使わなかったら時間が倍くらいかかっていたかもしれませんね。

中澤 はてなブログではこれまでもAWSを活用してきましたが、EC2がメインで、アーキテクチャとしてはオンプレミスの延長線上にあるものでした。けれど今回の経験で、AWSのマネージドサービスってよくできているんだなと実感しました。

Webエンジニアとしてはどうしても、プロプライエタリなサービスにロックインされることを懸念しますが、心配したほどのことはなかったですし、特に困ることもなかったです。また、いろいろな運用の負担が軽減された実感があります。この先、マネージドサービスはもっと積極的に活用してもいいかもしれないと考えています。

福本 第3フェーズでは、1~2週間かけてプロトタイプを書いたことも大きかったですね。まず、中澤がGoでプロトタイプを書いて、私はインフラ周りを見ていました。その後、本番の実装では、私がプロトタイプを見てGoを勉強しながら書き、中澤がAWS周りを作ったという感じです。

プロトタイプを作ったことで見積りの精度もよくなり、その後のプロジェクトに影響を及ぼすことなく、オンスケジュールで進行できたメリットもありました。

papix

ひたすら地道に、丁寧に対応していった「Mixed Content」問題

── Mixed Contentの問題はどうでしょう?

福本 とにかく丁寧に対応していきました。はてなブログの記事編集画面にある編集サイドバーでは、公式で20個くらいの外部コンテンツの埋め込みに対応しています。それら1個1個について、レスポンスやAPIを見たり、仕様に変更がないか確認したりといった地道な作業を繰り返し、リソースをHTTPSで埋め込むよう改善していきました。

中澤 企画・サービスの面でも重要な意思決定をする必要がありました。自社で配信するコンテンツならHTTPSにすればよいのですが、外部のプロバイダーが提供するコンテンツを、われわれの裁量でHTTPS化することはできません。最終的には、弊社が責任を担保できない以上、一部の外部コンテンツをサポートしない判断に至りました。

福本 そのため、はてなブログのディレクターと一緒に、ひとつひとつ検証していきました。

中澤 そういった編集画面で公式にサポートしているコンテンツだけではなく、思いもよらないところで影響が生じたこともあります。その1つが、自分が見つけた「絵文字」に関する特別な記法でした。

福本 はてなブログで使っているコンテンツなのに、もう終了した自社サービスの古いサーバーになぜか絵文字の画像ファイルが置いてあって……。やることは「はてなブログのサーバーに画像を持ってきてHTTPSで配信する」だけなのですが、Mixed Contentに関してはこういった細かな問題をたくさん解消していく必要があり、絵文字の発見は精神的にけっこう堪えました。

激闘! Mixed Contents!! 〜はてなブログHTTPS化への道〜 / Hatena Engineer Seminar #10

中澤 はてなダイアリーから記事を移行する機能を提供していることもあって、2003年から提供してきたもの全てを考慮する必要があります。これは認識していたつもりでしたが、実際にやってみると、こういったエッジケースが思っていた以上に見つかりました。

── 隠れているエッジケースを発見するのはかなり大変だと思いますが。

中澤 エッジケースについては、ユーザーサポートを担当する部署にもかなり助けてもらいました。

福本 サポート部署を巻き込んで動作テストやQAを実施したことで、どうしても残ってしまうエッジケースや意図しない挙動を丁寧に見つけてもらえて、助かりました。

HTTPS化の提供によってユーザーさんに起きることを、サポートの方にあらかじめ体験してもらえたことも良かったと思います。

中澤 リリース前には、こちらから「こういう問い合わせが増えるかもしれないので、こう案内してください」というようなコミュニケーションをあらかじめ取っておいて、なるべく不安なく使えるように配慮しました。

「ユーザーのコンテンツを残す」ことに強いこだわりを持って対応

── 公式のアナウンスを見ると、Mixed Contentの解消(第1・第2フェーズ)には結局約半年かかっていて、その後でより複雑な独自ドメインに対応した第3フェーズより期間が長かったのですね。

はてなが提供しているドメインを使用した全てのブログが、HTTPSで配信できるようになりました - はてなブログ開発ブログ
独自ドメインで運用されているブログが、HTTPSで配信できるようになりました - はてなブログ開発ブログ

福本 当初予定していたよりもリリースが遅れてしまった背景には、これまで説明してきたようなMixed Contentのエッジケース対応という事情があります。

とは言え、ユーザーさんが書いてくれたコンテンツをできるだけ望ましい形で残すには、慎重かつ丁寧に作業するしかありませんでした。結果として、データが消えたり、サービスが止まったりといった障害もなく達成できたのはよかったなと思っています。

中澤 はてなという会社では、ユーザーさんのコンテンツがインターネットに残り続けることに対し、強い使命感を持ってサービスを提供しています。サービスをHTTPS化する際に過去のコンテンツをばっさり切り捨てるという意思決定をするケースもあるようですが、エンジニア視点では「その方がラクかも……」という気持ちは少なからずあるものの、ユーザーとしては複雑ですよね。

福本 技術的に新しいチャレンジもあった第3フェーズに比べると、第1・第2フェーズはかなり地味な作業だったのですが、ここをしっかりやり切ったことで、第3フェーズがスムーズに、オンスケジュールで進行できたように思います。

中澤 最近、このHTTPS化の経緯をさまざまなセミナーで話しているのですが、「よくできてますよね」とか「コンテンツ移行のケアをしてもらえて助かりました」という反応をいただきます。スケジュールの遅れについては申し訳なかったのですが、手をかけてよかったな、と思います。

── 今回のHTTPS化の作業を通して、学んだことや新しい体験があれば教えてください。

中澤 HTTPS化は、仕様もあってやるべきことは既に決まっています。それを、はてなブログというサービスの中で、どう解決策に落とし込むかという仕事は、今までにない経験で新鮮でした。エンジニアとしての知的好奇心も刺激され、楽しかったですね。

福本 私は、中澤がばりばり手戻りなく進めていくのを、横で「すげー!」って思いながら見ていましたね。特等席でそれを見ている感じでした。

中澤 福本はGoを書くのが今回で初めてでしたが、成長スピードが想定以上でした。僕の大雑把な指示でも、期待を超えるアウトプットが出てくるので、信頼できるメンバーと一緒に仕事ができると早いし楽だなと、改めて思いましたね。

自分は他の人より手が割と早い方だと思いますが、今回のシステムは本当に規模が大きくて、1人では手が回りきらないのは自明でした。ワンマンじゃできない仕事を、他の人と一緒にやっていくことができて、自分としても1つステージが上がったと感じています。

仕事の進め方でもいい経験になりました。本当にこのやり方が最善か、ベンチマークや見積りを取り、ファクトを集めて「このやり方がいいよね」と決めていくことで、チームの内外に納得感を持って仕事をしてもらうことができました。

福本 私も、開発に加えて、複数の対応パターンそれぞれのメリット・デメリットなどの材料を事前に準備するなど、ディレクターが判断を下すサポートをすることがこれまで以上に必要でしたから、仕事の進め方について学びがあったと思います。

この先「HTTPS2」といった新しい仕様が登場して、それに合わせてコンテンツを全面的に移行しなければならなくなる、ってことはまずないと思いますし、そういった意味でも、こういう大きな施策に携われてよかったなって思いますね。

papix and aereal

中澤 亮太(なかざわ・りょうた)@aereal aereal
株式会社はてな サービス・システム開発本部 アプリケーションエンジニア
2012年はてな入社。はてなブログ、はてなブックマーク、他社協業案件を経て再びはてなブログの開発に携わる。はてなブログのテックリードを務め、安定と発展のために技術的な責任を負う。Webサービスのフロントエンドからバックエンドまで、開発から運用まで幅広く見ることが好き。
ブログ:Sexually Knowing 『言葉を吐く』

福本 貴之(ふくもと・たかゆき)__papix__ papix
株式会社はてな サービス・システム開発本部 アプリケーションエンジニア
2017年はてな入社。はてなブログの開発に携わる。現在は、はてなブログをCMSとして提供する「はてなブログMedia」のサービスリードを務め、職種間の連携やサービスの成長について思案する日々を過ごしている。趣味はPerlと旅行で、旅行のついでに全国各地のPerlコミュニティに足を運ぶのが好き。
ブログ:Masteries

(取材・文:高橋睦美)

*1:株式会社はてなは7月が決算月のため、2017年8月が2018会計年度の期初となる。

*2:Let's Encryptでは寄付を受け付けており、はてなブログでも継続的に寄付を実施することを表明している。はてな開発者ブログの2018年6月4日付けの記事 http://developer.hatenastaff.com/entry/2018/06/04/140000 を参照。