1
votes

I am trying to copy S3 Object which is encrypted using KMS to another account. The Lambda that will perform the copy operation resides in the same account where the S3 Bucket with object is present. Here is the architecture diagram for the same : I want to copy object from Account B to Account A

enter image description here

I have performed the following steps in order to carry out the activity.

Account A Operations:

  • Create a S3 Bucket in Account A ( Server Side Encryption Enabled )
  • Create a IAM Role with Trust Policy for Account B : Please refer to the attached Role Policy and Trust Policy respectively

Role Policy

    {
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": "arn:aws:s3:::Account-A-Bucket/*"
        }
    ]   }

Trust Policy

    {
    "Version": "2012-10-17",
    "Statement": [{
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::Account-B:role/COPY-LAMBDA-ROLE"
        },
        "Action": "sts:AssumeRole",
        "Condition": {
            "StringEquals": {
                "sts:ExternalId": "demo"
            }
        }
    }]
}
  • Bucket Policy for Account A Bucket

     {
     "Version": "2012-10-17",
     "Statement": [
         {
             "Sid": "DelegateS3Access",
             "Effect": "Allow",
             "Principal": {
                 "AWS": "arn:aws:iam::Account-B:role/COPY-LAMBDA-ROLE"
             },
             "Action": "s3:PutObject",
             "Resource": [
                 "arn:aws:s3:::Account-A-Bucket/*",
                 "arn:aws:s3:::Account-A-Bucket"
             ]
         }
     ]  }
    

Account B Operations:

  • Lambda IAM Role ( To assume Role and To acces S3 )

Assume Role Policy

    {
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::Account-A:role/S3_Cross_Account_Access"
    }
}

S3 Access Policy

{
"Version": "2012-10-17",
"Statement": [
    {
        "Action": [
            "s3:Put*",
            "s3:List*",
            "s3:Get*"
        ],
        "Resource": "arn:aws:s3:::Account-A-Bucket/*",
        "Effect": "Allow",
        "Sid": "S3"
    }
]   }
  • Lambda Code to copy from Account B to Account A

    def lambda_handler(event, context):
    
         file_key_name = event['Records'][0]['s3']['object']['key']
    
         src_bucket_name='Account-B-Bucket'
    
         s3 = boto3.resource('s3')
    
         copy_source = {
           'Bucket': src_bucket_name,
           'Key': file_key_name
         }
         des_bucket = s3.Bucket('Account-A-Bucket')
         des_bucket.copy(copy_source, file_key_name)
    

I am facing the following error :

[ERROR] ClientError: An error occurred (404) when calling the HeadObject operation: Not Found

What else I am missing here ?

1

1 Answers

0
votes

For doing the copy withing one api call you need a role which has permissions for both buckets.

Basically you need a role inside the destination account which allows access to both buckets. Allow this role access to the source bucket using a bucket policy. let lambda or else assume the role in the destination account and call the copy api.

I refer to this AWS article: https://aws.amazon.com/premiumsupport/knowledge-center/copy-s3-objects-account/

One general hint for everyone working with assuming roles: Roles like your one, which is allowed to be assumed using the sts:assumeRole policy need to be assumed explicit! Lambda assumes the execution role and cannot guess which role to assume in another account to dona certain job, therefore assume the role explicitly!