LoginSignup
7
0

はじめに

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やバケットポリシーに紐づけられるようにしております。

S3Bucket.yaml
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'

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両方のアクセス許可で設定しています。

CloudFront.yaml
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 への読み取り専用アクセスを許可する内容となっています。

S3BucketPolicy
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の中身は下記となります。

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もしくは履歴を削除すると改善する場合があります。

image.png

参考になれば、幸いです。

参考サイト

S3バケット

CloudFront

S3バケットポリシー

7
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
0