Skip to content

Commit a6f9942

Browse files
alexjurkiewiczNurukorenyoni
authored
S3 Replication Improvements (#93)
Co-authored-by: Nuru <[email protected]> Co-authored-by: Yonatan Koren <[email protected]>
1 parent e9eae04 commit a6f9942

17 files changed

+353
-63
lines changed

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,19 @@
2828
2929
-->
3030

31-
This module creates an S3 bucket with support of versioning, encryption, ACL and bucket object policy.
31+
This module creates an S3 bucket with support of versioning, replication, encryption, ACL, and bucket object policy.
3232
If `user_enabled` variable is set to `true`, the module will provision a basic IAM user with permissions to access the bucket.
3333

34-
This basic IAM system user is suitable for CI/CD systems (_e.g._ TravisCI, CircleCI) or systems which are *external* to AWS that cannot leverage [AWS IAM Instance Profiles](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html).
34+
This basic IAM system user is suitable for CI/CD systems (_e.g._ TravisCI, CircleCI) or systems which are *external* to AWS that cannot leverage
35+
[AWS IAM Instance Profiles](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html) and
36+
do not already have IAM credentials. Users or systems that have IAM credentials should either be granted access directly based on
37+
their IAM identity or be allowed to assume an IAM role with access.
3538

3639
We do not recommend creating IAM users this way for any other purpose.
3740

38-
It blocks public access to the bucket by default.
39-
https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html
41+
This module blocks public access to the bucket by default. See `block_public_acls`, `block_public_policy`,
42+
and `ignore_public_acls` to change the settings. See [AWS documentation](https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html)
43+
for more details.
4044

4145
---
4246

@@ -241,10 +245,12 @@ Available targets:
241245
| <a name="input_object_lock_configuration"></a> [object\_lock\_configuration](#input\_object\_lock\_configuration) | A configuration for S3 object locking. With S3 Object Lock, you can store objects using a `write once, read many` (WORM) model. Object Lock can help prevent objects from being deleted or overwritten for a fixed amount of time or indefinitely. | <pre>object({<br> mode = string # Valid values are GOVERNANCE and COMPLIANCE.<br> days = number<br> years = number<br> })</pre> | `null` | no |
242246
| <a name="input_policy"></a> [policy](#input\_policy) | A valid bucket policy JSON document. Note that if the policy document is not specific enough (but still valid), Terraform may view the policy as constantly changing in a terraform plan. In this case, please make sure you use the verbose/specific version of the policy | `string` | `""` | no |
243247
| <a name="input_regex_replace_chars"></a> [regex\_replace\_chars](#input\_regex\_replace\_chars) | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.<br>If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
244-
| <a name="input_replication_rules"></a> [replication\_rules](#input\_replication\_rules) | Specifies the replication rules if S3 bucket replication is enabled | `list(any)` | `null` | no |
248+
| <a name="input_replication_rules"></a> [replication\_rules](#input\_replication\_rules) | DEPRECATED: Use s3\_replication\_rules instead. | `list(any)` | `null` | no |
245249
| <a name="input_restrict_public_buckets"></a> [restrict\_public\_buckets](#input\_restrict\_public\_buckets) | Set to `false` to disable the restricting of making the bucket public | `bool` | `true` | no |
246-
| <a name="input_s3_replica_bucket_arn"></a> [s3\_replica\_bucket\_arn](#input\_s3\_replica\_bucket\_arn) | The ARN of the S3 replica bucket (destination) | `string` | `""` | no |
247-
| <a name="input_s3_replication_enabled"></a> [s3\_replication\_enabled](#input\_s3\_replication\_enabled) | Set this to true and specify `s3_replica_bucket_arn` to enable replication. `versioning_enabled` must also be `true`. | `bool` | `false` | no |
250+
| <a name="input_s3_replica_bucket_arn"></a> [s3\_replica\_bucket\_arn](#input\_s3\_replica\_bucket\_arn) | A single S3 bucket ARN to use for all replication rules.<br>Note: The destination bucket can be specified in the replication rule itself<br>(which allows for multiple destinations), in which case it will take precedence over this variable. | `string` | `""` | no |
251+
| <a name="input_s3_replication_enabled"></a> [s3\_replication\_enabled](#input\_s3\_replication\_enabled) | Set this to true and specify `s3_replication_rules` to enable replication. `versioning_enabled` must also be `true`. | `bool` | `false` | no |
252+
| <a name="input_s3_replication_rules"></a> [s3\_replication\_rules](#input\_s3\_replication\_rules) | Specifies the replication rules for S3 bucket replication if enabled. You must also set s3\_replication\_enabled to true. | `list(any)` | `null` | no |
253+
| <a name="input_s3_replication_source_roles"></a> [s3\_replication\_source\_roles](#input\_s3\_replication\_source\_roles) | Cross-account IAM Role ARNs that will be allowed to perform S3 replication to this bucket (for replication within the same AWS account, it's not necessary to adjust the bucket policy). | `list(string)` | `[]` | no |
248254
| <a name="input_sse_algorithm"></a> [sse\_algorithm](#input\_sse\_algorithm) | The server-side encryption algorithm to use. Valid values are `AES256` and `aws:kms` | `string` | `"AES256"` | no |
249255
| <a name="input_stage"></a> [stage](#input\_stage) | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
250256
| <a name="input_tags"></a> [tags](#input\_tags) | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no |

README.yaml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,19 @@ related:
6666

6767
# Short description of this project
6868
description: |-
69-
This module creates an S3 bucket with support of versioning, encryption, ACL and bucket object policy.
69+
This module creates an S3 bucket with support of versioning, replication, encryption, ACL, and bucket object policy.
7070
If `user_enabled` variable is set to `true`, the module will provision a basic IAM user with permissions to access the bucket.
7171
72-
This basic IAM system user is suitable for CI/CD systems (_e.g._ TravisCI, CircleCI) or systems which are *external* to AWS that cannot leverage [AWS IAM Instance Profiles](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html).
72+
This basic IAM system user is suitable for CI/CD systems (_e.g._ TravisCI, CircleCI) or systems which are *external* to AWS that cannot leverage
73+
[AWS IAM Instance Profiles](http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html) and
74+
do not already have IAM credentials. Users or systems that have IAM credentials should either be granted access directly based on
75+
their IAM identity or be allowed to assume an IAM role with access.
7376
7477
We do not recommend creating IAM users this way for any other purpose.
7578
76-
It blocks public access to the bucket by default.
77-
https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html
79+
This module blocks public access to the bucket by default. See `block_public_acls`, `block_public_policy`,
80+
and `ignore_public_acls` to change the settings. See [AWS documentation](https://docs.aws.amazon.com/AmazonS3/latest/dev/access-control-block-public-access.html)
81+
for more details.
7882
7983
# How to use this project
8084
usage: |-

docs/terraform.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,12 @@
6969
| <a name="input_object_lock_configuration"></a> [object\_lock\_configuration](#input\_object\_lock\_configuration) | A configuration for S3 object locking. With S3 Object Lock, you can store objects using a `write once, read many` (WORM) model. Object Lock can help prevent objects from being deleted or overwritten for a fixed amount of time or indefinitely. | <pre>object({<br> mode = string # Valid values are GOVERNANCE and COMPLIANCE.<br> days = number<br> years = number<br> })</pre> | `null` | no |
7070
| <a name="input_policy"></a> [policy](#input\_policy) | A valid bucket policy JSON document. Note that if the policy document is not specific enough (but still valid), Terraform may view the policy as constantly changing in a terraform plan. In this case, please make sure you use the verbose/specific version of the policy | `string` | `""` | no |
7171
| <a name="input_regex_replace_chars"></a> [regex\_replace\_chars](#input\_regex\_replace\_chars) | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.<br>If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
72-
| <a name="input_replication_rules"></a> [replication\_rules](#input\_replication\_rules) | Specifies the replication rules if S3 bucket replication is enabled | `list(any)` | `null` | no |
72+
| <a name="input_replication_rules"></a> [replication\_rules](#input\_replication\_rules) | DEPRECATED: Use s3\_replication\_rules instead. | `list(any)` | `null` | no |
7373
| <a name="input_restrict_public_buckets"></a> [restrict\_public\_buckets](#input\_restrict\_public\_buckets) | Set to `false` to disable the restricting of making the bucket public | `bool` | `true` | no |
74-
| <a name="input_s3_replica_bucket_arn"></a> [s3\_replica\_bucket\_arn](#input\_s3\_replica\_bucket\_arn) | The ARN of the S3 replica bucket (destination) | `string` | `""` | no |
75-
| <a name="input_s3_replication_enabled"></a> [s3\_replication\_enabled](#input\_s3\_replication\_enabled) | Set this to true and specify `s3_replica_bucket_arn` to enable replication. `versioning_enabled` must also be `true`. | `bool` | `false` | no |
74+
| <a name="input_s3_replica_bucket_arn"></a> [s3\_replica\_bucket\_arn](#input\_s3\_replica\_bucket\_arn) | A single S3 bucket ARN to use for all replication rules.<br>Note: The destination bucket can be specified in the replication rule itself<br>(which allows for multiple destinations), in which case it will take precedence over this variable. | `string` | `""` | no |
75+
| <a name="input_s3_replication_enabled"></a> [s3\_replication\_enabled](#input\_s3\_replication\_enabled) | Set this to true and specify `s3_replication_rules` to enable replication. `versioning_enabled` must also be `true`. | `bool` | `false` | no |
76+
| <a name="input_s3_replication_rules"></a> [s3\_replication\_rules](#input\_s3\_replication\_rules) | Specifies the replication rules for S3 bucket replication if enabled. You must also set s3\_replication\_enabled to true. | `list(any)` | `null` | no |
77+
| <a name="input_s3_replication_source_roles"></a> [s3\_replication\_source\_roles](#input\_s3\_replication\_source\_roles) | Cross-account IAM Role ARNs that will be allowed to perform S3 replication to this bucket (for replication within the same AWS account, it's not necessary to adjust the bucket policy). | `list(string)` | `[]` | no |
7678
| <a name="input_sse_algorithm"></a> [sse\_algorithm](#input\_sse\_algorithm) | The server-side encryption algorithm to use. Valid values are `AES256` and `aws:kms` | `string` | `"AES256"` | no |
7779
| <a name="input_stage"></a> [stage](#input\_stage) | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
7880
| <a name="input_tags"></a> [tags](#input\_tags) | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no |

examples/complete/fixtures.us-west-1.tfvars renamed to examples/complete/fixtures.us-east-2.tfvars

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
enabled = true
22

3-
region = "us-west-1"
3+
region = "us-east-2"
44

55
namespace = "eg"
66

examples/complete/grants.us-west-1.tfvars renamed to examples/complete/grants.us-east-2.tfvars

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
region = "us-west-1"
1+
region = "us-east-2"
22

33
namespace = "eg"
44

examples/complete/lifecycle.us-west-1.tfvars renamed to examples/complete/lifecycle.us-east-2.tfvars

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
region = "us-west-1"
1+
region = "us-east-2"
22

33
namespace = "eg"
44

examples/complete/main.tf

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
locals {
2+
replication_enabled = length(var.s3_replication_rules) > 0
3+
extra_rule = local.replication_enabled ? {
4+
id = "replication-test-explicit-bucket"
5+
status = "Enabled"
6+
prefix = "/extra"
7+
priority = 5
8+
destination_bucket = module.s3_bucket_replication_target_extra[0].bucket_arn
9+
} : null
10+
s3_replication_rules = local.replication_enabled ? concat(var.s3_replication_rules, [local.extra_rule]) : null
11+
}
12+
113
provider "aws" {
214
region = var.region
315
}
@@ -15,6 +27,39 @@ module "s3_bucket" {
1527
allowed_bucket_actions = var.allowed_bucket_actions
1628
bucket_name = var.bucket_name
1729
object_lock_configuration = var.object_lock_configuration
30+
s3_replication_enabled = local.replication_enabled
31+
s3_replica_bucket_arn = join("", module.s3_bucket_replication_target.*.bucket_arn)
32+
s3_replication_rules = local.s3_replication_rules
1833

1934
context = module.this.context
2035
}
36+
37+
module "s3_bucket_replication_target" {
38+
count = local.replication_enabled ? 1 : 0
39+
40+
source = "../../"
41+
42+
user_enabled = true
43+
acl = "private"
44+
force_destroy = true
45+
versioning_enabled = true
46+
s3_replication_source_roles = [module.s3_bucket.replication_role_arn]
47+
48+
attributes = ["target"]
49+
context = module.this.context
50+
}
51+
52+
module "s3_bucket_replication_target_extra" {
53+
count = local.replication_enabled ? 1 : 0
54+
55+
source = "../../"
56+
57+
user_enabled = true
58+
acl = "private"
59+
force_destroy = true
60+
versioning_enabled = true
61+
s3_replication_source_roles = [module.s3_bucket.replication_role_arn]
62+
63+
attributes = ["target", "extra"]
64+
context = module.this.context
65+
}

examples/complete/object-lock.us-west-1.tfvars renamed to examples/complete/object-lock.us-east-2.tfvars

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
region = "us-west-1"
1+
region = "us-east-2"
22

33
namespace = "eg"
44

examples/complete/outputs.tf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@ output "bucket_arn" {
1313
description = "Bucket ARN"
1414
}
1515

16+
output "replication_bucket_id" {
17+
value = local.replication_enabled ? join("", module.s3_bucket_replication_target.*.bucket_id) : null
18+
description = "Bucket Name (aka ID)"
19+
}
20+
21+
output "replication_bucket_arn" {
22+
value = local.replication_enabled ? join("", module.s3_bucket_replication_target.*.bucket_arn) : null
23+
description = "Bucket ARN"
24+
}
25+
26+
output "replication_role_arn" {
27+
value = module.s3_bucket.replication_role_arn
28+
description = "The ARN of the replication IAM Role"
29+
}
30+
1631
output "bucket_region" {
1732
value = module.s3_bucket.bucket_region
1833
description = "Bucket region"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Do not set "enabled", will be set by test framework
2+
# enabled = true
3+
region = "us-east-2"
4+
namespace = "eg"
5+
stage = "test"
6+
name = "s3-replication-test"
7+
acl = "private"
8+
force_destroy = true
9+
versioning_enabled = true
10+
allow_encrypted_uploads_only = true
11+
allowed_bucket_actions = [
12+
"s3:PutObject",
13+
"s3:PutObjectAcl",
14+
"s3:GetObject",
15+
"s3:DeleteObject",
16+
"s3:ListBucket",
17+
"s3:ListBucketMultipartUploads",
18+
"s3:GetBucketLocation",
19+
"s3:AbortMultipartUpload",
20+
]
21+
22+
# Rules will be augmented with an additional bucket rule, so prefix cannot be "/"
23+
s3_replication_rules = [
24+
{
25+
id = "replication-test"
26+
status = "Enabled"
27+
prefix = "/main"
28+
}
29+
]

0 commit comments

Comments
 (0)