跳至内容

如何解决我在尝试使用跨账户 Lambda 函数调用 Amazon Bedrock 时收到的"botocore.errorfactory.AccessDeniedException"错误?

2 分钟阅读
0

我想在我的 AWS 账户中调用我的 Amazon Bedrock 模型。我尝试使用跨账户 AWS Lambda 函数与 Python 运行时。但是,我收到了"botocore.errorfactory.AccessDeniedException"错误消息。

简短描述

当您使用跨账户 Lambda 函数调用 Amazon Bedrock 时,您可能会收到以下错误消息:

"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."

要解决此错误,请执行以下操作:

  • 在账户 A(拥有 Amazon Bedrock 模型的账户)中创建 AWS Identity and Access Management (IAM) 角色。然后,将 AmazonBedrockFullAccess 策略附加到该角色以允许其访问账户 B,即拥有 Lambda 函数的账户。
  • 在账户 B 中创建 IAM 角色。然后,将 IAM 角色与基本执行策略相关联,以允许其代入的角色访问账户 A 中的 IAM 角色。

**注意:**当您使用 Amazon Bedrock 基础模型时,请务必查看卖家的定价条款

请务必在账户 A 中申请对 Amazon Bedrock 模型的访问权限。确认 Access status(访问权限状态)更改为 Access granted(已授予访问权限)。

解决方法

配置账户 A

为拥有 Amazon Bedrock 模型的账户完成以下步骤:

  1. 打开 IAM 控制台
  2. 为账户 A 创建 IAM 角色
  3. AmazonBedrockFullAccess 策略附加到 IAM 角色。
  4. 附加信任关系策略,允许 Lambda 函数在账户 B 中的角色代入账户 A 中的角色。
    信任关系策略示例:
    {    
        "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_ID 替换为您的账户 B ID,将 my-lambda-execution-role 替换为您的 Lambda 函数执行角色。

配置账户 B

为拥有 Lambda 函数的角色完成以下步骤:

  1. 打开 IAM 控制台
  2. 创建 IAM 角色,Lambda 函数使用该角色在账户中运行。
  3. AWSLambdaBasicExecutionRole 策略附加到该角色。
  4. 附加策略,允许账户 B 中的 IAM 角色代入账户 A 中的 IAM 角色。
    策略示例:
    {    
        "Version": "2012-10-17",
        "Statement": {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::Account_A_ID:role/role-on-source-account"
        }
    }
    **注意:**将 Account_A_ID 替换为您的账户 A ID,将 role-on-source-account 替换为账户 A 中的 IAM 角色的名称。

有关跨账户最佳实践的信息,请参阅 IAM 中的安全最佳实践

创建 Lambda 函数

创建 Lambda 函数。Lambda 函数假设账户 A IAM 角色可以访问 Amazon Bedrock 模型。然后,该函数使用代入角色的凭证来创建与 Amazon Bedrock 模型交互的 Amazon Bedrock 运行时客户端。

您的 Lambda 函数必须与以下 Python 函数示例类似:

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')
     }