Skip to main content

S3 Buckets Replication Remediation

Triage and Remediation

Remediation

Using Console

Below are concise, step‑by‑step instructions to enable S3 bucket replication using the AWS Management Console.


Prerequisites

  1. Source and destination buckets created
    • Same or different AWS accounts/regions are allowed (CRR vs SRR).
  2. Versioning enabled on both buckets
    • Replication requires versioning on source and destination.
  3. Permissions
    • You must have permissions to configure replication and create an IAM role for replication.

Step 1: Enable Versioning on Source and Destination Buckets

Do this for both buckets (source and destination):

  1. Sign in to the AWS Management Console and open Amazon S3.
  2. In the left navigation, choose Buckets.
  3. Click the bucket name.
  4. Go to the Properties tab.
  5. Scroll to Bucket Versioning.
  6. Click Edit.
  7. Select Enable.
  8. Click Save changes.

Repeat for the destination bucket.


Step 2: Open Replication Configuration on the Source Bucket

  1. In the S3 console, go to Buckets.
  2. Click the source bucket name.
  3. Go to the Management tab.
  4. Under Replication rules, click Create replication rule (or Add rule if one exists).

Step 3: Define Basic Rule Settings

  1. Rule name: Enter a descriptive name, e.g., replicate-to-dr-bucket.
  2. Status: Leave as Enabled.

Step 4: Choose the Source Objects to Replicate

  1. Under Choose a rule scope:
    • Apply to all objects in the bucket – to replicate the entire bucket; or
    • Limit the scope of this rule using one or more filters – to use:
      • Prefix (e.g., logs/ or backup/)
      • Tags (key/value pairs)
  2. Configure prefixes/tags as needed for your policy requirement.

Step 5: Choose Destination Bucket and Options

  1. Under Destination, click Choose a bucket in this account or Choose a bucket in another account.
  2. Select or type the destination bucket.
  3. If cross‑region replication is required, select a bucket in a different region.
  4. (Optional) Configure:
    • Destination storage class (e.g., Standard, Standard‑IA, Glacier Instant Retrieval, etc.).
    • Change object ownership (if cross‑account, you typically set Destination bucket owner to own the replicated objects).
    • Replicate delete markers and/or existing objects:
      • To replicate deletes: check Delete marker replication.
      • To replicate existing objects: check Replicate existing objects (if shown as an option for the rule).

Step 6: Configure Encryption / KMS (If Used)

If you use SSE-KMS on source or destination:

  1. Under encryption settings, confirm:
    • Which KMS key is used for source objects.
    • Which KMS key will be used for destination objects.
  2. Make sure the KMS key policies allow:
    • The S3 replication role to use Decrypt on source key.
    • The S3 replication role to use Encrypt on destination key.

(You may need to separately adjust KMS key policies in the KMS console.)


Step 7: IAM Role for Replication

  1. In the IAM role section:
    • Choose Create new role (recommended) or select an existing role that S3 can use.
  2. If you choose Create new role:
    • S3 will propose a role name like AWSServiceRoleForS3Replication.
    • Review the auto‑generated trust and permissions.
    • Confirm to let S3 create and manage this role.
  3. If cross‑account:
    • Ensure the destination account bucket policy allows the source account’s replication role to write objects and, if needed, change ownership.

Step 8: Review and Save the Replication Rule

  1. Review all settings:
    • Source bucket and scope.
    • Destination bucket and region.
    • Storage class.
    • Ownership and delete marker options.
    • Replication of existing objects (if required).
  2. Click Save (or Create rule).

Step 9: Validate Replication

  1. Upload a new object (or modify an existing one) in the source bucket under the replicated prefix/tag.
  2. After a short delay, check the destination bucket for the replicated object.
  3. Confirm:
    • Object appears with the correct key (path).
    • Storage class and encryption match the configuration.
    • Object owner is as expected (especially cross‑account).

That is all you need in the AWS console to satisfy “S3 Bucket Replication Should Be Enabled” for the target bucket.

Using CLI

Below are the minimal steps to enable S3 bucket replication using the AWS CLI.

Assumptions:

  • Source bucket: SOURCE_BUCKET
  • Destination bucket: DEST_BUCKET
  • Region examples: us-east-1 (source), us-west-2 (destination)
  • You will create a replication IAM role: s3-replication-role

1. Ensure versioning is enabled on both buckets

aws s3api put-bucket-versioning \
--bucket SOURCE_BUCKET \
--versioning-configuration Status=Enabled

aws s3api put-bucket-versioning \
--bucket DEST_BUCKET \
--versioning-configuration Status=Enabled

2. Create an IAM role for replication

2.1 Create the trust policy (trust-policy.json)

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "s3.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}

Create the role:

aws iam create-role \
--role-name s3-replication-role \
--assume-role-policy-document file://trust-policy.json

3. Attach permissions to the role

3.1 Create the permissions policy (replication-policy.json)

Replace SOURCE_BUCKET and DEST_BUCKET with your names.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReplicationActionsOnSource",
"Effect": "Allow",
"Action": [
"s3:GetReplicationConfiguration",
"s3:ListBucket"
],
"Resource": "arn:aws:s3:::SOURCE_BUCKET"
},
{
"Sid": "AllowObjectReadsOnSource",
"Effect": "Allow",
"Action": [
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:GetObjectVersionTagging"
],
"Resource": "arn:aws:s3:::SOURCE_BUCKET/*"
},
{
"Sid": "AllowReplicationToDestination",
"Effect": "Allow",
"Action": [
"s3:ReplicateObject",
"s3:ReplicateDelete",
"s3:ReplicateTags",
"s3:GetObjectVersionTagging",
"s3:ObjectOwnerOverrideToBucketOwner"
],
"Resource": "arn:aws:s3:::DEST_BUCKET/*"
}
]
}

Attach the policy:

aws iam put-role-policy \
--role-name s3-replication-role \
--policy-name s3-replication-policy \
--policy-document file://replication-policy.json

4. Get the IAM role ARN

aws iam get-role --role-name s3-replication-role \
--query 'Role.Arn' --output text

Save the ARN as ROLE_ARN.


5. Create the replication configuration

Create replication-config.json (replace ROLE_ARN, DEST_BUCKET):

{
"Role": "ROLE_ARN",
"Rules": [
{
"ID": "replicate-all-objects",
"Status": "Enabled",
"Filter": { "Prefix": "" },
"DeleteMarkerReplication": { "Status": "Enabled" },
"Destination": {
"Bucket": "arn:aws:s3:::DEST_BUCKET",
"StorageClass": "STANDARD"
}
}
]
}

6. Apply replication configuration to the source bucket

aws s3api put-bucket-replication \
--bucket SOURCE_BUCKET \
--replication-configuration file://replication-config.json

7. Verify replication configuration

aws s3api get-bucket-replication \
--bucket SOURCE_BUCKET

You should now see the replication rule; new objects in SOURCE_BUCKET will replicate to DEST_BUCKET.

Using Python

To enable S3 bucket replication with Python (boto3), you need to:

  1. Ensure prerequisites
  2. Create an IAM role for replication
  3. Enable versioning on source and destination buckets
  4. Configure replication on the source bucket with Python

Below is a concise end‑to‑end guide.


1. Prerequisites

  • You have two buckets in the same or different AWS accounts:
    • Source bucket: e.g., my-source-bucket
    • Destination bucket: e.g., my-destination-bucket
  • You have Python 3 and boto3 installed:
    pip install boto3
  • Your AWS credentials allow:
    • s3:PutBucketReplication, s3:GetBucketReplication, s3:PutBucketVersioning
    • iam:CreateRole, iam:PutRolePolicy (if you create replication role via Python)

2. Create the IAM Role for Replication

S3 replication uses an IAM role that S3 assumes. You can create this role via the console or via Python. Below is a Python example.

2.1 Define trust policy and role policy

import json
import boto3

iam = boto3.client('iam')

replication_role_name = "S3ReplicationRole"

trust_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"Service": "s3.amazonaws.com"},
"Action": "sts:AssumeRole"
}
]
}

role = iam.create_role(
RoleName=replication_role_name,
AssumeRolePolicyDocument=json.dumps(trust_policy),
Description="Role for S3 cross-bucket replication"
)

role_arn = role['Role']['Arn']
print("Created role:", role_arn)

Attach an inline policy that allows replication operations:

source_bucket = "my-source-bucket"
destination_bucket = "my-destination-bucket"
destination_account_id = "123456789012" # AWS account of destination bucket

replication_policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetReplicationConfiguration",
"s3:ListBucket",
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:GetObjectVersionTagging"
],
"Resource": [
f"arn:aws:s3:::{source_bucket}",
f"arn:aws:s3:::{source_bucket}/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:ReplicateObject",
"s3:ReplicateDelete",
"s3:ReplicateTags",
"s3:GetObjectVersionTagging",
"s3:PutObjectAcl",
"s3:PutObjectVersionAcl",
"s3:PutObjectTagging",
"s3:PutObjectVersionTagging"
],
"Resource": [
f"arn:aws:s3:::{destination_bucket}/*"
]
}
]
}

iam.put_role_policy(
RoleName=replication_role_name,
PolicyName="S3ReplicationPolicy",
PolicyDocument=json.dumps(replication_policy)
)

print("Attached replication policy to role.")

If source and destination are in different accounts, also ensure the destination bucket policy allows the role to write objects (can be done via console or put_bucket_policy).


3. Enable Versioning on Both Buckets

Replication requires versioning.

import boto3

s3 = boto3.client('s3')

def enable_versioning(bucket_name):
s3.put_bucket_versioning(
Bucket=bucket_name,
VersioningConfiguration={"Status": "Enabled"}
)
print(f"Versioning enabled on {bucket_name}")

enable_versioning(source_bucket)
enable_versioning(destination_bucket)

4. Configure Replication on the Source Bucket

Now apply the replication configuration with Python.

replication_config = {
"Role": role_arn,
"Rules": [
{
"ID": "replicate-all-objects",
"Priority": 1,
"Status": "Enabled",
"DeleteMarkerReplication": {"Status": "Enabled"},
"Filter": {"Prefix": ""}, # empty = all objects
"Destination": {
"Bucket": f"arn:aws:s3:::{destination_bucket}",
# Optional: enable replica ownership override for different accounts
# "AccessControlTranslation": {"Owner": "Destination"},
# Optional: change storage class for replicas
# "StorageClass": "STANDARD_IA",
"Account": destination_account_id # required if different account
}
}
]
}

s3.put_bucket_replication(
Bucket=source_bucket,
ReplicationConfiguration=replication_config
)

print("Replication configuration set on source bucket.")

5. Verify Replication

response = s3.get_bucket_replication(Bucket=source_bucket)
print(response["ReplicationConfiguration"])

Upload a new object to the source bucket and confirm it appears in the destination bucket after a short delay.


This is the minimal Python/boto3 flow to remediate “S3 Bucket Replication Should Be Enabled” by turning on replication from a source bucket to a destination bucket.

Using Terraform
# Existing source bucket
resource "aws_s3_bucket" "source" {
bucket = "SOURCE_BUCKET_NAME" # replace with your source bucket name
}

# Existing destination bucket (must be in same or different region/account as needed)
resource "aws_s3_bucket" "destination" {
bucket = "DESTINATION_BUCKET_NAME" # replace with your destination bucket name
}

# IAM role used by S3 for replication
resource "aws_iam_role" "s3_replication_role" {
name = "S3ReplicationRole-FRIENDLY_NAME" # replace FRIENDLY_NAME

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "s3.amazonaws.com"
}
Action = "sts:AssumeRole"
}
]
})
}

# IAM policy granting S3 permission to replicate from source to destination
resource "aws_iam_role_policy" "s3_replication_policy" {
name = "S3ReplicationPolicy-FRIENDLY_NAME" # replace FRIENDLY_NAME
role = aws_iam_role.s3_replication_role.id

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "ReplicateObjects"
Effect = "Allow"
Action = [
"s3:GetReplicationConfiguration",
"s3:ListBucket"
]
Resource = aws_s3_bucket.source.arn
},
{
Sid = "ReadSourceObjects"
Effect = "Allow"
Action = [
"s3:GetObjectVersion",
"s3:GetObjectVersionAcl",
"s3:GetObjectVersionTagging"
]
Resource = "${aws_s3_bucket.source.arn}/*"
},
{
Sid = "WriteReplicaObjects"
Effect = "Allow"
Action = [
"s3:ReplicateObject",
"s3:ReplicateDelete",
"s3:ReplicateTags",
"s3:PutObjectAcl",
"s3:PutObjectTagging"
]
Resource = "${aws_s3_bucket.destination.arn}/*"
}
]
})
}

# Bucket versioning is required for replication on both source and destination
resource "aws_s3_bucket_versioning" "source" {
bucket = aws_s3_bucket.source.id

versioning_configuration {
status = "Enabled"
}
}

resource "aws_s3_bucket_versioning" "destination" {
bucket = aws_s3_bucket.destination.id

versioning_configuration {
status = "Enabled"
}
}

# Replication configuration on the source bucket
resource "aws_s3_bucket_replication_configuration" "source" {
bucket = aws_s3_bucket.source.id
role = aws_iam_role.s3_replication_role.arn

rule {
id = "replicate-all-objects"
status = "Enabled"

delete_marker_replication {
status = "Enabled"
}

filter {
prefix = "" # empty = all objects; change if you want to scope
}

destination {
bucket = aws_s3_bucket.destination.arn
storage_class = "STANDARD" # optional; change if you need another class
}
}

depends_on = [
aws_iam_role_policy.s3_replication_policy,
aws_s3_bucket_versioning.source,
aws_s3_bucket_versioning.destination,
]
}

Enabling or changing replication on an existing bucket does not force bucket replacement, but it can start copying data and incur storage/transfer costs.

To verify, terraform plan should show creation of aws_s3_bucket_replication_configuration.source (and any required IAM and versioning resources) with the rule status = "Enabled" attached to the source bucket.