すのふら

すのふら

日々の備忘録

CloudFrontについて勉強

AWS 認定ソリューションアーキテクト – アソシエイトを受けるため、改めてAmazon Web Service(AWS)の勉強をする。

今回もこの本を一読したうえで機能単位で勉強していく。


Amazon CloudFrontについて

Amazon CloudFront は、データ、動画、アプリケーション、および API をすべてデベロッパーにとって使いやすい環境で、低レイテンシーの高速転送により世界中の視聴者に安全に配信する高速コンテンツ配信ネットワーク (CDN) サービスです。
Amazon CloudFront(グローバルなコンテンツ配信ネットワーク)| AWS

CDNサービスと書いてある通り、WEBサイトの情報を取得する際のマスターのサーバ(ここでいうオリジンサーバー)がダウンしないようにするサービスのこと。
またWebサービスのコンテンツ配信に加えて、映像や音声のストリーミング配信にも対応していることも特徴。

Amazon CloudFrout(以下CloudFrout)は高可用性、高パフォーマンス、低レイテンシーを売りにしている機能。

CDNサービスなしで直接WEBサーバをホストしているEC2インスタンスを公開しているのであれば、リクエストが増加した場合にパフォーマンス低下するので、CloudFront使いましょうという感じ。

CDNサービスなしでS3を静的サイトとして公開している場合、URLはHTTPでセキュリティ面で問題あるので、CloudFrontを使用することでHTTPSで利用することが可能。


Amazon CloudFrontのイメージ

f:id:snofra:20200821003631p:plain
標準ログ (アクセスログ) の設定および使用 - Amazon CloudFrontより引用

これはログに関してのページから取ってきたものだけど、これが一番分かりやすかった。

登場人物は主に3人。


エッジロケーション

コンテンツをキャッシュしておくキャッシュサーバーのことで、閲覧者がコンテンツにアクセスした際に最初に接続されるサーバーがここ。

コンテンツがキャッシュされている場合はこのサーバーから配信することで、オリジンサーバーへの負荷を減らすことができる。

閲覧者は自分の一番近い場所(地理的ロケーション)エッジロケーションからしかデータが取れない。
エッジサーバーに情報がない場合は、オリジンサーバーから取得することになる。

地理的ロケーションでデータを取ってくるだけなので、位置情報でルーティングとかそういう機能はない。

また、エッジロケーション上にデータが存在しない場合は上で書いた通りオリジンサーバーからデータを取るので、404を返したり、処理を待ったりとかはしない。

接続ポイントは149か所。


リージョン別エッジロケーション

エッジロケーションにキャッシュされていない場合は、リージョン別エッジロケーションに接続される。
エッジロケーションよりも大容量データをキャッシュ可能なキャッシュサーバー。
ここでもだめならオリジンサーバーに接続して情報を取得する。

接続ポイントは11か所。


ディストリビューション

エッジロケーションとオリジンサーバーとをつなげる要素がここ。
エッジロケーション側にオリジンサーバのどこに情報があるかを伝えるのが役目。

オリジンサーバーの設定を行い、CDNドメインを取得する。

tracpath.com


ディストリビューションには大きく分けて2つ存在する。


ウェブディストリビューション

通常使われるディストリビューション

dev.classmethod.jp


RTMP(Real Time Messaging Protocol)ディストリビューション

RTMP (Real-Time Messaging Protocol)という形式でのストリーミングによるVOD動画配信が可能。
S3をオリジンとし、S3に格納している動画ファイル(mp4やflv)をRTMPでストリーミング配信できたりするらしい。

ちなみにRTMPはどういうものかというと

Real Time Messaging Protocol (RTMP) とは、Adobe が開発している、Adobe Flash プレーヤーとサーバーの間で、音声・動画・データをやりとりするストリーミングのプロトコル。 元々は Macromedia が開発していて、Adobe に買収された。
Real Time Messaging Protocol - Wikipedia

なので、
Flashのサポート終了するので、このディストリビューションもなんかどうやら廃止になるっぽい。

dev.classmethod.jp


ディストリビューションから地域制限が可能

特定の国からアクセスされたくない情報がある場合、ディストリビューションから地域制限を行うと、アクセスすることができなくなる。

地域制限 (地理的ブロッキング) を使用すると、CloudFront ウェブディストリビューションを通じて配信しているコンテンツについて、特定地域のユーザーによるアクセスを回避できます。地域制限を使用するには、次の 2 つの方法があります。


地域制限は次のような仕組みになっています。


1.仮に、コンテンツをリヒテンシュタインでのみ配信する権限を持っているとしましょう。自分の CloudFront ウェブディストリビューションを更新して、リヒテンシュタイン王国のみを含むホワイトリストを追加します。(または、リヒテンシュタイン王国以外のすべての国を含むブラックリストを追加することもできます。)


2.モナコ王国に住むユーザーがお客様のコンテンツをリクエストすると、DNS はそのリクエストをイタリア、ミラノにある CloudFront エッジロケーションにルーティングします。


3.ミラノのエッジロケーションはお客さまのディストリビューションを検索し、モナコ王国のユーザーはコンテンツをダウンロードすることは許可されていないと判断します。


4.CloudFront は HTTP ステータスコード 403 (Forbidden) をユーザーに返します。
コンテンツの地理的ディストリビューションの制限 - Amazon CloudFront

エッジロケーションが地理的ロケーションから場所を特定するのを利用して国を特定しているとのこと。

ただここで設定できるのはあくまで国単位。


オリジンサーバー

CloudFroutへキャッシュするコンテンツの提供元であるオリジンとして、ELBやEC2、S3などを指定できる。
オンプレサーバーも指定可能。


カスタムエラーページ

オリジン側がエラーコードが返却された場合、あらかじめ設定したエラーページを表示することができる。


CloudFrontを使用した構成図

主に以下ような構成が主流

f:id:snofra:20200821010809j:plain
AWS WAFを利用してCloudFrontのELBオリジンへ直接アクセスを制限してみた | Developers.IOより引用

f:id:snofra:20200821011210p:plain
Cache Distributionパターン(CloudFront+S3)を一撃で設定する | Developers.IOより引用

クラウドデザインパターンはほかにもあるけどとりあえず今は、CloudFront→S3orEC2と、CloudFront + AWS WAF (ウェブアプリケーションファイアウォール)の構成をベースに記載。


キャッシュされていないコンテンツの問い合わせ先として、静的コンテンツはS3、動的コンテンツであればELBでルーティングするように構成することで、フロントエンドの高い可用性を維持しつつ、バックエンドのELBやEC2の負荷を軽減することができる。


CloudFront内、もしくは別機能と組み合わせたセキュリティ

セキュリティとしてセキュアな通信をするためには以下があげられる。

HTTPS 接続を設定する
・特定の地理的な場所にいるユーザーがコンテンツにアクセスできないようにする
・CloudFront 署名付き URL または署名付き Cookie を使用してコンテンツにアクセスするようにユーザーに要求する
・特定のコンテンツフィールドのフィールドレベルの暗号化を設定する
AWS WAF を使用してコンテンツへのアクセスを管理する
コンテンツへのセキュアなアクセスとアクセス制限の設定 - Amazon CloudFront

ディストリビューションで地域制限の話を書いたのでそれ以外のセキュリティ要素について記載する。


署名付きURL・署名付きCookieを使用する

f:id:snofra:20200821012850j:plain
S3ってなんじゃ?(CloudFrontでアクセス制御:Origin Access Identity × 署名付きURL) | cloudpack.mediaより引用

一時的にユーザにアクセス権を与えたい場合に使用する。


署名付きURL

  • 個別ファイルに対してアクセス制限をかけたい場合に使用する。
  • RTMPディストリビューションを利用できる。
  • URLが変更されてしまうのが難点。

主に個のファイルに対して何かしたい場合に使用する。


署名付きCookie

  • URLを変更したくない。
  • 複数のメディアへのアクセス制限をかけたい

主に複数のファイルに対して何かしたい場合に使用する。


AWS WAFと組み合わせる

CloudFrontで永続的に外部リンクを利用させたくない、あるいは特定のリクエストのみ利用させたいという意図がある場合、WAFのreferer制限を使用することで実現可能。
ブロックされている場合、403エラーが返却する。

指定したリクエスト以外のすべてのリクエストを許可する
特定の攻撃者からのリクエストを排除するときに利用します。


指定したリクエスト以外のすべてのリクエストをブロックする
制限されたウェブサイトを作りたい時に利用します。
例 : 日本国内以外からのアクセスは出来ないようにしたい。
AWS WAF Referer制限ってなに? - Qiita

上記の通り、発信先IPに基づき着信Webリクエストの許可拒否を設定することができるが、この仕組みを移行ツールとして使用する!みたいなことはできない。

問題傾向としては、CloudFront周りの回答で「WAF」のワードがない状態でreferer制限があった場合は間違っているので除外していい。
referer制限はWAFの機能なので。


オリジンアクセスアイデンティティ(OAI)の利用

S3やに保存している静的コンテンツで普段全ユーザに公開していないものに対して、特定の閲覧者(IPアドレス)にだけ公開したい場合に使用する。
CloudFroutからプライベートサーバにアクセスしたい時に使うケースになる。

この場合、CloudFront経由でアクセスしてほしく、直接S3にアクセスしてほしくないため、バケットポリシーでを変更する。

Amazon S3 バケットから配信するコンテンツへのアクセスを制限するには、次のステップに従います。


・オリジンアクセスアイデンティティ (OAI) と呼ばれる特別な CloudFront ユーザーを作成し、ディストリビューションに関連付けます。


・CloudFront が OAI を使用してバケット内のファイルにアクセスし、ユーザーに提供できるように S3 バケットのアクセス許可を設定します。ユーザーが S3 バケットへのダイレクト URL を使用して、そこにあるファイルにアクセスできないようにしてください。


これらのステップを実行すると、ユーザーは S3 バケットから直接ではなく、CloudFront 経由でのみファイルにアクセスできます。
オリジンアクセスアイデンティティを使用して Amazon S3 コンテンツへのアクセスを制限する - Amazon CloudFront

f:id:snofra:20200821014344p:plain
[CloudFront + S3]特定バケットに特定ディストリビューションのみからアクセスできるよう設定する | Developers.IOより引用



SSLによる通信の暗号化

SSL証明書を利用したSSL暗号化通信が可能。

AWS Certificate Manager(ACM)を使用することで、ACMの証明書や、信頼できるサードパーティーの証明書をACMに取り込んで使用することで可能になる。

AWS Certificate Manager は、AWS のサービスとお客様の内部接続リソースで使用するパブリックとプライベートの Secure Sockets Layer/Transport Layer Security (SSL/TLS) 証明書のプロビジョニング、管理、デプロイを簡単にします。
AWS Certificate Manager(SSL/TLS 証明書のプロビジョン、管理、およびデプロイ)| AWS


CloudFront↔ELB(Elastic Load Balancing)間の証明書もACMを使用して使用できるが、一部注意が必要な点がある。


それはCloudFront↔ELB(Elastic Load Balancing)以外の機能間での証明書について。


通常のCloudFront↔ELB(Elastic Load Balancing)間の証明書

f:id:snofra:20200821101622p:plain
https://recipe.kc-cloud.jp/archives/11355より引用

通常はこのように、ACMが提供する証明書と、信頼できるサードパーティーの証明書をACMに取り込んで使用することで暗号化通信を可能とする。
エッジロケーション側とオリジンサーバー側両方に設定する。


CloudFront↔ELB(Elastic Load Balancing)以外の機能間の証明書

ここが問題になる。

f:id:snofra:20200821101854p:plain
CloudFront + EC2インスタンスでACMで発行した証明書を適用したら、結局他の証明書も必要になった話。 | ハックノートより引用

上のように、ELB経由せず直接EC2インスタンスを参照している場合(オリジンサーバーがELBを経由しない)、ACMが提供する証明書は使用できない。
したがって、ACMを使用せずに信頼できるサードパーティーの証明書を使用しなければならない。

SSL/TLS 証明書は、カスタムオリジンの次のソースから使用できます。


・オリジンが Elastic Load Balancing ロードバランサーの場合、AWS Certificate Manager (ACM) が提供する証明書を使用できます。信頼されたサードパーティー認証機関が署名して ACM にインポートされた証明書を使用することもできます。


・ELB ロードバランサー以外のオリジンの場合、信頼されたサードパーティー認証機関 (CA) (Comodo、DigiCert、Symantec など) によって署名された証明書を使用する必要があります。
CloudFront とカスタムオリジンとの間の通信に HTTPS を必須にする - Amazon CloudFront

dev.classmethod.jp


Amazon Cognitoを使用した認証

ユーザ認証したユーザ(ログインできた)にだけ情報を閲覧させたい場合に使用。


f:id:snofra:20200821110717p:plain
CloudFront + S3 + Cognito + AWS Amplify + Vue.js で会員制サイトをサーバーレスで構築 | ハックノートより引用

AWSサーバレスアーキテクチャでSPA(シングルページアプリケーション)を構築したい場合のテンプレート構成になる。

https://academy.gmocloud.com/know/20160201/1529

AWSサーバレスアーキテクチャでSPAを実装する(1)~SSLを経由してブラウザからLambda APIへアクセスするまでの下準備 (1/9):CodeZine(コードジン)


CloudFrontの料金体系

aws.amazon.com

このあたりで決まる。


トラフィックの分散
コンテンツのエッジロケーションの場所によって値段が異なる。

エッジロケーションの数ではなく、場所で値段が違うことに注意。


リクエスト数
これは単純にリクエスト数(HTTP/HTTPS


データ転送量
エッジロケーションやオリジンサーバーから転送したコンテンツのデータ量。
当然だけどオリジンサーバーからデータを転送すると料金が高くなる。

転送量が高い場合は、エッジロケーション側でコンテンツを圧縮して単純にファイルサイズを小さくして転送することでディスカウントすることができる。


Amazon CloudFrontへの監査

CloudFrontへのアクセスログを知りたい場合は、CloudFront内のアクセスログを有効にする。
そうするとS3に1時間で数回、ディストリビューションへのリクエストに関するアクセスログを格納するようになる。

コンソール画面や、CloudFront APIでログ記録設定を変更できる。

docs.aws.amazon.com


なおCloudFrontへの監査にあたって、VPCフローログや、CloudTrailは使用できない。


Lambda@Edge

名前はLambdaの1機能のように見えるが、CloudFrontの機能のひとつ。
その言葉の通りでCloudFrontでLambdaを使用しようというもの。

エッジロケーション側にLambdaと同様なコードを構築することで、地理的ロケーション別で表示させるコンテンツを変更させたい場合や、アクセス元のIPによって表示させるコンテンツを変更したいなどが可能となる。

techblog.zozo.com

qiita.com


Amazon CloudFrontのキャッシュ削除

キャッシュクリアをしたい場合は、CloudFrontのコンソールを開いてInvalidationsタブを選択し「Invalidate」ボタンを押す。
これは手動でしか方法がないのかな?

dev.classmethod.jp


Amazon CloudFrontのオリジンサーバーのフェイルオーバー機能

aws.amazon.com

CloudFront の Origin Failover の機能を使用すると、プライマリオリジンが利用できないことを CloudFront が検出した場合、セカンダリオリジンからコンテンツが提供されるように、プライマリとセカンダリの 2 つのオリジン を設定できます。
CloudFront では、カスタムエラーページを設定したり、オリジンを利用できない場合に Lambda @ Edge でリダイレクトを生成したりすることができるようになっています。

今まではRoute53でコントロールしなければならなかったけど、CloudFrontでも対応できるようになった。
プライマリとセカンダリに対して情報を設定して、プライマリがダメだったときにセカンダリを利用するようにできる。


[~.html?language=JP]のような末尾の国コードをどのように特定するのか

クエリ文字パラメーターの設定で可能。
ユーザが選択した言語に基づくクエリ文字パラメーターがセットされる。

クエリ文字パラメーターを使用することで、特定の言語ページをオリジンサーバーに転送して閲覧者に返すことが可能になる。

ナレッジQA


AWS サポート - ナレッジセンター


キャッシュしたファイルがエッジロケーション側にない問題

キャッシュしようとしたけど、全然エッジロケーション側にキャッシュされず毎回オリジンサーバーからデータを取ってきてしまう問題になる。

Cache-Control max-age ディレクティブが低すぎることが原因。

Cache-Control ヘッダーまたは Expires ヘッダーに設定したディレクティブが互いに矛盾していないことを確認してください。ベストプラクティスとして、Expires ヘッダーの代わりに Cache-Control max-age ディレクティブを使用してください。両方に値を指定した場合、CloudFront は Cache-Control max-age に設定した値のみを使用します。
CloudFront キャッシュ時間に関する問題のトラブルシューティング


オリジン側のS3を更新したのに古いバージョン使われちゃう問題

キャッシュコントロールヘッダでのキャッシュ保持期間がデフォルトの可能性がある(24時間)。
そのためオリジン側の情報を更新してもキャッシュの情報が変わっていない。

次のいずれかの方法で、CloudFront の更新された S3 コンテンツを CloudFront にプッシュできるようになります。
・S3 オブジェクトを無効にする。
・オブジェクトのバージョニングを使う
更新した Amazon S3 コンテンツを CloudFront からプッシュする

・S3 オブジェクトを無効にする

キャッシュからレスポンスを削除。キャッシュが削除されたので、次のリクエストではオリジンから取得するようになる。
・有効期限切れになる前に CloudFront エッジキャッシュからファイルを削除する場合、以下のいずれかの処理を行うことができます。
・エッジキャッシュからファイルを無効にします。ビューワーが次にファイルをリクエストしたときに、CloudFront はオリジンに戻ってファイルの最新バージョンをフェッチします。
ファイルの無効化 - Amazon CloudFront

ただしRTMPディストリビューションは無効にできない。
オブジェクトの無効化を完了するには、通常 60~300 秒かかるので注意。


・オブジェクトのバージョニングを使う

コンテンツを頻繁に更新する場合は、 オブジェクトバージョニングを使用して、CloudFront ディストリビューションのキャッシュをクリアすることをお勧めします。
頻繁にキャッシュを更新する場合、オブジェクトのバージョニングを行うことで、無効化するよりコストがかからない場合があります。
更新した Amazon S3 コンテンツを CloudFront からプッシュする


カスタムキャッシュがうまく機能しない問題

ディストリビューションにそのカスタムキャッシュありますか?設定おかしくないですか?

例えば、キャッシュ動作の パスパターンが test/ に設定されていると、example.com/test/file1.jpg へのリクエストはデフォルトのキャッシュ動作に従います。
このリクエストは test/に指定された動作に従いません。 末尾のワイルドカード (test/*) が含まれていないパスパターンだからです。
CloudFront ディストリビューションがカスタムキャッシュ動作に追従しない場合のトラブルシューティング

ちゃんと設定しないと機能しない。

・大文字と小文字区別するよ


特定のファイルをキャッシュしたくない問題

カスタムオリジンウェブサーバーアプリケーションで、CloudFront にキャッシュさせたくないオブジェクトに Cache-Control no-cache、no-store、または private ディレクティブを追加します。または、CloudFront にキャッシュさせたくないオブジェクトに Expires ディレクティブを追加します。
CloudFront が特定のファイルをキャッシュしないようにする


http接続はうまくいくのにhttps接続はうまくいかない問題

オリジンがALB(CLB)を使用している。
CloudFront←→ALB間のHTTPS通信が失敗する。HTTPはうまくいく状態。


関連付けている証明書、セキュリティグループ、ネットワークアクセスコントロールリスト(ACL)の設定ミスによるものの可能性が高い。

HTTPS 通信の失敗は、関連付けられている SSL 証明書、セキュリティグループ、またはネットワークアクセスコントロールリスト (ACL) に関する問題が原因である可能性があります。使用しているディストリビューションロードバランサーが次のセキュリティ要件を満たしていることを確認してください。

ロードバランサーに有効な SSL 証明書をインストールしておく必要があります。SSL 証明書をインストールしてもまだ HTTPS エラーが発生する場合は、CloudFront とカスタムオリジンサーバー間の SSL 接続をトラブルシューティングします。
・CloudFront ディストリビューションがポート 443 でロードバランサーに接続する場合、ロードバランサーに関連付けられているセキュリティグループは、CloudFront IP アドレスのポート 443 でトラフィックを許可する必要があります。セキュリティグループの更新の詳細については、Classic Load Balancer のセキュリティグループの設定または Application Load Balancer のセキュリティグループを参照してください。
ロードバランサーAmazon Virtual Private Cloud (Amazon VPC) に関連付けられている ネットワーク ACL は、HTTPS ポート (通常はポート 443) で CloudFront からのトラフィックを許可する必要があります。
CloudFront ディストリビューションとロードバランサーオリジン間の HTTPS 通信の問題を解決する

有効なSSL証明書をインストールしている?、ポート443空けてる?



AWS Certificate Manager (ACM) でSSL証明書を更新したけど、反映されない問題

証明書の更新や再インポートのプロセスがまだ完了していない場合、CloudFront が引き続き以前の証明書を使用し続けることがあります。
また、証明書の更新や再インポートは非同期的に行われるため、CloudFront に新しい証明書が表示されるまで数時間かかることがあります
ACM と CloudFront で認証の有効期限切れの問題を回避する