Goalist Developers Blog

10分でWordPressをEC2+CloudFront+ACMでHTTPSにする

「EC2上にあるWordPressをHTTPS化して!」と頼まれることは誰しも一度は経験すると思います。
今回はそんな時に10分で設定を終わらせる手順を残しておきます。
もちろん証明書はAWS Certificate Manager(ACM)を利用します。
CloudFrontの反映に30分とWordPressのDB置換が人によって時間がかかるので、その時間はご飯でも食べに行ってください。
最後の「まとめ」で詳しく書いていますが、ALB(ELB)をCloudFrontとEC2の間に挟まないと見た目上はHTTPSに見えていても、CloudFrontとEC2の間はHTTP通信(初期設定)でインターネットを経由します。

1. ACMで対象ドメインの証明書を作る

ACMのページで基本デフォルトのまま進めていけばできあがります。
注意点としては以下。特にリージョンは嵌りポイントの1つだと思います。

  • リージョンを東京ではなくバージニア北部を選ぶ
  • 確認メールで設定を完了する場合は最後の「検証方法の選択」画面でEメールの検証を選ぶ

CloudFrontはCDNなので特定リージョンではなく、グローバル扱いです。CloudFrontの設定画面でもグローバルになっています。作ったはずの証明書がCloudFrontの設定画面で出てこない!という場合は証明書のリージョンが間違っている場合が100%だと思います。

2. WordPressのあるEC2のパブリックDNSを確認する

f:id:t-moritsugu:20180424191806p:plain

ElasticIPを貼り付けたらパブリックDNSが消えたよ!という場合はサービス一覧からVPCにいき、対象のEC2に紐づいているVPCを選択し、アクションからDNS解決の編集とDNSホスト名の編集を「はい」にすればパブリックDNSは復活します。

f:id:t-moritsugu:20180424193320p:plain

3. CloudFrontを設定する

Create Distribution > WebのほうでGet Started
以下特に記載のないものはデフォルト値です。

Origin Settings

  • Origin Domain Name: EC2のパブリックDNS
  • Origin ID: 自動で入力されるので、変更したければ変える

Default Cache Behavior Settings

  • Viewer Protocol Policy: Redirect HTTP to HTTPS
  • Allowed HTTP Methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
  • Cache Based on Selected Request Headers: All (Whitelistの場合は許可するヘッダを追加)
  • Forward Cookies: All (Whitelistの場合は許可するcookieを追加)
  • Query String Forwarding and Caching: Forward all, cache based on all (Whitelistの場合は許可するパラメータを追加)

Distribution Settings

  • Alternate Domain Names(CNAMEs): WordPressで公開しているサイトのドメイン
  • SSL Certificate: Custom SSL Certificateを選択し、ACMで作成した証明書を選択する

※証明書が出てこない場合は作成の際にリージョンが間違っているか、Eメールでの認証を行っていないために証明書の作成が完了していないかを確認してください。

特に記載のないものはデフォルトでOKなのでCreate Distributionして30分ぐらいまちます。

4. WordPressをHTTPSに対応させる

現行のWordPressはEC2で動いているのでAMIでバックアップを取ります。
DBがRDSなどでEC2上に無い場合、DBのバックアップもとります。
今回は以下のツールを利用してhttp://xxx.comhttps://xxx.comに置換しました。 interconnectit.com

wp-config.phpに以下を追記

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
        $_SERVER['HTTPS'] = 'on';
} elseif (isset( $_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO']) && $_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'] === 'https') {
        $_SERVER['HTTPS'] ='on';
}

/* That's all, stop editing! Happy blogging.  ←これの前ぐらいに追記*/

CloudFrontはX_FORWARDED_PROTOヘッダをCLOUDFRONT_FORWARDED_PROTOに勝手に変換するので今回はWordPress側でCLOUDFRONT_FORWARDED_PROTOを判定することにしました。
CloudFront側でX_FORWARDED_PROTOをねじ込む方法もあると思います。

5. Route53でドメインをCloudFrontにむける

以下の値で設定します。

  • Name: WordPressで公開しているサイトのドメイン
  • Type: A
  • Alias: Yes
  • Alias Target: CloudFrontのDomainNameの値

まとめ

念のためですが、今回の構成ではCloudFrontとEC2の間はインターネットを通ります。
CloudFront作成後にOriginタブから選択してEditするとOrigin Protocol Policyという設定があり、デフォルトではHTTPです。従ってデフォルトではCloudFrontとEC2の間は全く暗号化されずれにインターネットを通ります。
とりあえずHTTPSになれば良いよ!ということであれば今回の方法でよいですし、そうでない場合でACMしか許されない場合はCloudFrontとEC2の間にALB(ELB)をはさめば良いです。ALBにはACMの証明書が置けるのでCloudFrontとALBの間をHTTPS通信にします。ALBとEC2の間の通信はインターネットに出ないので目的は達成できます。