1

I have a usecase to use AWS Lambda to copy files/objects from one S3 bucket to another. In this usecase Source S3 bucket is in a separate AWS account(say Account 1) where the provider has only given us AccessKey & SecretAccess Key. Our Lambda runs in Account 2 and the destination bucket can be either in Account 2 or some other account 3 altogether which can be accessed using IAM role. The setup is like this due to multiple partner sharing data files

Usually, I used to use the following boto3 command to copy the contents between two buckets when everything is in the same account but want to know how this can be modified for the new usecase

copy_source_object = {'Bucket': source_bucket_name, 'Key': source_file_key}
s3_client.copy_object(CopySource=copy_source_object, Bucket=destination_bucket_name, Key=destination_file_key)

How can the above code be modified to fit my usecase of having accesskey based connection to source bucket and roles for destination bucket(which can be cross-account role as well)? Please let me know if any clarification is required

Exelian
  • 5,364
  • 1
  • 28
  • 46
  • Related: https://stackoverflow.com/questions/56380673/how-to-copy-files-between-s3-buckets-in-2-different-accounts-using-boto3 – jarmod Sep 30 '20 at 17:31
  • What is the exact issue you're running into? AccessDenied errors? Or something else. – Exelian Sep 30 '20 at 18:19

2 Answers2

1

There's multiple options here. Easiest is by providing credentials to boto3 (docs). I would suggest retrieving the keys from the SSM parameter store or secrets manager so they're not stored hardcoded.


Edit: I realize the problem now, you can't use the same session for both buckets, makes sense. The exact thing you want is not possible (ie. use copy_object). The trick is to use 2 separate session so you don't mix the credentials. You would need to get_object from the first account and put_object to the second objects. You should be able to simply put the resp['Body'] from the get in the put request but I haven't tested this.


import boto3
acc1_session = boto3.session.Session(
    aws_access_key_id=ACCESS_KEY_acc1,
    aws_secret_access_key=SECRET_KEY_acc1
)
acc2_session = boto3.session.Session(
    aws_access_key_id=ACCESS_KEY_acc2,
    aws_secret_access_key=SECRET_KEY_acc2
)
acc1_client = acc1_session.client('s3')
acc2_client = acc2_session.client('s3')

copy_source_object = {'Bucket': source_bucket_name, 'Key': source_file_key}
resp = acc1_client.get_object(Bucket=source_bucket_name, Key=source_file_key)
acc2_client.put_object(Bucket=destination_bucket_name, Key=destination_file_key, Body=resp['Body'])
Exelian
  • 5,364
  • 1
  • 28
  • 46
  • yes these can be used to obtain credentials to connect to one of the account but those credentials wont be valid agianst the destination bucket as thats in a different account. I am trying to use COPY command instead of wanting to download the file from source using one set of credentials and then uploading to the destination using another set of credentials(i.e different boto client). From the above-linked article, it looks like thats not posssible to use COPY using a different set of credentials. – user14368903 Sep 30 '20 at 18:44
0

Your situation appears to be:

Account-1:

  • Amazon S3 bucket containing files you wish to copy
  • You have an Access Key + Secret Key from Account-1 that can read these objects

Account-2:

  • AWS Lambda function that has an IAM Role that can write to a destination bucket

When using the CopyObject() command, the credentials used must have read permission on the source bucket and write permission on the destination bucket. There are normally two ways to do this:

  1. Use credentials from Account-1 to 'push' the file to Account-2. This requires a Bucket Policy on the destination bucket that permits PutObject for the Account-1 credentials. Also, you should set ACL= bucket-owner-full-control to handover control to Account-2. (This sounds similar to your situation.) OR
  2. Use credentials from Account-2 to 'pull' the file from Account-1. This requires a Bucket Policy on the source bucket that permits GetObject for the Account-2 credentials.

If you can't ask for a change to the Bucket Policy on the source bucket that permits Account-2 to read the contents, then **you'll need a Bucket Policy on the Destination bucket that permits write access by the credentials from Account-1`.

This is made more complex by the fact that you are potentially copying the object to a bucket in "some other account". There is no easy answer if you are starting to use 3 accounts in the process.

Bottom line: If possible, ask them for a change to the source bucket's Bucket Policy so that your Lambda function can read the files without having to change credentials. It can then copy objects to any bucket that the function's IAM Role can access.

John Rotenstein
  • 165,783
  • 13
  • 223
  • 298