CloudFront経由でS3コンテンツを配信する
CDNサービスであるCloudFrontを使用して、S3バケットに配置したコンテンツを配信することができます。
今回は静的ウェブサイトホスティング機能を有効化し、パブリックにアクセス可能なS3バケットを対象とします。
なおOAI(Origin Access Identity)を使用することで、今回の構成と同様の動作を実現するすることもできます。こちらも併せてご確認ください。
構築する環境
S3バケットを作成し、静的ウェブサイトホスティング機能を有効化します。
バケットポリシーでバケット内のコンテンツを、パブリックに公開するように設定します。
CloudFrontディストリビューションを作成し、バケットをオリジンに設定します。
Lambda関数を作成します。
この関数をCloudFormationカスタムリソースとして設定します。
この関数の働きですが、スタック生成・削除時に、自動的にバケットにオブジェクト生成・削除を実行するように設定します。
生成するオブジェクトは静的ウェブサイトホスティング用のindex.htmlとします。
関数のランタイムはPython3.8とします。
CloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。
https://github.com/awstut-an-r/awstut-fa/tree/main/048
テンプレートファイルのポイント解説
本ページはCloudFrontを使用して、S3バケットコンテンツを配信する方法を中心に取り上げます。
S3バケットの静的ウェブサイトホスティング機能については、以下のページをご確認ください。
CloudFormationのカスタムリソースを使用して、スタック生成・削除時に、バケットにオブジェクト生成・削除を実行する方法については、以下のページをご確認ください。
(参考)S3バケットの静的ウェブサイトホスティング
Resources:
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref Prefix
PublicAccessBlockConfiguration:
BlockPublicAcls: false
BlockPublicPolicy: false
IgnorePublicAcls: false
RestrictPublicBuckets: false
WebsiteConfiguration:
IndexDocument: index.html
BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref Bucket
PolicyDocument:
Statement:
Action:
- s3:GetObject
Effect: Allow
Resource: !Sub "arn:aws:s3:::${Bucket}/*"
Principal: "*"
Outputs:
BucketArn:
Value: !GetAtt Bucket.Arn
BucketWebsiteURL:
Value: !GetAtt Bucket.WebsiteURL
BucketName:
Value: !Ref Bucket
Code language: YAML (yaml)
ポイントは2点です。
1点目はバケットポリシーです。
バケットポリシーによって、作成するバケットへのパブリックアクセスを許可します。
2点目はバケットから取得するデータです。
今回はバケットウェブサイトURLが重要な値です。
このURLは組み込み関数Fn::GetAttで取得することができます。
後述しますが、CloudFrontのオリジンサーバを指定する際に、このURLの一部を使用します。
以下にバケットウェブサイトURLのサンプルを記載します。
http://[bucket-name].s3-website-[region-name].amazonaws.com
CloudFrontディストリビューション
Resources:
Distribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
DefaultCacheBehavior:
AllowedMethods:
- GET
- HEAD
CachedMethods:
- GET
- HEAD
Compress: true
ForwardedValues:
Cookies:
Forward: none
QueryString: false
TargetOriginId: !Ref BucketName
ViewerProtocolPolicy: allow-all
Enabled: true
Origins:
- DomainName: !Select
- 2
- !Split
- /
- !Ref BucketWebsiteURL
Id: !Ref BucketName
#S3OriginConfig:
CustomOriginConfig:
OriginProtocolPolicy: http-only
PriceClass: PriceClass_All
Code language: YAML (yaml)
パブリックに公開しているS3バケットを、CloudFrontのオリジンに設定する上でのポイントを2点取り上げます。
1点目はドメイン名の設定です。
これはDomainNameプロパティに設定します。
静的ウェブサイトホスティング機能を有効化してパブリックに公開しているバケットの場合、バケットウェブサイトエンドポイントのドメイン名を指定します。
先ほどご紹介したバケットウェブサイトURLの「http://」以降の文字列がこれに該当します。
そのため組み込み関数Fn::Selectと同じくFn::Splitを使用して、ドメイン名の箇所を抽出した上で、本プロパティに指定します。
2点目はオリジンの詳細設定に関するプロパティです。
S3バケットをオリジンとする場合、以下の2つのどちらかのプロパティを設定する必要があります。
- CustomOriginConfig:S3バケットで静的ウェブサイトホスティングを有効化している場合に設定する。
- S3OriginConfig:S3バケットで静的ウェブサイトホスティングを有効化していない場合に設定する。
今回は有効化していますので、CustomOriginConfigプロパティに設定を行います。
バケットウェブサイトエンドポイントにアクセスする場合、CloudFrontからS3バケット間の通信は、SSL化されていないHTTP通信である必要があります。
ですからOriginProtocolPolicyプロパティで「http-only」を設定します。
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。
各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- S3バケット:fa-048
- CloudFrontディストリビューションのドメイン:https://d3pnwba2gu8n7s.cloudfront.net
AWS Management ConsoleからもCloudFrontを確認します。
CloudFrontディストリビューションが作成されています。
ディストリビューションのオリジンにS3バケットのウェブサイトエンドポイントが設定されています。
動作確認
準備が整いましたので、CloudFrontディストリビューションにアクセスします。
S3バケットのコンテンツが表示されました。
CloudFrontを経由して、オリジンであるS3バケットのウェブサイトエンドポイントにアクセスしているということです。
ちなみにオリジンであるS3バケットに、直接アクセスすることもできます。
現状の設定では、直接オリジンにアクセスすることを制限する設定を行っていないためです。
まとめ
CloudFrontを使用して、S3バケットに配置したコンテンツを配信することができました。