How can I copy S3 objects from another AWS account?

Last updated: 2022-01-07

I want to copy Amazon Simple Storage Service (Amazon S3) objects across AWS accounts. Then, I want to make sure that the destination account owns the copied objects. How can I do that?

Resolution

Important: Objects in Amazon S3 are no longer automatically owned by the AWS account that uploads it. By default, any newly created buckets now have the Bucket owner enforced setting enabled. It's also a best practice to use the Bucket owner enforced setting when changing Object Ownership. However, note that this option disables all bucket ACLs and ACLs on any objects in your bucket.

With the Bucket owner enforced setting in S3 Object Ownership, all objects in an Amazon S3 bucket are automatically owned by the bucket owner. The Bucket owner enforced feature also disables all access control lists (ACLs), which simplifies access management for data stored in S3. However, for existing buckets, an Amazon S3 object is still owned by the AWS account that uploaded it, unless you explicitly disable the ACLs. To change object ownership of objects in an existing bucket, see How can I change the ownership of publicly owned objects in my S3 bucket?

If your existing method of sharing objects relies on using ACLs, then identify the principals that use ACLs to access objects. For more information about how to review permissions before disabling any ACLs, see Prerequisites for disabling ACLs.

If you can't disable your ACLs, then follow these steps to take ownership of objects until you can adjust your bucket policy:

1.    In the source account, create an AWS Identity and Access Management (IAM) customer managed policy that grants an IAM identity (user or role) proper permissions. The IAM user must have access to retrieve objects from the source bucket and put objects back into the destination bucket. You can use an IAM policy similar to the following:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::source-DOC-EXAMPLE-BUCKET",
                "arn:aws:s3:::source-DOC-EXAMPLE-BUCKET/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::destination-DOC-EXAMPLE-BUCKET",
                "arn:aws:s3:::destination-DOC-EXAMPLE-BUCKET/*"
            ]
        }
    ]
}

Note: This example IAM policy includes only the minimum required permissions for listing objects and copying objects across buckets in different accounts. You must customize the allowed S3 actions according to your use case. For example, if the user must copy objects that have object tags, then you must also grant permissions for s3:GetObjectTagging. If you experience an error, try performing these steps as an admin user.

2.    In the source account, attach the customer managed policy to the IAM identity that you want to use to copy objects to the destination bucket.

3.    In the destination account, set S3 Object Ownership on the destination bucket to bucket owner preferred. After you set S3 Object Ownership, new objects uploaded with the access control list (ACL) set to bucket-owner-full-control are automatically owned by the bucket's account.

4.    In the destination account, modify the bucket policy of the destination bucket to grant the source account permissions for uploading objects. Additionally, include a condition in the bucket policy that requires object uploads to set the ACL to bucket-owner-full-control. You can use a statement similar to the following:

Note: Replace destination-DOC-EXAMPLE-BUCKET with the name of the destination bucket. Then, replace arn:aws:iam::222222222222:user/Jane with the Amazon Resource Name (ARN) of the IAM identity from the source account.

{
    "Version": "2012-10-17",
    "Id": "Policy1611277539797",
    "Statement": [
        {
            "Sid": "Stmt1611277535086",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::222222222222:user/Jane"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::destination-DOC-EXAMPLE-BUCKET/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        },
        {
            "Sid": "Stmt1611277877767",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::222222222222:user/Jane"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::destination-DOC-EXAMPLE-BUCKET"
        }
    ]
}

Note: This example bucket policy includes only the minimum required permissions for uploading an object with the required ACL. You must customize the allowed S3 actions according to your use case. For example, if the user must copy objects that have object tags, you must also grant permissions for s3:GetObjectTagging

5.    After you configure the IAM policy and bucket policy, the IAM identity from the source account must upload objects to the destination bucket. Make sure that the ACL is set to bucket-owner-full-control. For example, the source IAM identity must run the cp AWS CLI command with the --acl option:

aws s3 cp s3://source-DOC-EXAMPLE-BUCKET/object.txt s3://destination-DOC-EXAMPLE-BUCKET/object.txt --acl bucket-owner-full-control

Note: If you receive errors when running AWS CLI commands, make sure that you’re using the most recent version of the AWS CLI.

With S3 Object Ownership set to bucket owner preferred, the objects uploaded with the bucket-owner-full-control ACL are automatically owned by the destination bucket's account.

Important: If your S3 bucket has default encryption with AWS Key Management Service (AWS KMS) enabled, then you must also modify the AWS KMS key permissions. For instructions, see My Amazon S3 bucket has default encryption using a custom AWS KMS key. How can I allow users to download from and upload to the bucket?