Bhavesh Bendale
Bhavesh Bendale

Reputation: 23

Access Denied on CopyObject operation for Cross Account S3 object copy via IAM assume role - STS

I'm trying to copy cross account s3 bucket data by assuming the source IAM role and using AssumeRole call in my lambda but getting an error as ACCESS DENIED when calling the CopyObject operation

Setup is as follows -.

In Account-A

Bucket-A - No bucket level policies for the Bucket-A.

IAM Role => Role-A

Role-A has custom inline policy as follows

Role-A Permission Policies - Inline Policy.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt",
                "kms:GenerateDataKey"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:GetObjectAcl",
                "s3:CopyObject",
                "s3:HeadObject",
                "s3:GetObjectTagging",
                "s3:PutObjectTagging"
            ],
            "Resource": "arn:aws:s3:::Bucket-A/*"
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:ListAllMyBuckets",
                "s3:GetBucketAcl",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::Bucket-A"
        }
    ]
}

Role-A > Trust Relationships > Trusted Entities (Granted assume role to IAM lambda role of Account - B).

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::xxxxxxxxxx:role/service-role/Role-B"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

In Account-B - I have a S3 bucket, Lambda and Lambda Role -> Lambda-B access Bucket-A using Role-A assume STS and would need to copy data from Account-A's bucket-A and put it into Account-B's Bucket-B

Bucket-B - Bucket-B has no bucket level policies.

Lambda-B - S3 to S3 copy python lambda

IAM Lambda Role => Role-B

Role-B has following policies

Role-B Permission Policies Assume role for Role-A.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "iam:PassRole",
                "iam:GetRole"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam:: xxxxxxxxxx:role/Role-A",
            "Effect": "Allow"
        }
    ]
}

Rest all policies to the Role-B are as follows -

Encrypt and Decrypt KMS - of KMS-A and KMS-B *(tried adding both accounts KMS IDs too)*
AmazonSSMFullAccess
AWSLambdaVPCAccessExecutionRole
AmazonRedshiftFullAccess
AmazonS3FullAccess

With the above mentioned setup, when I run the AWS lambda it errors out stating ACCESS DENIED

[ERROR] ClientError: An error occurred (AccessDenied) when calling the CopyObject operation: Access Denied
Traceback (most recent call last):
   File "/var/task/lambda_function.py", line 136, in lambda_handler
    s3_resource.meta.client.copy(copy_source, TARGET_BUCKET, SOURCE_PATH)
   File "/var/runtime/boto3/s3/inject.py", line 380, in copy
    return future.result()
   File "/var/runtime/s3transfer/futures.py", line 103, in result
    return self._coordinator.result()
   File "/var/runtime/s3transfer/futures.py", line 266, in result
    raise self._exception
   File "/var/runtime/s3transfer/tasks.py", line 139, in __call__
    return self._execute_main(kwargs)
   File "/var/runtime/s3transfer/tasks.py", line 162, in _execute_main
    return_value = self._main(**kwargs)
   File "/var/runtime/s3transfer/copies.py", line 313, in _main
    client.copy_object(
   File "/var/runtime/botocore/client.py", line 391, in _api_call
    return self._make_api_call(operation_name, kwargs)
   File "/var/runtime/botocore/client.py", line 719, in _make_api_call
    raise error_class(parsed_response, operation_name)END RequestId: 80c88cc3-46ee-4707-85d1-6b62b0f3f50d

I tried using either of both S3 copy methods mentioned below and lambda errors out for both of them. If I remove/comment out the copy object methods, the code is able to assume role for role-A and retrieve the bucket-A and its objects but cannot do copy of those objects

s3_client.copy_object(CopySource=copy_source, Bucket=TARGET_BUCKET, Key=TARGET_KEY)

as well as

s3_resource.meta.client.copy(copy_source, TARGET_BUCKET, SOURCE_PATH)

Does anyone know what am I missing here? Any particular permissions or an error in my setup or maybe copying in this particular way is not feasible and only way is to to assume the STS role and download the data and upload to S3. But if file size are huge what is the recommended approach to perform s3 to s3 copy?

End Goal - To copy objects in S3-Bucket-A to S3-Bucket-B via Role-B associated with Lambda-B

Upvotes: 0

Views: 1475

Answers (1)

Ol Chappy
Ol Chappy

Reputation: 1

I struggled with a similar issue today, only in my case it is a Role in our AWS account which is permitted access by a bucket policy in another account. We could ls the other account's bucket contents but not cp them, until I read the first recommended action on this page and realized that we also needed to explicitly allow our Role the necessary S3 actions for the target bucket. For some reason the API behavior in this situation allows you to list the bucket contents but not do anything else, which seems misleading to me, but there it is.

Upvotes: 0

Related Questions