【CloudFormation】S3をデプロイしてみる
1. はじめに
はじめまして、Mitsuoです。
Zennでアカウントを作成し、初めて技術ブログを投稿します。
お手柔らかにお願いします。
2. 今回のお題
CloudFormationを用いてS3バケットをデプロイしてみました。
S3バケットの作成自体は簡単ですが、何回も利用するサービスですし、他サービスと比べても機能が豊富なので、手動で作成するのは中々面倒だと思います。
そこで、ある程度標準化する為に雛形のテンプレートを作ったいう訳です。
ありふれた物かもしれませんが、自分用でもあるので、一石二鳥ということで。
3. 作成したリソース
テンプレートで作成するリソースは以下の通りです。
- S3バケット4つ
- バケットポリシー4つ
S3バケットを2つ、それらのアクセスログ用のバケットが2つで計4つ作成します。
加えて、バケット用にバケットポリシーを設定します。
4. テンプレート
作成したテンプレートになります。
AWSTemplateFormatVersion: '2010-09-09'
Description: Deploy S3 Buckets with Bucket policies.
# ------------------------------------------------------------#
# Prerequisite:
# This template is for deploying four Buckets(S3) with Bucket policies.
# Two of them are for collecting log datas from 2 buckets.
# Additionally, this template is intended to simplify the creation of versatile buckets.
# If you use this template in an actual project and encounter any problems, we take no responsibility in regards to that.
# But you notice the problems about this template, please let me know what needs to correct.I will modify them you point out.
# ------------------------------------------------------------#
# Metadata:
# This can provide details about the template.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html.
# As Metadata Keys, AWS::CloudFormation::Interface can define the grouping and ordering of input parameters
# when they are displayed in the AWS CloudFormation console.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-interface.html.
# ------------------------------------------------------------#
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
-
Parameters:
- ProjectName
- EnvType
- Tagprefix
- Owner
ParameterLabels:
ProjectName:
default: "Please type your project Name you would like to name"
EnvType:
default: "Please select which environment you would like to deploy buckets in from among dev, stg and prod."
Tagprefix:
default: "Please type the prefix you would like to add as logical unit name about each resource(e.g. webserver,monitoring,logging)"
Owner:
default: "Please type who owns these resources (e.g. project name, worker or for cost management)"
# ------------------------------------------------------------#
# Parameters
# This Can enable templates to input custom values each time you create or update a stack.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html.
# ------------------------------------------------------------#
Parameters:
ProjectName:
Type: String
EnvType:
Type: String
Default: "dev"
AllowedValues:
- dev
- stg
- prod
Tagprefix:
Type: String
Owner:
Type: String
# ------------------------------------------------------------#
# Resources
# This can declare the AWS resources that you want to include in the stack.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html.
# ------------------------------------------------------------#
Resources:
# ------------------------------------------------------------#
# Create S3 Bucket 1
# ------------------------------------------------------------#
S3Bucket1:
Type: 'AWS::S3::Bucket'
DeletionPolicy: Retain
Properties:
BucketName: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-s3bucket1-${AWS::AccountId}
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
VersioningConfiguration:
Status: Suspended
LoggingConfiguration:
DestinationBucketName: !Ref S3Bucket3
LogFilePrefix: AccessLog/
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
LifecycleConfiguration:
Rules:
- Id: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-Lifecycle-s3bucket1
Status: Enabled
ExpirationInDays: 30
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
NotificationConfiguration:
EventBridgeConfiguration:
EventBridgeEnabled: true
Tags:
- Key: Name
Value: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-s3bucket1-${AWS::AccountId}
- Key: Owner
Value: !Sub ${Owner}
DependsOn: S3Bucket3
# ------------------------------------------------------------#
# Create S3 Bucket 2
# ------------------------------------------------------------#
S3Bucket2:
Type: 'AWS::S3::Bucket'
DeletionPolicy: Retain
Properties:
BucketName: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-s3bucket2-${AWS::AccountId}
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
VersioningConfiguration:
Status: Enabled
LoggingConfiguration:
DestinationBucketName: !Ref S3Bucket4
LogFilePrefix: AccessLog/
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
LifecycleConfiguration:
Rules:
- Id: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-Lifecycle-s3bucket2
Status: Enabled
ExpirationInDays: 365
Transitions:
- StorageClass: GLACIER
TransitionInDays: 30
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
NotificationConfiguration:
EventBridgeConfiguration:
EventBridgeEnabled: true
Tags:
- Key: Name
Value: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-s3bucket2-${AWS::AccountId}
- Key: Owner
Value: !Sub ${Owner}
DependsOn: S3Bucket4
# ------------------------------------------------------------#
# Create S3 Bucket 3 for collecting access log from S3 Bucket 1
# ------------------------------------------------------------#
S3Bucket3:
Type: 'AWS::S3::Bucket'
DeletionPolicy: Retain
Properties:
BucketName: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-s3bucket3-${AWS::AccountId}
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
VersioningConfiguration:
Status: Suspended
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
NotificationConfiguration:
EventBridgeConfiguration:
EventBridgeEnabled: true
LifecycleConfiguration:
Rules:
- Id: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-Lifecycle-s3bucket3
Status: Enabled
ExpirationInDays: 30
Tags:
- Key: Name
Value: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-s3bucket3-${AWS::AccountId}
- Key: Owner
Value: !Sub ${Owner}
# ------------------------------------------------------------#
# Create S3 Bucket 4 for collecting access log from S3 Bucket 2
# ------------------------------------------------------------#
S3Bucket4:
Type: 'AWS::S3::Bucket'
DeletionPolicy: Retain
Properties:
BucketName: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-s3bucket4-${AWS::AccountId}
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
VersioningConfiguration:
Status: Suspended
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
NotificationConfiguration:
EventBridgeConfiguration:
EventBridgeEnabled: true
LifecycleConfiguration:
Rules:
- Id: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-Lifecycle-s3bucket4
Status: Enabled
ExpirationInDays: 30
Tags:
- Key: Name
Value: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-s3bucket4-${AWS::AccountId}
- Key: Owner
Value: !Sub ${Owner}
# ------------------------------------------------------------#
# Create S3 Bucket Policy
# ------------------------------------------------------------#
BucketPolicy1:
Type: 'AWS::S3::BucketPolicy'
Properties:
Bucket: !Ref S3Bucket1
PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- 's3:*'
Sid: BucketPolicy1
Effect: Allow
Resource:
- !Sub 'arn:aws:s3:::${S3Bucket1}'
- !Sub 'arn:aws:s3:::${S3Bucket1}/*'
Principal:
AWS:
- !Sub 'arn:aws:iam::${AWS::AccountId}:root'
DependsOn: S3Bucket1
BucketPolicy2:
Type: 'AWS::S3::BucketPolicy'
Properties:
Bucket: !Ref S3Bucket2
PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- 's3:*'
Sid: BucketPolicy2
Effect: Allow
Resource:
- !Sub 'arn:aws:s3:::${S3Bucket2}'
- !Sub 'arn:aws:s3:::${S3Bucket2}/*'
Principal:
AWS:
- !Sub 'arn:aws:iam::${AWS::AccountId}:root'
DependsOn: S3Bucket2
BucketPolicy3:
Type: 'AWS::S3::BucketPolicy'
Properties:
Bucket: !Ref S3Bucket3
PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- 's3:PutObject'
Sid: BucketPolicy3
Effect: Allow
Resource:
- !Sub 'arn:aws:s3:::${S3Bucket3}'
- !Sub 'arn:aws:s3:::${S3Bucket3}/*'
Principal:
Service: logging.s3.amazonaws.com
DependsOn: S3Bucket3
BucketPolicy4:
Type: 'AWS::S3::BucketPolicy'
Properties:
Bucket: !Ref S3Bucket4
PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- 's3:PutObject'
Sid: BucketPolicy4
Effect: Allow
Resource:
- !Sub 'arn:aws:s3:::${S3Bucket4}'
- !Sub 'arn:aws:s3:::${S3Bucket4}/*'
Principal:
Service: logging.s3.amazonaws.com
DependsOn: S3Bucket4
# ------------------------------------------------------------#
# Outputs
# This can output each value specified as output section.
# For more information, see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html.
# ------------------------------------------------------------#
Outputs:
S3Bucket1:
Description: S3Bucket1
Value: !Ref S3Bucket1
S3Bucket2:
Description: S3Bucket2
Value: !Ref S3Bucket2
S3Bucket3:
Description: S3Bucket3
Value: !Ref S3Bucket3
S3Bucket4:
Description: S3Bucket4
Value: !Ref S3Bucket4
5. テンプレートの補足
テンプレートに関して、以下の通り補足します。
5.1 Metadata/Parameters
メタデータおよびパラメターセクションで、4つの値を定義します。
項目 | 備考 |
---|---|
ProjectName |
プロジェクト名や利用目的等を入力する |
EnvType |
デプロイする環境を選択する 検証、ステージング、本番の3点 |
Tagprefix |
任意で入力するPrefix値 |
Owner |
作業者、所有者、コスト管理用に入力する |
バケット名およびバケットのNameタグの値に、ProjectName
、EnvType
、Tagprefix
の3点が含みます。
Owner
はOwnerタグの値に利用します。
5.2 Resources (Type: 'AWS::S3::Bucket')
リソースセクションで以下の用に定義しています。
具体的なプロパティに解説は公式ドキュメントを参照ください。
5.2.1 S3Bucket1
- パブリックアクセスの無効化
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
- バージョニング設定の無効化
VersioningConfiguration:
Status: Suspended
- S3アクセスログ設定
バケット直下にAccessLogフォルダを切ってその下にログを格納します。
LoggingConfiguration:
DestinationBucketName: !Ref S3Bucket3
LogFilePrefix: AccessLog/
- 暗号化設定
S3のサーバサイド暗号化を設定します。KMSにする事も可能です。
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
- ライフサイクル設定
30日後にオブジェクトを削除します。
LifecycleConfiguration:
Rules:
- Id: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-Lifecycle-s3bucket1
Status: Enabled
ExpirationInDays: 30
- ACL設定
ACLは無効、バケットポリシーで制御する想定です。
全てのオブジェクトにおける所有者を「バケットを所有しているアカウント」にしています。
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
- 通知設定
S3からEventBridgeへの連携を有効化しています。
NotificationConfiguration:
EventBridgeConfiguration:
EventBridgeEnabled: true
- タグ設定
Tags:
- Key: Name
Value: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-s3bucket1-${AWS::AccountId}
- Key: Owner
Value: !Sub ${Owner}
5.2.2 S3Bucket2
他のリソースとの差異がある箇所のみ補足します。
- バージョニングの有効化
Enabled
が有効化、Suspended
が無効化です。
VersioningConfiguration:
Status: Enabled
- ライフサイクル設定
365日後にオブジェクトを削除します。
ストレージクラスの変更もTransitions
で指定可能です。
30日後に、Glacier Flexible Retrievalにデータを移行します。
LifecycleConfiguration:
Rules:
- Id: !Sub ${ProjectName}-${EnvType}-${Tagprefix}-Lifecycle-s3bucket2
Status: Enabled
ExpirationInDays: 365
Transitions:
- StorageClass: GLACIER
TransitionInDays: 30
5.2.3 S3Bucket3/4
アクセスログの設定は無効化
5.3 Resources (AWS::S3::BucketPolicy)
リソースセクションで以下の用に定義しています。
具体的なプロパティに解説は公式ドキュメントを参照ください。
5.3.1 BucketPolicy1
ルートユーザによるS3Bucket1のみS3の全てのアクションを許可する設定です。
実際に利用する際には、適切な権限付与をおこなってください。
パブリックアクセスが無効化されている場合に、Principalが*
の場合は、
エラーになるので注意してください。
BucketPolicy2の補足事項は特に無いです。
PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- 's3:*'
Sid: BucketPolicy1
Effect: Allow
Resource:
- !Sub 'arn:aws:s3:::${S3Bucket1}'
- !Sub 'arn:aws:s3:::${S3Bucket1}/*'
Principal:
AWS:
- !Sub 'arn:aws:iam::${AWS::AccountId}:root'
5.3.2 BucketPolicy3
サービスにlogging.s3.amazonaws.com
を指定する事で、アクセスログ機能に必要な、
S3Bucket3に対するPutObjectアクションを許可しています。
実際に利用する際には、適切な権限付与をおこなってください。
BucketPolicy4の補足事項は特に無いです。
PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- 's3:PutObject'
Sid: BucketPolicy3
Effect: Allow
Resource:
- !Sub 'arn:aws:s3:::${S3Bucket3}'
- !Sub 'arn:aws:s3:::${S3Bucket3}/*'
Principal:
Service: logging.s3.amazonaws.com
5.4 Outputs
各バケットの値を出力します。
Outputs:
S3Bucket1:
Description: S3Bucket1
Value: !Ref S3Bucket1
S3Bucket2:
Description: S3Bucket2
Value: !Ref S3Bucket2
S3Bucket3:
Description: S3Bucket3
Value: !Ref S3Bucket3
S3Bucket4:
Description: S3Bucket4
Value: !Ref S3Bucket4
5.5 その他
-
S3バケットの
DeletionPolicy
をRetainにしています- オブジェクトが存在すると削除出来ない事と、バケットが気付かない内に削除されるケースを懸念して、手動で削除する様にしています
-
DependsOn
の設定をおこなっています- バケット1、バケット2はそれぞれアクセスログ用のバケットが作成されていないと、
エラーが発生する為、DependsOn
の設定をそれぞれ行っています - バケットポリシーも同様に設定しています
- バケットを作成した後にバケットポリシーを作成しています
- バケット1、バケット2はそれぞれアクセスログ用のバケットが作成されていないと、
6. まとめ
ありきたりなテンプレートかもしれませんが、工数削減に助力できるバケットになってくれれば嬉しいです。
また書きます。Mitsuoでした!
Discussion