CloudFront + S3 静的サイト(開発/本番環境)のCI/CDパイプラインをCloudFormationで構築する

AWS

2023.12.25

Topics

はじめに

こんにちは、フクナガです。
この記事はNHN テコラス Advent Calendar 2023の25日目の記事です。

本記事では、CloudFront + S3でホストする静的サイト環境とCI/CDパイプラインの環境概要や設定とそれらを構築するためのCloudFormationテンプレートをご紹介します。

構築する環境

S3のアクセス許可について

CloudFrontからS3の接続はOAC(Origin Access Control)を利用し、S3への直接接続を禁止することで、セキュアな接続を実現します。OACについての詳細はこちらの記事をご参考にしていただければ幸いです。
【アップデート】Amazon CloudFront で Origin Access Control (OAC) が利用開始されました!

運用IAMユーザーについて

ご紹介するテンプレート内にはIAMユーザーも含まれております。こちらを利用すると、CodeCommitへのソースコードアップロードが可能になります。
また、対象IAMユーザーが直接mainブランチへプッシュやマージを行うことができないように権限を設定してあります。

開発/本番環境デプロイについて

今回の環境は開発/本番環境と用途に応じて環境を分ける構成としています。また、S3にデプロイするソースコードはCodeCommit上で管理する設定となっています。

1. ブランチ戦略

CodeCommitの「dev」ブランチの更新時に開発環境へデプロイ、「main」ブランチの更新時に本番環境へデプロイする設定を実装します。
開発作業を実施する際は、個別でブランチを作成し、「dev」ブランチへプルリクエストを作成、マージします。
「main」ブランチの更新は、必ず「dev」ブランチの内容を「main」ブランチへマージすることで実施することとします。

2. S3へのデプロイ

CodeDeployを利用し、S3へのコンテンツアップロードを実施します。

3. キャッシュクリア

CloudFrontでキャッシュを利用する場合も考慮し、CI/CDパイプライン実行時にCloudFrontのキャッシュクリアを実行する設定とします。
CodeDeployでS3にコンテンツをデプロイ後、CodeBuildで下記キャッシュクリアコマンドを実施します。

aws cloudfront create-invalidation --distribution-id $CloudFront_Distribution --paths "$CloudFront_Invalidation_Path" --region us-east-1

CloudFormationテンプレート

※こちらのテンプレートはバージニア北部リージョン(us-east-1)で実行してください

AWSTemplateFormatVersion: 2010-09-09
Description: Static contents distribution using S3 and CloudFront.

Parameters:
  SiteNameProd:
    Type: String
    Description: domain name e.g. test-site.com
  SiteNameDev:
    Type: String
    Description: domain name e.g. dev.test-site.com
  SiteIdentifier:
    Type: String
    Description: Site Identifier. Don't Use [.] !! e.g. test-site-com
  CloudFrontInvalidationPath:
    Description: input the invalidation path of CloudFront cache clear
    Type: String
    Default: /*

Resources:
  AssetsBucketProd:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    Properties:
      BucketName: !Sub ${SiteNameProd}-s3-bucket
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True
      WebsiteConfiguration:
        IndexDocument: index.html
  AssetsBucketProdPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref AssetsBucketProd
      PolicyDocument:
        Statement:
          - Action: s3:GetObject
            Effect: Allow
            Resource: !Sub arn:aws:s3:::${AssetsBucketProd}/*
            Principal:
              Service: "cloudfront.amazonaws.com"
            Condition:
              StringEquals:
                AWS:SourceArn:
                  - !Join
                    - ""
                    - - !Sub "arn:aws:cloudfront::${AWS::AccountId}:distribution/"
                      - !Ref AssetsCloudFrontDistributionProd
          - Action:
              - "s3:GetObject"
              - "s3:DeleteObject"
              - "s3:GetObjectVersion"
              - "s3:DeleteObjectVersion"
              - "s3:PutObject"
              - "s3:ListBucket"
              - "s3:ListBucketVersions"
            Effect: Allow
            Resource:
              - !Sub arn:aws:s3:::${AssetsBucketProd}/*
              - !Sub arn:aws:s3:::${AssetsBucketProd}
            Principal:
              AWS: !GetAtt CodeBuildServiceRole.Arn

  AssetsBucketDev:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    Properties:
      BucketName: !Sub ${SiteNameDev}-s3-bucket
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True
      WebsiteConfiguration:
        IndexDocument: index.html

  AssetsBucketDevPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref AssetsBucketDev
      PolicyDocument:
        Statement:
          - Action: s3:GetObject
            Effect: Allow
            Resource: !Sub arn:aws:s3:::${AssetsBucketDev}/*
            Principal:
              Service: "cloudfront.amazonaws.com"
            Condition:
              StringEquals:
                AWS:SourceArn:
                  - !Join
                    - ""
                    - - !Sub "arn:aws:cloudfront::${AWS::AccountId}:distribution/"
                      - !Ref AssetsCloudFrontDistributionDev
          - Action:
              - "s3:GetObject"
              - "s3:DeleteObject"
              - "s3:GetObjectVersion"
              - "s3:DeleteObjectVersion"
              - "s3:PutObject"
              - "s3:ListBucket"
              - "s3:ListBucketVersions"
            Effect: Allow
            Resource:
              - !Sub arn:aws:s3:::${AssetsBucketDev}/*
              - !Sub arn:aws:s3:::${AssetsBucketDev}
            Principal:
              AWS: !GetAtt CodeBuildServiceRole.Arn

  AssetsCloudFrontDistributionProd:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
          - Id: S3
            DomainName: !GetAtt AssetsBucketProd.DomainName
            OriginAccessControlId: !GetAtt OACProd.Id
            S3OriginConfig:
              OriginAccessIdentity: ""
        Enabled: true
        DefaultRootObject: index.html
        Comment: !Ref SiteNameProd
        DefaultCacheBehavior:
          AllowedMethods:
            - HEAD
            - GET
          CachedMethods:
            - HEAD
            - GET
          DefaultTTL: 0
          MaxTTL: 0
          MinTTL: 0
          TargetOriginId: S3
          ForwardedValues:
            QueryString: false
          ViewerProtocolPolicy: redirect-to-https
        IPV6Enabled: false

  OACProd:
    Type: AWS::CloudFront::OriginAccessControl
    Properties:
      OriginAccessControlConfig:
        Description: !Ref SiteNameProd
        Name: !Ref SiteNameProd
        OriginAccessControlOriginType: s3
        SigningBehavior: always
        SigningProtocol: sigv4

  AssetsCloudFrontDistributionDev:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
          - Id: S3
            DomainName: !GetAtt AssetsBucketDev.DomainName
            OriginAccessControlId: !GetAtt OACDev.Id
            S3OriginConfig:
              OriginAccessIdentity: ""
        Enabled: true
        DefaultRootObject: index.html
        Comment: !Ref SiteNameDev
        DefaultCacheBehavior:
          AllowedMethods:
            - HEAD
            - GET
          CachedMethods:
            - HEAD
            - GET
          DefaultTTL: 0
          MaxTTL: 0
          MinTTL: 0
          TargetOriginId: S3
          ForwardedValues:
            QueryString: false
          ViewerProtocolPolicy: redirect-to-https
        IPV6Enabled: false

  OACDev:
    Type: AWS::CloudFront::OriginAccessControl
    Properties:
      OriginAccessControlConfig:
        Description: !Ref SiteNameDev
        Name: !Ref SiteNameDev
        OriginAccessControlOriginType: s3
        SigningBehavior: always
        SigningProtocol: sigv4

  CodeCommit:
    Type: AWS::CodeCommit::Repository
    Properties:
      RepositoryName: !Sub ${SiteIdentifier}-source-repository
      RepositoryDescription: CodeCommit Repository

  CodeBuildCWLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub ${SiteIdentifier}-CodeBuild

  AmazonCloudWatchEventRule:
    Type: AWS::Events::Rule
    Properties:
      EventPattern:
        source:
          - aws.codecommit
        detail-type:
          - "CodeCommit Repository State Change"
        resources:
          - !Join [
              "",
              [
                "arn:aws:codecommit:",
                !Ref AWS::Region,
                ":",
                !Ref AWS::AccountId,
                ":",
                !GetAtt CodeCommit.Name,
              ],
            ]
        detail:
          event:
            - referenceCreated
            - referenceUpdated
          referenceType:
            - branch
          referenceName:
            - main
      Targets:
        - Arn: !Join
            - ""
            - - "arn:aws:codepipeline:"
              - !Ref AWS::Region
              - ":"
              - !Ref AWS::AccountId
              - ":"
              - !Ref Pipeline
          RoleArn: !GetAtt AmazonCloudWatchEventRole.Arn
          Id: codepipeline-AppPipeline

  AmazonCloudWatchEventRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - events.amazonaws.com
            Action:
              - "sts:AssumeRole"
      Path: /
      Policies:
        - PolicyName: cwe-pipeline-execution
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: "codepipeline:StartPipelineExecution"
                Resource: !Join
                  - ""
                  - - "arn:aws:codepipeline:"
                    - !Ref AWS::Region
                    - ":"
                    - !Ref AWS::AccountId
                    - ":"
                    - !Ref Pipeline

  CodeBuildProjectCloudFrontCacheClearProd:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: !Sub ${SiteIdentifier}-prod-CacheClear
      Artifacts:
        Type: CODEPIPELINE
      Source:
        Type: CODEPIPELINE
        BuildSpec: |
          version: 0.2
          phases:
            build:
              commands:
                - aws cloudfront create-invalidation --distribution-id $CloudFront_Distribution --paths "$CloudFront_Invalidation_Path" --region us-east-1
      Environment:
        Type: LINUX_CONTAINER
        Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0
        ComputeType: BUILD_GENERAL1_SMALL
        EnvironmentVariables:
          - Name: CloudFront_Distribution
            Type: PLAINTEXT
            Value: !GetAtt AssetsCloudFrontDistributionProd.Id
          - Name: CloudFront_Invalidation_Path
            Type: PLAINTEXT
            Value: !Ref CloudFrontInvalidationPath
      LogsConfig:
        CloudWatchLogs:
          GroupName: !Sub ${SiteIdentifier}-CodeBuild
          Status: ENABLED
      ServiceRole: !Ref CodeBuildServiceRole
      TimeoutInMinutes: 60
      QueuedTimeoutInMinutes: 480

  CodeBuildServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: codebuild.amazonaws.com
            Action:
              - "sts:AssumeRole"
      Policies:
        - PolicyName: CodeBuildAccess
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Resource: "*"
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
              - Effect: Allow
                Resource: "arn:aws:s3:::*"
                Action:
                  - s3:PutObject
                  - s3:GetObject
                  - s3:GetObjectVersion
                  - s3:GetBucketAcl
                  - s3:GetBucketLocation
              - Effect: Allow
                Resource: !Join
                  - ""
                  - - "arn:aws:codebuild:"
                    - !Ref AWS::Region
                    - ":"
                    - !Ref AWS::AccountId
                    - ":report-group/"
                    - !Ref SiteIdentifier
                    - "-prod-CacheClear"
                Action:
                  - codebuild:CreateReportGroup
                  - codebuild:CreateReport
                  - codebuild:UpdateReport
                  - codebuild:BatchPutTestCases
                  - codebuild:BatchPutCodeCoverages
              - Effect: Allow
                Resource: "*"
                Action:
                  - iam:*
              - Effect: Allow
                Resource:
                  - "*"
                Action:
                  - cloudfront:CreateInvalidation

  Pipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: !Sub ${SiteIdentifier}-prod-codepipeline
      RoleArn: !GetAtt CodePipelineServiceRole.Arn
      Stages:
        - Name: Source
          Actions:
            - Name: Source
              ActionTypeId:
                Category: Source
                Owner: AWS
                Provider: CodeCommit
                Version: 1
              Configuration:
                RepositoryName: !GetAtt CodeCommit.Name
                PollForSourceChanges: false
                BranchName: main
              RunOrder: 1
              OutputArtifacts:
                - Name: BuildArtifact
        - Name: "Deploy"
          Actions:
            - Name: "Deploy"
              ActionTypeId:
                Category: "Deploy"
                Owner: "AWS"
                Version: "1"
                Provider: "S3"
              Configuration:
                BucketName: !Ref AssetsBucketProd
                Extract: "true"
              RunOrder: 1
              InputArtifacts:
                - Name: "BuildArtifact"
        - Name: CacheClear
          Actions:
            - Name: CacheClear
              ActionTypeId:
                Category: Build
                Owner: AWS
                Version: 1
                Provider: CodeBuild
              Configuration:
                ProjectName: !Ref CodeBuildProjectCloudFrontCacheClearProd
              RunOrder: 1
              InputArtifacts:
                - Name: BuildArtifact
      ArtifactStore:
        Type: S3
        Location: !Ref ArtifactBucket

  CodePipelineServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: codepipeline.amazonaws.com
            Action:
              - "sts:AssumeRole"
      Policies:
        - PolicyName: PipelinePolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Resource:
                  - !Sub arn:aws:s3:::${ArtifactBucket}/*
                Action:
                  - s3:PutObject
                  - s3:GetObject
                  - s3:GetObjectVersion
                  - s3:GetBucketVersioning
              - Effect: Allow
                Resource: "*"
                Action:
                  - cloudformation:*
                  - codecommit:*
                  - codedeploy:*
                  - codebuild:*
                  - s3:*

  CodeBuildCWLogGroupDev:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub ${SiteIdentifier}-CodeBuild-dev

  AmazonCloudWatchEventRuleDev:
    Type: AWS::Events::Rule
    Properties:
      EventPattern:
        source:
          - aws.codecommit
        detail-type:
          - "CodeCommit Repository State Change"
        resources:
          - !Join [
              "",
              [
                "arn:aws:codecommit:",
                !Ref AWS::Region,
                ":",
                !Ref AWS::AccountId,
                ":",
                !GetAtt CodeCommit.Name,
              ],
            ]
        detail:
          event:
            - referenceCreated
            - referenceUpdated
          referenceType:
            - branch
          referenceName:
            - dev
      Targets:
        - Arn: !Join
            - ""
            - - "arn:aws:codepipeline:"
              - !Ref AWS::Region
              - ":"
              - !Ref AWS::AccountId
              - ":"
              - !Ref PipelineDev
          RoleArn: !GetAtt AmazonCloudWatchEventRoleDev.Arn
          Id: codepipeline-AppPipeline-Dev

  AmazonCloudWatchEventRoleDev:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - events.amazonaws.com
            Action:
              - "sts:AssumeRole"
      Path: /
      Policies:
        - PolicyName: cwe-pipeline-execution-dev
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: "codepipeline:StartPipelineExecution"
                Resource: !Join
                  - ""
                  - - "arn:aws:codepipeline:"
                    - !Ref AWS::Region
                    - ":"
                    - !Ref AWS::AccountId
                    - ":"
                    - !Ref PipelineDev

  CodeBuildProjectCloudFrontCacheClearDev:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: !Sub ${SiteIdentifier}-dev-CacheClear
      Artifacts:
        Type: CODEPIPELINE
      Source:
        Type: CODEPIPELINE
        BuildSpec: |
          version: 0.2
          phases:
            build:
              commands:
                - aws cloudfront create-invalidation --distribution-id $CloudFront_Distribution --paths "$CloudFront_Invalidation_Path" --region us-east-1
      Environment:
        Type: LINUX_CONTAINER
        Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0
        ComputeType: BUILD_GENERAL1_SMALL
        EnvironmentVariables:
          - Name: CloudFront_Distribution
            Type: PLAINTEXT
            Value: !GetAtt AssetsCloudFrontDistributionDev.Id
          - Name: CloudFront_Invalidation_Path
            Type: PLAINTEXT
            Value: !Ref CloudFrontInvalidationPath
      LogsConfig:
        CloudWatchLogs:
          GroupName: !Sub ${SiteIdentifier}-CodeBuild-dev
          Status: ENABLED
      ServiceRole: !Ref CodeBuildServiceRoleDev
      TimeoutInMinutes: 60
      QueuedTimeoutInMinutes: 480

  CodeBuildServiceRoleDev:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: codebuild.amazonaws.com
            Action:
              - "sts:AssumeRole"
      Policies:
        - PolicyName: CodeBuildAccessDev
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Resource: "*"
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
              - Effect: Allow
                Resource: "arn:aws:s3:::*"
                Action:
                  - s3:PutObject
                  - s3:GetObject
                  - s3:GetObjectVersion
                  - s3:GetBucketAcl
                  - s3:GetBucketLocation
              - Effect: Allow
                Resource: !Join
                  - ""
                  - - "arn:aws:codebuild:"
                    - !Ref AWS::Region
                    - ":"
                    - !Ref AWS::AccountId
                    - ":report-group/"
                    - !Ref SiteIdentifier
                    - "-dev-CacheClear"
                Action:
                  - codebuild:CreateReportGroup
                  - codebuild:CreateReport
                  - codebuild:UpdateReport
                  - codebuild:BatchPutTestCases
                  - codebuild:BatchPutCodeCoverages
              - Effect: Allow
                Resource: "*"
                Action:
                  - iam:*
              - Effect: Allow
                Resource:
                  - "*"
                Action:
                  - cloudfront:CreateInvalidation

  PipelineDev:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: !Sub ${SiteIdentifier}-dev-codepipeline
      RoleArn: !GetAtt CodePipelineServiceRoleDev.Arn
      Stages:
        - Name: Source
          Actions:
            - Name: Source
              ActionTypeId:
                Category: Source
                Owner: AWS
                Provider: CodeCommit
                Version: 1
              Configuration:
                RepositoryName: !GetAtt CodeCommit.Name
                PollForSourceChanges: false
                BranchName: dev
              RunOrder: 1
              OutputArtifacts:
                - Name: BuildArtifact
        - Name: "Deploy"
          Actions:
            - Name: "Deploy"
              ActionTypeId:
                Category: "Deploy"
                Owner: "AWS"
                Version: "1"
                Provider: "S3"
              Configuration:
                BucketName: !Ref AssetsBucketDev
                Extract: "true"
              RunOrder: 1
              InputArtifacts:
                - Name: "BuildArtifact"
        - Name: CacheClear
          Actions:
            - Name: CacheClear
              ActionTypeId:
                Category: Build
                Owner: AWS
                Version: 1
                Provider: CodeBuild
              Configuration:
                ProjectName: !Ref CodeBuildProjectCloudFrontCacheClearDev
              RunOrder: 1
              InputArtifacts:
                - Name: BuildArtifact
      ArtifactStore:
        Type: S3
        Location: !Ref ArtifactBucket

  CodePipelineServiceRoleDev:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: codepipeline.amazonaws.com
            Action:
              - "sts:AssumeRole"
      Policies:
        - PolicyName: PipelinePolicyDev
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Resource:
                  - !Sub arn:aws:s3:::${ArtifactBucket}/*
                Action:
                  - s3:PutObject
                  - s3:GetObject
                  - s3:GetObjectVersion
                  - s3:GetBucketVersioning
              - Effect: Allow
                Resource: "*"
                Action:
                  - cloudformation:*
                  - codecommit:*
                  - codedeploy:*
                  - codebuild:*
                  - s3:*

  ArtifactBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub ${SiteIdentifier}-artifact-bucket
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True

  IAMUserForGit:
    Type: AWS::IAM::User
    Properties:
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AWSCodeCommitFullAccess
        - arn:aws:iam::aws:policy/ReadOnlyAccess
      Policies:
        - PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Deny
                Action:
                  - codecommit:GitPush
                  - codecommit:DeleteBranch
                  - codecommit:PutFile
                  - codecommit:CreateCommit
                  - codecommit:MergeBranchesByFastForward
                  - codecommit:MergeBranchesBySquash
                  - codecommit:MergeBranchesByThreeWay
                  - codecommit:MergePullRequestByFastForward
                  - codecommit:MergePullRequestBySquash
                Resource: "*"
                Condition:
                  StringEqualsIfExists:
                    codecommit:References:
                      - refs/heads/main
                  "Null":
                    codecommit:References:
                      - false
          PolicyName: DenyCommit
      UserName: !Sub ${SiteIdentifier}-Developer


テンプレートの利用方法

バージニア北部リージョン(us-east-1)でCloudFormationコンソールから上記テンプレートをアップロードし、下記パラメータを入力し、実行することで構築が完了します。

  • SiteNameProd
    構築対象の本番サイトの名前を入力します。本番用S3バケット、CloudFrontのCommentなどで利用されます。
    主に識別子としての役割になるので、S3バケットの命名規則に準じていれば任意の値で問題ありません。

  • SiteNameDev
    構築対象の開発サイトの名前を入力します。開発用S3バケット、CloudFrontのCommentなどで利用されます。
    主に識別子としての役割になるので、S3バケットの命名規則に準じていれば任意の値で問題ありません。

  • SiteIdentifier
    CI/CD関連リソースの命名に利用される値です。他リソースや名前との兼ね合いからアンダースコアではなくハイフンを使うことを推奨します。

  • CloudFrontInvalidationPath
    デフォルトのままで実行します。

稼働確認

実運用とCI/CDパイプラインが動作する様子を簡単にデモします。

事前準備

事前にこういったサイトをCI/CDパイプラインを使って初回デプロイをしておきます。

【初回デプロイ手順】
1. 作成したCodeCommitでdev、mainブランチを作成
2. 任意のhtmlを「index.html」という名前でアップロード
3. 自動デプロイが開始、1~2分以内に反映される

【サイトへの接続】
対象のCloudFront「ディストリビューションドメイン名」をURLとして入力すると、構築したサイトへ接続できます。

実行準備が整ったので、実際に一部を変更し、CI/CDパイプラインを実行します。

稼働確認

1. ソースの変更

今回は、元々「Technology Event 2023」となっていた部分を「Techblog Test Event 2023」と変更します。
CodeCommitからローカルに取得したソースを変更します。

【変更前】

【変更後】

ソース変更後に、「20231215-title-change」という名前で新たなブランチを作成しました。

2. devブランチへ変更をマージ

新規作成した「20231215-title-change」から「dev」ブランチへプルリクエストを作成し、マージします。

3. パイプラインの実行が開始される

4. パイプラインが完了後、開発環境サイトへアクセスする

開発環境へは、変更が適応されていることが確認できました!

「main」ブランチは変更していないため、本番環境サイトは変更前の状態でした!

まとめ

本記事では、CloudFront + S3でホストする静的サイト環境とCI/CDパイプラインの環境概要や設定とそれらを構築するためのCloudFormationテンプレートをご紹介しました。誰がどういった変更を加えた、という情報を素早く把握できるうえ、セキュアなデプロイを実現できるため、開発/本番環境の構築やCI/CDの構築は非常に大切です。今回ご紹介したテンプレートを活用して、CI/CDパイプライン構築のハードルが少しでも下がればとてもうれしいです!!

テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!

フクナガ

インフラエンジニア歴5年のフクナガです。2024 Japan AWS Top Engineers / Google Cloud Partner Top Engineer 2025 に選出されました! 生成 AI 多めで発信していますが、CI/CDやIaCへの関心も高いです。休日はベースを弾いてます。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら