AWS CloudFormation で S3 バケットを作成してみた

AWS CloudFormation から Amazon S3 バケットを作成する手順と要点についてまとめました。 また、作成時はコンソールからではなく AWS CLI から行っていきたいと思います。
2023.10.31

はじめに

おばんです!

データアナリティクス事業本部ビジネスソリューション部の大谷(おおや)です。

今回は、AWS CloudFormation テンプレートを作成し、 Amazon S3 バケットを作成したので要点をまとめてみました。

また、 AWS CLI を使用してスタックを作成したことがなかったので、こちらも試してみました。

環境

  • AWS CLI: v2.13.28
  • テンプレートファイル形式: YAML

AWS CloudFormation テンプレート

今回作成したテンプレートは下記の通りです。

セクションごとに要点をまとめていきます。

Parameters:
  ProjectName:
    Description: "Enter the name of your project"
    Type: String
    AllowedPattern: "^[a-z0-9][a-z0-9\\-]{0,51}$"
    ConstraintDescription: "Must be a string of 1 to 51 characters containing only lowercase letters, numbers and hyphens (-)"
    Default: "oya-s3-sample"

  Stage:
    Description: "Select stage type from dev, stg, prod"
    Type: String
    AllowedValues:
      - dev
      - stg
      - prod
    Default: "dev"

Resources:
  SampleBucket:
    Type: "AWS::S3::Bucket"
    DeletionPolicy: Delete
    Properties:
      BucketName: !Sub ${ProjectName}-sample-${Stage}
      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerEnforced
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
  SampleBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref SampleBucket
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: AllowSSLRequestsOnly
            Action: "s3:*"
            Effect: Deny
            Resource:
              - !Sub "arn:${AWS::Partition}:s3:::${SampleBucket}"
              - !Sub "arn:${AWS::Partition}:s3:::${SampleBucket}/*"
            Condition:
              Bool:
                "aws:SecureTransport": false
            Principal: "*"

Outputs:
  SampleBucket:
    Value: !Ref SampleBucket
    Description: "Name of SampleBucket"
    Export:
      Name: !Sub ${AWS::StackName}-SampleBucket

Parameters セクション

Parametersセクションを記述することで、スタックの作成時や更新時にカスタム値を入力できるようになります。

また、Defaultプロパティを記述することでデフォルトのカスタム値を指定できます。

Parameters:
  ProjectName:
    Description: "Enter the name of your project"
    Type: String
    AllowedPattern: "^[a-z0-9][a-z0-9\\-]{0,51}$"
    ConstraintDescription: "Must be a string of 1 to 51 characters containing only lowercase letters, numbers and hyphens (-)"
    Default: "oya-s3-sample"

  Stage:
    Description: "Select stage type from dev, stg, prod"
    Type: String
    AllowedValues:
      - dev
      - stg
      - prod
    Default: "dev"

要点1: 今回ProjectNameパラメータは Amazon S3 のバケット名にも使用するため、下記ドキュメントに従い、AllowedPatternプロパティによって一部使用できる文字や文字数に制限をかけています。

要点2: Stageパラメータでは使用したい値が任意の個数で定まっているため、AllowValuesプロパティによって選択肢を記述しています。

Resources セクション

バケット作成

要点3から要点5に関しては、 デフォルトで有効化されている設定がほとんどですが、今後デフォルト値が変わることで、作成時と意図が変わる可能性を抑えるため、明示的に設定しています。

Resources:
  SampleBucket:
    Type: "AWS::S3::Bucket"
    DeletionPolicy: Delete
    Properties:
      BucketName: !Sub ${ProjectName}-sample-${Stage}
      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerEnforced
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256

要点3: アクセスコントロールリストは無効化し、バケットポリシーやユーザーポリシーを使用してアクセスの管理を行います

      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerEnforced

要点4: パブリックアクセスブロックを明示的に有効化し、バケット内データへのパブリックアクセスを拒否します。

      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

要点5: 保管時のデータ暗号化として、S3のデフォルト暗号化を明示的に有効化します。

      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256

バケットポリシー適用

要点6: バケットポリシーを使用して HTTPS(TLS) 経由での暗号化された接続のみを許可します

  SampleBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref SampleBucket
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: AllowSSLRequestsOnly
            Action: "s3:*"
            Effect: Deny
            Resource:
              - !Sub "arn:${AWS::Partition}:s3:::${SampleBucket}"
              - !Sub "arn:${AWS::Partition}:s3:::${SampleBucket}/*"
            Condition:
              Bool:
                "aws:SecureTransport": false
            Principal: "*"

Outputs セクション

他の CloudForamtion スタックや Serverless Framework プロジェクトなどで今回作成したバケットを使用したいケースが出てくる場合があります。

その際にバケット名などを参照しやすくするために、 Outputs セクションで出力値を宣言します

Outputs:
  SampleBucket:
    Value: !Ref SampleBucket
    Description: "Name of SampleBucket"
    Export:
      Name: !Sub ${AWS::StackName}-SampleBucket

要点7: Exportフィールドの値はアカウントごとにリージョン内で一意にする

上記に関しては、制限なので、一意でない場合作成に失敗します。

また、別のスタックが出力を参照している時、スタックを削除したり、その出力値を変更・削除することはできないため注意してください。

AWS CLI によるデプロイ

それでは、作成したテンプレートファイルS3.ymlと AWS CLI を使用して実際に S3 バケットを作成します。

create-stackまたはdeployコマンドによってスタックを作成することができます。

今回は、スタックの更新時にも同じコマンドが使用でき、作成過程を出力してくれるためdeployコマンドを使用します。

aws cloudformation deploy \
--stack-name oya-s3-sample-dev \
--template-file S3.yml \

※ パラメータの値にデフォルト値以外を設定したい場合は、--parameter-overrides <パラメータ名>=<値>とする事で設定可能です。

おわりに

今回は CloudFormation でひとつの S3 バケットを作成する形のご紹介でしたが、複数のバケットの作成をまとめて行う場面や、頻繁に同じ内容のバケットを作成する場面などに CloudFormation の力が特に発揮されると思います。

上記のような場面では、CloudFormation を使用したバケット作成を検討してみてください。

また、AWS CLI を使用して CloudFormation スタックを作成する場合、慣れないうちは大変かもしれませんが、コマンドの各種パラメータがわかってくると、コンソール画面から操作する場合に比べ手順が少ないため、手軽に作成することができるのが利点だと思います。