0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[JAWS-UG CLI] ACM入門 #6 CloudFrontでACMを用いたS3コンテンツのHTTP/2配信環境の構築

Last updated at Posted at 2016-11-05

これはAWS Certificate Manager (ACM)入門ハンズオン資料の一部です。
最初から続けて行っている場合「0.準備」の各項は作業不要です。第1項へ進んでください

前提条件

ACMによるSSL証明書が発行済みであること。
S3によるWebコンテンツ配信環境が構築済みであること。
Route53へドメインが登録済みであること。

  1. 準備
    =======

0.1. ドメイン名の変数への格納

変数へドメイン名を格納します。
ここでは example.tk とします。自分のドメイン名に読み替えてください。

コマンド
DOMAINNAME="example.tk" && echo ${DOMAINNAME}
結果(例)
      example.tk

0.2. コンテンツ配信用S3バケット名とルートオブジェクトの変数への格納

S3バケット名を www.ドメイン名 とします。(例: www.example.tk
独自のバケット名を設定した場合は、それを設定してください。

コマンド
WEB_S3_BUCKET="www.${DOMAINNAME}" && echo ${WEB_S3_BUCKET}
結果
      www.example.tk

ルートオブジェクト( / でアクセスした場合に表示する内容)を index.html とします。

コマンド
ROOT_OBJECT="index.html" && echo ${ROOT_OBJECT}
結果
      index.html

0.3. ACM証明書arnの変数への格納

証明書のarnを変数 CERT_ARN へ格納します。

コマンド(例)
CERT_ARN=`aws acm list-certificates --region us-east-1 \
 --query CertificateSummaryList[].CertificateArn \
 --output text` && echo ${CERT_ARN}
結果
      arn:aws:acm:us-east-1:777777777777:certificate/9eb6865a-63a3-48df-92c2-ae113c877b33

0.4. Route53 HostedIdの変数への格納

Route53のHostedIdを変数 HOSTED_ZONE_ID へ格納します。

コマンド(例)
HOSTED_ZONE_ID=`aws route53 list-hosted-zones \
 --query HostedZones[].Id --output text` && echo ${HOSTED_ZONE_ID}
結果
      /hostedzone/Z1S92TCRCPLEYH
  1. CloudFrontの設定
    =================

CloudFrontではELB(ALB,CLB),S3バケットなどを配信するコンテンツ元に設定できますが、今回はS3バケットに配信を行うコンテンツを作成します。

1.1. プレビュー機能の有効化

AWS CLIのCloudFrontは未だに何故かPreviewです。このためそのままでは使用できません。
次のコマンドを実行してプレビュー機能を有効化します。

コマンド
aws configure set preview.cloudfront true
結果
      返り値なし

1.2. コーラーリファレンスの決定

コーラーリファレンスはディストリビューション作成時に他と区別できるようにするため一意性が必要な任意の文字列です。
アクセスする際には何ら影響を及ぼしません。無機質な文字列でも構いません。
ここでは便宜上S3バケット名と同じにしておきます。

コマンド
CALLER_REFERENCE="${WEB_S3_BUCKET}" && echo ${CALLER_REFERENCE}
結果
      www.example.tk

1.3. ディストリビューション用JSONファイルの作成

ディストリビューションの構成情報はJSONファイルに記載します。
・ACM証明書によるTLS(HTTPS)ターミネート
・コンテンツ元はS3バケット
・HTTP/2対応
・利用エッヂロケーションはアジア・欧州・北米 (料金クラス200)

コマンド
cat << EOF > cf.json
{
    "CallerReference": "${CALLER_REFERENCE}", 
    "Aliases": {
        "Items": [
            "${DOMAINNAME}"
        ],
        "Quantity": 1
    },
    "DefaultRootObject": "${ROOT_OBJECT}", 
    "Origins": {
        "Quantity": 1, 
        "Items": [
            {
                "Id": "${WEB_S3_BUCKET}", 
                "DomainName": "${WEB_S3_BUCKET}.s3.amazonaws.com", 
                "S3OriginConfig": {
                    "OriginAccessIdentity": ""
                }
            }
        ]
    }, 
    "DefaultCacheBehavior": {
        "TargetOriginId": "${WEB_S3_BUCKET}", 
        "ForwardedValues": {
            "QueryString": false, 
            "Cookies": {
                "Forward": "none"
            } 
        }, 
        "TrustedSigners": {
            "Enabled": false, 
            "Quantity": 0
        }, 
        "ViewerProtocolPolicy": "allow-all", 
        "MinTTL": 0, 
        "AllowedMethods": {
            "Quantity": 2, 
            "Items": [
                "GET",
                "HEAD"
            ]
        }
    }, 
    "CacheBehaviors": {
        "Quantity": 0 
    }, 
    "Comment": "", 
    "Logging": {
        "Enabled": false,
        "IncludeCookies": false,
        "Bucket": "",
        "Prefix": ""
    }, 
    "PriceClass": "PriceClass_200", 
    "Enabled": true, 
    "ViewerCertificate": {
        "ACMCertificateArn": "${CERT_ARN}", 
        "SSLSupportMethod": "sni-only", 
        "MinimumProtocolVersion": "TLSv1", 
        "Certificate": "${CERT_ARN}", 
        "CertificateSource": "acm"
    }, 
    "Restrictions": {
        "GeoRestriction": {
            "RestrictionType": "none", 
            "Quantity": 0
        }
    },
    "HttpVersion": "http2"
}
EOF
結果
      返り値なし

JSONファイルを作成したら、フォーマットが壊れてないか必ず確認します。

コマンド
jsonlint -q cf.json
結果
      返り値なし

1.4. ディストリビューションの作成

準備が整ったのでディストリビューションを作成します。

コマンド
aws cloudfront create-distribution --distribution-config file://cf.json
結果(例)
      {
          "Distribution": {
              "Status": "InProgress",
              "DomainName": "d2k4r1uwgpraj8.cloudfront.net",
              "InProgressInvalidationBatches": 0,
              "DistributionConfig": {
                  "Comment": "",
                  "CacheBehaviors": {
                      "Quantity": 0
                  },
                  "Logging": {
                      "Bucket": "",
                      "Prefix": "",
                      "Enabled": false,
                      "IncludeCookies": false
                  },
                  "WebACLId": "",
                  "Origins": {
                      "Items": [
                          {
                              "S3OriginConfig": {
                                  "OriginAccessIdentity": ""
                              },
                              "OriginPath": "",
                              "CustomHeaders": {
                                  "Quantity": 0
                              },
                              "Id": "www.example.tk",
                              "DomainName": "www.example.tk.s3.amazonaws.com"
                          }
                      ],
                      "Quantity": 1
                  },
                  "DefaultRootObject": "index.html",
                  "PriceClass": "PriceClass_All",
                  "Enabled": true,
                  "DefaultCacheBehavior": {
                      "TrustedSigners": {
                          "Enabled": false,
                          "Quantity": 0
                      },
                      "TargetOriginId": "www.example.tk",
                      "ViewerProtocolPolicy": "allow-all",
                      "ForwardedValues": {
                          "Headers": {
                              "Quantity": 0
                          },
                          "Cookies": {
                              "Forward": "none"
                          },
                          "QueryStringCacheKeys": {
                              "Quantity": 0
                          },
                          "QueryString": false
                      },
                      "MaxTTL": 31536000,
                      "SmoothStreaming": false,
                      "DefaultTTL": 86400,
                      "AllowedMethods": {
                          "Items": [
                              "HEAD",
                              "GET"
                          ],
                          "CachedMethods": {
                              "Items": [
                                  "HEAD",
                                  "GET"
                              ],
                              "Quantity": 2
                          },
                          "Quantity": 2
                      },
                      "MinTTL": 0,
                      "Compress": false
                  },
                  "CallerReference": "www.example.tk",
                  "ViewerCertificate": {
                      "SSLSupportMethod": "sni-only",
                      "ACMCertificateArn": "arn:aws:acm:us-east-1:777777777777:certificate/3429271a-b281-4996-829a-068d938679ea",
                      "MinimumProtocolVersion": "TLSv1",
                      "Certificate": "arn:aws:acm:us-east-1:777777777777:certificate/3429271a-b281-4996-829a-068d938679ea",
                      "CertificateSource": "acm"
                  },
                  "CustomErrorResponses": {
                      "Quantity": 0
                  },
                  "HttpVersion": "http2",
                  "Restrictions": {
                      "GeoRestriction": {
                          "RestrictionType": "none",
                          "Quantity": 0
                      }
                  },
                  "Aliases": {
                      "Items": [
                          "example.tk"
                      ],
                      "Quantity": 1
                  }
              },
              "ActiveTrustedSigners": {
                  "Enabled": false,
                  "Quantity": 0
              },
              "LastModifiedTime": "2016-10-13T15:30:46.198Z",
              "Id": "EQSY786QZ6BPJ",
              "ARN": "arn:aws:cloudfront::571972591141:distribution/E121BR1Z9DCSQB"
          },
          "ETag": "E1EMCKDD6ZMT90",
          "Location": "https://cloudfront.amazonaws.com/2016-09-07/distribution/EQSY786QZ6BPJ"
      }

ディストリビューションIDの取得

コマンド
CF_DIST_ID=`aws cloudfront list-distributions \
 --query DistributionList.Items[].Id --output text` && echo ${CF_DIST_ID}
結果(例)
      EQSY786QZ6BPJ

ディストリビューションのFQDNの取得

コマンド
CF_DOMAINNAME=`aws cloudfront list-distributions \
 --query DistributionList.Items[].DomainName \
 --output text` && echo ${CF_DOMAINNAME}
結果(例)
      d1ah72z09rcb49.cloudfront.net

このFQDNでディストリビューションへアクセスできます。
自分のドメイン名のCNAMEレコードにこれを登録することで独自ドメインでもアクセスできるようになります。

  1. Route53の設定
    =================

example.tk でアクセスできるようにするため、Route53の設定を行います。

2.1. Route53レコードセットの作成

CloudFrontやELBはCNAMEでDNSへ通常登録しますが、Zone APEX(www等が付かない example.tk )にはCNAMEレコードを登録できないためこれができません。
そこでRoute53の独自機能であるエイリアスレコードによってこれを実現します。

まずRoute53へレコードを登録するためのJSONファイルを作成します。

コマンド
cat << EOF > route53b.json
{
  "Comment": "AliasRecord",
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "AliasTarget": {
          "HostedZoneId": "Z2FDTNDATAQYW2",
          "EvaluateTargetHealth": false,
          "DNSName": "${CF_DOMAINNAME}."
        },
        "Type": "A",
        "Name": "${DOMAINNAME}."
      }
    }
  ]
}
EOF
cat route53b.json
結果
      {
        "Comment": "AliasRecord",
        "Changes": [
          {
            "Action": "CREATE",
            "ResourceRecordSet": {
              "AliasTarget": {
                "HostedZoneId": "Z2FDTNDATAQYW2",
                "EvaluateTargetHealth": false,
                "DNSName": "d1ah72z09rcb49.cloudfront.net."
              },
              "Type": "A",
              "Name": "example.tk."
            }
          }
        ]
      }

HostedZoneIdに書かれている文字列は全ユーザ共通の固定値です。
CloudFrontをエイリアスレコードに登録する場合は常にこの値を使用します。

JSONファイルを作成したら、フォーマットが壊れてないか必ず確認します。

コマンド
jsonlint -q route53.json
結果
      返り値なし

2.2. Route53への登録

コマンド
aws route53 change-resource-record-sets \
 --hosted-zone-id ${HOSTED_ZONE_ID} --change-batch file://route53b.json
結果(例)
      {
          "ChangeInfo": {
              "Status": "PENDING",
              "Comment": "AliasRecord",
              "SubmittedAt": "2016-10-13T08:34:57.794Z",
              "Id": "/change/C3SSDTIES1RAMM"
          }
      }
  1. 動作確認
    =================

3.1. CloudFrontのデプロイ完了を待つ

コマンド
aws cloudfront wait distribution-deployed --id ${CF_DIST_ID}
結果
      返り値なし

プロンプトが帰ってくるまでこれは15~30分ぐらいかかります。
waitコマンドには待てる限界が存在し、万一タイムアウトして
Waiter DistributionDeployed failed: Max attempts exceeded
という出力が返って来たらコマンドを再実行してください。

AWSJ亀田さんによる基調講演

この待ち時間の間に、本日は亀田さんによる基調講演を行います。
皆様ステージにご注目ください。
基調講演終了後、次へ進みます。

3.2. Webブラウザでアクセス

コマンド
echo https://${DOMAINNAME}/
結果(例)
      https://example.tk/

WebブラウザでURLへアクセスしてみます。問題無く表示されたでしょうか。
Route53の機能であるエイリアスレコード機能によって、Zone APEXでも別名が利用できることがわかります。

3.3. HTTP/2対応の確認

これは外部のサイトで確認することができます。
https://tools.keycdn.com/http2-test
へアクセスして、URL欄に自分のサイトを入力してみましょう。

結果(例)
      Yeah! example.tk supports HTTP/2.0.

緑色でこのような表示がされればHTTP/2対応です。

0
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?