Passer au contenu

Comment résoudre l'erreur "botocore.errorfactory.AccessDeniedException" qui s'affiche lorsque j'essaie d'utiliser une fonction Lambda intercompte pour invoquer Amazon Bedrock ?

Lecture de 4 minute(s)
0

Je souhaite invoquer mes modèles Amazon Bedrock dans mon compte AWS. J'ai essayé d'utiliser une fonction AWS Lambda intercompte avec des environnements d'exécution Python. Cependant, j'ai reçu un message d'erreur "botocore.errorfactory.AccessDeniedException".

Brève description

Lorsque vous utilisez une fonction Lambda intercompte pour invoquer Amazon Bedrock, le message d'erreur suivant peut s'afficher :

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

Pour résoudre cette erreur, effectuez les actions suivantes :

  • Créez un rôle Gestion des identités et des accès AWS (AWS IAM) dans le compte A, le compte qui est propriétaire du modèle Amazon Bedrock. Puis, associez la politique AmazonBedrockFullAccess au rôle pour lui permettre d'accéder au compte B, le compte qui est propriétaire de la fonction Lambda.
  • Créez un rôle IAM dans le compte B. Puis, associez le rôle IAM à une politique d'exécution de base pour permettre à son rôle endossé d'accéder au rôle IAM dans le compte A.

Remarque : Lorsque vous utilisez les modèles Amazon Bedrock Foundation, assurez-vous de vérifier les conditions tarifaires du vendeur.

Assurez-vous de demander l'accès au modèle pour votre modèle Amazon Bedrock dans le compte A. Vérifiez que le statut de l'accès passe à Accès accordé.

Résolution

Configurer le compte A

Procédez comme suit pour le compte propriétaire des modèles Amazon Bedrock :

  1. Ouvrez la console IAM.
  2. Créez un rôle IAM pour le compte A.
  3. Associez la politique AmazonBedrockFullAccess au rôle IAM.
  4. Associez une politique de relation d’approbation qui permet au rôle de la fonction Lambda dans le compte B d'endosser le rôle dans le compte A.
    Exemple de politique de relation d’approbation :
    {    
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Principal": {
                    "AWS": "arn:aws:iam::Account_B_ID:role/my-lambda-execution-role"
                },
                "Action": "sts:AssumeRole"
            }
        ]
    }
    Remarque : Remplacez Account_B_ID par l'ID de votre compte B et my-lambda-execution-role par votre rôle d'exécution de la fonction Lambda.

Configurer le compte B

Procédez comme suit pour le rôle propriétaire de la fonction Lambda :

  1. Ouvrez la console IAM.
  2. Créez un rôle IAM que la fonction Lambda utilise pour s'exécuter dans le compte.
  3. Associez la politique AWSLambdaBasicExecutionRole au rôle.
  4. Associez une politique qui permet au rôle IAM du compte B d'endosser le rôle IAM du compte A.
    Exemple de politique :
    {    
        "Version": "2012-10-17",
        "Statement": {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::Account_A_ID:role/role-on-source-account"
        }
    }
    Remarque : Remplacez Account_A_ID par l'ID de votre compte A et role-on-source-account par le nom du rôle IAM du compte A.

Pour plus d'informations sur les bonnes pratiques sur la configuration intercompte, consultez la section Bonnes pratiques relatives à la sécurité dans IAM.

Créer une fonction Lambda

Créez une fonction Lambda. La fonction Lambda endosse le rôle IAM du compte A qui a accès aux modèles Amazon Bedrock. Elle utilise ensuite les informations d'identification du rôle endossé pour créer les clients d’exécution Amazon Bedrock qui interagissent avec les modèles Amazon Bedrock.

Votre fonction Lambda doit se présenter comme dans l'exemple de fonction Python suivant :

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