Reputation: 783
I have two aws accounts, A and B. Account A has a lambda function that needs access to a s3 bucket in Account B.
To simulate this case, I have the following settings:
The Account B (data source) has a role:
arn:aws:iam::${Account_B}:role/jeff-full-s3-access-role
and is attached with AmazonS3FullAccess
policy. This role has a trusted entity arn:aws:iam::${Account_A}:role/jeff-test-lambda-role
Meanwhile, arn:aws:iam::${Account_A}:role/jeff-test-lambda-role
resides in Account A and it has a trusted entity lambda.amazonaws.com
. And I've attached the following in-line policy with it:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::${Account_B}:role/jeff-full-s3-access-role"
}
}
Now when I invoked the lambda function (python):
import json
from boto3 import client
def lambda_handler(event, context):
conn = client('s3') # again assumes boto.cfg setup, assume AWS S3
for key in conn.list_objects(Bucket='Bucket_in_Account_B')['Contents']:
print(key['Key'])
return {}
But getting the following error:
{
"errorMessage": "An error occurred (AccessDenied) when calling the ListObjects operation: Access Denied",
"errorType": "ClientError",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 6, in lambda_handler\n for key in conn.list_objects(Bucket='Bucket_in_Account_B')['Contents']:\n",
" File \"/var/runtime/botocore/client.py\", line 386, in _api_call\n return self._make_api_call(operation_name, kwargs)\n",
" File \"/var/runtime/botocore/client.py\", line 705, in _make_api_call\n raise error_class(parsed_response, operation_name)\n"
]
}
Does anyone know the reason why this is not working? This post may work but it's a couple of years ago. I'm wondering if there's a way to achieve this without using Bucket Policy.
Thank you!
Upvotes: 0
Views: 921
Reputation: 269091
The easiest way to meet your requirement is to add a Bucket Policy on the bucket in Account B that permits access from the IAM Role used by the AWS Lambda function in Account A. This avoids any requirement to assume roles.
As for your current code, it is failing because your program needs to call assume_role()
to obtain credentials from Account B. It then needs to use those credentials to create a new boto3.client()
object for use when accessing resources in Account B. For an example, see: boto - AWS: Boto3: AssumeRole example which includes role usage - Stack Overflow
Upvotes: 1