Heyloo ! Recently I came across a weird scenario. An application written in Java that uses AWS S3 bucket for some sort of data ingestion was only allowed to use a single AWS region configured via either environment variable or application properties file. Of course, a patch could have been developed, but the release process does take time on its own. Also, this S3 bucket in cross-region happens to be in a different AWS account. We had an IAM role configured as principal on cross-region bucket policy. This mitigates our access issue. But not the cross-region issue. We came up with a solution to replicate the bucket for time being. It took some time digging up on the internet and some custom configuration, but we were able to configure cross-account cross-region replication. For the folks who are looking for a similar solution, here is how you should configure it. Please be noted that the replication works on newly created objects. This guide doesn’t help you with replicating existing objects in your bucket.
Alternative to using built-in s3 replication is writing your own lambda script that will be triggered with an s3 PUT event that will download the object that is recently published to the s3 bucket and upload it to the destination bucket. The cons of using lambda script are that your object size can not be huge, or else your lambda will timeout. Another major drawback is if your bucket is expecting frequent object uploads, your lambda will be triggered for those many events and sometimes concurrent execution might fail. You also pay for lambda execution cost (beyond free tier usage).
Replication enables automatic, asynchronous copying of objects across Amazon S3 buckets. Buckets that are configured for object replication can be owned by the same AWS account or by different accounts. Object may be replicated to a single destination bucket or multiple destination buckets. Destination buckets can be in different AWS Regions or within the same Region as the source bucket.
– AWS Docs
Let’s assume AWS Account A is where you need data to be replicated. We will call bucket in Account A as Destination Bucket and assume this bucket is in the us-west-2 region. AWS Account B is where you want the data to be replicated from. We will call bucket in Account B as Source Bucket and let’s assume this bucket is in the us-east-1 region.
In order for replication to work, both the source and destination bucket must have bucket versioning enabled. You can configure this by going to bucket properties -> Edit -> Enable -> and Save Changes. If you are creating the bucket from scratch you will always get the versioning option in bucket creation wizard. Be noted that versioning cost implication as s3 maintains copy (versions) of object each time you modify them.
Once you have versioning configured, we will enable replication on the source bucket (Account B). Go to Management -> Replication Rules -> Create Replication Rule.
- Enter the replication rule name as “rule01”
- Status enabled checked in (I would suggest you keep it disabled, till the time you are not done with destination bucket configuration)
- Choose a rule scope :
- Limit the scope using filter (based on a prefix to your objects)
- This rule applies to all the objects in the bucket. (we kept this because we wanted all the objects to be replicated)
- Destination :
- Select -> Specify Bucket in Another Account
- Account ID (Account A 12 digit AWS account number, you can get this by going to support center or IAM console)
- Bucket Name: Destination Bucket Name
- Check: Change the object ownership to destination bucket owner. (This is very important, if you keep it unchecked, Account A will not be able to access objects replicated. By default, the permission belongs to Account B)
- IAM Role
- Create a new role from a drop-down (this one is simplest, IAM role will be auto-created)
- We opted for creating IAM role manually due to some environmental restrictions in place set by our administrator.
- For folks looking for creating role manually, use the JSON IAM policy given below.
- Go to IAM console -> click on policies on the left side of pane -> create policy -> click on JSON editor. Paste the JSON policy from below (Make sure to change the SOURCE and DESTINATION bucket names)
- Name the policy as iam-s3-replication-policy and save. (or whatever name you prefer)
- Now go to roles -> create role -> select s3 -> select your use case as s3 -> next permissions -> select newly created policy iam-s3-replication-policy from filter list. Name the role as iam-s3-replication-role and save.
- Note down the IAM role ARN of the newly created role.
- You can skip the rest of the configuration and save it.
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:ListBucket", "s3:GetReplicationConfiguration", "s3:GetObjectVersionForReplication", "s3:GetObjectVersionAcl", "s3:GetObjectVersionTagging", "s3:GetObjectRetention", "s3:GetObjectLegalHold" ], "Effect": "Allow", "Resource": [ "arn:aws:s3:::SOURCE-BUCKET-NAME", "arn:aws:s3:::SOURCE-BUCKET-NAME/*", "arn:aws:s3:::DESTINATION-BUCKET-NAME", "arn:aws:s3:::DESTINATION-BUCKET-NAME/*" ] }, { "Action": [ "s3:ReplicateObject", "s3:ReplicateDelete", "s3:ReplicateTags", "s3:ObjectOwnerOverrideToBucketOwner" ], "Effect": "Allow", "Resource": [ "arn:aws:s3:::SOURCE-BUCKET-NAME/*", "arn:aws:s3:::DESTINATION-BUCKET-NAME/*" ] } ] }
IAM Policy for S3 Service IAM role.
Switch to destination account s3 bucket (Account B)
- Go to s3 console and select destination bucket.
- Click on permissions tab.
- Scroll down to bucket policy and click Edit.
- Use the below JSON bucket policy.
- Make sure to update DESTINATION-BUCKET-NAME with your bucket name.
- Also, update ROLE ARN that we created in Account A
Enable Replication rule, if not already done in Account B S3 bucket.
{ "Version": "2012-10-17", "Id": "", "Statement": [ { "Sid": "Set permissions for objects", "Effect": "Allow", "Principal": { "AWS": "ROLE_ARN_FROM_SOURCE_ACCOUNT" }, "Action": [ "s3:ReplicateObject", "s3:ReplicateDelete", "s3:ReplicateTags", "s3:ObjectOwnerOverrideToBucketOwner" ], "Resource": "arn:aws:s3:::DESTINATION-BUCKET-NAME/*" }, { "Sid": "Set permissions on bucket", "Effect": "Allow", "Principal": { "AWS": "ROLE_ARN_FROM_SOURCE_ACCOUNT" }, "Action": [ "s3:List*", "s3:GetBucketVersioning", "s3:PutBucketVersioning" ], "Resource": "arn:aws:s3:::DESTINATION-BUCKET-NAME" } ] }
Bucket policy to be used by destination bucket.
You can now test by uploading object in source bucket. Object will be replicated in destination bucket. Some times replication may take longer time depending upon the size of object. Hope this tutorial helps you setting up cross region, cross account s3 bucket replication. Feel free to add comment and blockers you may be facing.
References:
1. https://docs.aws.amazon.com/AmazonS3/latest/userguide/replication-walkthrough1.html
2. https://docs.aws.amazon.com/AmazonS3/latest/userguide/replication-walkthrough-2.html