AWS code-library medium security documentation change
Summary
Added comprehensive code example for creating, deploying, and invoking an Amazon Bedrock flow to generate music playlists, including IAM role management and resource cleanup
Security assessment
The change demonstrates IAM role creation with least-privilege policy updates (replacing wildcard '*' with specific ARNs) and proper resource cleanup. While not fixing a specific vulnerability, it implements security best practices by showing how to properly scope permissions for Bedrock flows. The initial wildcard permission followed by policy update pattern addresses potential over-permission risks.
Diff
diff --git a/code-library/latest/ug/python_3_bedrock-agent-runtime_code_examples.md b/code-library/latest/ug/python_3_bedrock-agent-runtime_code_examples.md index 0707d0296..703337486 100644 --- a//code-library/latest/ug/python_3_bedrock-agent-runtime_code_examples.md +++ b//code-library/latest/ug/python_3_bedrock-agent-runtime_code_examples.md @@ -359,0 +360,689 @@ Invoke a flow. +The following code example shows how to: + + * Create an execution role for the flow. + + * Create the flow. + + * Deploy the fully configured flow. + + * Invoke the flow with user-provided prompts. + + * Delete all created resources. + + + + +**SDK for Python (Boto3)** + + +###### Note + +There's more on GitHub. Find the complete example and learn how to set up and run in the [AWS Code Examples Repository](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/python/example_code/bedrock-agent#code-examples). + +Generates a music playlist based on user-specified genre and number of songs. + + + from datetime import datetime + import logging + import boto3 + + from botocore.exceptions import ClientError + + from roles import create_flow_role, delete_flow_role, update_role_policy + from flow import create_flow, prepare_flow, delete_flow + from run_flow import run_playlist_flow + from flow_version import create_flow_version, delete_flow_version + from flow_alias import create_flow_alias, delete_flow_alias + + logging.basicConfig( + level=logging.INFO + ) + logger = logging.getLogger(__name__) + + def create_input_node(name): + """ + Creates an input node configuration for an Amazon Bedrock flow. + + The input node serves as the entry point for the flow and defines + the initial document structure that will be passed to subsequent nodes. + + Args: + name (str): The name of the input node. + + Returns: + dict: The input node configuration. + + """ + return { + "type": "Input", + "name": name, + "outputs": [ + { + "name": "document", + "type": "Object" + } + ] + } + + + def create_prompt_node(name, model_id): + """ + Creates a prompt node configuration for a Bedrock flow that generates music playlists. + + The prompt node defines an inline prompt template that creates a music playlist based on + a specified genre and number of songs. The prompt uses two variables that are mapped from + the input JSON object: + - {{genre}}: The genre of music to create a playlist for + - {{number}}: The number of songs to include in the playlist + + Args: + name (str): The name of the prompt node. + model_id (str): The identifier of the foundation model to use for the prompt. + + Returns: + dict: The prompt node. + + """ + + return { + "type": "Prompt", + "name": name, + "configuration": { + "prompt": { + "sourceConfiguration": { + "inline": { + "modelId": model_id, + "templateType": "TEXT", + "inferenceConfiguration": { + "text": { + "temperature": 0.8 + } + }, + "templateConfiguration": { + "text": { + "text": "Make me a {{genre}} playlist consisting of the following number of songs: {{number}}." + } + } + } + } + } + }, + "inputs": [ + { + "name": "genre", + "type": "String", + "expression": "$.data.genre" + }, + { + "name": "number", + "type": "Number", + "expression": "$.data.number" + } + ], + "outputs": [ + { + "name": "modelCompletion", + "type": "String" + } + ] + } + + + def create_output_node(name): + """ + Creates an output node configuration for a Bedrock flow. + + The output node validates that the output from the last node is a string + and returns it unmodified. The input name must be "document". + + Args: + name (str): The name of the output node. + + Returns: + dict: The output node configuration containing the output node: + + """ + + return { + "type": "Output", + "name": name, + "inputs": [ + { + "name": "document", + "type": "String", + "expression": "$.data" + } + ] + } + + + + + def create_playlist_flow(client, flow_name, flow_description, role_arn, prompt_model_id): + """ + Creates the playlist generator flow. + Args: + client: bedrock agent boto3 client. + role_arn (str): Name for the new IAM role. + prompt_model_id (str): The id of the model to use in the prompt node. + Returns: + dict: The response from the create_flow operation. + """ + + input_node = create_input_node("FlowInput") + prompt_node = create_prompt_node("MakePlaylist", prompt_model_id) + output_node = create_output_node("FlowOutput") + + # Create connections between the nodes + connections = [] + + # First, create connections between the output of the flow + # input node and each input of the prompt node. + for prompt_node_input in prompt_node["inputs"]: + connections.append( + { + "name": "_".join([input_node["name"], prompt_node["name"], + prompt_node_input["name"]]), + "source": input_node["name"], + "target": prompt_node["name"], + "type": "Data", + "configuration": { + "data": { + "sourceOutput": input_node["outputs"][0]["name"], + "targetInput": prompt_node_input["name"] + } + }