Skip to content

AWS Bedrock Knowledge Base Role Error with AWS CDK

0

Hi team, I'm trying to create a knowledge base using AWS CDK by following guidelines from:

The snippet of CDK code in Typescript I have is like: (notice I have some resources defined previously like the rds cluster and others)

/**
 * Data Source
 */
const dataSourceBucket = this.bucket = new s3.Bucket(this, `KnowledgeBaseDataSource${id}`, {
    bucketName: getStackPrefixed('data-source-bucket', environment),
    removalPolicy: cdk.RemovalPolicy.DESTROY,
    autoDeleteObjects: true,
    publicReadAccess: false,
    blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
    encryption: s3.BucketEncryption.S3_MANAGED,
});

/**
 * IAM
 */
const bedrockPrincipal = new iam.ServicePrincipal('bedrock.amazonaws.com', {
    conditions: {
        StringEquals: {
            'aws:SourceAccount': this.account,
        },
        ArnLike: {
            'aws:SourceArn': `arn:aws:bedrock:${this.region}:${this.account}:knowledge-base/*`,
        },
    },
});
const knowledgeBaseRole = new iam.Role(this, `KnowledgeBaseRole${id}`, {
    roleName: getStackPrefixed('knowledge-base-role', environment),
    assumedBy: bedrockPrincipal,
    inlinePolicies: {
        secretAccessPolicy: new iam.PolicyDocument({
            statements: [
                new iam.PolicyStatement({
                    sid: 'AllowGetSecret',
                    effect: iam.Effect.ALLOW,
                    actions: [
                        'secretsmanager:GetSecretValue',
                    ],
                    resources: [
                        databaseSecret.secretArn,
                        databaseSecretFullARN,
                    ],
                }),
            ],
        }),
        bedrockModelsPolicies: new iam.PolicyDocument({
            statements: [
                new iam.PolicyStatement({
                    sid: 'AllowInvokeEmbeddingModel',
                    effect: iam.Effect.ALLOW,
                    actions: [
                        'bedrock:InvokeModel',
                        'bedrock:InvokeModelWithResponseStream',
                    ],
                    resources: [
                        embeddingModel.modelArn,
                    ],
                }),
                new iam.PolicyStatement({
                    sid: 'AllowListModels',
                    effect: iam.Effect.ALLOW,
                    actions: [
                        'bedrock:ListCustomModels',
                    ],
                    resources: ['*'],
                }),
            ],
        }),
        s3BucketPolicies: new iam.PolicyDocument({
            statements: [
                new iam.PolicyStatement({
                    sid: 'AllowBucketAccess',
                    effect: iam.Effect.ALLOW,
                    actions: [
                        's3:ListBucket',
                        's3:GetObject',
                    ],
                    resources: [
                        dataSourceBucket.bucketArn,
                        dataSourceBucket.arnForObjects('*'),
                    ],
                    conditions: {
                        StringEquals: { 'aws:PrincipalAccount': [this.account], },
                    },
                }),
            ],
        }),
        rdsClusterPolicies: new iam.PolicyDocument({
            statements: [
                new iam.PolicyStatement({
                    sid: 'AllowDescribeCluster',
                    effect: iam.Effect.ALLOW,
                    actions: [
                        'rds:DescribeDBClusters',
                    ],
                    resources: [
                        databaseCluster.clusterArn,
                    ],
                }),
                new iam.PolicyStatement({
                    sid: 'AllowExecutionRDSData',
                    effect: iam.Effect.ALLOW,
                    actions: [
                        'rds-data:BatchExecuteStatement',
                        'rds-data:ExecuteStatement',
                    ],
                    resources: [
                        databaseCluster.clusterArn,
                    ],
                }),
            ],
        }),
    },
});

And then I create the KnowledgeBase and its DataSource as follows

/**
 * Bedrock
 */
this.knowledgeBase = new bedrock.CfnKnowledgeBase(this, `KnowledgeBase${id}`, {
    name: getStackPrefixed('knowledge-base', environment),
    description: 'Knowledge base for the rag playground project for learning purposes',
    roleArn: knowledgeBaseRole.roleArn,
    storageConfiguration: {
        type: 'RDS',
        rdsConfiguration: {
            credentialsSecretArn: databaseSecret.secretArn,
            databaseName,
            resourceArn: databaseCluster.clusterArn,
            tableName: 'bedrock_integration.bedrock_kb',
            fieldMapping: {
                metadataField: 'metadata',
                primaryKeyField: 'id',
                textField: 'chunks',
                vectorField: 'embeddings',
            },
        },
    },
    knowledgeBaseConfiguration: {
        type: 'VECTOR',
        vectorKnowledgeBaseConfiguration: {
            embeddingModelArn: embeddingModel.modelArn,
        },
    },
});

this.dataSource = new bedrock.CfnDataSource(this, `KnowledgeBaseDataSource`, {
    name: getStackPrefixed('data-source', environment),
    dataDeletionPolicy: 'DELETE',
    description: 'Data source that holds files to ingest as embeddings',
    knowledgeBaseId: this.knowledgeBase.attrKnowledgeBaseId,
    vectorIngestionConfiguration: {
        chunkingConfiguration: {
            chunkingStrategy: 'SEMANTIC',
            semanticChunkingConfiguration: {
                maxTokens: 300,
                bufferSize: 1,
                breakpointPercentileThreshold: 90,
            },
        },
    },
    dataSourceConfiguration: {
        type: 'S3',
        s3Configuration: {
            bucketArn: dataSourceBucket.bucketArn,
            inclusionPrefixes: [
                '/docs',
            ],
        },
    },
});

I'm running cdk deploy locally using an IAM user with key/secret. And I'm getting the following error message:

Resource handler returned message: "The knowledge base storage configuration provided is invalid... The vector database encountered an error while processing the request: Failed to fetch secret arn:aws:secretsmanager:{REGION}:{ACCOUNT}:secret:rag-playground-dev-database-secret: User: arn:aws:sts::{ACCOUNT}:assumed-role/rag-playground-dev-knowledge-base-role/BKB-CP-PUSWYJPM2G-ADmvKF1boAMEbnA= is not authorized to perform: secretsmanager:GetSecretValue on resource: arn:aws:secretsmanager:{REGION}:{ACCOUNT}:secret:rag-playground-dev-database-secret because no session policy allows the secretsmanager:GetSecretValue action.

I'd appreciate any help as I'm trying to setup a demo/talk for a studying group around bedrock, but would need it to be replicable via CDK.

Thanks in advance, LuisK

3 Answers
0
Accepted Answer

Finally, got it solved!

It wasn't been able to read the database secret because I was using the secret Arn. But there's a variation of it called FullArn, which has a 6 random characters suffix that AWS adds to secrets. In the docs it says:

CredentialsSecretArn The Amazon Resource Name (ARN) of the secret that you created in AWS Secrets Manager that is linked to your Amazon RDS database.

But it never mentions that it should be the FullArn.

I was giving permissions to the Role for both anyways:

new iam.PolicyStatement({
    sid: 'AllowGetSecret',
    effect: iam.Effect.ALLOW,
    actions: [
        'secretsmanager:GetSecretValue',
    ],
    resources: [
        databaseSecretARN,
        databaseSecretFullARN,
    ],
}),

but seems that didn't matter, the rdsConfiguration needed the FullArn.

Basically

DON'T:

storageConfiguration: {
                type: 'RDS',
                rdsConfiguration: {
                    credentialsSecretArn: databaseSecret.secretArn,

RATHER DO:

storageConfiguration: {
                type: 'RDS',
                rdsConfiguration: {
                    credentialsSecretArn: databaseSecret.secretFullArn,

That way I was able to create the KnowledgeBase. Thing is, the error message showed the Arn, never suggested anything about the FullArn

But, anyway, glad to finally find out what was it.

Hope it helps others.

Regards, LuisK

answered a year ago
EXPERT
reviewed a year ago
0

Hello.

It seems that you cannot access SecretsManager using the Bedrock Knowledge Base IAM role, so please check if you can access it by setting the "resources" section of the policy below to "*".

const knowledgeBaseRole = new iam.Role(this, `KnowledgeBaseRole${id}`, {
    roleName: getStackPrefixed('knowledge-base-role', environment),
    assumedBy: bedrockPrincipal,
    inlinePolicies: {
        secretAccessPolicy: new iam.PolicyDocument({
            statements: [
                new iam.PolicyStatement({
                    sid: 'AllowGetSecret',
                    effect: iam.Effect.ALLOW,
                    actions: [
                        'secretsmanager:GetSecretValue',
                    ],
                    resources: [
                        "*"
                    ],
                }),
            ],
        }),

By the way, the ARN displayed in the error message seems to be as shown below. Is this ARN correct?
Please also check that the SecretsManager you are connecting to is correct.

arn:aws:secretsmanager:{REGION}:{ACCOUNT}:secret:rag-playground-dev-database-secret
EXPERT
answered a year ago
  • Hi Riku, yes, I just masked the region and account values from its name. But I replace those with this.region and this.account in CDK Typescript.

    That secret comes from an instance of rds.DatabaseSecret, like:

    new rds.DatabaseSecret(this, `DatabaseSecret${id}`, {
        username: 'some-username-goes-here',
        secretName: getStackPrefixed('database-secret', environment), // This just prefixes strings with stack name and environment
    });
    

    Update:

    I tried giving it permissions to actions: secretsmanager:* and resources: * and got same error.

  • Will it result in an error if you use 'new iam.ServicePrincipal('bedrock.amazonaws.com')' for 'assumedBy'? Also, I think the contents of the IAM policy itself are correct, so it is possible that IAM's eventual consistency is being affected. So, why not create the IAM-related resources and then wait for a while to create the Bedrock knowledge base?

    const knowledgeBaseRole = new iam.Role(this, `KnowledgeBaseRole${id}`, {
        roleName: getStackPrefixed('knowledge-base-role', environment),
        assumedBy: new iam.ServicePrincipal('bedrock.amazonaws.com'),
        inlinePolicies: {
            secretAccessPolicy: new iam.PolicyDocument({
                statements: [
                    new iam.PolicyStatement({
                        sid: 'AllowGetSecret',
                        effect: iam.Effect.ALLOW,
                        actions: [
                            'secretsmanager:GetSecretValue',
                        ],
                        resources: [
                            "*"
                        ],
                    }),
                ],
            }),
    
  • Hey Riku, thanks for reaching back.

    Yeah, if you see in my code, I'm passing an instance of ServicePrincipal for bedrock already. That's failing, with and/or without the conditions. Also tried adding more general permissions like:

    new iam.PolicyStatement({
                        sid: 'AllowGetSecret',
                        effect: iam.Effect.ALLOW,
                        actions: [
                            'secretsmanager:*',
                        ],
                        resources: [
                           '*'
                        ],
                    }),
    

    and still didn't work. Could be a cyclic dependency between Bedrock and IAM, since Bedrock is kinda a new service, idk.

  • There appears to be a difference in error messages between automatically generated IAM roles and IAM roles created with CDK. First, try creating an IAM role with CDK without creating a Bedrock knowledge base and see if there is any difference from the automatically created IAM role.

    # CDK
    because no session policy allows the secretsmanager:GetSecretValue action.
    
    # automatically
    no identity-based policy allows the secretsmanager:GetSecretValue action
    
  • Hey Riku, yeah, that was my thought too. I've already done that, compared the trusted policy and each policy attached, line by line, they look the same, only difference are the Sid properties and naming of policies and roles.

    Still no luck

0

I wanted to try something to see if it was something wrong about the Role and seems it could be about the CDK KnowledgeBase construct, not sure, but, here what I tried.

  1. I manually created a knowledge base through aws console Enter image description here

  2. I verified it works, it ingests files in a s3 bucket and vectorizes it in the aurora database and I can ask it questions about the documents ingested, that works.

  3. I used the ARN of that Role that was created automatically by using the aws console in my CDK construct.

And guess what, got same error but for the new Role auto-created:

CREATE_FAILED        | AWS::Bedrock::KnowledgeBase | KnowledgeBaseknowledgebase
Resource handler returned message: "The knowledge base storage configuration provided is invalid... The vector database encountered an error while processing the request: Failed to fetch secret arn:aws:secretsmanager:us-east-1:{MY ACCOUNT ID GOES HERE}:secret:rag-playground-dev-database-secret: User: arn:aws:sts::{MY ACCOUNT ID GOES HERE}:assumed-role/AmazonBedrockExecutionRoleForKnowledgeBase_ng35e/BKB-CP-IAWGPUFYTE-AIZo_FdnoAMEg5A= is not authorized to perform: secretsmanager:GetSecretValue on resource: arn:aws:secretsmanager:us-east-1:{MY ACCOUNT ID GOES HERE}:secret:rag-playground-dev-database-secret because no identity-based policy allows the secretsmanager:GetSecretValue action (Service: RdsData, Status Code: 403, Request ID: 99512149-746e-47eb-a115-f97c7afdcad2) (Service: BedrockAgent, Status Code: 400, Request ID:a1107d35-f3e3-4744-8282-81d9016b8bb3)" (RequestToken: c33b73cd-5ada-9c43-3f21-54466d233b0b, HandlerErrorCode: InvalidRequest)

Note: I'm using CDK Typescript version 2.162.3 in case it helps for debugging purposes.

Thanks

answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.