How do I use a cross-account to invoke Amazon Bedrock in my account?

4 minute read
0

I want to invoke my Amazon Bedrock models that use a cross-account AWS Lambda function with Python runtimes.

Short description

You might receive the following error when you use an AWS Lambda function in a cross-account to invoke Amazon Bedrock in your account.

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.

Resolution

Use a two-step process to resolve this error:

  1. Create an AWS Identity and Access Management (IAM) role in account A (owner of the Amazon Bedrock model). This role is associated with the Amazon BedrockFullAccess policy to grant its assumed role access to account B.
  2. Create an IAM role in account B (owner of the Lambda function). This role is associated with a basic execution policy to grant its assumed role access to the IAM role in account A.

Note: When you use the Amazon Bedrock foundation models, you are subject to the seller's pricing terms.

Prerequisite

Make sure that the Amazon Bedrock models have their access set to Granted in the account that holds them (for example, in account A). For more information on how to request access, see Add model access.

Invoke Amazon Bedrock from a different account

Follow the instructions in this section to use a Lambda function in one account to invoke the Amazon Bedrock models in another account.
Note: For information regarding cross-account best practices, see Security best practices in IAM.

Account A (the account that has the Amazon Bedrock models with granted access)

Complete the following steps:

  1. Log in to the IAM console.

  2. Create an AWS Identity and Access Management (IAM) role for account A.

  3. 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"
            }
        ]
    }

Account B (the account that has the Lambda function)

Complete the following steps:

  1. Log in to the IAM console.

  2. Create an IAM role for the Lambda function. The Lambda function uses this role to run in the account.

  3. Make sure that the IAM role has the following:

    A Lambda basic execution policy.

    An assumed role, with permissions to assume the role created in account A (Amazon Bedrock's account). For example:

    {
        "Version": "2012-10-17",
        "Statement": {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::<Account A ID>:role/role-on-source-account"
        }
    }

Create an AWS Lambda function

Create a Lambda function.

This Lambda function assumes the IAM role in account A that has the necessary permissions to access the Amazon Bedrock models. It then uses the assumed role's credentials to create the Amazon Bedrock and Amazon Bedrock-runtime clients that interact with the Amazon Bedrock models.

Your Lambda function must look similar to the following sample function in Python.

import boto3
import botocore
import json

    
def lambda_handler(event, context):
    bedrock_role="arn:aws:iam:::role/BedrockLambdaCrossAccount"   #### Account A Role 
    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 client used to invoke and question the models
    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)
   # Just shows an example of how to retrieve information about available models
    foundation_models = bedrock.list_foundation_models()
    print(foundation_models)

    
    prompt = "Please list the 10 most popular movies from the 90's"
    
     # The payload to be provided to Bedrock 
    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'))
     
     # The response from the model now mapped to the answer
    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')
     }
AWS OFFICIAL
AWS OFFICIALUpdated a month ago