Reputation: 2334
we are trying to implement the lambda function which will copy the object from one S3 to another S3 bucket in cross account based on the source S3 bucket events. Currently we are able to copy the file between source and target within same SAG . But when we tried to implement the same logic with cross account , getting the CopyObject operation: Access Denied issue . I have given following bucket policy. Can you please help me to get the correct IAM and bucket policy to resolve this issue .
{
"Version": "2012-10-17",
"Id": "Policy1603404813917",
"Statement": [
{
"Sid": "Stmt1603404812651",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::6888889898:role/Staff"
},
"Action": [
"s3:GetObject",
"s3:GetObjectAcl",
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::source-bucktet-testing-lambda/*",
"arn:aws:s3:::source-bucktet-testing-lambda"
]
}
]
}
based on the https://www.lixu.ca/2016/09/aws-lambda-and-s3-how-to-do-cross_83.html
link , Yes, we can implement the same logic with help of access ID and access secret keys for source and dest. But am trying to implement same logic instead of access ID and access secret keys for source and dest, granting access for both source and target buckets with appropriate policy and make it work as like same account .
Upvotes: 4
Views: 9049
Reputation: 270224
To reproduce your situation, I did the following:
Bucket-A
)Role-A
)Lambda-A
) and assigned Role-A
to the functionBucket-A
to trigger Lambda-A
for "All object create events"Bucket-B
) with a bucket policy (see below)IAM Role
Role-A
has the AWSLambdaBasicExecutionRole
managed policy, and also this Inline Policy that assigns the Lambda function permission to read from Bucket-A
and write to Bucket-B
:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket-a/*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::bucket-b/*"
}
]
}
Bucket Policy on destination bucket
The Bucket Policy on Bucket-B
permits access from the Role-A
IAM Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT-A:role/role-a"
},
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::bucket-b/*"
}
]
}
Lambda Function
Lambda-A
is triggered when an object is created in Bucket-A
, and copies it to Bucket-B
:
import boto3
import urllib
TARGET_BUCKET = 'bucket-b'
def lambda_handler(event, context):
# Get incoming bucket and key
source_bucket = event['Records'][0]['s3']['bucket']['name']
source_key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'])
# Copy object to different bucket
s3_resource = boto3.resource('s3')
copy_source = {
'Bucket': source_bucket,
'Key': source_key
}
target_key = source_key # Change if desired
s3_resource.Bucket(TARGET_BUCKET).Object(target_key).copy(copy_source, ExtraArgs={'ACL': 'bucket-owner-full-control'})
I grant ACL=bucket-owner-full-control
because copying objects to buckets owned by different accounts can sometimes cause the objects to still be 'owned' by the original account. Using this ACL grants ownership to the account that owns the destination bucket.
Testing
I uploaded a file to Bucket-A
in Account-A
.
The file was correctly copied to Bucket-B
in Account-B
.
Comments
The solution does NOT require:
Bucket-A
, since Role-A
grants the necessary permissionsUpvotes: 13
Reputation: 1354
Assuming the following
Even after setting all these correctly, the copy operation may fail. This is because the Policy allows you to get/put s3 objects, but not the tags associated with those s3 objects.
You will need to ALLOW the following actions as well "s3:GetObjectTagging" and "s3:PutObjectTagging"
Upvotes: 0