AWS CloudFrontにサブドメインを割り当ててhttpsでS3上の画像を参照する

# 概要

`img.hitou.nyango.com`という画像参照用のサブドメインを使ってS3バケットに格納した画像をCloudFrontでhttps限定で参照させたときの手順です。

- S3バケットを作成して公開
- 証明書を取得して[ACM(AWS Certificate Manager)](https://aws.amazon.com/jp/certificate-manager/)に登録
- CloudFront Distribution作成
- DNS設定（発行されたCloudFrontドメインをサブドメインのCNAMEに割当）
- CloudFrontにサブドメインを設定

# S3バケットを作成して公開する
[![Image from Gyazo](https://i.gyazo.com/5bafcd9364f6c9a0d18b390da92ad96b.png)](https://gyazo.com/5bafcd9364f6c9a0d18b390da92ad96b)

参照用画像を格納するS3バケットを作成して公開します。この操作によりCloudFrontで自動的に参照先候補として認識してくれるようになります。

[S3 バケットのパブリックアクセス設定を編集する方法 - Amazon Simple Storage Service](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/user-guide/block-public-access-bucket.html)

なお、類似記事に「バケット名をサブドメインにする」と書かれている記事がありますが、今回のユースケースではこのような制限はありません。任意のバケット名を利用できます。
また、類似記事に「静的Webホスティングを有効にする」と書かれている記事がありますが、今回のユースケースでは不要です。

# 証明書取得してACMに登録

## ★重要/取得時の留意点★
以下の操作は「北部バージニア(us-east-1)」リージョンで実行する必要があります．他のリージョンで取得・設定された証明書はCloudFrontからは認識されないという落とし穴があります。

[CloudFront ディストリビューションにカスタム SSL 証明書を使用できないのはなぜですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/custom-ssl-certificate-cloudfront/)

## 手順

CloudFrontで独自サブドメインを利用してかつアクセスをhttpsに制限したい場合はCloudFrontに証明書を割り当てる必要があります。

[SSL/TLS 証明書を使用するように CloudFront ディストリビューションを設定する方法を教えてください。](https://aws.amazon.com/jp/premiumsupport/knowledge-center/install-ssl-cloudfront/)

証明書は外部のものも利用できますが今回は[ACM(AWS Certificate Manager)](https://aws.amazon.com/jp/certificate-manager/)で取得しました。

ACMではパブリックな証明書は無料で取得できます。また証明書期限切れ前に自動更新してくれます。

 [パブリック証明書のリクエスト（AWS公式）](https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/gs-acm-request-public.html)

なお、今回CloudFrontに割り当てたサブドメインは別AWSアカウントのroute53で管理していますが、特に問題はありませんでした。


# CloudFront Distributionの作成

[ディストリビューションの作成](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/distribution-web-creating-console.html)に従ってCloudFront Distributionを作成します。この時に`Custom SSL Certificate`が無効化されていることがありますが，原因は２つ考えられます。

+ 証明書を北部バージニア以外で発行している
+ 操作しているIAMアカウントの権限不足。`AdministratorAccess`が付与されていても不足です。以下のポリシー追加が必要でした．

```json
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": [
            "acm:ListCertificates",
            "cloudfront:List*",
            "cloudfront:Get*",
            "cloudfront:Update*",
            "iam:GetServerCertificate",
            "iam:ListServerCertificates",
            "iam:UpdateServerCertificate"
        ],
        "Resource": "*"
    }
}
```

# DNS設定（サブドメインをCloudFrontドメインに割当）

Distributionを作成すると，CloudFrontのドメイン(`xxxxx.cloudfront.net`)が発行されるので，この値をサブドメインのCNAMEに設定します。

[![CloudFrontドメイン](https://i.gyazo.com/560740b47b21a2c17802fe724edbc621.png)](https://gyazo.com/560740b47b21a2c17802fe724edbc621)

[![CNAME設定](https://i.gyazo.com/275bba08fb05c455381a1bf3d8534a44.png)](https://gyazo.com/275bba08fb05c455381a1bf3d8534a44)

# CloudFrontにサブドメインを設定

Distributionの詳細画面「General」タブで編集（Edit)状態にして、`Alternate Domain Names`にサブドメインを設定します．

[![Image from Gyazo](https://i.gyazo.com/ebd3c9d3f113f2fe255c27dcbfe51b17.png)](https://gyazo.com/ebd3c9d3f113f2fe255c27dcbfe51b17)

# 動作確認

たとえば画像が`<S3バケット>/images/001.jpg`に配置されている場合、`https://img.hitou.nyango.com/images/001.jpg`で参照できるようになります。