Skip to content

Commit 6613d91

Browse files
authored
Adding supporting for s3 bucket replication (#66)
1 parent 849a55c commit 6613d91

File tree

6 files changed

+157
-12
lines changed

6 files changed

+157
-12
lines changed

README.md

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,13 @@ Follow this procedure just once to create your deployment.
9494
# be bootstrapped according to the simple yet essential procedure in
9595
# https://github.com/cloudposse/terraform-aws-tfstate-backend#usage
9696
module "terraform_state_backend" {
97-
source = "git::https://github.com/cloudposse/terraform-aws-tfstate-backend.git?ref=master"
98-
namespace = "eg"
99-
stage = "test"
100-
name = "terraform"
101-
attributes = ["state"]
102-
region = "us-east-1"
97+
source = "git::https://github.com/cloudposse/terraform-aws-tfstate-backend.git?ref=master"
98+
namespace = "eg"
99+
stage = "test"
100+
name = "terraform"
101+
attributes = ["state"]
102+
region = "us-east-1"
103+
103104
terraform_backend_config_file_path = "."
104105
terraform_backend_config_file_name = "backend.tf"
105106
force_destroy = false
@@ -174,6 +175,28 @@ Follow this procedure to delete your deployment.
174175
175176
![s3-bucket-with-terraform-state](images/s3-bucket-with-terraform-state.png)
176177
178+
### Bucket Replication (Disaster Recovery)
179+
180+
To enable S3 bucket replication in this module, set `s3_replication_enabled` to `true` and populate `s3_replica_bucket_arn` with the ARN of an existing bucket.
181+
182+
```hcl
183+
module "terraform_state_backend" {
184+
source = "git::https://github.com/cloudposse/terraform-aws-tfstate-backend.git?ref=master"
185+
namespace = "eg"
186+
stage = "test"
187+
name = "terraform"
188+
attributes = ["state"]
189+
region = "us-east-1"
190+
191+
terraform_backend_config_file_path = "."
192+
terraform_backend_config_file_name = "backend.tf"
193+
force_destroy = false
194+
195+
s3_replication_enabled = true
196+
s3_replica_bucket_arn = "arn:aws:s3:::eg-test-terraform-tfstate-replica"
197+
}
198+
```
199+
177200

178201

179202

@@ -241,6 +264,8 @@ Available targets:
241264
| restrict\_public\_buckets | Whether Amazon S3 should restrict public bucket policies for this bucket | `bool` | `true` | no |
242265
| role\_arn | The role to be assumed | `string` | `""` | no |
243266
| s3\_bucket\_name | S3 bucket name. If not provided, the name will be generated by the label module in the format namespace-stage-name | `string` | `""` | no |
267+
| s3\_replica\_bucket\_arn | The ARN of the S3 replica bucket (destination) | `string` | `""` | no |
268+
| s3\_replication\_enabled | Set this to true and specify `s3_replica_bucket_arn` to enable replication | `bool` | `false` | no |
244269
| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `""` | no |
245270
| tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no |
246271
| terraform\_backend\_config\_file\_name | Name of terraform backend config file | `string` | `"terraform.tf"` | no |

README.yaml

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,13 @@ usage: |-
6868
# be bootstrapped according to the simple yet essential procedure in
6969
# https://github.com/cloudposse/terraform-aws-tfstate-backend#usage
7070
module "terraform_state_backend" {
71-
source = "git::https://github.com/cloudposse/terraform-aws-tfstate-backend.git?ref=master"
72-
namespace = "eg"
73-
stage = "test"
74-
name = "terraform"
75-
attributes = ["state"]
76-
region = "us-east-1"
71+
source = "git::https://github.com/cloudposse/terraform-aws-tfstate-backend.git?ref=master"
72+
namespace = "eg"
73+
stage = "test"
74+
name = "terraform"
75+
attributes = ["state"]
76+
region = "us-east-1"
77+
7778
terraform_backend_config_file_path = "."
7879
terraform_backend_config_file_name = "backend.tf"
7980
force_destroy = false
@@ -148,6 +149,27 @@ usage: |-
148149
149150
![s3-bucket-with-terraform-state](images/s3-bucket-with-terraform-state.png)
150151
152+
### Bucket Replication (Disaster Recovery)
153+
154+
To enable S3 bucket replication in this module, set `s3_replication_enabled` to `true` and populate `s3_replica_bucket_arn` with the ARN of an existing bucket.
155+
156+
```hcl
157+
module "terraform_state_backend" {
158+
source = "git::https://github.com/cloudposse/terraform-aws-tfstate-backend.git?ref=master"
159+
namespace = "eg"
160+
stage = "test"
161+
name = "terraform"
162+
attributes = ["state"]
163+
region = "us-east-1"
164+
165+
terraform_backend_config_file_path = "."
166+
terraform_backend_config_file_name = "backend.tf"
167+
force_destroy = false
168+
169+
s3_replication_enabled = true
170+
s3_replica_bucket_arn = "arn:aws:s3:::eg-test-terraform-tfstate-replica"
171+
}
172+
```
151173
152174
include:
153175
- "docs/targets.md"

docs/terraform.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
| restrict\_public\_buckets | Whether Amazon S3 should restrict public bucket policies for this bucket | `bool` | `true` | no |
4949
| role\_arn | The role to be assumed | `string` | `""` | no |
5050
| s3\_bucket\_name | S3 bucket name. If not provided, the name will be generated by the label module in the format namespace-stage-name | `string` | `""` | no |
51+
| s3\_replica\_bucket\_arn | The ARN of the S3 replica bucket (destination) | `string` | `""` | no |
52+
| s3\_replication\_enabled | Set this to true and specify `s3_replica_bucket_arn` to enable replication | `bool` | `false` | no |
5153
| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `""` | no |
5254
| tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no |
5355
| terraform\_backend\_config\_file\_name | Name of terraform backend config file | `string` | `"terraform.tf"` | no |

main.tf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,24 @@ resource "aws_s3_bucket" "default" {
141141
}
142142
}
143143

144+
dynamic "replication_configuration" {
145+
for_each = var.s3_replication_enabled ? toset([var.s3_replica_bucket_arn]) : []
146+
content {
147+
role = aws_iam_role.replication[0].arn
148+
149+
rules {
150+
id = module.base_label.id
151+
prefix = ""
152+
status = "Enabled"
153+
154+
destination {
155+
bucket = var.s3_replica_bucket_arn
156+
storage_class = "STANDARD"
157+
}
158+
}
159+
}
160+
}
161+
144162
tags = module.s3_bucket_label.tags
145163
}
146164

replication.tf

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
resource "aws_iam_role" "replication" {
2+
count = var.s3_replication_enabled ? 1 : 0
3+
4+
name = format("%s-replication", module.base_label.id)
5+
assume_role_policy = data.aws_iam_policy_document.replication_sts[0].json
6+
}
7+
8+
data "aws_iam_policy_document" "replication_sts" {
9+
count = var.s3_replication_enabled ? 1 : 0
10+
11+
statement {
12+
sid = "AllowPrimaryToAssumeServiceRole"
13+
effect = "Allow"
14+
actions = [
15+
"sts:AssumeRole"
16+
]
17+
18+
principals {
19+
type = "Service"
20+
identifiers = ["s3.amazonaws.com"]
21+
}
22+
}
23+
}
24+
25+
resource "aws_iam_policy" "replication" {
26+
count = var.s3_replication_enabled ? 1 : 0
27+
28+
name = format("%s-replication", module.base_label.id)
29+
policy = data.aws_iam_policy_document.replication[0].json
30+
}
31+
32+
data "aws_iam_policy_document" "replication" {
33+
count = var.s3_replication_enabled ? 1 : 0
34+
35+
statement {
36+
sid = "AllowPrimaryToGetReplicationConfiguration"
37+
effect = "Allow"
38+
actions = [
39+
"s3:Get*",
40+
"s3:ListBucket"
41+
]
42+
resources = [
43+
aws_s3_bucket.default.arn,
44+
"${aws_s3_bucket.default.arn}/*"
45+
]
46+
}
47+
48+
statement {
49+
sid = "AllowPrimaryToReplicate"
50+
effect = "Allow"
51+
actions = [
52+
"s3:ReplicateObject",
53+
"s3:ReplicateDelete",
54+
"s3:ReplicateTags",
55+
"s3:GetObjectVersionTagging"
56+
]
57+
58+
resources = ["${var.s3_replica_bucket_arn}/*"]
59+
}
60+
}
61+
62+
resource "aws_iam_role_policy_attachment" "replication" {
63+
count = var.s3_replication_enabled ? 1 : 0
64+
role = aws_iam_role.replication[0].name
65+
policy_arn = aws_iam_policy.replication[0].arn
66+
}

variables.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,15 @@ variable "s3_bucket_name" {
227227
default = ""
228228
description = "S3 bucket name. If not provided, the name will be generated by the label module in the format namespace-stage-name"
229229
}
230+
231+
variable "s3_replication_enabled" {
232+
type = bool
233+
default = false
234+
description = "Set this to true and specify `s3_replica_bucket_arn` to enable replication"
235+
}
236+
237+
variable "s3_replica_bucket_arn" {
238+
type = string
239+
default = ""
240+
description = "The ARN of the S3 replica bucket (destination)"
241+
}

0 commit comments

Comments
 (0)