はじめに
1年ほど前からAWSに関わる業務に携わっておりました。
そこでCloudFormationを用いてAWS環境を構築してきたため、
今回はS3とCloudFrontで静的webサイトを表示させる環境をCloudFormationで構築する手順について記載します。
また、S3やCloudFront、CloudFormationについての説明は割愛させていただきます。
目次
・CloudFormationのスタック構成
・CloudFormation作成
・最後に
・参考
CloudFormationのスタック構成
CloudFormationで使用するスタックセットは下記に分けます
・S3バケット
・CloudFront(OAC設定含む)
・S3バケットポリシー
S3バケットとバケットポリシーを分けている理由としては、
バケットポリシーにCloudFrontの情報(ディストリビューション)が必要なためです。
そのため、S3バケット⇒CloudFront⇒バケットポリシーの順に構築していくこととなります。
CloudFormation作成
S3バケット
S3バケットを作成するCloudFormationを下記に記載します。
OutputsでS3バケットの情報をエクスポートしておくことで後に作成するCloudFrontやバケットポリシーに紐づけられるようにしております。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
#------------------------------------------------------------#
#Parameters
#------------------------------------------------------------#
Parameters:
PJPrefix:
Description: Project Name
Type: String
Default: pj-ogataro
AllowedPattern: ^[a-zA-Z0-9\-]*$
Environment:
Description: Environment Name
Type: String
Default: dev
AllowedPattern: ^[a-zA-Z0-9\-]*$
#------------------------------------------------------------#
#Resources
#------------------------------------------------------------#
Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub '${PJPrefix}-${Environment}-storage'
VersioningConfiguration:
Status: Enabled
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
Tags:
- Key: Name
Value: !Sub '${PJPrefix}-${Environment}-storage'
#------------------------------------------------------------#
#Outputs
#------------------------------------------------------------#
Outputs:
cloudfront:
Value: !Ref S3Bucket
Export:
Name: !Sub "${PJPrefix}-${Environment}-storage-Output"
CloudFront
次にCloudFrontを作成するCloudFormationを下記に記載します
AWSでは現在OAIではなく、OACを推奨していますのでOACで構築していきます。
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html
また、今回はhttpとhttps両方のアクセス許可で設定しています。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
#------------------------------------------------------------#
#Parameters
#------------------------------------------------------------#
Parameters:
PJPrefix:
Description: Project Name
Type: String
Default: pj-ogataro
AllowedPattern: ^[a-zA-Z0-9\-]*$
Environment:
Description: Environment Name
Type: String
Default: dev
AllowedPattern: ^[a-zA-Z0-9\-]*$
#------------------------------------------------------------#
#Resources
#------------------------------------------------------------#
Resources:
OAC:
Type: AWS::CloudFront::OriginAccessControl
Properties:
OriginAccessControlConfig:
Description: Access Control
Name: !Sub '${PJPrefix}-${Environment}-OAC'
OriginAccessControlOriginType: s3
SigningBehavior: always
SigningProtocol: sigv4
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
Origins:
- Id: S3Origin
DomainName: !Sub '${PJPrefix}-${Environment}-storage.s3.amazonaws.com'
OriginAccessControlId: !GetAtt OAC.Id
S3OriginConfig:
OriginAccessIdentity: '' #OAIを使用しない場合、空で設定しないとエラーになるため
DefaultCacheBehavior:
TargetOriginId: S3Origin
ViewerProtocolPolicy: allow-all
AllowedMethods:
- GET
- HEAD
ForwardedValues:
QueryString: false
Cookies:
Forward: none
PriceClass: PriceClass_200
DefaultRootObject: index.html
HttpVersion: 'http2'
#------------------------------------------------------------#
#Outputs
#------------------------------------------------------------#
Outputs:
cloudfront:
Value: !Ref CloudFrontDistribution
Export:
Name: !Sub '${PJPrefix}-${Environment}-Distribution-Output'
S3バケットポリシー
最後にS3バケットポリシーを作成するCloudFormationを下記に記載します。
CloudFront OAC への読み取り専用アクセスを許可する内容となっています。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
#------------------------------------------------------------#
#Parameters
#------------------------------------------------------------#
Parameters:
PJPrefix:
Description: Project Name
Type: String
Default: pj-ogataro
AllowedPattern: ^[a-zA-Z0-9\-]*$
Environment:
Description: Environment Name
Type: String
Default: dev
AllowedPattern: ^[a-zA-Z0-9\-]*$
#------------------------------------------------------------#
#Resources
#------------------------------------------------------------#
Resources:
S3BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !ImportValue
Fn::Sub: "${PJPrefix}-${Environment}-storage-Output"
PolicyDocument:
Version: "2012-10-17"
Id: "PolicyForCloudFrontPrivateContent"
Statement:
- Sid: "AllowCloudFrontService"
Effect: "Allow"
Principal:
Service: "cloudfront.amazonaws.com"
Action: "s3:GetObject"
Resource: !Sub "arn:aws:s3:::${PJPrefix}-${Environment}-storage/*"
Condition:
StringEquals:
AWS:SourceArn:
- !Join
- ''
- - !Sub "arn:aws:cloudfront::${AWS::AccountId}:distribution/"
- !ImportValue
Fn::Sub: "${PJPrefix}-${Environment}-Distribution-Output"
最後に
上記設定を完了したうえで、S3にindex.htmlファイルをアップロードします。
index.htmlの中身は下記となります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
Hello,World!!
</body>
</html>
反映までに時間がかかりますので、アップロード後CloudFrontのキャッシュ削除を実施してください。
CloudFrontにアクセスして下記のようになれば完了です。
※Access Deniedなどでアクセスできない場合、ブラウザのcookieもしくは履歴を削除すると改善する場合があります。
参考になれば、幸いです。
参考サイト
S3バケット
CloudFront
S3バケットポリシー