Saltar al contenido

¿Cómo soluciono el error "botocore.errorfactory.AccessDeniedException" que recibo cuando intento usar una función Lambda entre cuentas para invocar Amazon Bedrock?

4 minutos de lectura
0

Quiero invocar mis modelos de Amazon Bedrock en mi cuenta de AWS. He intentado usar una función AWS Lambda entre cuentas con versiones ejecutables de Python. Sin embargo, he recibido un mensaje de error "botocore.errorfactory.AccessDeniedException".

Descripción corta

Cuando utilizas una función de Lambda entre cuentas para invocar Amazon Bedrock, es posible que recibas el siguiente mensaje de error:

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

Para resolverlo, haz lo siguiente:

  • Crea un rol de AWS Identity and Access Management (IAM) en la cuenta A, la cuenta propietaria del modelo de Amazon Bedrock. A continuación, adjunte la política AmazonBedrockFullAccess al rol para que pueda acceder a la cuenta B, la cuenta propietaria de la función de Lambda.
  • Crea un rol de IAM en la cuenta B. A continuación, asocia el rol de IAM a una política de ejecución básica para permitir que el rol asumido acceda al rol de IAM de la cuenta A.

Nota: Cuando utilices modelos fundacionales de Amazon Bedrock, asegúrate de consultar las condiciones de precios del vendedor.

Asegúrate de solicitar el acceso al modelo para tu modelo de Amazon Bedrock en la cuenta A. Confirma que el estado de acceso cambia a Acceso concedido.

Resolución

Configuración de la cuenta A

Completa los siguientes pasos para la cuenta propietaria de los modelos de Amazon Bedrock:

  1. Abre la consola de IAM.
  2. Crea un rol de IAM para la cuenta A.
  3. Adjunta la política AmazonBedrockFullAccess al rol de IAM.
  4. Adjunta una política de relación de confianza que permita que el rol de la función de Lambda en la cuenta B asuma el rol en la cuenta A.
    Ejemplo de política de relación de confianza:
    {    
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam::Account_B_ID:role/my-lambda-execution-role"
                },
                "Action": "sts:AssumeRole"
            }
        ]
    }
    Nota: Sustituye Account_B_ID por el ID de la cuenta B y my-lambda-execution-role por el rol de ejecución de la función de Lambda.

Configuración de la cuenta B

Completa los siguientes pasos para el rol propietario de la función de Lambda:

  1. Abre la consola de IAM.
  2. Crea un rol de IAM que la función de Lambda utilice para ejecutarse en la cuenta.
  3. Adjunta la política AWSLambdaBasicExecutionRole al rol.
  4. Adjunta una política que permita al rol de IAM de la cuenta B asumir el rol de IAM de la cuenta A.
    Ejemplo de política:
    {    
        "Version": "2012-10-17",
        "Statement": {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::Account_A_ID:role/role-on-source-account"
        }
    }
    Nota: Sustituye Account_A_ID por el ID de la cuenta A y role-on-source-account por el nombre del rol de IAM de la cuenta A.

Para obtener información sobre las prácticas recomendadas entre cuentas, consulta Prácticas recomendadas de seguridad en IAM.

Creación de una función de Lambda

Crea una función de Lambda. La función de Lambda asume el rol de IAM de la cuenta A que tiene acceso a los modelos de Amazon Bedrock. A continuación, la función utiliza las credenciales del rol asumido para crear los clientes de versión ejecutable de Amazon Bedrock que interactúan con los modelos de Amazon Bedrock.

La función de Lambda debe tener un aspecto similar al siguiente ejemplo de función de 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')
     }