目次

前回の振り返り
構成イメージ
大阪リージョン用テンプレート
itport-s3-osaka.yaml
東京リージョン用テンプレート
itport-s3-tokyo.yaml
確認
おわりに

前回の振り返り

前回まではVPCやEC2の起動をCloud Formationを使って構築してみました。今回はS3バケットをCloud Formationを使用して構築します。

構成イメージ

Amzon S3の標準ストレージは 99.999999999 %(9 × 11)の堅牢性があると言われております。
1つのリージョンで使用するだけでもハード障害によるデータのロストは心配いらないように思いますが、ビジネス要件によっては遠隔地へのバックアップやオペレーションミス等によるデータロストに備えるといった事も出てくるかもしれません。
今回は2つのバケットを作成しクロスリージョンレプリケーション(CRR)をする構成をCloud Formationで実現してみたいと思います。

構成イメージ
  • クロスリージョンレプリケーション(東京→大阪)
  • オブジェクトのバージョニングを有効
  • 過去バージョンのオブジェクトは180日経過でスタンダードIAクラスへ変更
  • S3のデフォルト暗号化を有効化

という4点を盛り込んでいきたいと思います。

大阪リージョン用テンプレート

Cloud Formationのスタックは作成するリソースのリージョンと同じリージョンでスタックを実行する必要があります。まずは大阪リージョンでバックアップストレージ用S3を作成します。

itport-s3-osaka.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
AWSTemplateFormatVersion: "2010-09-09"
Description:
  Create S3 bucket in Osaka Region
 
Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          Default: "Project Name Prefix"
        Parameters:
          - PJPrefix
      - Label:
          Default: "Group Name"
        Parameters:
          - Group
      - Label:
          Default: "Environment"
        Parameters:
          - Environment
 
    ParameterLabels:
      PJPrefix:
        default: "Project Name Prefix"
      Group:
        default: "Group Tag Value"
      Environment:
        default: "Environment Tag Value"
 
# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
Parameters:
  PJPrefix:
    Type: String
    Default: "itport"
  Group:
    Type: String
    Default: "itport"
  Environment:
    Type: String
    AllowedValues:
      - development
      - production
 
  # バケット名
  BucketName:
    Type: String
    Default: "itport-osaka"
 
Resources:
# ------------------------------------------------------------#
# S3 Bucket
# ------------------------------------------------------------#
  # 大阪リージョン(DR用)
  S3Bucket:
    Type: "AWS::S3::Bucket"
    # CFnスタック削除時のポリシー (Retain = 保持)
    DeletionPolicy: Retain
    # CFnスタック更新時のポリシー (Retain = 保持)
    UpdateReplacePolicy: Retain
    Properties:
      # バケット名
      BucketName: !Sub ${BucketName}
      # バージョニング
      VersioningConfiguration:
        Status: Enabled
      # バケットACL
      AccessControl: BucketOwnerFullControl
      # 暗号化
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      # パブリックアクセスブロック
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      # ライフサイクル
      LifecycleConfiguration:
        Rules:
          - Id: !Join ['-', [!Sub '${BucketName}', 'Contents-LifeCycle']]
            Status: Enabled
            # バージョニングされているデータは180日経過したらスタンダードIAに移行する
            NoncurrentVersionTransition:
              StorageClass: STANDARD_IA
              TransitionInDays: 180
      # タグ
      Tags:
        - Key: "Name"
          Value: !Sub ${BucketName}
        - Key: "Group"
          Value: !Ref Group
        - Key: "Environment"
          Value: !Ref Environment
 
  # バケットポリシー(大阪用)
  BucketPolicy:
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Statement:
          - Sid: "DenyIncorrectEncryptionHeader"
            Action:
              - "s3:PutObject"
            Effect: "Deny"
            Principal: "*"
            Resource: !Sub "arn:aws:s3:::${BucketName}/*"
            Condition:
              "StringNotEquals":
                "s3:x-amz-server-side-encryption": "AES256"
          - Sid: "DenyUnencryptedObjectUploads"
            Action:
              - "s3:PutObject"
            Effect: "Deny"
            Principal: "*"
            Resource: !Sub "arn:aws:s3:::${BucketName}/*"
            Condition:
              "Null":
                "s3:x-amz-server-side-encryption": "true"

作成したyamlファイルからスタックを作成します。

Cloud Formation「スタックの作成」画面

東京リージョン用テンプレート

続いて東京リージョンに移動してスタックを作成します。今回のスタックではバケットを作成する以外にIAM Roleなども作成します。

itport-s3-tokyo.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
AWSTemplateFormatVersion: "2010-09-09"
Description:
  Create S3 Bucket in Tokyo Region
 
Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          Default: "Project Name Prefix"
        Parameters:
          - PJPrefix
      - Label:
          Default: "Group Name"
        Parameters:
          - Group
      - Label:
          Default: "Environment"
        Parameters:
          - Environment
 
    ParameterLabels:
      PJPrefix:
        default: "Project Name Prefix"
      Group:
        default: "Group Tag Value"
      Environment:
        default: "Environment Tag Value"
 
# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
Parameters:
  PJPrefix:
    Type: String
    Default: "itport"
  Group:
    Type: String
    Default: "itport"
  Environment:
    Type: String
    AllowedValues:
      - development
      - production
 
  # バケット名
  BucketName:
    Type: String
    Default: "itport-tokyo"
 
  # バックアップバケット名(完全なバケット名)
  BackupBucketName:
    Type: String
    Default: "itport-osaka"
 
Resources:
# ------------------------------------------------------------#
# IAM Role
# ------------------------------------------------------------#
  WorkItemBucketBackupRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - s3.amazonaws.com
      # ポリシー
      Policies:
        - PolicyName: S3Replication
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - s3:GetReplicationConfiguration
                  - s3:ListBucket
                Resource:
                  - !Sub "arn:aws:s3:::${BucketName}"
                  - !Sub "arn:aws:s3:::${BackupBucketName}"
              - Effect: Allow
                Action:
                  - s3:GetObjectVersion
                  - s3:GetObjectVersionAcl
                  - s3:GetObjectVersionTagging
                Resource:
                  - !Sub "arn:aws:s3:::${BucketName}/*"
                  - !Sub "arn:aws:s3:::${BackupBucketName}/*"
              - Effect: Allow
                Action:
                  - s3:ReplicateObject
                  - s3:ReplicateDelete
                  - s3:ReplicateTags
                Resource:
                  - !Sub "arn:aws:s3:::${BucketName}/*"
                  - !Sub "arn:aws:s3:::${BackupBucketName}/*"
      # タグ
      Tags:
        - Key: "Name"
          Value: !Sub ${PJPrefix}-s3-backup-role
        - Key: "Group"
          Value: !Ref Group
        - Key: "Environment"
          Value: !Ref Environment
 
# ------------------------------------------------------------#
# S3 Bucket
# ------------------------------------------------------------#
  # 東京リージョン(メイン)
  S3Bucket:
    Type: "AWS::S3::Bucket"
    # CFnスタック削除時のポリシー (Retain = 保持)
    DeletionPolicy: Retain
    # CFnスタック更新時のポリシー (Retain = 保持)
    UpdateReplacePolicy: Retain
    Properties:
      # バケット名
      BucketName: !Sub ${BucketName}
      # レプリケーション (東京リージョンのみ)
      ReplicationConfiguration:
        Role: !GetAtt
          - WorkItemBucketBackupRole
          - Arn
        Rules:
          - Destination:
              Bucket: !Sub arn:aws:s3:::${BackupBucketName}
              StorageClass: STANDARD
            Id: Backup
            Prefix: ''
            Status: Enabled
      # バージョニング
      VersioningConfiguration:
        Status: Enabled
      # バケットACL
      AccessControl: BucketOwnerFullControl
      # 暗号化
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      # パブリックアクセスブロック
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      # ライフサイクル
      LifecycleConfiguration:
        Rules:
          - Id: !Join ['-', [!Sub '${BucketName}', 'Contents-LifeCycle']]
            Status: Enabled
            # バージョニングされているデータは180日経過したらスタンダードIAに移行する
            NoncurrentVersionTransition:
              StorageClass: STANDARD_IA
              TransitionInDays: 180
      # タグ
      Tags:
        - Key: "Name"
          Value: !Sub ${BucketName}
        - Key: "Group"
          Value: !Ref Group
        - Key: "Environment"
          Value: !Ref Environment
 
  # バケットポリシー(東京用)
  BucketPolicy:
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Statement:
          - Sid: "DenyIncorrectEncryptionHeader"
            Action:
              - "s3:PutObject"
            Effect: "Deny"
            Principal: "*"
            Resource: !Sub "arn:aws:s3:::${BucketName}/*"
            Condition:
              "StringNotEquals":
                "s3:x-amz-server-side-encryption": "AES256"
          - Sid: "DenyUnencryptedObjectUploads"
            Action:
              - "s3:PutObject"
            Effect: "Deny"
            Principal: "*"
            Resource: !Sub "arn:aws:s3:::${BucketName}/*"
            Condition:
              "Null":
                "s3:x-amz-server-side-encryption": "true"

確認

東京リージョンのバケットにファイルをアップロードすると大阪リージョンのバケットにもファイルがコピーされました。

Amazon S3「itport-osaka」バケットの状況

おわりに

別リージョンへのレプリケーション設定がテンプレートを使用することで比較的簡単に出来るようになりました。S3のレプリケーションはバックアップ目的で利用することがほとんどかと思います。今回は削除は同期されませんが、削除マーカーのレプリケーションも可能です。要件によってカスタマイズして使っていきたいと思います。

削除マーカーのレプリケーション設定は「AWS::S3::Bucket DeleteMarkerReplication」をご参照ください。