Skip to content

Commit 0dec32e

Browse files
committed
Added IAM role and scenario for running knowledge base APIs
1 parent 8351553 commit 0dec32e

File tree

3 files changed

+308
-10
lines changed

3 files changed

+308
-10
lines changed

python/example_code/bedrock-agent/knowledge_bases/knowledge_base.py

Lines changed: 114 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
1010
This example demonstrates how to:
1111
- Create a Bedrock Agent client
12-
- Create a knowledge base
1312
- Get details of a knowledge base
1413
- Update a knowledge base
1514
- List knowledge bases in your account
@@ -21,7 +20,9 @@
2120
from pprint import pprint
2221
import boto3
2322
import uuid
23+
import time
2424
from botocore.exceptions import ClientError
25+
from roles import create_knowledge_base_role, delete_knowledge_base_role
2526

2627
logger = logging.getLogger(__name__)
2728

@@ -232,6 +233,107 @@ def list_knowledge_bases(bedrock_agent_client, max_results=None):
232233
# snippet-end:[python.example_code.bedrock-agent.list_knowledge_bases]
233234

234235

236+
def run_knowledge_base_scenario():
237+
"""
238+
1. Create an IAM role for the knowledge base
239+
2. Create a knowledge base
240+
3. Get details of the knowledge base
241+
4. Update the knowledge base
242+
5. Delete the knowledge base and IAM role
243+
"""
244+
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
245+
246+
print("-" * 88)
247+
print("Welcome to the Amazon Bedrock Knowledge Bases scenario.")
248+
print("-" * 88)
249+
250+
# Create clients
251+
bedrock_agent_client = boto3.client(service_name="bedrock-agent")
252+
iam_client = boto3.client(service_name="iam")
253+
254+
# Generate unique names for resources
255+
kb_name = "example-knowledge-base-" + str(uuid.uuid4().hex[:8])
256+
role_name = "example-kb-role" + str(uuid.uuid4().hex[:8])
257+
258+
knowledge_base_id = None
259+
260+
try:
261+
# Step 1: Create IAM role
262+
print("\nCreating IAM role: " + role_name + " ...")
263+
role = create_knowledge_base_role(iam_client, role_name)
264+
role_arn = role['Arn']
265+
print("Created role with ARN: " + role_arn)
266+
267+
# Wait for role to propagate
268+
print("Waiting for role to propagate...")
269+
time.sleep(10)
270+
271+
# Step 2: Create knowledge base
272+
print("Creating knowledge base: " + kb_name + " ...")
273+
kb = create_knowledge_base(
274+
bedrock_agent_client,
275+
kb_name,
276+
role_arn,
277+
"Example knowledge base for demonstration"
278+
)
279+
knowledge_base_id = kb["knowledgeBaseId"]
280+
print("Created knowledge base with ID: " + knowledge_base_id)
281+
282+
# Step 3: Get knowledge base details
283+
print("\nGetting details for knowledge base: " + knowledge_base_id + " ...")
284+
kb_details = get_knowledge_base(bedrock_agent_client, knowledge_base_id)
285+
print("Knowledge base details:")
286+
pprint(kb_details)
287+
288+
# Step 4: Update knowledge base
289+
new_name = kb_name + "-updated"
290+
print("\nUpdating knowledge base name to: " + new_name + " ...")
291+
updated_kb = update_knowledge_base(
292+
bedrock_agent_client,
293+
knowledge_base_id,
294+
new_name,
295+
"Updated description for the knowledge base",
296+
role_arn
297+
)
298+
print("Updated knowledge base details:")
299+
pprint(updated_kb)
300+
301+
# Step 5: List knowledge bases
302+
print("\nListing all knowledge bases:")
303+
all_kbs = list_knowledge_bases(bedrock_agent_client)
304+
print("Found " + len(all_kbs) + " knowledge bases.")
305+
306+
print("\nCleaning up resources...")
307+
if knowledge_base_id:
308+
print("Deleting knowledge base " + knowledge_base_id + " ...")
309+
delete_knowledge_base(bedrock_agent_client, knowledge_base_id)
310+
print("Knowledge base " + knowledge_base_id + " deleted successfully.")
311+
312+
print("Deleting IAM role " + role_name + " ...")
313+
delete_knowledge_base_role(iam_client, role_name)
314+
print("Role " + role_name + " deleted successfully.")
315+
316+
print("\nScenario completed successfully!")
317+
318+
except ClientError as error:
319+
print("Operation failed: " + error)
320+
# Clean up resources on error
321+
if knowledge_base_id:
322+
try:
323+
print("Attempting to delete knowledge base " + knowledge_base_id + " ...")
324+
delete_knowledge_base(bedrock_agent_client, knowledge_base_id)
325+
except Exception as e:
326+
print("Failed to delete knowledge base: " + e)
327+
328+
try:
329+
print("Attempting to delete IAM role: " + role_name + " ...")
330+
delete_knowledge_base_role(iam_client, role_name)
331+
except Exception as e:
332+
print("Failed to delete IAM role: " + e)
333+
334+
print("-" * 88)
335+
336+
235337
def main():
236338
"""
237339
Shows how to use the Bedrock Agent API to work with knowledge bases.
@@ -243,7 +345,7 @@ def main():
243345
)
244346
parser.add_argument(
245347
"--action",
246-
choices=["list", "create", "get", "update", "delete"],
348+
choices=["list", "create", "get", "update", "delete", "scenario"],
247349
default="list",
248350
help="The action to perform on knowledge bases.",
249351
)
@@ -277,12 +379,14 @@ def main():
277379
bedrock_agent_client = boto3.client(service_name="bedrock-agent")
278380

279381
try:
280-
if args.action == "list":
382+
if args.action == "scenario":
383+
run_knowledge_base_scenario()
384+
elif args.action == "list":
281385
print("Listing knowledge bases in your AWS account...")
282386
knowledge_bases = list_knowledge_bases(bedrock_agent_client, args.max_results)
283387

284388
if knowledge_bases:
285-
print(f"Found {len(knowledge_bases)} knowledge bases:")
389+
print("Found " + len(knowledge_bases) + " knowledge bases")
286390
for kb in knowledge_bases:
287391
print("\n" + "-" * 40)
288392
pprint(kb)
@@ -294,7 +398,7 @@ def main():
294398
print("Error: --name and --role-arn are required for create action.")
295399
return
296400

297-
print(f"Creating knowledge base '{args.name}'...")
401+
print("Creating knowledge base " + args.name + " ...")
298402
kb = create_knowledge_base(
299403
bedrock_agent_client,
300404
args.name,
@@ -309,7 +413,7 @@ def main():
309413
print("Error: --knowledge-base-id is required for get action.")
310414
return
311415

312-
print(f"Getting details for knowledge base {args.knowledge_base_id}...")
416+
print("Getting details for knowledge base " + args.knowledge_base_id + " ...")
313417
kb = get_knowledge_base(bedrock_agent_client, args.knowledge_base_id)
314418
print("Knowledge base details:")
315419
pprint(kb)
@@ -319,7 +423,7 @@ def main():
319423
print("Error: --knowledge-base-id is required for update action.")
320424
return
321425

322-
print(f"Updating knowledge base {args.knowledge_base_id}...")
426+
print("Updating knowledge base " + args.knowledge_base_id + " ...")
323427
kb = update_knowledge_base(
324428
bedrock_agent_client,
325429
args.knowledge_base_id,
@@ -335,12 +439,12 @@ def main():
335439
print("Error: --knowledge-base-id is required for delete action.")
336440
return
337441

338-
print(f"Deleting knowledge base {args.knowledge_base_id}...")
442+
print("Deleting knowledge base " + args.knowledge_base_id + " ...")
339443
if delete_knowledge_base(bedrock_agent_client, args.knowledge_base_id):
340-
print(f"Knowledge base {args.knowledge_base_id} deleted successfully.")
444+
print("Knowledge base " + args.knowledge_base_id + " deleted successfully.")
341445

342446
except ClientError as error:
343-
print(f"Operation failed: {error}")
447+
print("Operation failed: " + error)
344448

345449
print("-" * 88)
346450

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
"""
5+
IAM Role Management for Amazon Bedrock Knowledge Bases
6+
7+
This module provides functionality to create, update, and delete IAM roles specifically
8+
configured for Amazon Bedrock knowledge bases. It handles the complete lifecycle of IAM roles
9+
including trust relationships, inline policies, and permissions management.
10+
"""
11+
import logging
12+
import json
13+
from botocore.exceptions import ClientError
14+
15+
logging.basicConfig(
16+
level=logging.INFO
17+
)
18+
logger = logging.getLogger(__name__)
19+
20+
# snippet-start:[python.example_code.bedrock-agent.knowledge_base_iam_role]
21+
22+
def create_knowledge_base_role(client, role_name):
23+
"""
24+
Creates an IAM role for Amazon Bedrock with permissions to manage knowledge bases.
25+
26+
Args:
27+
client: The Boto3 IAM client.
28+
role_name (str): Name for the new IAM role.
29+
Returns:
30+
dict: The created role information including ARN.
31+
"""
32+
33+
# Trust relationship policy - allows Amazon Bedrock service to assume this role.
34+
trust_policy = {
35+
"Version": "2012-10-17",
36+
"Statement": [{
37+
"Effect": "Allow",
38+
"Principal": {
39+
"Service": "bedrock.amazonaws.com"
40+
},
41+
"Action": "sts:AssumeRole"
42+
}]
43+
}
44+
45+
# Basic inline policy for knowledge base operations
46+
knowledge_base_policy = {
47+
"Version": "2012-10-17",
48+
"Statement": [
49+
{
50+
"Effect": "Allow",
51+
"Action": [
52+
"bedrock:InvokeModel",
53+
"bedrock:Retrieve",
54+
"bedrock:RetrieveAndGenerate",
55+
"aoss:APIAccessAll",
56+
"aoss:CreateIndex",
57+
"aoss:DeleteIndex",
58+
"aoss:UpdateIndex",
59+
"aoss:BatchGetCollection",
60+
"aoss:CreateCollection",
61+
"aoss:DeleteCollection"
62+
],
63+
# Using * as placeholder - Later you can update with specific ARNs.
64+
"Resource": "*"
65+
}
66+
]
67+
}
68+
69+
try:
70+
# Create the IAM role with trust policy
71+
logging.info("Creating role: %s", role_name)
72+
role = client.create_role(
73+
RoleName=role_name,
74+
AssumeRolePolicyDocument=json.dumps(trust_policy),
75+
Description="Role for Amazon Bedrock knowledge base operations"
76+
)
77+
78+
# Attach inline policy to the role
79+
print("Attaching inline policy")
80+
client.put_role_policy(
81+
RoleName=role_name,
82+
PolicyName=f"{role_name}-policy",
83+
PolicyDocument=json.dumps(knowledge_base_policy)
84+
)
85+
86+
logging.info("Created Role ARN: %s", role['Role']['Arn'])
87+
return role['Role']
88+
89+
except ClientError as e:
90+
logging.warning("Error creating role: %s", str(e))
91+
raise
92+
except Exception as e:
93+
logging.warning("Unexpected error: %s", str(e))
94+
raise
95+
96+
97+
def update_role_policy(client, role_name, resource_arns):
98+
"""
99+
Updates an IAM role's inline policy with specific resource ARNs.
100+
101+
Args:
102+
client: The Boto3 IAM client.
103+
role_name (str): Name of the existing role.
104+
resource_arns (list): List of resource ARNs to allow access to.
105+
"""
106+
107+
updated_policy = {
108+
"Version": "2012-10-17",
109+
"Statement": [
110+
{
111+
"Effect": "Allow",
112+
"Action": [
113+
"bedrock:InvokeModel",
114+
"bedrock:Retrieve",
115+
"bedrock:RetrieveAndGenerate",
116+
"aoss:APIAccessAll",
117+
"aoss:CreateIndex",
118+
"aoss:DeleteIndex",
119+
"aoss:UpdateIndex",
120+
"aoss:BatchGetCollection",
121+
"aoss:CreateCollection",
122+
"aoss:DeleteCollection"
123+
],
124+
"Resource": resource_arns
125+
}
126+
]
127+
}
128+
129+
try:
130+
client.put_role_policy(
131+
RoleName=role_name,
132+
PolicyName=f"{role_name}-policy",
133+
PolicyDocument=json.dumps(updated_policy)
134+
)
135+
logging.info("Updated policy for role: %s", role_name)
136+
137+
except ClientError as e:
138+
logging.warning("Error updating role policy: %s", str(e))
139+
raise
140+
141+
142+
def delete_knowledge_base_role(client, role_name):
143+
"""
144+
Deletes an IAM role.
145+
146+
Args:
147+
client: The Boto3 IAM client.
148+
role_name (str): Name of the role to delete.
149+
"""
150+
try:
151+
# Detach and delete inline policies
152+
policies = client.list_role_policies(RoleName=role_name)['PolicyNames']
153+
for policy_name in policies:
154+
client.delete_role_policy(RoleName=role_name, PolicyName=policy_name)
155+
156+
# Delete the role
157+
client.delete_role(RoleName=role_name)
158+
logging.info("Deleted role: %s", role_name)
159+
160+
except ClientError as e:
161+
logging.info("Error Deleting role: %s", str(e))
162+
raise
163+
164+
# snippet-end:[python.example_code.bedrock-agent.knowledge_base_iam_role]
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
"""
5+
Purpose
6+
7+
Shows how to use the AWS SDK for Python (Boto3) with Amazon Bedrock to run a complete
8+
knowledge base scenario.
9+
10+
This example demonstrates how to:
11+
- Create an IAM role for the knowledge base
12+
- Create a knowledge base
13+
- Get details of a knowledge base
14+
- Update a knowledge base
15+
- List knowledge bases in your account
16+
- Delete the knowledge base and IAM role
17+
"""
18+
19+
import logging
20+
from knowledge_base import run_knowledge_base_scenario
21+
22+
def main():
23+
"""
24+
Runs the Amazon Bedrock Knowledge Bases scenario.
25+
"""
26+
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
27+
run_knowledge_base_scenario()
28+
29+
if __name__ == "__main__":
30+
main()

0 commit comments

Comments
 (0)