Upgrade to Pro — share decks privately, control downloads, hide ads and more …

その「s」を付けるために 〜はてなブログHTTPS化の軌跡〜 / Rejectcon 2018

120b74af626c2b23f954926ef68ac5d6?s=47 papix
September 29, 2018

その「s」を付けるために 〜はてなブログHTTPS化の軌跡〜 / Rejectcon 2018

120b74af626c2b23f954926ef68ac5d6?s=128

papix

September 29, 2018
Tweet

Transcript

  1. その「s」を付けるために ~はてなブログHTTPS化の軌跡~ by id:papix (@__papix__) 株式会社はてな

  2. papix 株式会社はてな アプリケーションエンジニア (2017年2月~) ブログMediaチーム サービスリード 「はてなブログ」をつくっています アカウント類 はてな: id:papix

    Twitter: @__papix__ GitHub: papix CPAN: PAPIX ブログ: https://papix.hatena(blog.(com|jp)|diary.jp)/ 趣味はPerlと, (交通機関を利用した)旅行 去年JGC修行(JAL)を完遂しました(年間53搭乗/40,573km) 来年はいよいよSFC修行(ANA)をします
  3. もくじ はてなブログとHTTPS化 ~ここまでの流れ~ なぜHTTPSにするのか? はてなブログHTTPS化の難易度 第1部: 激闘! Mixed Contents!! 第2部:

    組み上げろ! 証明書自動発行システム!! まとめ
  4. はてなブログとHTTPS化 ~ここまでの流れ~

  5. はてなブログとHTTPS化 ~ここまでの流れ~ 2017年9月25日 ... 告知 http://staff.hatenablog.com/entry/2017/09/25/143000 2017年11月20日 ... 管理画面HTTPS化完了 (第1フェイズ)

    http://staff.hatenablog.com/entry/2017/11/20/175000 2018年2月22日 ... はてな提供ドメインブログのHTTPS化完了 (第2 フェイズ) http://staff.hatenablog.com/entry/2018/02/22/150000 2018年6月13日 ... 独自ドメインブログのHTTPS化完了 (第3フェイ ズ) http://staff.hatenablog.com/entry/2018/06/13/160000
  6. 今日話すこと 第1部: 激闘! Mixed Contents!! 第1フェイズ~第2フェイズの出来事 主にMixed Contents対応を中心に... 第2部: 組み上げろ!

    証明書自動発行システム!! 第3フェイズの出来事 Let's Encryptを活用した証明書取得の仕組みについて
  7. なぜHTTPSにするのか?

  8. なぜHTTPS化が必要か http://staff.hatenablog.com/entry/2018/02/22/150000

  9. なぜHTTPS化が必要か より安全にはてなブログを活用して頂くため 「はてなブログMedia」という企業向けの展開も行っているため セキュリティ強化は重要 HTTPSが前提となる技術スタックの登場 Progressive Web Apps, Service Worker...

    HTTPS化推進の波 様々な企業/団体がWebサイトのHTTPS化を推進している Let's Encryptもその流れの中で登場してきた Chromeでは, HTTPの場合に警告が出るようになっている
  10. はてなブログHTTPS化の難易度

  11. UGCサービス UGC = User Generated Content サービスの利用者がコンテンツを生み出すサービス ブログの場合, サービスの利用者(はてなブロガー)が記事という コンテンツを"生み出す"

    はてなブログはUGCプラットフォームとして"自由度"が高い HTMLで自由にブログをデザイン出来る, ブログの記事の中に も自由にHTMLを記述出来る
  12. マルチテナント ユーザーごとにブログを開設できる 更に, 1人で複数のブログを持てる ブログは, デザインもCSS含めてかなり柔軟にアレンジ出来る 加えて, 企業向けの「はてなブログMedia」も同じコードの上で動い ている

  13. 他サービスとの連携 公式で様々なサービスのコンテンツを埋め込める Twitter, ニコニコ動画, はてなブックマーク, Amazon, iTunes... 自社サービスとの連携もある はてなスター, はてなブックマーク

  14. Mixed Contents ユーザーが自由にHTMLを書ける = 様々なコンテンツを埋め込める/ 読み込める 画像, 動画, iframe, JavaScript,

    CSS... HTTPSのブログでHTTPのコンテンツを読み込むと, Mixed Contentsが発生する
  15. 独自ドメイン はてなブログが提供するドメインだけでなく, 任意のドメインでブ ログを開設できる 正確に言えば, はてなブログが提供するドメインから, 任意のド メインに切り替えることができる 独自ドメインについては, これまではHTTPS対応が難しかった

    ユーザが発行した証明書を預かるのは難しい(出来れば避けた い) Let's Encryptによって独自ドメインのHTTPS化も目処が立っ てきた
  16. 要するに... はてなブログはHTTPS化という観点で見ると「数え役満」状態 UGCサービス マルチテナント 他サービスの連携 Mixed Contents 独自ドメイン 日本でも屈指のHTTPS化難易度を誇るのではないか...?

  17. 第1部: 激闘! Mixed Contents!!

  18. はじめに: Mixed Contentsとは? HTTPSのURLでウェブサイトを読み込んだ時に起こりうる 読み込んだHTMLから, 更に読み込まれるコンテンツがHTTPで 読み込まれる時に発生する HTTP接続は暗号化されていないので, 改竄されたり, 通信を盗

    聴される危険性がある ウェブサイトを閲覧しているユーザーに注意を呼びかけるため, ブ ラウザ上に警告が表示される
  19. Mixed Contentsを回避するには? やることはシンプル HTTPSのウェブサイトから読み込むコンテンツは, 全てHTTPS で読み込むようにする つまり, http://... で読み込んでいる所に s

    を足して, https://... にすれば良い
  20. Mixed Contentsを回避するには? しかし, 単純に http://... を https://... に置換するだけでは いけない 当然ながら,

    そのコンテンツがHTTPSで配信されていなければ 意味がない! 従って... 機械的に/自動的に解決するのは難しい(埋め込むことが出来る コンテンツの種類が増えれば増えるほど) コンテンツごとに作戦を建てて, 丁寧に取り組んでいく必要が ある
  21. 第1フェイズ~第2フェイズの方針

  22. 方針 まずは, はてなブログが公式に提供する機能で埋め込んだコンテン ツによって, Mixed Contentsが発生しない状態を目指す(Mixed Contents対策) 写真(Fotolife/Google Photo), はてなブログで書いた過去記事,

    他のはてなブログの記事の引用, Amazon, 楽天, YouTube, Twitter, Instagram, はてなブックマーク, ニコニコ動画, pixiv, iTunes, Evernote, ぐるなび/食べログ, Gist, Flickr, 絵, ミイル... 他にも, ユーザーが入力したはてな記法によって展開され, 埋め 込まれるコンテンツも存在する
  23. 方針 その後に, アプリケーションの改修を実施してHTTPSで利用可能に なる状態を目指す(アプリケーション改修) HTTPSでページを表示出来るようにする HTTPSに対応したページにHTTPでアクセスした場合, HTTPS にリダイレクトするようにする HTTPSに対応したページへはHTTPSでリンクを貼る フォームの送信先をHTTPSに変更する

  24. Mixed Contents対策 HTTPS化したときに起こりうるMixed Contentsに対して, 取りうる 対策は以下のどれか: HTTPSで配信する HTTPSのリソースが使えるように改良する 機能を撤廃する

  25. HTTPSで配信する 自社が提供するコンテンツであれば, HTTPSで配信するように修正 することもできる 部署間で調整して作業を依頼したり, 直接修正してPull Requestを送ったり... これで済むなら一番手っ取り早い

  26. HTTPSのリソースが使えるように改良する 他社のサービスが提供するコンテンツを埋め込む場合, そのサービ スが提供するAPIを使って, 埋め込むための情報を取得していること が多い API側も昨今のHTTPS化の流れに乗って, HTTPSでリソースを 提供してくれることが多い HTTP/HTTPSの両方でリソースのURLを示してくれてい

    たり... 利用するAPIのバージョンを上げると, リソースのURLが HTTPSになることもあった
  27. 機能を撤廃する 最終手段 どうしてもHTTPでしか配信されていないものもある 対応が難しい場合, 記事中での利用状況なども調査して, 機能そのものを撤廃することもあった 例: ニコニコ動画のマイリスト埋め込み機能 当時は動画とコミュニティしかHTTPSでの埋め込みに対 応していなかった

  28. 絵文字事件 果てしないMixed Contents対策の中でも, 特に思い出深いエピソード...

  29. 「絵文字記法」の発見

  30. 「絵文字記法」の発見

  31. 「絵文字記法」の発見 古参スタッフですら知らなかった「絵文字記法」の存在に気づいた 絵文字記法を使うと, 指定したコードに従って, 最終的に画像が 埋め込まれる その画像がHTTPでしか配信されていなかった! 更に何故か, その絵文字の画像ははてな社内の他サービスが配信し ていた!!!

  32. 「絵文字記法」の対応 そもそも, はてなブログで使っているコンテンツを, 他サービスが配 信しているという状況が良くない そのサービスが万が一撤退することになった時, またてんやわ んやすることになる この機会に, 丁寧にはてなブログ側で配信するように手を加え

    た 手間としてはそこまでかからなかったが, 延々と対応している中で 唐突に作業対象が増えるのは精神的に参った...
  33. アプリケーション改修 これもまた, Mixed Contentsと同じく地道な作業が必要 HTTPS化が必要な(可能な)エンドポイントをリストアップし て, 1つずつ対応していく

  34. 開発環境のHTTPS化 まずは開発者の環境もHTTPS化しておきたい 出来れば手元でもHTTPSで確認したい 開発環境はHTTPで本番環境はHTTPSだと, 意図せぬMixed Contentsを埋め込んでしまうかもしれない... 今回は, Docker + Nginx

    + いわゆるオレオレ証明書で解決 ちょうどHTTPS化の作業が始まる前に, 開発環境のDocker化 を推進していた アプリケーションの前にNginxのコンテナを立てて, 開発環境 もHTTP/HTTPSの両方に対応
  35. テストの追加やリファクタリング 当然, テストもHTTPS環境に準拠したものに書き換えていく 平行して, リファクタリングした方が良さそうなポイントは積 極的に手を入れていった 特に, リダイレクト周りの処理は丁寧にテストを用意 はてなブログに存在する様々なパターンを網羅してテストした 例:

    HTTPSが有効なはてなブログに, HTTPでリクエストする と, HTTPSにリダイレクトする...
  36. QA アプリケーションの改修が完了した後, リリース前にQAフェイズを 用意した はてなには専属のQAチームはないので, カスタマーサポートを 担当するサポート部に協力を依頼 "QAシート"を用意して, それに従って操作を試し, 結果をまと

    めてもらう
  37. QAシートの用意

  38. QAの成果 幾つか考慮漏れだったポイントを発見できた サポート部とHTTPS化による成果を共有できた 言うまでもなく, ユーザーからのお問い合わせに対しては, サポ ート部のメンバーが対応する HTTPS化によって, ブログの挙動がどのように変わるかを, QA

    を通じて共有することができた
  39. リリース

  40. リリース まずは社員向けにリリースして動作検証 問題がなければ, 一般公開を進めていく GitHubのIssueに手順書を用意して, リリースにあたって必要な作業 を全て列挙 関係部署への連絡, リリース後の動作確認手順など...

  41. None
  42. None
  43. リリース 前述の通り, 2017年11月20日に管理画面のHTTPS化(第1フェイズ), 2018年2月22日にはてな提供ドメインブログのHTTPS化(第2フェ イズ)が完遂 リリース前後でデータロストやサービス停止などの問題もな く, 平和にリリース出来た そしていよいよ正念場, 独自ドメインブログのHTTPS化(第3フェイ

    ズ)へと足を踏み入れる...
  44. 第2部: 組み上げろ! 証明書自動発行システム!!

  45. はじめに 技術的詳細については, 一緒に実装を担当した id:aereal の 「Builderscon tokyo 2018」における発表資料を参考にしてください 「ブログサービスのHTTPS化を支えたAWSで作るピタゴラスイ ッチ」

    https://speakerdeck.com/aereal/the‑construction‑of‑large‑ scale‑tls‑certificates‑management‑system‑with‑aws
  46. 前提 はてなブログでは数万単位のブログが独自ドメインで配信されてい る それらの証明書を取得し, 配信時に適切に利用する必要がある 「証明書発行」についてはLet's Encryptの登場によって解決 独自ドメインのための「証明書取得」と「証明書配信」を実装しな ければならない

  47. 余談: Let's Encryptへの貢献 Let's Encryptは, Internet Security Research Group(ISRG)という非 営利団体によって運営されている

    このような仕組みを無料で提供するISRGに経緯を評し, 寄付も 実施した http://developer.hatenastaff.com/entry/2018/06/04/14 0000 毎年, 継続して寄付の活動を続けていきます
  48. 証明書取得の技術選定 AWS Certificate Manager はてなブログはAWSで構築されているので, AWSのフルマネー ジドサービスで対応出来ないか検討 AWS Certificate Managerで取得した証明書は,

    ELBに紐 づけて利用することが出来る 結果としては, 今回のオーダー(数万単位のブログ)では用途に適 さないことが判明し, 断念
  49. 証明書取得の技術選定 自前実装 こうなってくると, 自前で仕組みを作るしかなさそうという結 論に至る 証明書の取得だけでなく, 更新(Let's Encryptの証明書は3 ヶ月で有効期限が切れる)も考慮しないとけない Step

    Functionsを軸に, LambdaやDynamoDBなど, AWSのフ ルマネージドサービスをフル活用して実装することを計画 Lambdaで動かすコードは, 公式に対応されたGo言語を活用す ることに決定 チームメイトの言語習熟度や, 社内においてMackerelなど でGoが使われていることも後押しとなった
  50. 証明書配信の技術選定 AWS Certificate Managerが利用出来れば取得だけでなく配信も担 えたが, これは断念 SAN Subject Alternative Names,

    1つの証明書で複数のドメインを 紐付ける仕組み Let's EncryptでSANを使う場合, ACME challenge(証明書発行 のための認証)は, 現時点ではdns‑01のみが利用可能 dns‑01の認証ではDNSの設定が必要であり, はてなブログ ではドメインのDNS設定は各ユーザーに委ねなければな らないので, 自動化が困難 また, そもそもとしてLet's EncryptのSANでは, 1つの証明書あ たり100ドメインまでしか含めることができない 結果としては, 証明書配信についても自前実装することを決意
  51. 証明書配信の技術選定 はてなブログでは, ProxyとしてNginxを採用している(EC2上に構築 し, 複数台のProxyが配置されている) Q. 取得した証明書を, 複数台のProxyに配信どのように配信する? 取得した全ての証明書を配信するのは厳しい 万単位のブログの証明書を読み込むと,

    メモリ使用量が著 しく増加する 証明書の更新が行われる度に読み込み直す必要がある
  52. 証明書配信の技術選定 最終的には, GMOペパボでの事例なども参考に, 証明書の動的読み 込みシステムを構築した ngx_mrubyを利用して, リクエストがある度に証明書をロード する Nginxではmruby以外にLuaを動かすことも可能だが, チームメ

    イトの言語習熟度を考慮してmrubyを採用した
  53. プロトタイプ実装 本格的に開発を始める前に, 2週間のプロトタイプ実装期間を用意し た プロトタイプを実装することで, 見積もりの最適化(誤差を減ら す)と技術的課題点の早期発見を狙える 正式版(?)の実装においては, プロトタイプの知見を利用す るが成果物はそのまま使わない

    ...ので, 「ひとまず動くものを作る」の精神で, 素直に実装を 進めていく エンジニアは東京オフィス/京都オフィスで別れていたので, 東京オ フィスに集まって実装
  54. プロトタイプ実装 プロトタイプ実装は, Mackerelの次世代TSDBでの知見を活用 予めプロトタイプ実装することで, 見積もりの精度を高めるこ とができた 実際, 第3フェイズはプロトタイプ実装後の見積もりとに対してほぼ 誤差なく終えることができた

  55. ベンチマーク プロトタイプを利用して, ベンチマークも実装した 実際にLet's Encryptで取得した証明書を, Nginx + ngx_mruby で捌くことが出来るか? 結果としては,

    後述するキャッシュの仕組みなども想定して実 装していたため, 無事に捌き切ることができた
  56. プロトタイプの成果 実際に動作するものを一通り構築する中で, 事前にタスクを見積も った時に考慮が漏れていた点を発見できた 正式版の開発に着手するにあたって, 良い「お手本」が出来た 自分の場合, Go言語にそこまで慣れていなかったので, プロト タイプで書いたコードはとても良いお手本になった

    デプロイの仕組み, CIの仕組みなども構築でき, それを正式版に活か すことができた
  57. 実装 第3フェイズは, 2つのフェイズに分けて作業を進めた 第3フェイズα ... 証明書の取得/配信の仕組みを作る 第3フェイズβ ... 構築した証明書の取得/配信の仕組みと, 既存

    のはてなブログを繋ぎこむ 前述の通り, プロトタイプ実装の成果もあって, 第3フェイズαについ ては見積もりどおり終わった 第3フェイズβについては, 予定よりも少し伸びてしまった とはいえ, 第3フェイズ開始前の予定から大きく後ろに伸びるこ とはなかった
  58. 詳解

  59. 結果 2018年6月13日, 無事独自ドメインのHTTPS対応(第3フェイズ)をリ リースできた こちらもまた, サービスの停止やデータロストといった大きな 障害なくリリースすることが出来た

  60. このようにしてHTTPS化は進んだのです!!!

  61. まとめ ほぼ1年をかけて, はてなブログのHTTPS化を成し遂げることができ た これほどの規模で, 長期間のプロジェクトに携わったことはな かったので, 良い経験になった 第3フェイズの中で, Go言語やAWSの各種フルマネージドサービス

    といった, 新しい知見を得ることができて良かった また, それぞれのフェイズでサービスダウンやデータロストと いった大規模な障害なくリリースを終えることが出来たのも自 信になった 様々な条件がある中で, それらを満たしつつ, サービスをHTTPSする 良い実装が作れたと思う
  62. ご清聴ありがとうございました!