-
-
Save avoidik/e1a8b2c5ff58e2f9b91ae5a708fe7ccd to your computer and use it in GitHub Desktop.
CRR replication (same or distinct accounts, mandatory different regions): s3 replicated bucket with terraform
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Create all variables used in this Terraform run | |
| variable "aws_access_key" {} | |
| variable "aws_access_secret_key" {} | |
| variable "aws_bucket_name" {} | |
| variable "aws_region_main" { | |
| default = "eu-west-1" | |
| } | |
| variable "aws_region_replica" { | |
| default = "eu-central-1" | |
| } | |
| # Use AWS credentials | |
| provider "aws" { | |
| access_key = "${var.aws_access_key}" | |
| secret_key = "${var.aws_access_secret_key}" | |
| } | |
| # Give Different aliases for aws regions | |
| provider "aws" { | |
| alias = "west" | |
| region = "eu-west-1" | |
| } | |
| provider "aws" { | |
| alias = "central" | |
| region = "eu-central-1" | |
| } | |
| # Create replication role | |
| resource "aws_iam_role" "replication" { | |
| name = "tf-iam-role-replication-12345" | |
| assume_role_policy = <<POLICY | |
| { | |
| "Version": "2012-10-17", | |
| "Statement": [ | |
| { | |
| "Action": "sts:AssumeRole", | |
| "Principal": { | |
| "Service": "s3.amazonaws.com" | |
| }, | |
| "Effect": "Allow", | |
| "Sid": "" | |
| } | |
| ] | |
| } | |
| POLICY | |
| } | |
| resource "aws_iam_policy" "replication" { | |
| name = "tf-iam-role-policy-replication-12345" | |
| policy = <<POLICY | |
| { | |
| "Version": "2012-10-17", | |
| "Statement": [ | |
| { | |
| "Action": [ | |
| "s3:GetReplicationConfiguration", | |
| "s3:ListBucket" | |
| ], | |
| "Effect": "Allow", | |
| "Resource": [ | |
| "${aws_s3_bucket.uploads.arn}" | |
| ] | |
| }, | |
| { | |
| "Action": [ | |
| "s3:GetObjectVersion", | |
| "s3:GetObjectVersionAcl" | |
| ], | |
| "Effect": "Allow", | |
| "Resource": [ | |
| "${aws_s3_bucket.uploads.arn}/*" | |
| ] | |
| }, | |
| { | |
| "Action": [ | |
| "s3:ReplicateObject", | |
| "s3:ReplicateDelete" | |
| ], | |
| "Effect": "Allow", | |
| "Resource": "${aws_s3_bucket.replica.arn}/*" | |
| } | |
| ] | |
| } | |
| POLICY | |
| } | |
| resource "aws_iam_policy_attachment" "replication" { | |
| name = "tf-iam-role-attachment-replication-12345" | |
| roles = ["${aws_iam_role.replication.name}"] | |
| policy_arn = "${aws_iam_policy.replication.arn}" | |
| } | |
| # This is the replication bucket for uploads | |
| resource "aws_s3_bucket" "replica" { | |
| provider = "aws.central" | |
| bucket = "${var.aws_bucket_name}-replica-1" | |
| region = "${var.aws_region_replica}" | |
| acl = "public-read" | |
| # Enable versioning so that files can be replicated | |
| versioning { | |
| enabled = true | |
| } | |
| # Remove old versions of images after 15 days | |
| lifecycle_rule { | |
| prefix = "" | |
| enabled = true | |
| noncurrent_version_expiration { | |
| days = 15 | |
| } | |
| } | |
| } | |
| # This is the main s3 bucket for uploads | |
| resource "aws_s3_bucket" "uploads" { | |
| provider = "aws.west" | |
| bucket = "${var.aws_bucket_name}" | |
| acl = "public-read" | |
| region = "${var.aws_region_main}" | |
| # Enable versioning so that files can be replicated | |
| versioning { | |
| enabled = true | |
| } | |
| # Remove old versions after 15 days, these shouldn't happen that often because | |
| # humanmade/s3-uploads will rename files which have same name | |
| lifecycle_rule { | |
| prefix = "" | |
| enabled = true | |
| noncurrent_version_expiration { | |
| days = 15 | |
| } | |
| } | |
| replication_configuration { | |
| role = "${aws_iam_role.replication.arn}" | |
| rules { | |
| id = "replica" | |
| prefix = "" | |
| status = "Enabled" | |
| destination { | |
| bucket = "${aws_s3_bucket.replica.arn}" | |
| storage_class = "STANDARD" | |
| } | |
| } | |
| } | |
| } | |
| resource "aws_iam_user" "uploads_user" { | |
| name = "${var.aws_bucket_name}-user" | |
| } | |
| resource "aws_iam_access_key" "uploads_user" { | |
| user = "${aws_iam_user.uploads_user.name}" | |
| } | |
| resource "aws_iam_user_policy" "wp_uploads_policy" { | |
| name = "WordPress-S3-Uploads" | |
| user = "${aws_iam_user.uploads_user.name}" | |
| # S3 policy from humanmade/s3-uploads for WordPress uploads | |
| policy = <<EOF | |
| { | |
| "Version": "2012-10-17", | |
| "Statement": [ | |
| { | |
| "Sid": "Stmt1392016154000", | |
| "Effect": "Allow", | |
| "Action": [ | |
| "s3:AbortMultipartUpload", | |
| "s3:DeleteObject", | |
| "s3:GetBucketAcl", | |
| "s3:GetBucketLocation", | |
| "s3:GetBucketPolicy", | |
| "s3:GetObject", | |
| "s3:GetObjectAcl", | |
| "s3:ListBucket", | |
| "s3:ListBucketMultipartUploads", | |
| "s3:ListMultipartUploadParts", | |
| "s3:PutObject", | |
| "s3:PutObjectAcl" | |
| ], | |
| "Resource": [ | |
| "arn:aws:s3:::${aws_s3_bucket.uploads.bucket}/*" | |
| ] | |
| }, | |
| { | |
| "Sid": "AllowRootAndHomeListingOfBucket", | |
| "Action": ["s3:ListBucket"], | |
| "Effect": "Allow", | |
| "Resource": ["arn:aws:s3:::${aws_s3_bucket.uploads.bucket}"], | |
| "Condition":{"StringLike":{"s3:prefix":["*"]}} | |
| } | |
| ] | |
| } | |
| EOF | |
| } | |
| # These output the created access keys and bucket name | |
| output "s3-bucket-name" { | |
| value = "${var.aws_bucket_name}" | |
| } | |
| output "s3-user-access-key" { | |
| value = "${aws_iam_access_key.uploads_user.id}" | |
| } | |
| output "s3-user-secret-key" { | |
| value = "${aws_iam_access_key.uploads_user.secret}" | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| provider "aws" { | |
| shared_credentials_file = "~/.aws/credentials" | |
| profile = "prod" | |
| region = "eu-west-1" | |
| } | |
| provider "aws" { | |
| shared_credentials_file = "~/.aws/credentials" | |
| profile = "prod" | |
| alias = "us" | |
| region = "us-east-1" | |
| } | |
| terraform { | |
| backend "s3" { | |
| bucket = "ps-terraform-state-ca770e80-f59b-4281-a74c-00c98ab14017" | |
| key = "prod/backups.tf" | |
| region = "eu-central-1" | |
| } | |
| } | |
| resource "aws_iam_role" "ps-db-backups-replication" { | |
| name = "ps-db-backups-replication" | |
| assume_role_policy = <<POLICY | |
| { | |
| "Version": "2012-10-17", | |
| "Statement": [ | |
| { | |
| "Action": "sts:AssumeRole", | |
| "Principal": { | |
| "Service": "s3.amazonaws.com" | |
| }, | |
| "Effect": "Allow", | |
| "Sid": "" | |
| } | |
| ] | |
| } | |
| POLICY | |
| } | |
| resource "aws_iam_policy" "ps-db-backups-replication" { | |
| name = "ps-db-backups-replication" | |
| policy = <<POLICY | |
| { | |
| "Version": "2012-10-17", | |
| "Statement": [ | |
| { | |
| "Action": [ | |
| "s3:GetReplicationConfiguration", | |
| "s3:ListBucket" | |
| ], | |
| "Effect": "Allow", | |
| "Resource": [ | |
| "${aws_s3_bucket.ps-db-backups.arn}" | |
| ] | |
| }, | |
| { | |
| "Action": [ | |
| "s3:GetObjectVersion", | |
| "s3:GetObjectVersionAcl" | |
| ], | |
| "Effect": "Allow", | |
| "Resource": [ | |
| "${aws_s3_bucket.ps-db-backups.arn}/*" | |
| ] | |
| }, | |
| { | |
| "Action": [ | |
| "s3:ReplicateObject", | |
| "s3:ReplicateDelete" | |
| ], | |
| "Effect": "Allow", | |
| "Resource": "${aws_s3_bucket.ps-db-backups-replica.arn}/*" | |
| } | |
| ] | |
| } | |
| POLICY | |
| } | |
| resource "aws_iam_policy_attachment" "ps-db-backups-replication" { | |
| name = "ps-db-backups-replication" | |
| roles = ["${aws_iam_role.ps-db-backups-replication.name}"] | |
| policy_arn = "${aws_iam_policy.ps-db-backups-replication.arn}" | |
| } | |
| resource "aws_s3_bucket" "ps-db-backups-replica" { | |
| bucket = "ps-db-backups-replica-ec8d82b8-8e47-44ed-90f4-73dfc999fac4" | |
| acl = "private" | |
| region = "us-east-1" | |
| provider = "aws.us" | |
| server_side_encryption_configuration { | |
| rule { | |
| apply_server_side_encryption_by_default { | |
| sse_algorithm = "AES256" | |
| } | |
| } | |
| } | |
| } | |
| resource "aws_s3_bucket" "ps-db-backups" { | |
| bucket = "ps-db-backups-b3bd1643-8cbf-4927-a64a-f0cf9b58dfab" | |
| acl = "private" | |
| region = "eu-west-1" | |
| versioning { | |
| enabled = true | |
| } | |
| lifecycle_rule { | |
| id = "transition" | |
| enabled = true | |
| transition { | |
| days = 30 | |
| storage_class = "STANDARD_IA" | |
| } | |
| expiration { | |
| days = 180 | |
| } | |
| } | |
| replication_configuration { | |
| role = "${aws_iam_role.ps-db-backups-replication.arn}" | |
| rules { | |
| id = "ps-db-backups-replication" | |
| status = "Enabled" | |
| destination { | |
| bucket = "${aws_s3_bucket.ps-db-backups-replica.arn}" | |
| storage_class = "GLACIER" | |
| } | |
| } | |
| } | |
| server_side_encryption_configuration { | |
| rule { | |
| apply_server_side_encryption_by_default { | |
| sse_algorithm = "AES256" | |
| } | |
| } | |
| } | |
| } | |
| resource "aws_iam_role" "ps-server-backups-replication" { | |
| name = "ps-server-backups-replication" | |
| assume_role_policy = <<POLICY | |
| { | |
| "Version": "2012-10-17", | |
| "Statement": [ | |
| { | |
| "Action": "sts:AssumeRole", | |
| "Principal": { | |
| "Service": "s3.amazonaws.com" | |
| }, | |
| "Effect": "Allow", | |
| "Sid": "" | |
| } | |
| ] | |
| } | |
| POLICY | |
| } | |
| resource "aws_iam_policy" "ps-server-backups-replication" { | |
| name = "ps-server-backups-replication" | |
| policy = <<POLICY | |
| { | |
| "Version": "2012-10-17", | |
| "Statement": [ | |
| { | |
| "Action": [ | |
| "s3:GetReplicationConfiguration", | |
| "s3:ListBucket" | |
| ], | |
| "Effect": "Allow", | |
| "Resource": [ | |
| "${aws_s3_bucket.ps-server-backups.arn}" | |
| ] | |
| }, | |
| { | |
| "Action": [ | |
| "s3:GetObjectVersion", | |
| "s3:GetObjectVersionAcl" | |
| ], | |
| "Effect": "Allow", | |
| "Resource": [ | |
| "${aws_s3_bucket.ps-server-backups.arn}/*" | |
| ] | |
| }, | |
| { | |
| "Action": [ | |
| "s3:ReplicateObject", | |
| "s3:ReplicateDelete" | |
| ], | |
| "Effect": "Allow", | |
| "Resource": "${aws_s3_bucket.ps-server-backups-replica.arn}/*" | |
| } | |
| ] | |
| } | |
| POLICY | |
| } | |
| resource "aws_iam_policy_attachment" "ps-server-backups-replication" { | |
| name = "ps-server-backups" | |
| roles = ["${aws_iam_role.ps-server-backups-replication.name}"] | |
| policy_arn = "${aws_iam_policy.ps-server-backups-replication.arn}" | |
| } | |
| resource "aws_s3_bucket" "ps-server-backups-replica" { | |
| bucket = "ps-server-backups-replica" | |
| acl = "private" | |
| region = "us-east-1" | |
| provider = "aws.us" | |
| versioning { | |
| enabled = true | |
| } | |
| } | |
| resource "aws_s3_bucket" "ps-server-backups" { | |
| bucket = "ps-server-backups" | |
| acl = "private" | |
| region = "eu-west-1" | |
| versioning { | |
| enabled = true | |
| } | |
| lifecycle_rule { | |
| id = "transition" | |
| enabled = true | |
| transition { | |
| days = 30 | |
| storage_class = "STANDARD_IA" # or "ONEZONE_IA" | |
| } | |
| expiration { | |
| days = 180 | |
| } | |
| } | |
| replication_configuration { | |
| role = "${aws_iam_role.ps-server-backups-replication.arn}" | |
| rules { | |
| id = "ps-server-backups-replication" | |
| status = "Enabled" | |
| destination { | |
| bucket = "${aws_s3_bucket.ps-server-backups-replica.arn}" | |
| storage_class = "STANDARD" | |
| } | |
| } | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://docs.aws.amazon.com/AmazonS3/latest/dev/replication-example-walkthroughs.html
https://aws.amazon.com/blogs/big-data/trigger-cross-region-replication-of-pre-existing-objects-using-amazon-s3-inventory-amazon-emr-and-amazon-athena/