こんにちは。
ココネでサービスインフラを担当しているインフラエンジニアのSです。
CloudFrontとS3の組み合わせは、多くのエンジニアがコンテンツ配信に利用している一般的な手法かと思います、
今回は、自分が業務でCloudFront+S3を使用して、セキュアなWebサイトや画像配信を実現した方法についてご紹介します。
概要
CloudFrontはAWSのCDN(コンテンツ配信ネットワーク)サービスであり、S3はAWSのSimple Storage Service(オブジェクトストレージサービス)です。この二つを組み合わせることで、静的なウェブコンテンツの高速配信する環境を構築できます。
ここでは、CloudFront+S3の基本設定の詳細は割愛し、コンテンツ配信に関する重要な設定ポイントについて説明します。
なぜかCloudFontとS3を組み合わせる?
S3だけでも、ウェブサイトや画像などのウェブコンテンツを配信できますが、なぜかCloudFrontをS3の上に設定するのは、アクセススピードを向上させるためです。
特に、サービスをグローバルに展開する際には、CloudFrontのエッジロケーションが利用されることで、ユーザーからのコンテンツへの通信速度は、S3のリージョンに依存するボトルネックが解消されます。
下記のようなネットワークルーティング図を見ると、通信の速さは一目瞭然です。
キャッシュ設定で高速化する
CloudFrontとS3を連携した状態でキャッシュ設定がない場合、ユーザのアクセスは毎回CloudFrontを経由してS3からオリジンオブジェクトを取得します。
しかし、キャッシュを設定すると、最初のアクセスでS3のオリジンオブジェクトがCloudFrontにキャッシュされ、2回目以降のアクセスではCloudFront側のキャッシュを利用するため、S3からオリジンデータを取得する必要がなくなり、通信速度が向上します。
よく使われているキャッシュ設定方法は、主に2つあります。
- S3にあるファイルのメタデータを設定する(Cache-Control: max-age=<秒数>を設定)
- CloudFront側のオブジェクトキャッシュを設定する(最小TTL、最大TTL、Default TTLを設定)
CloudFront のキャッシュ動作は、CloudFront 最小 TTL および最大 TTL、Cache-Control: max-ageの値によって異なります。
- Cache-Control: max-ageが設定されている場合、以下のようにキャッシュ期間が決まります。
- max-age < 最小TTL の場合、CloudFrontのキャッシュ期間は最小TTLの値になる。
- 最小TTL < max-age < 最大TTL の場合、CloudFrontのキャッシュ期間はmax-ageの値になる。
- max-age > 最大TTL の場合、CloudFrontのキャッシュ期間は最大TTLの値になる。
- Cache-Control: max-ageが設定されていない場合、以下のようにキャッシュ期間が決まります。
- Default TTL < 最小TTL の場合、CloudFrontのキャッシュ期間は最小TTLの値になる。
- 最小TTL < Default TTL < 最大TTL の場合、CloudFrontのキャッシュ期間はDefault TTLの値になる。
- Default TTL > 最大TTL の場合、CloudFrontのキャッシュ期間は最大TTLの値になる。
注意点:
要件によって特定のパスにあるファイルが頻繁に更新される場合は、キャッシュを無効にする必要があります。
その際、対象パスに対してビヘイビアを作成し、CloudFrontのキャッシュ設定を「最大TTL=0、デフォルトTTL=0」に変更すればOKです。
セキュアなコンテンツ配信を設定する
AWSのベストプラクティスでは、S3バケットの公開アクセスは推奨されていないため、CloudFrontと連携する際には、CloudFrontからのアクセスのみを許可するように設定します。
S3バケットで「静的ウェブサイトホスティング」を有効にするかどうかによって、CloudFrontとS3の設定方法が異なります。
S3の「静的ウェブサイトホスティング」が無効になっている場合、CloudFrontのOAC(オリジンアクセスコントロール)設定を使用して、S3へのアクセスを制限する
1、S3側の「パブリックアクセスのブロック」を有効にする
2、CloudFront側の「オリジンアクセス」でOACを作成
3、CloudFront側の対象ディストリビューションの「オリジン」設定に先ほど作ったOACを選択
4、上記の図にある「ポリシーをコピー」ボタンでポリシー内容を事前にメモし、後ほどS3のバケットポリシーに設定
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::******/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::******:distribution/E1QN2*********"
}
}
}
]
}
5、S3の「バケットポリシー」を編集
6、設定が完了すると、S3のアクセスを公開せずに、CloudFrontを経由してバケットのコンテンツを配信できるようになります。
S3の「静的ウェブサイトホスティング」が有効になっている場合、
CloudFrontのカスタムヘッダーを使用して、S3へのアクセスを制限する
1、S3側の「パブリックアクセスのブロック」を無効にする必要があります
2、CloudFront側の対象ディストリビューションの「オリジン」設定にカスタムヘッダーを追加
例: Referer:test123456
3、S3の「バケットポリシー」を編集
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::******/*",
"Condition": {
"StringEquals": {
"aws:Referer": "test123456"
}
}
}
]
}
6、設定が完了すると、S3のアクセスを公開せずに、CloudFrontを経由してWEBサイトを配信できるようになります。
おまけ
S3にはリクエストの上限があるため、バケットのプレフィックスを設計する際には、この制限を考慮する必要があるかもしれません!
最後に
以上で、CloudFrontとS3を組み合わせて、高速かつセキュアなコンテンツ配信を設定する方法をご紹介しました。
CloudFrontを活用することで、エンドユーザーへのレスポンス時間を短縮し、世界中どこからでも安定したパフォーマンスでコンテンツを配信することが可能になります。また、S3との連携によって、コンテンツを安全に保管し、オリジンアクセスコントロールやキャッシュ設定を使って、よりセキュアな環境を構築できます。
ぜひ、今回の内容を参考にして、あなたのプロジェクトで活用してみてください。
どこかでお役に立てれば幸いです。

