Skip to content

How do I troubleshoot the "botocore.errorfactory.AccessDeniedException" error that I receive when I try to use a cross-account Lambda function to invoke Amazon Bedrock?

3 minute read
0

I want to invoke my Amazon Bedrock models in my AWS account. I tried to use a cross-account AWS Lambda function with Python runtimes. However, I received a "botocore.errorfactory.AccessDeniedException" error message.

Short description

When you use a cross-account Lambda function to invoke Amazon Bedrock, you might receive the following error message:

"botocore.errorfactory.AccessDeniedException: An error occurred (AccessDeniedException) when calling the InvokeModel operation: You don't have access to the model with the specified model ID."

To resolve this error, take the following actions:

  • Create an AWS Identity and Access Management (IAM) role in account A, the account that owns the Amazon Bedrock model. Then, attach the AmazonBedrockFullAccess policy to the role to allow it to access account B, the account that owns the Lambda function.
  • Create an IAM role in account B. Then, associate the IAM role with a basic execution policy to allow its assumed role to access the IAM role in account A.

Note: When you use Amazon Bedrock foundation models, make sure to check the seller's pricing terms.

Make sure to request model access for your Amazon Bedrock model in account A. Confirm that the Access status changes to Access granted.

Resolution

Configure account A

Complete the following steps for the account that owns the Amazon Bedrock models:

  1. Open the IAM console.
  2. Create an IAM role for account A.
  3. Attach the AmazonBedrockFullAccess policy to the IAM role.
  4. Attach a trust relationship policy that allows the Lambda function's role in account B to assume the role in account A.
    Example trust relationship policy:
    {    
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam::Account_B_ID:role/my-lambda-execution-role"
                },
                "Action": "sts:AssumeRole"
            }
        ]
    }
    Note: Replace Account_B_ID with your account B ID and my-lambda-execution-role with your Lambda function execution role.

Configure account B

Complete the following steps for the role that owns the Lambda function:

  1. Open the IAM console.
  2. Create an IAM role that the Lambda function uses to run in the account.
  3. Attach the AWSLambdaBasicExecutionRole policy to the role.
  4. Attach a policy that allows the IAM role in account B to assume the IAM role in account A.
    Example policy:
    {    
        "Version": "2012-10-17",
        "Statement": {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::Account_A_ID:role/role-on-source-account"
        }
    }
    Note: Replace Account_A_ID with your account A ID and role-on-source-account with the name of the IAM role from account A.

For information about cross-account best practices, see Security best practices in IAM.

Create a Lambda function

Create a Lambda function. The Lambda function assumes the account A IAM role that has access to the Amazon Bedrock models. The function then uses the assumed role's credentials to create the Amazon Bedrock runtime clients that interact with the Amazon Bedrock models.

Your Lambda function must look similar to the following example Python function:

import boto3import botocore
import json

    
def lambda_handler(event, context):
    bedrock_role="arn:aws:iam:::role/BedrockLambdaCrossAccount"   
    credentials = 
boto3.client('sts').assume_role(RoleArn=bedrock_role,RoleSessionName='assume-role')
    ACCESS_KEY = credentials['Credentials']['AccessKeyId']
    SECRET_KEY = credentials['Credentials']['SecretAccessKey']
    SESSION_TOKEN = credentials['Credentials']['SessionToken']

    bedrock_session = boto3.session.Session(aws_access_key_id=ACCESS_KEY,aws_secret_access_key=SECRET_KEY,aws_session_token=SESSION_TOKEN)
    bedrock = boto3.client(service_name='bedrock', region_name='us-east-1',aws_access_key_id=ACCESS_KEY,aws_secret_access_key=SECRET_KEY,aws_session_token=SESSION_TOKEN)
    print(bedrock)
     
    bedrock_runtime = boto3.client(service_name='bedrock-runtime', region_name='us-east-1',aws_access_key_id=ACCESS_KEY,aws_secret_access_key=SECRET_KEY,aws_session_token=SESSION_TOKEN)
    foundation_models = bedrock.list_foundation_models()
    print(foundation_models)

    
    prompt = "Please list the 10 most popular movies from the 90's"
    
    body = json.dumps({"inputText": "Please list the 10 most popular movies from the 90's"})
    modelId = 'anthropic.claude-v2'
    accept = 'application/json'
    contentType = 'application/json'
    response = bedrock_runtime.invoke_model(body=body, modelId=modelId, 
accept=accept,contentType=contentType)
    response_body = json.loads(response.get('body').read())
    print(response_body.get('results')[0].get('outputText'))
     
    output=response_body.get('results')[0].get('outputText')    
    print(output)
    return {
     'statusCode': 200,
     'headers': {
       'Access-Control-Allow-Headers': '*',
       'Access-Control-Allow-Origin': '*',
       'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
     },
       'body': response_body.get('results')[0].get('outputText')
     }
2 Comments

Hello,

There appears to be a mistake in the steps.

For Account A (the account that has the Amazon Bedrock models with granted access), it mentions:

Make sure that the IAM role has the following:

An AmazonBedrockFullAccess policy.

An assumed role, with permissions, to invoke the Lambda function in account B. For example:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<Account B ID>:role/my-lambda-execution-role"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

We are not trying to invoke the Lambda function in account B. We want the Lambda function execution role to assume this role (Account A IAM role). So the trust relationship for Account A IAM role needs to be updated to allow Account B IAM role to assume it.

The video attached includes the correct steps however.

AWS
replied 7 months ago

Thank you for your comment. We'll review and update the Knowledge Center article as needed.

AWS
replied 7 months ago