Let's EncryptでS3静的ウェブサイトホスティングのブログをHTTPS化

証明書

従来通りHTTPでもアクセスできます。無償で利用可能なSSL証明書の発行サービスLet's Encryptがパブリックベータになったので、count0.orgの証明書の発行とブログをHTTPS化してみました。結論から言うと証明書の発行は簡単。ブログのHTTPS化は面倒でした。

追記(2016/1)

AWC Certificate Manager(ACM)がリリースされました。S3でWebサイトを配信している場合Let's EncryptよりもACMを使ったほうが簡単にSSLを導入できるでしょう。しかし、どちらにせよS3とCloudfrontは連携する必要があります。

Let's Encryptとは

Let's Encryptについてはこちらこちらの説明を一読することをオススメします。

証明書を手に入れる

Let's Encryptのクライアントソフトをダウンロードします。OSXのサポート状況はvery experimentalらしいので覚悟を決めてコマンドを実行します。 homebrewが依存関係を解決してクライアントソフトをインストールしてくれます。その後対話形式の画面が立ち上がってそれに従って進む感じです。

git clone https://github.com/letsencrypt/letsencrypt
cd letsencrupt

# 実行
./letsencrypt-auto certonly --manual --email [email protected] -d count0.org

途中ドメイン所有者か確認するためにS3のバケットに.wll-known/acme-challenge/適当なファイル名という中身が適当な文字列なファイルを置いて、確認が取れたら/etc/letsencrypt/live/count0.org/以下に証明書が作られました。ゲットだぜ!

$ sudo tree /etc/letsencrypt/live/count0.org
/etc/letsencrypt/live/count0.org
├── cert.pem -> ../../archive/count0.org/cert1.pem
├── chain.pem -> ../../archive/count0.org/chain1.pem
├── fullchain.pem -> ../../archive/count0.org/fullchain1.pem
└── privkey.pem -> ../../archive/count0.org/privkey1.pem

インストールから証明書の入手まではクラスメソッドさんの記事を参考にしました。

ブログをHTTPS化する

証明書を手に入れたのでcount0.orgをHTTPS化します。このブログはS3を使っています。しかし、独自ドメインで静的ウェブサイトホスティングをしている場合、SSLはサポートされないみたいです(REST APIエンドポイントとウェブサイトエンドポイントの表を参照)それでどうするか。Cloudfrontを使えば独自ドメインでSSLを使えるとのこと。

今までの構成

インターネット > Route53 > S3のバケット

これからの構成

インターネット > Route53 > Cloudfront > S3のバケット

正直なところ大してアクセスのないこのブログにCDNを使うのは気が引けますが、こうしなきゃHTTPSにできないのでやってみます。

IAMに証明書をアップする

Cloudfrontで独自ドメインのSSLを利用する場合、IAMに証明書を登録しておく必要があります。マネジメントコンソールでは登録できないのでaws-cliを使い登録します。 count0.org-sslという名前で登録しました。

sudo aws iam upload-server-certificate --server-certificate-name count0.org-ssl \
--certificate-body file:///etc/letsencrypt/live/count0.org/cert.pem \
--private-key file:///etc/letsencrypt/live/count0.org/privkey.pem \
--certificate-chain file:///etc/letsencrypt/live/count0.org/chain.pem \
--path /cloudfront/blog/

Cloudfrontを設定する

マネジメントコンソールのCloudfrontに移動してCreate Destributionボタンをクリックし、WebのGet Startedボタンから作成画面に進みます。

下記項目以外はデフォルトのままで作成しました。

  • Origin Domain Name

    入力候補にS3のREST APIエンドポイントが表示されますが、ウェブサイトエンドポイントを入力します。これの意味ですが、サブディレクトリにおけるDefault Root Objectの挙動に関係します。REST APIエンドポイントを指定した場合、サブディレクトリに対してDefalt Root Objectが効かないのです。

    S3のREST APIエンドポイントを指定した場合

    パス アクセス
    / OK
    /index.html OK
    /archives/index.html OK
    /archives/ NG

    S3のウェブサイトエンドポイントを指定した場合

    パス アクセス
    / OK
    /index.html OK
    /archives/index.html OK
    /archives/ OK

    ウェブサイトエンドポイントのURLはS3のバケットのプロパティ、静的ウェブサイトホスティングから確認できます。

    S3のウェブサイトエンドポイント

  • Origin ID

    適当な名前でいいのですが、今回はS3-count0.orgと入力しました。

  • Alternate Domain Names(CNAMEs)

    独自ドメインでCloudfrontを使うので、ブログのドメインを指定します。count0.org

  • SSL Certificate

    IAMにSSLを登録していればCustom SSL Certificate (stored in AWS IAM)に選択肢が表示されるので、それを選択します。 選択するとCustom SSL Client Supportが現れるので、Only Clients that Support Server Name Indication (SNI)を選択します。 All clientsを選択した場合は月$600かかります。詳しくはドキュメントを参照。またSNIをサポートしているブラウザはWikipediaの記事を参照してください。Android 2系、Phantom JS 1系はサポートされませんが、それはまあいいです。

  • Default Root Object

    前述のようにOrigin Domain Nameの指定で挙動が変化します。平たく言うとDirectory Indexです。index.htmlにします。

作成完了後、配信準備に入ります。statusがIn ProgressからDeployedになれば配信準備完了です。

Route53を設定する

Route53でAレコードのAlias Targetを作成したCloudfrontのDomain Name(xxxxxxxx.cloudfront.net)に変更します。

s3_website

ブログをS3へデプロイするのに使っているs3_websiteの設定を編集します。s3_website.ymlcloudfront_distribution_idを追記しました。値は作成したCloudfrontのdestributionのID。それに加えブログ更新用IAMのグループに対してCloudfrontFullAccessのポリシーを追加しました。これでブログを更新したらCloudfrontも更新されるようになります。

今後

祝HTTPS化です。副作用でCDN配信も実現してしまいました。そして個人では学習する機会がなかったであろうCloudfrontを体験できました。

今後の課題は2016年3月に切れる証明書を自動更新する仕組みを作らなければいけないことです。きっとaws-cliを使うことになるでしょう。その役目は家でリモートスピーカーになっているRaspberry Piにお願いしようと思っています。

一覧へ戻る