サイトをHTTPSにする

2018年7月に公開されるChrome 68でHTTPなサイトは"Not Secure"と表示されるようになるので、このサイトもHTTPS化することにしました。

個人的なサイトなので適当にやってもいいですが、一応ちゃんと追跡できる方法を使ってHTTPS化することにしました。

この記事では次のことを目標しました。

  • https化後にhttpでアクセスしているリソースがないことをツールで確認できる
    • 要はMixed Contentがないことを検知する方法をもつ
  • 常時HTTPSでアクセスできるようにする

Content-Security-Policy-Report-Only

このサイトはJekyll + GitHub Pagesで動いている(動いていた)静的サイトです。

HTTPSにした際にmixed contentにかかるリソースがないかを確認するには、 Content-Security-Policy-Report-Onlyを使い挙動を変更せずにレポートだけするHTTPヘッダが有用です。 しかし、GitHub PagesはレスポンスのHTTPヘッダを指定できないため、Content-Security-Policy-Report-Onlyを使ったレポーティングが行なえません。 (CSPは<meta>要素でも指定できますが、<meta>要素はContent-Security-Policy-Report-Onlyをサポートしていません)

Netlify

GitHub PagesではHTTPヘッダが指定できないので、Netlifyの方にサイトを移してから、その後HTTPS化することにしました。 GitHub PagesでHTTPS化するときはCloudFlareなどを使いますが、NetlifyではLet's Encryptを使って対応する仕組みがあります。

Netlifyへサイトを移行

以下を参考にしました。

GitHubからNetlifyに移行するためにドメインレジストラで以下を設定してNetlifyに移行しました。

  • Aレコード
  • CNAME
  • DNS

GitHub Pages と Netlifyの違い

基本的にドメインの変更だけでそのままJekyllのサイトは移行できましたが、一箇所だけ挙動が異なる部分がありました。

GitHub Pageはindex.xmlをindexとして認識しますが、Netlifyはindex.xmlをindexとして認識しないという違いがありました。 これが原因で http://efcl.info/feed/ にアクセスすると404となる問題がありました。 (http://efcl.info/feed/index.xmlならアクセスできた。

そのため、NetlifyのRewrite Ruleを_redirectファイルにて定義してこの問題を解決しています。

# Rewrite rule
# https://www.netlify.com/docs/redirects/
# Netlifyはindex.xmlをDirectoryIndexとして認識しない
/feed/                        /feed/index.xml    200
/feed/index.html              /feed/index.xml    200
/feed/atom/                   /feed/             301
/feed/atom/index.html /feed/ 301

http:// でアクセスしているリソースを収集

https化した後にhttp://でアクセスしているリソースが残っているとMixed Contentの問題が発生し、画像が表示されなかったりURLバーに警告がでるので、Mixed Contentを検知できる仕組みをまず作ることにしました。

Content-Security-Policy-Report-Only HTTPヘッダを使いCSPレポートを収集するのですが、その集計先が問題となりました。 AWS Gatewayなどを使えばある程度簡単につくれることは分かっていましたが、データを貯める場所はコストや管理などが問題になりやすいためです。

CSPについて調べているとCSPレポートはJavaScriptからもSecurityPolicyViolationEventとして取得できることが分かりました。 このイベントで取得したCSPレポートをGoogle Analyticsに送信して、Google AnalyticsでMixed Contentsがないかをみられるようにしました。

Netlifyの_headersファイルを使いHTTPヘッダに次のようにCSPを設定しました。 意味的にはすべてのアクセスに Content-Security-Policy-Report-Only のレスポンスヘッダを付けて返しています。(report-toも付けろと警告がでますが付けなくて動きます)

/*
Content-Security-Policy-Report-Only: default-src https: blob: data: http://www.google-analytics.com/* 'unsafe-eval' 'unsafe-inline';

このCSPにかかった結果をGoogle Analyticsに送信しています。

詳しくは次の記事で解説しています。

https化

万が一Mixed Contentsが残っていても見つけられる仕組みができたので、サイトをHTTPSでアクセスできるようにしました。

NetlifyはLet's Encryptを使ったhttps化をサポートしています。 コントロールパネルから有効化するだけでhttpsでアクセスできるようになります。

この時点ではhttpsにリダイレクトはせずにどちらでもアクセスできる状態です。

参照するリソースをHTTPSに変更

次のPRでhttpでアクセスした画像やJSなどをhttpsでアクセスするように書き換えました。

httpsをデフォルト化

書き換えたリソースが参照できているのを確認してから、Netlifyのコントロールパネルから"Force HTTPS"でHTTPSでのアクセスをデフォルト化しました。

これで、 http://efcl.info でアクセスしても https://efcl.info にリダイレクトされるようになりました。

数日後にMixed Contentのチェック

数日後にGoogle Analyticsに集計していたCSPレポートを見ると、http://でアクセスするリソースはほぼなくなっていることが確認できました。

一部変更のミスがあることが分かったので、それをhttps://に書き換えて、HTTP化は完了しました。

まとめ

まとめるとこのサイトは次のようなステップでHTTPS化しました。

もう少し丁寧にやるならば、デフォルト化をする前にmcdetectのようなツールでMixed Contentが残ってないかをチェックしたりもできそうです。 またCSPレポート(Mixed Contentの問題)をGoogle Analyticsに集約する | Web Scratchでも書いていますが、もっとCSPレポートを詳細に分析するならAWS Gatewayなどを使って分析基盤にデータを貯めるのが良さそうな気がしています。

実際のウェブサービスだともっと色々なリソースがあると思いますが、CSPには色々な機能があるのでその辺を参照するのが良さそうです。