![[Update] I tried Amazon Bedrock AgentCore Runtime after it added support for resource-based policies](https://images.ctfassets.net/ct0aopd36mqt/7qr9SuOUauNHt4mdfTe2zu/8f7d8575eed91c386015d09e022e604a/AgentCore.png?w=3840&fm=webp)
[Update] I tried Amazon Bedrock AgentCore Runtime after it added support for resource-based policies
This page has been translated by machine translation. View original
Introduction
Hello, this is Kamino from the consulting department who loves La Moo.
While enthusiastically working with Amazon Bedrock AgentCore Runtime, I suddenly noticed that resource-based policies had been added.
While wondering if there had been such an update, I searched the official documentation and found a page mentioning it.
Wow, really? It seems they quietly added support for Runtime and Gateway...
Let's immediately check how it works with Runtime!
What's now possible
Until now, resource-based policies couldn't be configured, so
even if you used a proxy like API Gateway + Lambda, anyone with IAM user execution permissions could execute it.

Now that resource-based permissions can be granted, we can more strictly limit who can execute the runtime.
It looks something like this:

Being able to narrow down the execution source more precisely is beneficial in cases like when you're proxying AgentCore executions. Let's try it out!
Preparation
I'm using the following versions:
- CDK: 2.230.0
- Node.js v24.10.0
Let's set up resources using pre-prepared CDK code.
To immediately test resource-based policies, I'll create a full set of Lambda + API Gateway + AgentCore using CDK.
The Lambda function's execution role will have permissions to execute AgentCore.
Create a directory and clone the source code:
mkdir resource-policy-sample
cd resource-policy-sample
git clone https://github.com/yuu551/agentcore-apigw-streaming-cdk
cd agentcore-apigw-streaming-cdk
# Install libraries
bun install
Let's proceed with deployment:
# First-time execution only
cdk bootstrap
# Deploy
cdk deploy
After deployment completes, the following parameters will be displayed:
# Execution result
Outputs:
AgentCoreProxyStack.AgentCoreProxyAPIEndpoint9D0E07BE = https://<api-id>.execute-api.<region>.amazonaws.com/prod/
AgentCoreProxyStack.ApiGatewayInvokeUrl = https://<api-id>.execute-api.<region>.amazonaws.com/prod/invoke
AgentCoreProxyStack.ApiGatewayUrl = https://<api-id>.execute-api.<region>.amazonaws.com/prod/
AgentCoreProxyStack.ProxyFunctionArn = arn:aws:lambda:<region>:<account-id>:function:agentcore-proxy
AgentCoreProxyStack.ProxyFunctionName = agentcore-proxy
AgentCoreProxyStack.ProxyFunctionRoleArn = arn:aws:iam::<account-id>:role/AgentCoreProxyStack-AgentCoreProxyFunctionRole4FDE4-<suffix>
AgentCoreProxyStack.RuntimeArn = arn:aws:bedrock-agentcore:<region>:<account-id>:runtime/<runtime-name>-<suffix>
AgentCoreProxyStack.RuntimeId = <runtime-name>-<suffix>
AgentCoreProxyStack.RuntimeName = <runtime-name>
Please note the following values from your environment as they will be used in subsequent steps:
ApiGatewayInvokeUrl- API Gateway invocation URL, used for making calls later
ProxyFunctionRoleArn- Lambda function's IAM role ARN (used for resource-based policy)
RuntimeArn- AgentCore Runtime ARN
Let's perform a test to verify functionality.
First, let's confirm that we can execute the Runtime via API Gateway:
# Replace <ApiGatewayInvokeUrl> with the URL output during deployment
curl --no-buffer -X POST <ApiGatewayInvokeUrl> \
-H "Content-Type: application/json" \
-d '{"prompt":"こんにちは、あなたは何ができますか?"}'
Execution Result
# Execution result
data: {"event": {"messageStart": {"role": "assistant"}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "こんにち"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "は!"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "私は"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "天"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "気情"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "報を調"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "べること"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ができ"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "る"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "A"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "Iアシス"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "タントです。"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "特"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "定の都"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "市の現在"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "の天気を"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "確認した"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "い"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "場合は、"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "お"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "気"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "軽にお"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "尋ね"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ください。例"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "えば、「"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "東"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "京の天"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "気を教え"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "て」や"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "「"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ニ"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ューヨーク"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "の天気は"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "どうですか"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "?"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "」の"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ような"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "質問に"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "お答えでき"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ます。\n\nまた"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "、天気に"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "関する"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "簡単な質"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "問にも対"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "応できます。"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ど"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "の"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ようなお"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "手"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "伝いができ"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "る"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "か"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "、お"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "聞かせください"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "。どん"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "な都"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "市の天気"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "情"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "報で"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "もす"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ぐに調"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "べること"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ができます。何"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "か特"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "別な都"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "市の天気"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "が"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "知"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "りたい"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ですか?"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockStop": {"contentBlockIndex": 0}}}
data: {"event": {"messageStop": {"stopReason": "end_turn"}}}
data: {"event": {"metadata": {"usage": {"inputTokens": 429, "outputTokens": 187, "totalTokens": 616}, "metrics": {"latencyMs": 3213}}}}
Execution via API Gateway was successful!
Next, let's test from the console.
Since the logged-in IAM user has Admin permissions, we expect it to work without issues.
To invoke it, select Test > Agent Sandbox and choose the Runtime we created.

Enter the following prompt for testing:
{"prompt":"こんにちは、あなたは何ができますか?"}

This also executed without issue!
Now that execution works, let's set up policy-based permissions to ensure it can only be called through Lambda.
Setting Up Resource-Based Policy Permissions
Let's directly edit the settings of the Runtime we created in the console.
Select the Runtime name created by CDK.

After selecting the Runtime, choose the DEFAULT endpoint.

Select the Add button in the Resource-based policy section. It seems resource-based policies can be configured per endpoint, which allows for different permission levels in different environments.

Enter a policy that specifies the previously noted Lambda function role ARN and denies execution for anything else.
After entering it, select the Save button.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyAllOthers",
"Effect": "Deny",
"Principal": "*",
"Action": "bedrock-agentcore:InvokeAgentRuntime",
"Resource": "arn:aws:bedrock-agentcore:<region>:<account-id>:runtime/<runtime-id>/runtime-endpoint/DEFAULT",
"Condition": {
"StringNotEquals": {
"aws:PrincipalArn": "<ProxyFunctionRoleArn>"
}
}
}
]
}
Replace the placeholders with the following values:
<region>: The deployed region (e.g., us-west-2)<account-id>: Your AWS account ID<runtime-id>: TheRuntimeIdoutput during deployment<ProxyFunctionRoleArn>: TheProxyFunctionRoleArnoutput during deployment

Now that the permissions are set, let's try again.
First, let's execute via API Gateway + Lambda:
curl --no-buffer -X POST <ApiGatewayInvokeUrl> \
-H "Content-Type: application/json" \
-d '{"prompt":"こんにちは、あなたは何ができますか?"}'
Execution Result
# Execution result
data: {"event": {"messageStart": {"role": "assistant"}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "こ"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "んにちは!"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "私は、天気情"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "報を取得するお"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "手伝いができる"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "AIアシス"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "タントです。例"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "えば、特定の都"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "市の現在の天気"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "を知"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "りたい場"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "合は、その"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "都市の名"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "前を教"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "えていただければ"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "、get"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "_weatherツールを使用して"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "最新の天気"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "情報を提"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "供いたします。"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "\n\nその他にも、"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "一般的な会"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "話や"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "お手"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "伝いが"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "可能です。"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "何かお困"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "りのことや、知"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "りたい"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ことはありますか?"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "どんな"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ことでも、でき"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "る限りサ"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "ポートさせていただきます"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockDelta": {"delta": {"text": "。"}, "contentBlockIndex": 0}}}
data: {"event": {"contentBlockStop": {"contentBlockIndex": 0}}}
data: {"event": {"messageStop": {"stopReason": "end_turn"}}}
data: {"event": {"metadata": {"usage": {"inputTokens": 429, "outputTokens": 160, "totalTokens": 589}, "metrics": {"latencyMs": 3151}}}}
This executed without issues! Now let's try from the console, which should be denied because it uses user permissions.
Let's test with the same prompt as before:
{"prompt":"こんにちは、あなたは何ができますか?"}

The resource-based policy was evaluated and the request was denied!
As expected, execution is now only possible through Lambda.
Conclusion
I tried out the newly added resource-based IAM policy control for Amazon Bedrock AgentCore Runtime!
This update offers more options for cases where you want to proxy or more strictly limit execution sources. I hope those who needed this feature find it useful.
I hope this article was helpful! Thanks for reading to the end!
Additional Note: Important Points from the Official Documentation
In this test, I used minimal policies since our main goal was to "only allow execution via Lambda", but
reading the official documentation revealed several important points.
Here are some key points worth highlighting:
Both Runtime/Endpoint and Gateway are Eligible
Resource-based policies can be used not only for Runtime but also for Gateway.
For Gateway, use cases might include allowing only specific Runtimes.
Policy Syntax Differs Based on Authentication Method (SigV4 vs OAuth)
This seems subtly important to remember:
- SigV4: Principal can specify IAM users/roles/accounts
- OAuth: Principal must be fixed as
"*"(wildcard required), and instead conditions likeaws:SourceVpcoraws:SourceVpcemust be used to restrict access
Actions That Can Be Restricted by Policy-Based Controls
In this example, we targeted bedrock-agentcore:InvokeAgentRuntime, but there are multiple actions available:
InvokeAgentRuntimeInvokeAgentRuntimeWithWebSocketStreamInvokeAgentRuntimeForUser(when passing user id in headers)InvokeAgentRuntimeWithWebSocketStreamForUser(when passing user id in headers)bedrock-agentcore:StopRuntimeSession(for stopping sessions)bedrock-agentcore:GetAgentCard(for retrieving agent card information, used with A2A)bedrock-agentcore:InvokeGateway(for invoking Gateway)
To avoid cases where one path is blocked but another remains open, you should check which permissions apply to your calling methods.
Deny Takes Precedence in Policy Evaluation
While not unique to AgentCore (similar to resource-based policies in Lambda, etc.), Deny takes precedence:
- If there's an explicit Deny anywhere, it overrides any Allow
- If there's no Deny, an Allow in either IAM or resource-based policy is sufficient
- If neither has anything specified, access is denied
I'm quoting the table from the official documentation. Since this can get complex, it's important to decide on your IAM permission design early.
When a request is made to a Amazon Bedrock AgentCore resource, AWS evaluates both identity-based and resource-based policies. The following table shows how different policy combinations affect access:
IAM Policy Resource Policy Result Grants access Silent Allowed Grants access Grants access Allowed Grants access Denies access Denied Silent Silent Denied Silent Grants access Allowed Silent Denies access Denied Denies access Silent Denied Denies access Allows access Denied Denies access Denies access Denied

