🚲

【AWS】S3+CloudFront+Route53+ACMでSSL化(https)した静的Webサイトを公開する

25 min read

概要

本記事では、S3+CloudFront+Route53を利用して、静的サイトを公開する実装手順を紹介します。ACMを使ってSSL証明書を発行し、httpsで公開します。
LP(ランディングページ)、ポートフォリオサイト、シンプルなサイトなどをインターネット上に公開する際に役立ちます。

構成図
スクリーンショット 2021-06-16 16.02.39.png

本記事のゴール

今回のゴールは、以下のhtml,ccs,画像だけのシンプルな静的Webサイトを、独自ドメインを使用してインターネット上に公開することです。
スクリーンショット 2021-06-08 16.33.54.png

事前準備

  • AWSのアカウント
  • 公開するファイル(html,css,imageなど)

実装手順

  1. S3で静的Webサイトホスティングをする
  2. CloudFront経由でS3のファイルにアクセスする
  3. CloudFrontのOAIを使用して、S3への直接アクセスを制限する
  4. 独自ドメインを取得し、Route53へ設定する(freenomで無料ドメインを取得します)
  5. ACMでSSL証明書を発行する
  6. CloudFrontへSSL証明書を設定する
  7. Route53にCloudFrontのドメインを紐付ける
  8. 独自ドメインにアクセスしてブラウザで確認する

※テスト目的の場合、今回の実装は無料でできます。(AWS無料利用枠を利用かつ条件を満たす場合のみ)

きちんと運用する場合だと料金はかかりますが、安価だと思います。
料金の詳細については、下記を参照のもと、自己責任でお願いします。

AWS で静的ウェブサイトをホスティングするときの合計コストは、使用状況によって異なります。 一般的に、AWS 無料利用枠の制限を超えた場合の費用は 1 か月あたり 1~3 USD です。 AWS 無料利用枠の対象で、制限の範囲内にある場合、静的ウェブサイトをホスティングする費用は 1 か月あたり約 0.50 USD です。詳細なコストの分析と請求額の見積もりについては、料金計算ツールをご利用ください。
引用:静的ウェブサイトをホスティングする

S3で静的Webサイトホスティングをする

S3は、ストレージサービスだけでなく、静的Webサイトをホスティングできます。
静的Webサイトとは、シンプルなhtml,css,画像,JavaScriptなどで作られたサイトのことです。
バケットにURLを指定すると、誰でもサイトにアクセスできます。

「サービス」から**「S3」**を起動しましょう。
スクリーンショット_2021-06-08_19_36_24.png

バケットを作成する

バケットを作成するクリックしましょう。
スクリーンショット_2021-06-08_19_43_05.png

「バケット名」に任意のバケット名を入力しましょう。
今回はtest.co.jpというバケット名を作成します。
スクリーンショット_2021-06-08_19_50_38.png

ブロックパブリックアクセスをOFFにする

  • パブリックアクセスをすべてブロックのチェックを外しましょう。
  • 「現在の設定により、このバケットとバケット内のオブジェクトが公開される可能性があることを承認します。」にチェックを入れましょう。
    スクリーンショット_2021-06-08_19_55_34.png

※最終的にS3バケットへの直接アクセスではなく、CloudFront経由の独自ドメインでアクセスするように設定するので、後ほどS3のブロックパブリックアクセスはONします。現段階では、S3で静的WebサイトをホスティングするのでOFFにします。

その他は、デフォルト設定のままでOKなので、バケットを作成をクリックしましょう。
スクリーンショット_2021-06-08_20_07_33.png

以下のようにバケットが作成されたことを確認しましょう。
スクリーンショット_2021-06-08_20_12_02.png

ファイルをアップロードする

作成したバケットをクリックしましょう。
スクリーンショット_2021-06-08_20_12_02.png

以下のような画面に遷移します。
スクリーンショット 2021-06-09 7.28.11.png

アップロードをクリックしましょう。
スクリーンショット_2021-06-09_7_28_11.png

ファイルを追加をクリックしましょう。
スクリーンショット_2021-06-09_7_34_39.png

事前に作成したhtml,css,JavaScriptファイルなどを追加しましょう。
今回、画像は「images」フォルダに格納したので、フォルダの追加をクリックして追加しました。
スクリーンショット_2021-06-09_9_40_13.png
html,css,画像などが追加されていることを確認しましょう。

確認ができたら、アップロードをクリックしましょう。
スクリーンショット_2021-06-09_9_41_28.png
アップロードすると、追加したファイルがバケットに入ります。

アップロードが成功すると以下のような画面表示になります。
スクリーンショット_2021-06-09_9_43_25.png
成功したら、右上の閉じるをクリックしましょう。

以下のように、アップロードしたファイルがバケット内に入っていることを確認しましょう。
スクリーンショット_2021-06-09_8_13_27.png

静的ウェブサイトホスティングを「有効」にする

S3を使用して、静的ウェブサイトのホスティングを有効にします。

プロパティをクリックしましょう。
スクリーンショット_2021-06-09_9_45_09.png

一番下にスクロールし、静的ウェブサイトホスティングの「編集」をクリックしましょう。
スクリーンショット_2021-06-09_8_20_32.png

  • **「有効にする」**にチェックを入れましょう。
  • インデックスドキュメントにindex.htmlと入力しましょう。
    スクリーンショット_2021-06-09_8_37_06.png

※4XXエラーが発生すると表示されるエラードキュメントを指定する場合は、エラードキュメントにerror.htmlなどを入力しましょう。

変更の保存をクリックしましょう。
スクリーンショット_2021-06-09_8_44_06.png

バケットポリシーを追加する

バケットポリシーとは、S3のバケットにアクセスの制限を設定することです。
誰が、何に対して、どうできるのか、できないのかを設定できます。

今回は、バケットへのパブリック読み取りアクセスを許可するバケットポリシーを追加します。これを許可すると、インターネット上から誰でもS3バケットにアクセスできるようになります。

アクセス許可をクリックしましょう。
スクリーンショット_2021-06-09_8_58_52.png

バケットポリシーから編集をクリックしましょう。
スクリーンショット_2021-06-09_18_58_58.png

パブリック読み取りアクセスを許可するには、以下のバケットポリシーをコピーし、エディターに貼り付けます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::Bucket-Name/*"
            ]
        }
    ]
}

ResourceのBucket-Nameは、自身で作成したバケット名を指定します。
今回は、test.co.jpがバケット名です。


エディタにバケットポリシーを設定し、バケット名も確認したら変更の保存をクリックしましょう。
スクリーンショット_2021-06-09_19_07_49.png

バケットウェブサイトエンドポイントからURLを確認する

ここまで完了するとエンドポイント(インターネット上に公開されたURL)が発行されます。
URLをクリックして、静的サイトが表示されているか確認します。

「プロパティ」に移動し、「静的ウェブサイトホスティング」にURLが発行されているので、クリックしましょう。

このURLの内容は、http://【バケット名】.s3-website-【リージョン名】.amazonaws.com/となっています。
スクリーンショット_2021-06-09_19_24_47.png

静的サイトが表示されているか確認しましょう。
以下のように、今回公開するサイトが表示されたら成功です。
スクリーンショット_2021-06-09_19_29_11.png
以上で、S3で静的Webサイトのホスティング作業が完了しました。

CloudFront経由でS3のファイルにアクセスする

次に、S3バケットへ直接アクセスではなく、CloudFront経由でアクセスできるように設定します。

CloudFrontとは、Webコンテンツの配信が高速化し、安全性の高いコンテンツデリバリーネットワークです。(略してCDNと呼ばれます)

通常、ユーザーはWebサーバーにアクセスして見たいページを取得しますが、CloudFrontdでは、Webサーバーの中身をキャッシュするエッジサーバーを利用します。
エッジサーバーを利用すると、Webサーバーの負担が軽減されるので、レスポンスが高速化されます。
S3でホスティングしたWebサイトと紐付けてよく使われます。

Amazon CloudFrontとは

CloudFrontを利用するメリットとS3との違いについて

「サービス」から**「CloudFront」**を起動しましょう。
スクリーンショット_2021-06-10_8_29_36.png

Distributionを作成する

Create Distributionをクリックしましょう。
スクリーンショット_2021-06-10_8_33_35.png

Get Startedをクリックしましょう。
スクリーンショット_2021-06-10_8_35_35.png

オリジンを設定する

以下を参考に設定しましょう。
スクリーンショット_2021-06-10_8_39_04.png

  • Origin Domain Name→作成したS3バケットを選択

  • Restrict Bucket Access→Yes
    S3バケットへのアクセスを拒否し、CloudFront経由でのみアクセス可能にする

  • Origin Access Identity→Create a New Identity
    オリジンアクセスアイデンティティ(OAI)を作成する

  • Grant Read Permissions on Bucket→Yes, Update Bucket Policy
    作成したOAIをS3のバケットポリシーに自動で記載してくれる

http通信だった場合に、httpsにリダイレクトされるように設定しましょう。

  • Viewer Protocol Policy→Redirect HTTP to HTTPS
    スクリーンショット_2021-06-10_13_45_25.png

デフォルトのルートオブジェクトを設定しましょう。

S3の静的Webサイトホスティングのデフォルト設定は、index.htmlを返しますが、CloudFrontのURLへアクセスする際のデフォルト設定では、index.htmlは省略できないので、オブジェクトの名前の指定が必要です。

よって、URLのアクセス時にCloudFrontがindex.htmlをオブジェクトとして返す設定を行います。

  • Default Root Objectindex.htmlと入力しましょう。
    スクリーンショット_2021-06-10_13_55_06.png

他は全てデフォルト設定のままでOKです。
Create Distributionをクリックしましょう。
スクリーンショット_2021-06-10_14_03_54.png

Distributionが作成できたら、左のタブ1番上のDistributionsをクリックしましょう。

StatusがIn ProgressからDeployedになるのを待ちます。
Deployedになるまでには数分かかります。

  • In Progressの状態
    スクリーンショット_2021-06-10_14_14_48.png

  • Deployedの状態
    スクリーンショット_2021-06-10_14_11_54.png

CloudFront経由のURLを確認する

StatusがDeployedになったら、Donation NameタブにあるURL(d3XXXXXX36XXXX.cloudfront.net)をコピーし、ブラウザで確認しましょう。
スクリーンショット_2021-06-11_15_42_21.png

以下のように、今回公開するサイトが表示されたら成功です。
スクリーンショット_2021-06-15_20_31_31.png
以上でCloudFront経由でS3のファイルにアクセスする設定は完了となります。

CloudFrontのOAIを使用して、S3への直接アクセスを制限する

CloudFrontのオリジン設定時に、S3からOAIを使用したCloudFront経由のアクセスを可能にしたので、S3バケットから直接アクセスするのを無効にする設定をします。

ブロックパブリックアクセスをONにする

S3のバケットのブロックパブリックアクセスをONに設定することで安全な運用が行えます。

「S3」を起動し、アクセス許可のタブに移動しましょう。

ブロックパブリックアクセス(バケット設定)の編集をクリックしましょう。
スクリーンショット_2021-06-10_15_31_23.png

パブリックアクセスをすべてブロックにチェックを入れたら、変更の保存をクリックしましょう。
スクリーンショット_2021-06-10_15_33_08.png
モーダルが開くので、確認と入力ししましょう。
スクリーンショット_2021-06-10_15_36_10.png

S3バケットポリシーを編集する

現状のバケットポリシーを確認すると、以下のように先程のCloudFrontのオリジン設定時に、OAIを使用したS3へのバケットへのアクセスを許可する設定がすでに追加されています。

確認したら、編集をクリックしましょう。
スクリーンショット_2021-06-10_20_16_00.png

バケットポリシーの編集画面に遷移されます。

現状のポリシーを確認すると、"Sid": "PublicReadGetObject"という静的WebサイトホスティングでS3バケットのリソースをパブリックへ公開するためのポリシーが設定されています。

このポリシーを削除することで、S3のバケットからの直接アクセスを無効にし、OAIを使用したCloudFront経由のアクセスが可能となります。

以下の範囲を削除しましょう。
スクリーンショット_2021-06-10_20_02_31.png
もし、"Sid": "PublicReadGetObject"が残った状態でブロックパブリックアクセスをONにすると、CloudFront経由でアクセスした場合、403エラー(閲覧権限なし)になります。

以下のように編集できたら、変更の保存をクリックしましょう。
スクリーンショット_2021-06-10_19_59_44.png

編集が完了したら下記、3点を確認しましょう。

  • アクセス許可の概要︰非公開のバケットとオブジェクト
  • ブロックパブリックアクセス(バケット設定)︰パブリックアクセスをすべてブロックが「ON」
  • バケットポリシー︰OAIを使用したCloudFront経由のアクセスが許可されたポリシー
    スクリーンショット_2021-06-10_20_12_54.png

以上でOAIを使用したCloudFront経由のアクセスを可能にするバケットポリシーの編集は完了になります。

試しに、S3のエンドポイントから直接アクセスしようとすると、403エラーになります。(こうなるのが正常です)
スクリーンショット 2021-06-10 20.33.30.png

独自ドメインを取得し、Route53へ設定する

ドメインを取得する

ドメインはRoute53からも入手できますが、費用がかかります。
試験目的の場合は、freenomで無料ドメインを取得できます。

取得方法は割愛します。以下のサイトを参考にしてみましょう。

freenomで無料ドメインを取得する

今回はtestfile.tkという無料ドメインを取得しました。

ホストゾーンを作成する

Route53とは、DNS(ドメインネームサービス)です。
インターネット上でドメインを管理・運用するために開発されたシステムのことを指します。
DNSは、https://example.comみたいなURLをIPアドレス(123.456.789.123)に変換します。
ドメインの取得ができたり、Route53でアクセスしたいアドレスを使用したいS3のエンドポイントに紐付けます。

「サービス」からRoute53を起動しましょう。
スクリーンショット_2021-06-14_8_12_53.png

ホストゾーンの作成をクリックしましょう。
スクリーンショット_2021-06-14_8_24_55.png

  • ドメイン名に取得したドメイン名を入力しましょう。
  • 入力したらホストゾーンの作成をクリックしましょう。
    スクリーンショット_2021-06-14_14_01_42.png

完了すると以下のように、NSレコードとSOAレコードが作成されます。
スクリーンショット_2021-06-14_14_05_00.png

NSレコードが4件作成されるので、freenomのDNS設定をします。

freenom→Sevices→MyDomainに移動しましょう。

Manage Domainをクリックしましょう。
スクリーンショット_2021-06-14_19_39_09.png
freenomのNameserverとして登録します。
Management Tools→Nameserverをクリックしましょう。
スクリーンショット_2021-06-14_19_49_32.png

  • Route53で作成されたNSレコード4件を設定しましょう。
    Nameserver設定時、末尾の「.」は不要です。

  • 設定したら、Change Nameserverをクリックしましょう。
    スクリーンショット_2021-06-14_19_52_22.png

以上でドメインの設定とfreenomのDNS設定は完了です。

ACMでSSL証明書を発行する

ACM(AWS Certificate Manager)とは、AWSウェブサイトとアプリケーションを保護するhttps通信に必要なSSL証明書の作成、更新などができます。
SSL証明書の作成は無料です。

AWS Certificate Manager とは何ですか?

SSL証明書とは、Secure Socket Layerの略です。
ウェブサイトの「運営者の実在性を証明」し、インターネット上でやりとりされるデータの「盗聴」「なりすまし」「改ざん」などを防止するために通信データの暗号化を行います。

SSL化のメリット
SSL化することで、悪質な不正アクセスの被害を防げます。
セキュリティ面を強化でき、アクセス権限をもたない人がサーバーや情報システムの内部に侵入しないように防止できます。

「サービス」から**「Certificate Manager」**を起動しましょう。
スクリーンショット_2021-06-14_8_42_32.png

CloudFrontにACMで作成したSSL証明書を紐付けるためには、
リージョンを「米国東部 (バージニア北部) us-east-1」にする必要があります。

ビューワーと CloudFront との間で HTTPS を必須にするには、証明書をリクエストまたはインポートする前に AWS Certificate Manager コンソールで AWS リージョンを**米国東部 (バージニア北部) **に変更する必要があります。
引用:CloudFront で SSL/TLS 証明書を使用するための要件

リージョンを**「米国東部 (バージニア北部) (us-east-1)」**に変更し、今すぐ始めるをクリックしましょう。
スクリーンショット_2021-06-15_7_32_32.png

証明書を発行する

パブリック証明書のリクエストにチェック→証明書のリクエストをクリックしましょう。
スクリーンショット_2021-06-14_8_43_12.png
取得したいSSL証明書のドメイン名を入力しましょう。

今回は、*.example.comのようにワイルドカード証明書を発行する設定とします。ただし、*.example.comで証明書を発行した場合、example.comといったドメインは保護されません。また、複数のドメインを追加することも可能です。
スクリーンショット_2021-06-14_14_10_12.png
入力したら、**「次へ」**をクリックしましょう。

DNSの検証にチェック→**「次へ」**をクリックしましょう。
スクリーンショット_2021-06-14_14_10_21.png

タグ名は任意です。空欄でも問題ないです。
とくになければ、**「確認」をクリックしましょう。
スクリーンショット_2021-06-14_14_10_30.png
ドメイン名と「DNS」を確認し、
「確定とリクエスト」**をクリックしましょう。
スクリーンショット_2021-06-14_14_10_38.png

検証状態は、「検証保留中」になります。
Route53でのレコード作成をクリックしましょう。
スクリーンショット_2021-06-14_14_11_45.png

正常にCNAMEレコードがRoute53に追加されると**「成功」**と表示されます。

CNAMEレコードとは、ドメイン名に別名を指定するためのレコードです。
例えば、example.comなどの現在のレコードに対して、別のドメイン (example.jpなど)やサブドメイン (www.example.comなど) にマッピングします。
この時、www.example.comをcanonical name(正式名)、example.comをaliases(別名)と呼びます。
スクリーンショット_2021-06-15_21_04_16.png

Route53を起動すると、以下のように検証用のCNAMEレコードが追加されています。
スクリーンショット_2021-06-14_14_53_59.png

早ければ数分で**「発行済み」**になります。
※20分〜30分かかる場合もあるので、気長に待ちましょう。
スクリーンショット_2021-06-14_14_12_22.png

以上でSSL証明書の発行は完了です。

CloudFrontへSSL証明書を設定する

独自ドメインによるhttps接続の為、CloudFrontの設定をします。

CloudFront→Distribution→該当のDistributionIDをクリックしましょう。
スクリーンショット_2021-06-15_10_28_32.png

Distributionを編集する

「General」→Editをクリックしましょう。
スクリーンショット_2021-06-14_14_17_04.png

  • **Alternate Domain Names (CNAMEs)**は、www.testfile.tkとします。https://www.testfile.tkでのアクセスを可能にします。

  • Custom SSL Certificateにチェックします。
    先程、ACMで作成した*.testfile.tk(fb1a5....を指定します。
    スクリーンショット_2021-06-14_14_31_32.png

上記以外はそのままの設定でOKなので、**「Yes,Edit」**をクリックしましょう。

以下のように、設定されていたら成功です。
スクリーンショット_2021-06-14_14_31_21.png

「Distributions」に戻るとCNAMEsタブに指定したドメインが表示されています。

StatusがIn ProgressからDeployedになるのを待ちます。
以下のようにStatusがDeployedになったら設定は完了です。
※Deployedになるまでは数分かかります。
スクリーンショット_2021-06-14_14_41_18.png

以上でCloudFrontへSSL証明書を設定する作業は完了です。

Route53にCloudFrontのドメインを紐付ける

今回は、www.testfile.tkで公開するため、Route53のレコード設定をします。

レコードを作成する

Route53→ホストゾーン→ドメイン名(testfile.tk)をクリック→レコードを作成をクリックしましょう。
スクリーンショット_2021-06-14_14_53_59.png

  • レコード名
    →リダイレクト元のドメイン
    (CloudFrontでSSL証明書を設定した際に入力したドメイン名)

  • レコードタイプ
    →A

  • トラフィックのルーティング先
    エイリアスをONにする
    →**「CloudFront ディストリビューションへのエイリアス」**を指定
    →CloudFrontのDomain Nameを指定
    スクリーンショット_2021-06-14_15_10_05.png

入力ができたら、レコードを作成をクリックしましょう。

作成されると以下のように、Aレコードが作成されます。
スクリーンショット_2021-06-14_15_10_46.png

以上でRoute53へのドメイン名の紐付け作業は完了です。

独自ドメインにアクセスしてブラウザで確認する

作成したドメイン(https://www.testfile.tk/)をブラウザでアクセスして、静的サイトが表示されるか確認しましょう。
無事表示されたら、成功です!

※今は上記のURLでアクセスできません。

スクリーンショット_2021-06-14_15_11_53.png
以上で全工程が完了しました!

※テスト目的などの場合は、課金されないようにS3バケットの削除、CloudFrontのDistributionの削除、Route53のホストゾーンの削除(作成から12時間以内にホストゾーンを削除した場合は、月額0.5$の課金対象外です)など忘れずに実施しておきましょう。

番外編

S3バケットのオブジェクトをCloudFrontに即時反映させる方法

S3バケット内のオブジェクト(html,cssなど)を更新したいときに、オブジェクトをバケットにアップロードしても、CloudFrontには即時に反映されません。

なぜなら、CloudFrontはS3オブジェクトのキャッシュを24時間保持しているからです。

デフォルトでは、CloudFront は Amazon S3 からのレスポンスを 24 時間 (86,400 秒間のデフォルト TTL) キャッシュしています。リクエストが エッジロケーションに到着してから24 時間以内に Amazon S3 を提供した場合、Amazon S3 のコンテンツを更新したとしても、CloudFront はキャッシュされたレスポンスを使います。
引用:CloudFront が、Amazon S3 から古いコンテンツを提供し続けるのはなぜですか?

その場合の対処法は、CloudFrontのキャッシュをクリアすることでS3からオブジェクトを直接取得でき、ファイルが即時反映されます。

コンソールから「CloudFront」→対象のDistributionsを選択しましょう。
スクリーンショット_2021-06-11_15_42_21.png

Invalidationsをクリックしましょう。
※「Invalidation」とは直訳で「無効化」という意味です。
スクリーンショット_2021-06-11_15_55_29.png

Create Invalidationをクリックすると、モーダルが開きます。
スクリーンショット_2021-06-11_16_03_03.png

Object PathsにキャッシュをクリアをしたいS3のオブジェクトのパスを指定しましょう。

削除したいオブジェクトのキャッシュをパスで指定します。
今回は、/*と指定します。
これを指定すると、対象のS3バケット内全てのキャッシュがクリアされます。
データを指定したい場合などは、以下のように指定しましょう。
/index.html 
/css/*

入力したら、Invalidateをクリックしましょう。
スクリーンショット_2021-06-11_16_09_10.png

StatusがIn ProgressからCompletedに変われば、キャッシュの削除は完了です。
スクリーンショット_2021-06-11_16_35_39.png

ブラウザからCoudFrontのURL(d3XXXXXX36XXXX.cloudfront.net)にアクセスし、サイトが更新されたことを確認してみましょう。

独自ドメインの反映までには、時間がかかると思います。
自分の場合は3〜4時間かかりました。

※※注意事項※※

無料で 1 か月あたり 1,000 回のパスの無効化が許可されています。パスの無効化が 1 か月あたり 1000 回を超える場合は、「Amazon CloudFront の料金」にある「無効リクエスト」の覧をご参照ください。
引用:CloudFront が、Amazon S3 から古いコンテンツを提供し続けるのはなぜですか?

参考サイト

今回実装するにあたって以下のサイトを参考にさせていただきました。

Amazon S3 での静的ウェブサイトの設定
CloudFrontを使用して、Amazon S3 でホストされた静的ウェブサイトを公開する
CloudFront + S3 + Route53で独自ドメインをSSL通信(https)設定をする
無料ドメイン(.tk)とRoute53を利用して0円でHTTPS環境を設定してみた

Discussion

ログインするとコメントできます