LoginSignup
0
1

AWS CloudFormation: 04. S3 (+ CloudFront + OAC) による静的ウェブサイトのホスティング

Last updated at Posted at 2023-08-16

本記事について

S3の静的ウェブサイトホスティング

構築するアーキテクチャ

image.png

  • まず、S3バケットを作成します
    • バケット名は ${OrganizationName}-${SystemName}-bucket とします
      • S3バケット名はグローバル名前空間内でユニークである必要があります。そのため、プリフィックスに組織名をつけています
    • PublicAccessBlockConfiguration 内の全ての設定をfalseにすることで、ブロックパブリックアクセスを全て許可します
    • また、WebsiteConfiguration を設定することで、静的ウェブサイトホスティング機能を有効にします
  • 次に、S3バケットポリシーを作成します
    • Principal: '*' に対して、s3:GetObject 権限を付与します。これによって、誰でもオブジェクトを参照可能とします

作成するリソース

  • S3バケット関連
    • AWS::S3::Bucket
    • AWS::S3::BucketPolicy

デプロイ方法

必要な準備

デプロイコマンド

Region=ap-northeast-1
OrganizationName=iwatake2222
SystemName=sample-04-a

aws cloudformation deploy \
--region "${Region}" \
--stack-name "${SystemName}"-s3-hosting \
--template-file ./s3-hosting.yaml \
--parameter-overrides \
OrganizationName="${OrganizationName}" \
SystemName="${SystemName}"

上記コマンドでデプロイした後、下記コマンドで適当にindex.htmlをアップロードします

echo hello > index.html
aws s3 cp index.html s3://"${OrganizationName}-${SystemName}-bucket"

動作確認

  • URLは、 http://"${OrganizationName}-${SystemName}-bucket".s3-website-ap-northeast-1.amazonaws.com になります
  • ブラウザからアクセスして、index.htmlのコンテンツが表示されればOKです

テンプレート

  • デプロイコマンド実行時、以下のファイルを s3-hosting.yaml として配置してください
s3-hosting.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: |
  Create an S3 bucket for hosting a static website

Parameters:
  OrganizationName:
    Description: Organization Name
    Type: String
  SystemName:
    Description: System Name
    Type: String

Resources:
  #-----------------------------------------------------------------------------
  # S3 bucket
  #-----------------------------------------------------------------------------
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub ${OrganizationName}-${SystemName}-bucket
      PublicAccessBlockConfiguration:
        BlockPublicAcls: false
        IgnorePublicAcls: false
        BlockPublicPolicy: false
        RestrictPublicBuckets: false
      WebsiteConfiguration:
        IndexDocument: index.html
        ErrorDocument: error.html
      Tags:
        - Key: Name
          Value: !Sub ${OrganizationName}-${SystemName}-bucket

  S3BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Action:
              - s3:GetObject
            Effect: Allow
            Resource:
              - !Sub arn:aws:s3:::${S3Bucket}/*
            Principal: '*'

S3をオリジンとした、CloudFront + OAC (Origin Access Control)

構築するアーキテクチャ

image.png

  • 続いて、CloudFront経由で公開する方法を試します。S3とCloudFrontを繋ぐため、従来はOrigin Access Identity (OAI) というものが用いられていましたが、現在は非推奨となっているようです。ここでは、Origin Access Control(OAC)を使用します
  • まず、S3バケットを作成します
    • バケット名は ${OrganizationName}-${SystemName}-bucket とします
      • S3バケット名はグローバル名前空間内でユニークである必要があります。そのため、プリフィックスに組織名をつけています
      • S3バケットそのものに対して特別な設定は不要です
  • 次に、S3バケットポリシーを作成します
    • 後で作成するCloudFront Distributionに対して、s3:GetObject 権限を付与します。これによって、CloudFront Distributionのオリジンとして、コンテンツを提供可能となります
  • 次に、CloudFront Distributionを作成します
    • オリジンとして、先ほど作成したS3バケットを指定します
    • OAIは使用しないので空を指定し、OACは後で作成するものを指定します
    • その他キャッシュ関係の挙動を指定します。これらは必要に応じて変更してください
  • 最後に、OriginAccessControlを作成します

作成するリソース

  • S3バケット関連
    • AWS::S3::Bucket
    • AWS::S3::BucketPolicy
  • CloudFront関連
    • AWS::CloudFront::Distribution
    • AWS::CloudFront::OriginAccessControl

デプロイ方法

必要な準備

デプロイコマンド

Region=ap-northeast-1
OrganizationName=iwatake2222
SystemName=sample-04-b

aws cloudformation deploy \
--region "${Region}" \
--stack-name "${SystemName}"-s3-cloudfront \
--template-file ./s3-cloudfront.yaml \
--parameter-overrides \
OrganizationName="${OrganizationName}" \
SystemName="${SystemName}"

CloudFrontが有効になるのに時間がかかるため、デプロイには数分時間がかかります

上記コマンドでデプロイした後、下記コマンドで適当にindex.htmlをアップロードします

echo hello > index.html
aws s3 cp index.html s3://"${OrganizationName}-${SystemName}-bucket"

動作確認

image.png

  • URLは、AWS Console -> CloudFront -> Distribution -> 作成した ディストリビューションの ドメイン名 に、https:// を付けたものになります
  • ドメイン名はテンプレートからも出力しているため、下記コマンドでも確認出来ます
aws cloudformation describe-stacks --stack-name "${SystemName}"-s3-cloudfront --query "Stacks[0].Outputs[?OutputKey=='CloudFrontDomainName'].OutputValue" --output text
  • https://ドメイン名.net にブラウザからアクセスして、index.htmlのコンテンツが表示されればOKです
    • index.htmlを配置していないと AccessDenied エラーになるので注意してください

テンプレート

  • デプロイコマンド実行時、以下のファイルを s3-cloudfront.yaml として配置してください
s3-cloudfront.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: |
  Create an S3 bucket and CloudFront (OAC) for hosting a static website

Parameters:
  OrganizationName:
    Description: Organization Name
    Type: String
  SystemName:
    Description: System Name
    Type: String

Resources:
  #-----------------------------------------------------------------------------
  # S3 bucket
  #-----------------------------------------------------------------------------
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub ${OrganizationName}-${SystemName}-bucket
      Tags:
        - Key: Name
          Value: !Sub ${OrganizationName}-${SystemName}-bucket

  S3BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Action:
              - s3:GetObject
            Effect: Allow
            Resource:
              - !Sub arn:aws:s3:::${S3Bucket}/*
            Principal:
              Service: cloudfront.amazonaws.com
            Condition:
              StringEquals:
                AWS:SourceArn: !Sub arn:aws:cloudfront::${AWS::AccountId}:distribution/${CloudFrontDistribution}

  #-----------------------------------------------------------------------------
  # CloudFront
  #-----------------------------------------------------------------------------
  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Comment: !Sub ${SystemName}-distribution
        Origins:
          - DomainName: !GetAtt S3Bucket.RegionalDomainName
            Id: S3Origin
            OriginAccessControlId: !GetAtt OAC.Id
            S3OriginConfig:
              OriginAccessIdentity: ''
        Enabled: true
        DefaultRootObject: index.html
        DefaultCacheBehavior:
          TargetOriginId: S3Origin
          Compress: true
          ForwardedValues:
            QueryString: false
            Cookies:
              Forward: none
          CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6  # CachingOptimized (Recommended for S3)
          ViewerProtocolPolicy: redirect-to-https
          AllowedMethods:
            - GET
            - HEAD
          CachedMethods:
            - GET
            - HEAD
        PriceClass: PriceClass_All

  OAC:
    Type: AWS::CloudFront::OriginAccessControl
    Properties:
      OriginAccessControlConfig:
        Description: Access Control
        Name: !Sub ${SystemName}-oac
        OriginAccessControlOriginType: s3
        SigningBehavior: always
        SigningProtocol: sigv4


Outputs:
  CloudFrontDomainName:
    Value: !GetAtt CloudFrontDistribution.DomainName
    Export:
      Name: !Sub ${SystemName}-domain-name
0
1
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
0
1