Um blog sobre nada

Um conjunto de inutilidades que podem vir a ser úteis

AWS S3 – Copying objects between AWS accounts (TO and FROM)

Posted by Diego on December 21, 2020


There are two possible situation where you’d want to move S3 objects between different AWS accounts. You could be trying to copy an object FROM a different AWS account to your account, or you could be trying to copy an object that resides on your account TO a different AWS account. In both cases the approach is similar but slightly different.

OPTION 1 – Copy FROM another account
(you are on the destination account and want to copy the data from a source account)

First, add this POLICY to the source bucket:

  • DESTACCOUNT is the destination account ID
  • SOURCEACCOUNT: is the source account ID
  • YOURROLE: the role on the destination account that is performing the copy
  • SOURCEBUCKET is the name of the bucket where the data is
  • DESTINATIONBUCKET is the name of the bucket you want to copy the data to
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DelegateS3Access",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:sts::DESTACCOUNT:assumed-role/YOURROLE"
            },
            "Action": [
                "s3:ListBucket",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::SOURCEBUCKET/*",
                "arn:aws:s3:::SOURCEBUCKET"
            ]
        }
    ]
}

Second, add this policy to the role that will perform the copy (YOURROLE):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::SOURCEBUCKET",
                "arn:aws:s3:::SOURCEBUCKET/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::DESTINATIONBUCKET",
                "arn:aws:s3:::DESTINATIONBUCKET/*"
            ]
        }
    ]
}

OPTION 2 – Copy TO another account
(for example, a lambda function copies the data from the account it runs to a different account)

First, add this policy to the destination bucket on the Destination Account

{
    "Version": "2012-10-17",
    "Id": "MyPolicyID",
    "Statement": [
        {
            "Sid": "mySid",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::SOURCEACCOUNT:root"
            },
            "Action": "s3:PutObject",
            "Resource": [
                "arn:aws:s3:::DESTINATIONBUCKET/*",
                "arn:aws:s3:::DESTINATIONBUCKET"
            ]
        }
    ]
}

Second, add the exact same policy mentioned on the “second” item above to the role that will perform the copy (YOURROLE);

IMPORTANT: Object Ownership

If you are copying from account A TO account B (a lambda running on A for example), the objects on account B be will be owned by the user that performed the copy on account A. That may (definitely will) cause problems on account B, so make sure to add the “bucket-owner-full-control” ACL when copying the object. For example:

s3 = boto3.resource('s3')    
copy_source = {
    'Bucket': 'sourceBucket',
    'Key': 'sourceKey'
}
bucket = s3.Bucket('destBucket')
extra_args = {'ACL': 'bucket-owner-full-control'}
bucket.copy(copy_source, 'destKey', extra_args)

Leave a comment