diff --git a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/README.md b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/README.md index eb8b0c6ba6081..72c153b786e9c 100644 --- a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/README.md +++ b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/README.md @@ -580,6 +580,54 @@ runtime.connections.allowTo(databaseSecurityGroup, ec2.Port.tcp(5432), 'Allow Po runtime.connections.allowToAnyIpv4(ec2.Port.tcp(443), 'Allow HTTPS outbound'); ``` +### Runtime IAM Permissions + +The Runtime construct provides convenient methods for granting IAM permissions to principals that need to invoke the runtime or manage its execution role. + +```typescript fixture=default +const repository = new ecr.Repository(this, "TestRepository", { + repositoryName: "test-agent-runtime", +}); +const agentRuntimeArtifact = agentcore.AgentRuntimeArtifact.fromEcrRepository(repository, "v1.0.0"); + +// Create a runtime +const runtime = new agentcore.Runtime(this, "MyRuntime", { + runtimeName: "my_runtime", + agentRuntimeArtifact: agentRuntimeArtifact, +}); + +// Create a Lambda function that needs to invoke the runtime +const invokerFunction = new lambda.Function(this, "InvokerFunction", { + runtime: lambda.Runtime.PYTHON_3_12, + handler: "index.handler", + code: lambda.Code.fromInline(` +import boto3 +def handler(event, context): + client = boto3.client('bedrock-agentcore') + # Invoke the runtime... + `), +}); + +// Grant permission to invoke the runtime directly +runtime.grantInvokeRuntime(invokerFunction); + +// Grant permission to invoke the runtime on behalf of a user +// (requires X-Amzn-Bedrock-AgentCore-Runtime-User-Id header) +runtime.grantInvokeRuntimeForUser(invokerFunction); + +// Grant both invoke permissions (most common use case) +runtime.grantInvoke(invokerFunction); + +// Grant specific custom permissions to the runtime's execution role +runtime.grant(['bedrock:InvokeModel'], ['arn:aws:bedrock:*:*:*']); + +// Add a policy statement to the runtime's execution role +runtime.addToRolePolicy(new iam.PolicyStatement({ + actions: ['s3:GetObject'], + resources: ['arn:aws:s3:::my-bucket/*'], +})); +``` + ### Other configuration #### Lifecycle configuration diff --git a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/lib/runtime/runtime-base.ts b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/lib/runtime/runtime-base.ts index 255df5002bd49..b2e6634d6c630 100644 --- a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/lib/runtime/runtime-base.ts +++ b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/lib/runtime/runtime-base.ts @@ -258,7 +258,7 @@ export abstract class RuntimeBase extends Resource implements IBedrockAgentRunti return iam.Grant.addToPrincipal({ grantee, actions: RUNTIME_INVOKE_PERMS, - resourceArns: [this.agentRuntimeArn], + resourceArns: [this.agentRuntimeArn, `${this.agentRuntimeArn}/*`], // * is needed because it invoke the endpoint as subresource }); } @@ -272,7 +272,7 @@ export abstract class RuntimeBase extends Resource implements IBedrockAgentRunti return iam.Grant.addToPrincipal({ grantee, actions: RUNTIME_INVOKE_USER_PERMS, - resourceArns: [this.agentRuntimeArn], + resourceArns: [this.agentRuntimeArn, `${this.agentRuntimeArn}/*`], }); } @@ -285,7 +285,7 @@ export abstract class RuntimeBase extends Resource implements IBedrockAgentRunti return iam.Grant.addToPrincipal({ grantee, actions: [...RUNTIME_INVOKE_PERMS, ...RUNTIME_INVOKE_USER_PERMS], - resourceArns: [this.agentRuntimeArn], + resourceArns: [this.agentRuntimeArn, `${this.agentRuntimeArn}/*`], }); } diff --git a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/aws-cdk-bedrock-agentcore-runtime.assets.json b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/aws-cdk-bedrock-agentcore-runtime.assets.json index 06341f96eadd5..d1c46ded86069 100644 --- a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/aws-cdk-bedrock-agentcore-runtime.assets.json +++ b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/aws-cdk-bedrock-agentcore-runtime.assets.json @@ -1,16 +1,16 @@ { "version": "48.0.0", "files": { - "008eb50b72025e8f4132283a463edb475936194d2bd2cd8d6fb4b55109a263a1": { + "2a630006e347b69e07c2f17ca0fd6a668d64b08d3ad3652968938c65c7d354ac": { "displayName": "aws-cdk-bedrock-agentcore-runtime Template", "source": { "path": "aws-cdk-bedrock-agentcore-runtime.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region-5e906448": { + "current_account-current_region-ba9802a9": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "008eb50b72025e8f4132283a463edb475936194d2bd2cd8d6fb4b55109a263a1.json", + "objectKey": "2a630006e347b69e07c2f17ca0fd6a668d64b08d3ad3652968938c65c7d354ac.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -18,7 +18,7 @@ }, "dockerImages": { "f06c9f54828243752afd2df4e39ab9d2987b5ccf44e6bdc05621c18d5488f240": { - "displayName": "TestRuntime/AgentRuntimeArtifactf7fe664d1c8cde42a00e2487074af30f", + "displayName": "TestRuntime/AgentRuntimeArtifact57925e7ddb91ee239b55009d714f9548", "source": { "directory": "asset.f06c9f54828243752afd2df4e39ab9d2987b5ccf44e6bdc05621c18d5488f240" }, diff --git a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/aws-cdk-bedrock-agentcore-runtime.template.json b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/aws-cdk-bedrock-agentcore-runtime.template.json index c716731ef9d9a..8efdd542cda90 100644 --- a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/aws-cdk-bedrock-agentcore-runtime.template.json +++ b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/aws-cdk-bedrock-agentcore-runtime.template.json @@ -310,6 +310,122 @@ "Description": "Version 2 endpoint", "Name": "v2_endpoint" } + }, + "TestInvokerFunctionServiceRole08233DAF": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "TestInvokerFunctionServiceRoleDefaultPolicyC6DC62B6": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "bedrock-agentcore:InvokeAgentRuntime", + "bedrock-agentcore:InvokeAgentRuntimeForUser" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::GetAtt": [ + "TestRuntime65042BB5", + "AgentRuntimeArn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "TestRuntime65042BB5", + "AgentRuntimeArn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "TestInvokerFunctionServiceRoleDefaultPolicyC6DC62B6", + "Roles": [ + { + "Ref": "TestInvokerFunctionServiceRole08233DAF" + } + ] + } + }, + "TestInvokerFunction6708F5AE": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "def handler(event, context): return {\"statusCode\": 200}" + }, + "Description": "Test function to verify runtime grant permissions with sub-resources", + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "TestInvokerFunctionServiceRole08233DAF", + "Arn" + ] + }, + "Runtime": "python3.12" + }, + "DependsOn": [ + "TestInvokerFunctionServiceRoleDefaultPolicyC6DC62B6", + "TestInvokerFunctionServiceRole08233DAF" + ] + }, + "TestInvokerFunctionLogGroup003396AB": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": { + "Fn::Join": [ + "", + [ + "/aws/lambda/", + { + "Ref": "TestInvokerFunction6708F5AE" + } + ] + ] + }, + "RetentionInDays": 731 + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" } }, "Outputs": { diff --git a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/manifest.json b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/manifest.json index 73cbf0f0a233a..36de4937dc8f3 100644 --- a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/008eb50b72025e8f4132283a463edb475936194d2bd2cd8d6fb4b55109a263a1.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/2a630006e347b69e07c2f17ca0fd6a668d64b08d3ad3652968938c65c7d354ac.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -283,6 +283,115 @@ "data": "V2EndpointFFAF1748" } ], + "/aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "runtime": "*", + "handler": "*", + "code": "*", + "description": "*" + } + } + ], + "/aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/ServiceRole": [ + { + "type": "aws:cdk:warning", + "data": "Failed to add construct metadata for node [ServiceRole]. Reason: ValidationError: The result of fromAwsManagedPolicyName can not be used in this API [ack: @aws-cdk/core:addConstructMetadataFailed]" + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addToPrincipalPolicy": [ + {} + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachInlinePolicy": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachInlinePolicy": [ + "*" + ] + } + } + ], + "/aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/ServiceRole/ImportServiceRole": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + } + ], + "/aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "TestInvokerFunctionServiceRole08233DAF" + } + ], + "/aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/ServiceRole/DefaultPolicy": [ + { + "type": "aws:cdk:analytics:construct", + "data": "*" + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachToRole": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "attachToRole": [ + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addStatements": [ + {} + ] + } + } + ], + "/aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "TestInvokerFunctionServiceRoleDefaultPolicyC6DC62B6" + } + ], + "/aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "TestInvokerFunction6708F5AE" + } + ], + "/aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/LogGroup": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "logGroupName": "*" + } + } + ], + "/aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/LogGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "TestInvokerFunctionLogGroup003396AB" + } + ], "/aws-cdk-bedrock-agentcore-runtime/RuntimeId": [ { "type": "aws:cdk:logicalId", @@ -878,5 +987,5 @@ } } }, - "minimumCliVersion": "2.1031.2" + "minimumCliVersion": "2.1033.0" } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/tree.json b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/tree.json index cc166247822cc..67dd12bf1e29d 100644 --- a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.js.snapshot/tree.json @@ -1 +1 @@ -{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-bedrock-agentcore-runtime":{"id":"aws-cdk-bedrock-agentcore-runtime","path":"aws-cdk-bedrock-agentcore-runtime","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"TestRuntime":{"id":"TestRuntime","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime","constructInfo":{"fqn":"@aws-cdk/aws-bedrock-agentcore-alpha.Runtime","version":"0.0.0","metadata":["*"]},"children":{"ExecutionRole":{"id":"ExecutionRole","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/ExecutionRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"},"description":"*","maxSessionDuration":"*"},{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]}]},"children":{"ImportExecutionRole":{"id":"ImportExecutionRole","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/ExecutionRole/ImportExecutionRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/ExecutionRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Role","aws:cdk:cloudformation:props":{"assumeRolePolicyDocument":{"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"bedrock-agentcore.amazonaws.com"}}],"Version":"2012-10-17"},"description":"Execution role for Bedrock Agent Core Runtime","maxSessionDuration":28800}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/ExecutionRole/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/ExecutionRole/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Policy","aws:cdk:cloudformation:props":{"policyDocument":{"Statement":[{"Action":["logs:CreateLogGroup","logs:DescribeLogStreams"],"Effect":"Allow","Resource":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":logs:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":log-group:/aws/bedrock-agentcore/runtimes/*"]]},"Sid":"LogGroupAccess"},{"Action":"logs:DescribeLogGroups","Effect":"Allow","Resource":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":logs:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":log-group:*"]]},"Sid":"DescribeLogGroups"},{"Action":["logs:CreateLogStream","logs:PutLogEvents"],"Effect":"Allow","Resource":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":logs:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":log-group:/aws/bedrock-agentcore/runtimes/*:log-stream:*"]]},"Sid":"LogStreamAccess"},{"Action":["xray:GetSamplingRules","xray:GetSamplingTargets","xray:PutTelemetryRecords","xray:PutTraceSegments"],"Effect":"Allow","Resource":"*","Sid":"XRayAccess"},{"Action":"cloudwatch:PutMetricData","Condition":{"StringEquals":{"cloudwatch:namespace":"bedrock-agentcore"}},"Effect":"Allow","Resource":"*","Sid":"CloudWatchMetrics"},{"Action":["bedrock-agentcore:GetWorkloadAccessToken","bedrock-agentcore:GetWorkloadAccessTokenForJWT","bedrock-agentcore:GetWorkloadAccessTokenForUserId"],"Effect":"Allow","Resource":[{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":bedrock-agentcore:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":workload-identity-directory/default"]]},{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":bedrock-agentcore:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":workload-identity-directory/default/workload-identity/*"]]}],"Sid":"GetAgentAccessToken"},{"Action":["ecr:BatchCheckLayerAvailability","ecr:BatchGetImage","ecr:GetDownloadUrlForLayer"],"Effect":"Allow","Resource":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":ecr:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":repository/",{"Fn::Sub":"cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}"}]]}},{"Action":"ecr:GetAuthorizationToken","Effect":"Allow","Resource":"*"}],"Version":"2012-10-17"},"policyName":"TestRuntimeExecutionRoleDefaultPolicyC7A978D3","roles":[{"Ref":"TestRuntimeExecutionRoleF819113E"}]}}}}}}},"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_bedrockagentcore.CfnRuntime","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::BedrockAgentCore::Runtime","aws:cdk:cloudformation:props":{"agentRuntimeArtifact":{"containerConfiguration":{"containerUri":{"Fn::Sub":"${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}:f06c9f54828243752afd2df4e39ab9d2987b5ccf44e6bdc05621c18d5488f240"}}},"agentRuntimeName":"integ_test_runtime","tags":{"Environment":"Integration","TestType":"CDK"},"description":"Integration test runtime for BedrockAgentCore","environmentVariables":{"TEST_ENV":"integration","LOG_LEVEL":"INFO"},"lifecycleConfiguration":{"idleRuntimeSessionTimeout":60,"maxLifetime":28800},"networkConfiguration":{"networkMode":"PUBLIC"},"protocolConfiguration":"HTTP","roleArn":{"Fn::GetAtt":["TestRuntimeExecutionRoleF819113E","Arn"]}}}},"AgentRuntimeArtifactf7fe664d1c8cde42a00e2487074af30f":{"id":"AgentRuntimeArtifactf7fe664d1c8cde42a00e2487074af30f","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/AgentRuntimeArtifactf7fe664d1c8cde42a00e2487074af30f","constructInfo":{"fqn":"aws-cdk-lib.aws_ecr_assets.DockerImageAsset","version":"0.0.0"},"children":{"Staging":{"id":"Staging","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/AgentRuntimeArtifactf7fe664d1c8cde42a00e2487074af30f/Staging","constructInfo":{"fqn":"aws-cdk-lib.AssetStaging","version":"0.0.0"}},"Repository":{"id":"Repository","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/AgentRuntimeArtifactf7fe664d1c8cde42a00e2487074af30f/Repository","constructInfo":{"fqn":"aws-cdk-lib.aws_ecr.RepositoryBase","version":"0.0.0","metadata":[]}}}}}},"BasicEndpoint":{"id":"BasicEndpoint","path":"aws-cdk-bedrock-agentcore-runtime/BasicEndpoint","constructInfo":{"fqn":"@aws-cdk/aws-bedrock-agentcore-alpha.RuntimeEndpoint","version":"0.0.0","metadata":["*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/BasicEndpoint/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_bedrockagentcore.CfnRuntimeEndpoint","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::BedrockAgentCore::RuntimeEndpoint","aws:cdk:cloudformation:props":{"agentRuntimeId":{"Fn::GetAtt":["TestRuntime65042BB5","AgentRuntimeId"]},"agentRuntimeVersion":"1","description":"Basic endpoint for testing","name":"basic_endpoint"}}}}},"TaggedEndpoint":{"id":"TaggedEndpoint","path":"aws-cdk-bedrock-agentcore-runtime/TaggedEndpoint","constructInfo":{"fqn":"@aws-cdk/aws-bedrock-agentcore-alpha.RuntimeEndpoint","version":"0.0.0","metadata":["*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/TaggedEndpoint/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_bedrockagentcore.CfnRuntimeEndpoint","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::BedrockAgentCore::RuntimeEndpoint","aws:cdk:cloudformation:props":{"agentRuntimeId":{"Fn::GetAtt":["TestRuntime65042BB5","AgentRuntimeId"]},"agentRuntimeVersion":"1","tags":{"EndpointType":"Tagged","Version":"v1"},"description":"Endpoint with tags","name":"tagged_endpoint"}}}}},"V2Endpoint":{"id":"V2Endpoint","path":"aws-cdk-bedrock-agentcore-runtime/V2Endpoint","constructInfo":{"fqn":"@aws-cdk/aws-bedrock-agentcore-alpha.RuntimeEndpoint","version":"0.0.0","metadata":["*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/V2Endpoint/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_bedrockagentcore.CfnRuntimeEndpoint","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::BedrockAgentCore::RuntimeEndpoint","aws:cdk:cloudformation:props":{"agentRuntimeId":{"Fn::GetAtt":["TestRuntime65042BB5","AgentRuntimeId"]},"agentRuntimeVersion":"2","description":"Version 2 endpoint","name":"v2_endpoint"}}}}},"RuntimeId":{"id":"RuntimeId","path":"aws-cdk-bedrock-agentcore-runtime/RuntimeId","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"RuntimeArn":{"id":"RuntimeArn","path":"aws-cdk-bedrock-agentcore-runtime/RuntimeArn","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"BasicEndpointId":{"id":"BasicEndpointId","path":"aws-cdk-bedrock-agentcore-runtime/BasicEndpointId","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"TaggedEndpointId":{"id":"TaggedEndpointId","path":"aws-cdk-bedrock-agentcore-runtime/TaggedEndpointId","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"V2EndpointId":{"id":"V2EndpointId","path":"aws-cdk-bedrock-agentcore-runtime/V2EndpointId","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-bedrock-agentcore-runtime/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-bedrock-agentcore-runtime/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"BedrockAgentCoreRuntimeTest":{"id":"BedrockAgentCoreRuntimeTest","path":"BedrockAgentCoreRuntimeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"BedrockAgentCoreRuntimeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"BedrockAgentCoreRuntimeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"BedrockAgentCoreRuntimeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"BedrockAgentCoreRuntimeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"BedrockAgentCoreRuntimeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-bedrock-agentcore-runtime":{"id":"aws-cdk-bedrock-agentcore-runtime","path":"aws-cdk-bedrock-agentcore-runtime","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"TestRuntime":{"id":"TestRuntime","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime","constructInfo":{"fqn":"@aws-cdk/aws-bedrock-agentcore-alpha.Runtime","version":"0.0.0","metadata":["*"]},"children":{"ExecutionRole":{"id":"ExecutionRole","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/ExecutionRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"assumedBy":{"principalAccount":"*","assumeRoleAction":"*"},"description":"*","maxSessionDuration":"*"},{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]},{"addToPrincipalPolicy":[{}]}]},"children":{"ImportExecutionRole":{"id":"ImportExecutionRole","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/ExecutionRole/ImportExecutionRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/ExecutionRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Role","aws:cdk:cloudformation:props":{"assumeRolePolicyDocument":{"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"bedrock-agentcore.amazonaws.com"}}],"Version":"2012-10-17"},"description":"Execution role for Bedrock Agent Core Runtime","maxSessionDuration":28800}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/ExecutionRole/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/ExecutionRole/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Policy","aws:cdk:cloudformation:props":{"policyDocument":{"Statement":[{"Action":["logs:CreateLogGroup","logs:DescribeLogStreams"],"Effect":"Allow","Resource":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":logs:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":log-group:/aws/bedrock-agentcore/runtimes/*"]]},"Sid":"LogGroupAccess"},{"Action":"logs:DescribeLogGroups","Effect":"Allow","Resource":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":logs:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":log-group:*"]]},"Sid":"DescribeLogGroups"},{"Action":["logs:CreateLogStream","logs:PutLogEvents"],"Effect":"Allow","Resource":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":logs:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":log-group:/aws/bedrock-agentcore/runtimes/*:log-stream:*"]]},"Sid":"LogStreamAccess"},{"Action":["xray:GetSamplingRules","xray:GetSamplingTargets","xray:PutTelemetryRecords","xray:PutTraceSegments"],"Effect":"Allow","Resource":"*","Sid":"XRayAccess"},{"Action":"cloudwatch:PutMetricData","Condition":{"StringEquals":{"cloudwatch:namespace":"bedrock-agentcore"}},"Effect":"Allow","Resource":"*","Sid":"CloudWatchMetrics"},{"Action":["bedrock-agentcore:GetWorkloadAccessToken","bedrock-agentcore:GetWorkloadAccessTokenForJWT","bedrock-agentcore:GetWorkloadAccessTokenForUserId"],"Effect":"Allow","Resource":[{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":bedrock-agentcore:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":workload-identity-directory/default"]]},{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":bedrock-agentcore:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":workload-identity-directory/default/workload-identity/*"]]}],"Sid":"GetAgentAccessToken"},{"Action":["ecr:BatchCheckLayerAvailability","ecr:BatchGetImage","ecr:GetDownloadUrlForLayer"],"Effect":"Allow","Resource":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":ecr:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":repository/",{"Fn::Sub":"cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}"}]]}},{"Action":"ecr:GetAuthorizationToken","Effect":"Allow","Resource":"*"}],"Version":"2012-10-17"},"policyName":"TestRuntimeExecutionRoleDefaultPolicyC7A978D3","roles":[{"Ref":"TestRuntimeExecutionRoleF819113E"}]}}}}}}},"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_bedrockagentcore.CfnRuntime","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::BedrockAgentCore::Runtime","aws:cdk:cloudformation:props":{"agentRuntimeArtifact":{"containerConfiguration":{"containerUri":{"Fn::Sub":"${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}:f06c9f54828243752afd2df4e39ab9d2987b5ccf44e6bdc05621c18d5488f240"}}},"agentRuntimeName":"integ_test_runtime","tags":{"Environment":"Integration","TestType":"CDK"},"description":"Integration test runtime for BedrockAgentCore","environmentVariables":{"TEST_ENV":"integration","LOG_LEVEL":"INFO"},"lifecycleConfiguration":{"idleRuntimeSessionTimeout":60,"maxLifetime":28800},"networkConfiguration":{"networkMode":"PUBLIC"},"protocolConfiguration":"HTTP","roleArn":{"Fn::GetAtt":["TestRuntimeExecutionRoleF819113E","Arn"]}}}},"AgentRuntimeArtifact57925e7ddb91ee239b55009d714f9548":{"id":"AgentRuntimeArtifact57925e7ddb91ee239b55009d714f9548","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/AgentRuntimeArtifact57925e7ddb91ee239b55009d714f9548","constructInfo":{"fqn":"aws-cdk-lib.aws_ecr_assets.DockerImageAsset","version":"0.0.0"},"children":{"Staging":{"id":"Staging","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/AgentRuntimeArtifact57925e7ddb91ee239b55009d714f9548/Staging","constructInfo":{"fqn":"aws-cdk-lib.AssetStaging","version":"0.0.0"}},"Repository":{"id":"Repository","path":"aws-cdk-bedrock-agentcore-runtime/TestRuntime/AgentRuntimeArtifact57925e7ddb91ee239b55009d714f9548/Repository","constructInfo":{"fqn":"aws-cdk-lib.aws_ecr.RepositoryBase","version":"0.0.0","metadata":[]}}}}}},"BasicEndpoint":{"id":"BasicEndpoint","path":"aws-cdk-bedrock-agentcore-runtime/BasicEndpoint","constructInfo":{"fqn":"@aws-cdk/aws-bedrock-agentcore-alpha.RuntimeEndpoint","version":"0.0.0","metadata":["*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/BasicEndpoint/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_bedrockagentcore.CfnRuntimeEndpoint","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::BedrockAgentCore::RuntimeEndpoint","aws:cdk:cloudformation:props":{"agentRuntimeId":{"Fn::GetAtt":["TestRuntime65042BB5","AgentRuntimeId"]},"agentRuntimeVersion":"1","description":"Basic endpoint for testing","name":"basic_endpoint"}}}}},"TaggedEndpoint":{"id":"TaggedEndpoint","path":"aws-cdk-bedrock-agentcore-runtime/TaggedEndpoint","constructInfo":{"fqn":"@aws-cdk/aws-bedrock-agentcore-alpha.RuntimeEndpoint","version":"0.0.0","metadata":["*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/TaggedEndpoint/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_bedrockagentcore.CfnRuntimeEndpoint","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::BedrockAgentCore::RuntimeEndpoint","aws:cdk:cloudformation:props":{"agentRuntimeId":{"Fn::GetAtt":["TestRuntime65042BB5","AgentRuntimeId"]},"agentRuntimeVersion":"1","tags":{"EndpointType":"Tagged","Version":"v1"},"description":"Endpoint with tags","name":"tagged_endpoint"}}}}},"V2Endpoint":{"id":"V2Endpoint","path":"aws-cdk-bedrock-agentcore-runtime/V2Endpoint","constructInfo":{"fqn":"@aws-cdk/aws-bedrock-agentcore-alpha.RuntimeEndpoint","version":"0.0.0","metadata":["*"]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/V2Endpoint/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_bedrockagentcore.CfnRuntimeEndpoint","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::BedrockAgentCore::RuntimeEndpoint","aws:cdk:cloudformation:props":{"agentRuntimeId":{"Fn::GetAtt":["TestRuntime65042BB5","AgentRuntimeId"]},"agentRuntimeVersion":"2","description":"Version 2 endpoint","name":"v2_endpoint"}}}}},"TestInvokerFunction":{"id":"TestInvokerFunction","path":"aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.Function","version":"0.0.0","metadata":[{"runtime":"*","handler":"*","code":"*","description":"*"}]},"children":{"ServiceRole":{"id":"ServiceRole","path":"aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/ServiceRole","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Role","version":"0.0.0","metadata":[{"addToPrincipalPolicy":[{}]},{"attachInlinePolicy":["*"]},{"attachInlinePolicy":["*"]}]},"children":{"ImportServiceRole":{"id":"ImportServiceRole","path":"aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/ServiceRole/ImportServiceRole","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":["*"]}},"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/ServiceRole/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnRole","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Role","aws:cdk:cloudformation:props":{"assumeRolePolicyDocument":{"Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"}}],"Version":"2012-10-17"},"managedPolicyArns":[{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]]}]}}},"DefaultPolicy":{"id":"DefaultPolicy","path":"aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/ServiceRole/DefaultPolicy","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.Policy","version":"0.0.0","metadata":["*",{"attachToRole":["*"]},{"attachToRole":["*"]},{"addStatements":[{}]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/ServiceRole/DefaultPolicy/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_iam.CfnPolicy","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::IAM::Policy","aws:cdk:cloudformation:props":{"policyDocument":{"Statement":[{"Action":["bedrock-agentcore:InvokeAgentRuntime","bedrock-agentcore:InvokeAgentRuntimeForUser"],"Effect":"Allow","Resource":[{"Fn::GetAtt":["TestRuntime65042BB5","AgentRuntimeArn"]},{"Fn::Join":["",[{"Fn::GetAtt":["TestRuntime65042BB5","AgentRuntimeArn"]},"/*"]]}]}],"Version":"2012-10-17"},"policyName":"TestInvokerFunctionServiceRoleDefaultPolicyC6DC62B6","roles":[{"Ref":"TestInvokerFunctionServiceRole08233DAF"}]}}}}}}},"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_lambda.CfnFunction","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Lambda::Function","aws:cdk:cloudformation:props":{"code":{"zipFile":"def handler(event, context): return {\"statusCode\": 200}"},"description":"Test function to verify runtime grant permissions with sub-resources","handler":"index.handler","role":{"Fn::GetAtt":["TestInvokerFunctionServiceRole08233DAF","Arn"]},"runtime":"python3.12"}}},"LogGroup":{"id":"LogGroup","path":"aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/LogGroup","constructInfo":{"fqn":"aws-cdk-lib.aws_logs.LogGroup","version":"0.0.0","metadata":[{"logGroupName":"*"}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-bedrock-agentcore-runtime/TestInvokerFunction/LogGroup/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_logs.CfnLogGroup","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::Logs::LogGroup","aws:cdk:cloudformation:props":{"logGroupName":{"Fn::Join":["",["/aws/lambda/",{"Ref":"TestInvokerFunction6708F5AE"}]]},"retentionInDays":731}}}}}}},"RuntimeId":{"id":"RuntimeId","path":"aws-cdk-bedrock-agentcore-runtime/RuntimeId","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"RuntimeArn":{"id":"RuntimeArn","path":"aws-cdk-bedrock-agentcore-runtime/RuntimeArn","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"BasicEndpointId":{"id":"BasicEndpointId","path":"aws-cdk-bedrock-agentcore-runtime/BasicEndpointId","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"TaggedEndpointId":{"id":"TaggedEndpointId","path":"aws-cdk-bedrock-agentcore-runtime/TaggedEndpointId","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"V2EndpointId":{"id":"V2EndpointId","path":"aws-cdk-bedrock-agentcore-runtime/V2EndpointId","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-bedrock-agentcore-runtime/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-bedrock-agentcore-runtime/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"BedrockAgentCoreRuntimeTest":{"id":"BedrockAgentCoreRuntimeTest","path":"BedrockAgentCoreRuntimeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"BedrockAgentCoreRuntimeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"BedrockAgentCoreRuntimeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"BedrockAgentCoreRuntimeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"BedrockAgentCoreRuntimeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"BedrockAgentCoreRuntimeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.ts b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.ts index 92a40ccc6ae38..de000f50d9cf3 100644 --- a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.ts +++ b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/integ.runtime.ts @@ -7,6 +7,7 @@ import * as path from 'path'; import * as cdk from 'aws-cdk-lib'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as integ from '@aws-cdk/integ-tests-alpha'; import * as agentcore from '../../../lib'; @@ -67,6 +68,17 @@ const v2Endpoint = new agentcore.RuntimeEndpoint(stack, 'V2Endpoint', { description: 'Version 2 endpoint', }); +// Test grant methods to verify sub-resource permissions +const testFunction = new lambda.Function(stack, 'TestInvokerFunction', { + runtime: lambda.Runtime.PYTHON_3_12, + handler: 'index.handler', + code: lambda.Code.fromInline('def handler(event, context): return {"statusCode": 200}'), + description: 'Test function to verify runtime grant permissions with sub-resources', +}); + +// Grant invoke permissions - this will include sub-resource wildcard in IAM policy +runtime.grantInvoke(testFunction); + // Output runtime and endpoint information for verification new cdk.CfnOutput(stack, 'RuntimeId', { value: runtime.agentRuntimeId, diff --git a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/runtime.test.ts b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/runtime.test.ts index 2bae5d87ceeb2..6f70c47131b6f 100644 --- a/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/runtime.test.ts +++ b/packages/@aws-cdk/aws-bedrock-agentcore-alpha/test/agentcore/runtime/runtime.test.ts @@ -8,6 +8,7 @@ import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as ecr from 'aws-cdk-lib/aws-ecr'; import * as iam from 'aws-cdk-lib/aws-iam'; import * as s3 from 'aws-cdk-lib/aws-s3'; +import * as lambda from 'aws-cdk-lib/aws-lambda'; import { Runtime } from '../../../lib/runtime/runtime'; import { RuntimeEndpoint } from '../../../lib/runtime/runtime-endpoint'; import { AgentCoreRuntime, AgentRuntimeArtifact } from '../../../lib/runtime/runtime-artifact'; @@ -1503,6 +1504,291 @@ describe('Runtime description validation tests', () => { }); }); +describe('Runtime grantInvokeRuntime permission tests', () => { + let app: cdk.App; + let stack: cdk.Stack; + let repository: ecr.Repository; + let agentRuntimeArtifact: AgentRuntimeArtifact; + let runtime: Runtime; + let granteeRole: iam.Role; + + beforeEach(() => { + app = new cdk.App(); + stack = new cdk.Stack(app, 'test-stack', { + env: { + account: '123456789012', + region: 'us-east-1', + }, + }); + + repository = new ecr.Repository(stack, 'TestRepository', { + repositoryName: 'test-agent-runtime', + }); + agentRuntimeArtifact = AgentRuntimeArtifact.fromEcrRepository(repository, 'v1.0.0'); + + runtime = new Runtime(stack, 'test-runtime', { + runtimeName: 'test_runtime_grant', + agentRuntimeArtifact: agentRuntimeArtifact, + }); + + granteeRole = new iam.Role(stack, 'GranteeRole', { + assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + }); + + test('Should grant InvokeAgentRuntime permission with grantInvokeRuntime', () => { + runtime.grantInvokeRuntime(granteeRole); + + const template = Template.fromStack(stack); + + // Verify that a policy is created with the correct permission + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'bedrock-agentcore:InvokeAgentRuntime', + Effect: 'Allow', + Resource: [ + { + 'Fn::GetAtt': [ + Match.stringLikeRegexp('testruntime.*'), + 'AgentRuntimeArn', + ], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + Match.stringLikeRegexp('testruntime.*'), + 'AgentRuntimeArn', + ], + }, + '/*', + ], + ], + }, + ], + }), + ]), + }, + }); + }); + + test('Should grant InvokeAgentRuntimeForUser permission with grantInvokeRuntimeForUser', () => { + runtime.grantInvokeRuntimeForUser(granteeRole); + + const template = Template.fromStack(stack); + + // Verify that a policy is created with the correct permission + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'bedrock-agentcore:InvokeAgentRuntimeForUser', + Effect: 'Allow', + Resource: [ + { + 'Fn::GetAtt': [ + Match.stringLikeRegexp('testruntime.*'), + 'AgentRuntimeArn', + ], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + Match.stringLikeRegexp('testruntime.*'), + 'AgentRuntimeArn', + ], + }, + '/*', + ], + ], + }, + ], + }), + ]), + }, + }); + }); + + test('Should grant both permissions with grantInvoke', () => { + runtime.grantInvoke(granteeRole); + + const template = Template.fromStack(stack); + + // Verify that a policy is created with both permissions + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: [ + 'bedrock-agentcore:InvokeAgentRuntime', + 'bedrock-agentcore:InvokeAgentRuntimeForUser', + ], + Effect: 'Allow', + Resource: [ + { + 'Fn::GetAtt': [ + Match.stringLikeRegexp('testruntime.*'), + 'AgentRuntimeArn', + ], + }, + { + 'Fn::Join': [ + '', + [ + { + 'Fn::GetAtt': [ + Match.stringLikeRegexp('testruntime.*'), + 'AgentRuntimeArn', + ], + }, + '/*', + ], + ], + }, + ], + }), + ]), + }, + }); + }); + + test('Should attach policy to grantee role', () => { + runtime.grantInvokeRuntime(granteeRole); + + const template = Template.fromStack(stack); + + // Verify that the policy is attached to the grantee role + template.hasResourceProperties('AWS::IAM::Policy', { + Roles: [ + { + Ref: Match.stringLikeRegexp('GranteeRole.*'), + }, + ], + }); + }); + + test('Should work with imported runtime', () => { + const importedRuntime = Runtime.fromAgentRuntimeAttributes(stack, 'ImportedRuntime', { + agentRuntimeArn: 'arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/test-runtime-id', + agentRuntimeId: 'test-runtime-id', + agentRuntimeName: 'test-runtime', + roleArn: 'arn:aws:iam::123456789012:role/test-role', + agentRuntimeVersion: '1', + }); + + importedRuntime.grantInvokeRuntime(granteeRole); + + const template = Template.fromStack(stack); + + // Verify that a policy is created for the imported runtime + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'bedrock-agentcore:InvokeAgentRuntime', + Effect: 'Allow', + Resource: [ + 'arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/test-runtime-id', + 'arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/test-runtime-id/*', + ], + }), + ]), + }, + }); + }); + + test('Should grant to Lambda function', () => { + const lambdaFunction = new lambda.Function(stack, 'TestLambda', { + runtime: lambda.Runtime.PYTHON_3_12, + handler: 'index.handler', + code: lambda.Code.fromInline('def handler(event, context): pass'), + }); + + runtime.grantInvokeRuntime(lambdaFunction); + + const template = Template.fromStack(stack); + + // Verify that the Lambda function's role has the permission + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'bedrock-agentcore:InvokeAgentRuntime', + Effect: 'Allow', + }), + ]), + }, + Roles: [ + { + Ref: Match.stringLikeRegexp('TestLambdaServiceRole.*'), + }, + ], + }); + }); + + test('Should grant multiple permissions to same role', () => { + runtime.grantInvokeRuntime(granteeRole); + runtime.grantInvokeRuntimeForUser(granteeRole); + + const template = Template.fromStack(stack); + + // Should have two separate policies + template.resourceCountIs('AWS::IAM::Policy', 2); + }); + + test('Should return Grant object with success', () => { + const grant = runtime.grantInvokeRuntime(granteeRole); + + expect(grant).toBeDefined(); + expect(grant.success).toBe(true); + expect(grant.principalStatement).toBeDefined(); + }); + + test('Should work with runtime that has custom execution role', () => { + const customRole = new iam.Role(stack, 'CustomExecutionRole', { + assumedBy: new iam.ServicePrincipal('bedrock-agentcore.amazonaws.com'), + }); + + const customRuntime = new Runtime(stack, 'custom-runtime', { + runtimeName: 'custom_runtime', + agentRuntimeArtifact: agentRuntimeArtifact, + executionRole: customRole, + }); + + const lambdaRole = new iam.Role(stack, 'LambdaRole', { + assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), + }); + + customRuntime.grantInvokeRuntime(lambdaRole); + + const template = Template.fromStack(stack); + + // Verify policy is created for the lambda role + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'bedrock-agentcore:InvokeAgentRuntime', + Effect: 'Allow', + }), + ]), + }, + Roles: [ + { + Ref: Match.stringLikeRegexp('LambdaRole.*'), + }, + ], + }); + }); +}); + describe('Runtime role validation tests', () => { let app: cdk.App; let stack: cdk.Stack;