Skip to content

Commit

Permalink
feat(bedrockconstruct): added support for IAM existingRole (#454)
Browse files Browse the repository at this point in the history
* feat(constructprop): added existinRole to bedrock agent and kb

* feat(constructprop): added existinRole to bedrock agent and kb

* chore: self mutation

Signed-off-by: github-actions <[email protected]>

* chore: self mutation

Signed-off-by: github-actions <[email protected]>

---------

Signed-off-by: github-actions <[email protected]>
Signed-off-by: Dinesh Sajwan <[email protected]>
Co-authored-by: Dinesh Sajwan <[email protected]>
Co-authored-by: github-actions <[email protected]>
Co-authored-by: Alain Krok <[email protected]>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
5 people authored May 22, 2024
1 parent 8225896 commit a8d4373
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 66 deletions.
10 changes: 10 additions & 0 deletions apidocs/interfaces/bedrock.AgentProps.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Properties for a Bedrock Agent.
- [description](bedrock.AgentProps.md#description)
- [enableUserInput](bedrock.AgentProps.md#enableuserinput)
- [encryptionKey](bedrock.AgentProps.md#encryptionkey)
- [existingRole](bedrock.AgentProps.md#existingrole)
- [foundationModel](bedrock.AgentProps.md#foundationmodel)
- [idleSessionTTL](bedrock.AgentProps.md#idlesessionttl)
- [instruction](bedrock.AgentProps.md#instruction)
Expand Down Expand Up @@ -98,6 +99,15 @@ KMS encryption key to use for the agent.

___

### existingRole

`Optional` `Readonly` **existingRole**: `Role`

The existing IAM Role for the agent with a trust policy that
allows the Bedrock service to assume the role.

___

### foundationModel

`Readonly` **foundationModel**: [`BedrockFoundationModel`](../classes/bedrock.BedrockFoundationModel.md)
Expand Down
13 changes: 13 additions & 0 deletions apidocs/interfaces/bedrock.KnowledgeBaseProps.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Properties for a knowledge base

- [description](bedrock.KnowledgeBaseProps.md#description)
- [embeddingsModel](bedrock.KnowledgeBaseProps.md#embeddingsmodel)
- [existingRole](bedrock.KnowledgeBaseProps.md#existingrole)
- [indexName](bedrock.KnowledgeBaseProps.md#indexname)
- [instruction](bedrock.KnowledgeBaseProps.md#instruction)
- [knowledgeBaseState](bedrock.KnowledgeBaseProps.md#knowledgebasestate)
Expand Down Expand Up @@ -45,6 +46,18 @@ The embeddings model for the knowledge base

___

### existingRole

`Optional` `Readonly` **existingRole**: `Role`

Existing IAM role with a policy statement
granting permission to invoke the specific embeddings model.
Any entity (e.g., an AWS service or application) that assumes
this role will be able to invoke or use the
specified embeddings model within the Bedrock service.

___

### indexName

`Optional` `Readonly` **indexName**: `string`
Expand Down
80 changes: 45 additions & 35 deletions src/cdk-lib/bedrock/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,13 @@ export interface AgentProps {
* @default - A name is automatically generated.
*/
readonly name?: string;

/**
* The existing IAM Role for the agent with a trust policy that
* allows the Bedrock service to assume the role.
*/
readonly existingRole?: iam.Role;

/**
* A narrative instruction to provide the agent as context.
*/
Expand Down Expand Up @@ -376,44 +383,47 @@ export class Agent extends Construct {
'bedrock-agent',
{ maxLength: 32, lower: true, separator: '-' });

this.role = new iam.Role(this, 'Role', {
assumedBy: new iam.ServicePrincipal('bedrock.amazonaws.com'),
roleName: generatePhysicalNameV2(
this,
'AmazonBedrockExecutionRoleForAgents_',
{ maxLength: 64, lower: false }),
});

this.role.assumeRolePolicy!.addStatements(
new iam.PolicyStatement({
actions: ['sts:AssumeRole'],
principals: [new iam.ServicePrincipal('bedrock.amazonaws.com')],
conditions: {
StringEquals: {
'aws:SourceAccount': cdk.Stack.of(this).account,
},
ArnLike: {
'aws:SourceArn': cdk.Stack.of(this).formatArn({
service: 'bedrock',
resource: 'agent',
resourceName: '*',
arnFormat: cdk.ArnFormat.SLASH_RESOURCE_NAME,
}),
},
},
}),
);
if (props.existingRole) {
this.role = props.existingRole;
} else {
this.role = new iam.Role(this, 'Role', {
assumedBy: new iam.ServicePrincipal('bedrock.amazonaws.com'),
roleName: generatePhysicalNameV2(
this,
'AmazonBedrockExecutionRoleForAgents_',
{ maxLength: 64, lower: false }),
});

new iam.Policy(this, 'AgentFMPolicy', {
roles: [this.role],
statements: [
this.role.assumeRolePolicy!.addStatements(
new iam.PolicyStatement({
actions: ['bedrock:InvokeModel'],
resources: [props.foundationModel.asArn(this)],
actions: ['sts:AssumeRole'],
principals: [new iam.ServicePrincipal('bedrock.amazonaws.com')],
conditions: {
StringEquals: {
'aws:SourceAccount': cdk.Stack.of(this).account,
},
ArnLike: {
'aws:SourceArn': cdk.Stack.of(this).formatArn({
service: 'bedrock',
resource: 'agent',
resourceName: '*',
arnFormat: cdk.ArnFormat.SLASH_RESOURCE_NAME,
}),
},
},
}),
],
});

);

new iam.Policy(this, 'AgentFMPolicy', {
roles: [this.role],
statements: [
new iam.PolicyStatement({
actions: ['bedrock:InvokeModel'],
resources: [props.foundationModel.asArn(this)],
}),
],
});
}

const agent = new bedrock.CfnAgent(this, 'Agent', {

Expand Down
75 changes: 44 additions & 31 deletions src/cdk-lib/bedrock/knowledge-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ export interface KnowledgeBaseProps {
*/
readonly description?: string;

/**
* Existing IAM role with a policy statement
* granting permission to invoke the specific embeddings model.
* Any entity (e.g., an AWS service or application) that assumes
* this role will be able to invoke or use the
* specified embeddings model within the Bedrock service.
*/
readonly existingRole?: iam.Role;

/**
* A narrative description of the knowledge base.
*
Expand Down Expand Up @@ -261,39 +270,43 @@ export class KnowledgeBase extends Construct {
'KB',
{ maxLength: 32 });

const roleName = generatePhysicalNameV2(
this,
'AmazonBedrockExecutionRoleForKnowledgeBase',
{ maxLength: 64 });
this.role = new iam.Role(this, 'Role', {
roleName: roleName,
assumedBy: new iam.ServicePrincipal('bedrock.amazonaws.com'),
});
this.role.assumeRolePolicy!.addStatements(
new iam.PolicyStatement({
actions: ['sts:AssumeRole'],
principals: [new iam.ServicePrincipal('bedrock.amazonaws.com')],
conditions: {
StringEquals: {
'aws:SourceAccount': cdk.Stack.of(this).account,
},
ArnLike: {
'aws:SourceArn': cdk.Stack.of(this).formatArn({
service: 'bedrock',
resource: 'knowledge-base',
resourceName: '*',
arnFormat: cdk.ArnFormat.SLASH_RESOURCE_NAME,
}),
},
},
}),
);

this.role.addToPolicy(new iam.PolicyStatement({
actions: ['bedrock:InvokeModel'],
resources: [embeddingsModel.asArn(this)],
}));
if (props.existingRole) {
this.role = props.existingRole;
} else {
const roleName = generatePhysicalNameV2(
this,
'AmazonBedrockExecutionRoleForKnowledgeBase',
{ maxLength: 64 });
this.role = new iam.Role(this, 'Role', {
roleName: roleName,
assumedBy: new iam.ServicePrincipal('bedrock.amazonaws.com'),
});
this.role.assumeRolePolicy!.addStatements(
new iam.PolicyStatement({
actions: ['sts:AssumeRole'],
principals: [new iam.ServicePrincipal('bedrock.amazonaws.com')],
conditions: {
StringEquals: {
'aws:SourceAccount': cdk.Stack.of(this).account,
},
ArnLike: {
'aws:SourceArn': cdk.Stack.of(this).formatArn({
service: 'bedrock',
resource: 'knowledge-base',
resourceName: '*',
arnFormat: cdk.ArnFormat.SLASH_RESOURCE_NAME,
}),
},
},
}),
);

this.role.addToPolicy(new iam.PolicyStatement({
actions: ['bedrock:InvokeModel'],
resources: [embeddingsModel.asArn(this)],
}));
}
/**
* Create the vector store if the vector store was provided by the user.
* Otherwise check againts all possible vector datastores.
Expand Down

0 comments on commit a8d4373

Please sign in to comment.