
AgentCore RuntimeからAgentCore GatewayへのIAM認証をMCP Proxy for AWSで実装してみた
はじめに
こんにちは、スーパーマーケットのラ・ムーが好きなコンサル部の神野(じんの/@yjinno)です。
皆さんはAmazon Bedrock AgentCoreのRuntimeからGatewayを呼び出すとき、Inbound Authの認証方式どうしていますか?
AgentCoreがPreview時はM2M認証かなと思っていたのですが、
今やGatewayはIAM認証も対応しているので、場合によってはIAM認証の方がシンプルなのでは・・・と思ったのがきっかけで記事を書いてみました。
前提
使用環境
今回は下記バージョンを使用しました。
| 項目 | バージョン |
|---|---|
| Terraform | >= 1.5.0 |
| AWS Provider | >= 6.25.0 |
| Python | 3.12 |
| bedrock-agentcore | >= 1.2.0 |
| strands-agents | >= 1.22.0 |
| mcp-proxy-for-aws | >= 1.1.5 |
アーキテクチャ概要
今回構築するアーキテクチャは下記の通りです。
Gatewayの呼び出しはIAM認証として、Runtimeの呼び出しも簡略化のためIAM認証とします。

Terraformのコード全体は下記リポジトリを参照してください。
用語整理
AgentCoreでは認証の話が Runtime / Gateway で2段あるため、用語を先に整理します。
- Runtime Inbound Auth
- クライアント(人・アプリ)が AgentCore Runtime を呼び出すときの認証(IAM または JWT)
- Gateway Inbound Auth
- Runtime が AgentCore Gateway を呼び出すときの認証(IAM(SigV4)または JWT)
- Gateway Outbound Auth
- Gateway が ターゲット(例:Lambda / 外部API)を呼び出すときの認証(SigV4 等)
本記事の主題は Runtime → Gateway の呼び出し(= Gateway Inbound Auth)です。
Runtime Inbound Auth は検証を簡単にするため IAM に寄せています。
Runtime→Gatewayの認証方法の整理
M2M認証の場合
当初、Runtime→Gatewayの認証はM2M(Machine-to-Machine)認証を検討していました。
しかし、M2M認証を使う場合は下記が必要になります。
- Cognito User Poolの構築
- Machine-to-Machineアプリケーションクライアントの作成
- クライアントシークレットの管理
- トークン取得・リフレッシュの実装
Cognitoの作成やトークンの取得が少しだけ手間になりますよね。
もちろんトークンの取得部分はSDKを活用すればシンプルに取得することは可能です。
import asyncio
from bedrock_agentcore.identity.auth import requires_access_token, requires_api_key
@requires_access_token(
provider_name= "sample-provider",
scopes= [],
auth_flow= 'M2M',
)
async def need_token_2LO_async(*, access_token: str):
IAM認証の場合
一方、IAM認証であれば下記のメリットがあります。
- Cognito不要
- シークレット管理不要(IAMロールで完結)
- RuntimeのIAMロールに
bedrock-agentcore:InvokeGateway権限を付与するだけ mcp-proxy-for-awsでSigV4署名を自動化
AgentCore Runtimeは既にIAMロールを持っているため、Gatewayに対する権限さえ付与すれば、
追加の認証基盤を構築する必要がないのは良いですね。
Gateway側の設定もシンプルで、authorizer_typeにAWS_IAMを指定するだけです。
resource "aws_bedrockagentcore_gateway" "main" {
name = "${var.project_name}-gateway"
role_arn = aws_iam_role.gateway.arn
protocol_type = "MCP"
# Inbound認証: IAM認証を指定
authorizer_type = "AWS_IAM"
# ...省略
}
Runtime側にはbedrock-agentcore:InvokeGatewayの権限を付与します。
resource "aws_iam_role_policy" "agent_runtime_gateway" {
name = "${var.project_name}-agent-runtime-gateway-policy"
role = aws_iam_role.agent_runtime.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "InvokeGateway"
Effect = "Allow"
Action = [
"bedrock-agentcore:InvokeGateway"
]
Resource = aws_bedrockagentcore_gateway.main.gateway_arn
}
]
})
}
Gatewayに接続する際のMCPクライアントは通常トークン認証を想定していますが、
AgentCore GatewayはIAM(SigV4)認証が必要になるので、あれ署名の処理が必要?と不安になりそうですが、便利なライブラリMCP Proxy for AWSがこのギャップを埋めてくれます!
細かい実装は後で確認していきます。
IAM認証とM2M認証の使い分け
ここまでIAM認証の良さをお伝えしてきましたが、じゃあM2M認証はいつ使うの?という疑問が出てくると思います。
複数エージェントが存在し、エージェント毎にツール単位の細かい認可制御が必要な場合はM2M認証を検討した方が良いと思います。細かく違いを見ていきます。
IAM認証の制約
IAM認証でできるのはGateway単位のアクセス制御です。
{
"Action": "bedrock-agentcore:InvokeGateway",
"Resource": "arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/my-gateway"
}
このRuntimeはGateway内のこのツールだけ使えるといったツール単位の制御はできません。
なのでそれぞれのエージェント毎に異なったツール群を実行させる際はGatewayを分離する形になるかと思います。
下記絵のような感じです。

そもそも利用するツールが少なければGatewayは使わない、全てのエージェントで使用できる汎用的なものしかツールにしないならGatewayは1つでも良いかもしれませんね。
M2M認証 + Interceptor/Policyならできること
他方でM2M JWT認証とGateway Interceptors/Cedar Policiesを組み合わせると、
より細かい認可制御が可能になります。
複数のAIエージェントがいて、エージェントごとに使えるツールを制限したい場合を考えてみます。

JWTのスコープや属性をInterceptorやCedar Policyで検証することで、このような制御が実現できます。
認証方式の選び方
| パターン | ユースケース | ツール単位の認可 |
|---|---|---|
| IAM認証 | シンプル構成、全ツール使えてOK | できない |
| M2M JWT + Interceptor/Policy | マルチエージェント、ツール単位の認可が必要 | できる |
シンプルな構成でエージェントが1つであればIAM認証で十分かなと思いました。
複数のエージェントがいて、1つのGatewayに対してそれぞれに異なるツールへのアクセス権限を付与したい場合はM2M認証を検討すると棲み分けになるかなと私は理解しました。
ここのエージェント毎に権限分離するやり方はまた検証して紹介したいと思います。
M2M認証の注意点
M2M認証でカスタムの属性を採用する場合、いくつか注意点があります。
そもそもユーザー権限に応じての認可制御したい場合は、ユーザー委任型の権限制御を実装する必要があるかと思います。今回はあくまで認可主体がエージェントであるケースに話を限定しています。
Strands Agentsでの実装
Agentの実装
実装するコードを見ていきます。
シンプルにGatewayと接続してツールを呼び出すだけのエージェントとなります。
import os
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from strands import Agent
from strands.models import BedrockModel
from strands.tools.mcp import MCPClient
from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client
GATEWAY_URL = os.getenv("GATEWAY_URL", "")
AWS_REGION = os.getenv("AWS_REGION", "us-east-1")
MODEL_ID = os.getenv("BEDROCK_MODEL_ID", "us.anthropic.claude-haiku-4-5-20251001-v1:0")
app = BedrockAgentCoreApp()
model = BedrockModel(model_id=MODEL_ID, region_name=AWS_REGION)
@app.entrypoint
def invoke(payload: dict) -> dict:
message = payload.get("prompt") or payload.get("message", "")
if not message:
return {"error": "No message", "status": "error"}
if GATEWAY_URL:
# mcp-proxy-for-aws で SigV4 署名付きの MCP クライアントを作成
mcp_factory = lambda: aws_iam_streamablehttp_client(
endpoint=GATEWAY_URL,
aws_region=AWS_REGION,
aws_service="bedrock-agentcore"
)
mcp_client = MCPClient(mcp_factory)
agent = Agent(model=model, tools=[mcp_client])
result = agent(message)
else:
agent = Agent(model=model)
result = agent(message)
return {"response": str(result.message), "status": "success"}
if __name__ == "__main__":
app.run()
ポイントはIAM認証でGatewayに接続するための核となる部分です。aws_iam_streamablehttp_clientを使用します。
mcp_factory = lambda: aws_iam_streamablehttp_client(
endpoint=GATEWAY_URL,
aws_region=AWS_REGION,
aws_service="bedrock-agentcore"
)
| パラメータ | 設定値 | 説明 |
|---|---|---|
| endpoint | Gateway URL | AgentCore GatewayのエンドポイントURL |
| aws_region | us-east-1等 | AWSリージョン |
| aws_service | bedrock-agentcore | SigV4署名に使用するサービス名 |
aws_serviceにbedrock-agentcoreを指定することで、
Gatewayへのリクエストに正しいSigV4署名が付与されます。シンプルに使えて良いですね。
そのあとは通常のMCP Clientの実装とほぼ同じです。
クライアントからlist_tools_syncを実行しGatewayのツールを同期します。
mcp_factory = lambda: aws_iam_streamablehttp_client(
endpoint=GATEWAY_URL,
aws_region=AWS_REGION,
aws_service="bedrock-agentcore"
)
with MCPClient(mcp_factory) as mcp:
agent = Agent(model=model, tools=mcp.list_tools_sync())
result = agent(message)
実際に試してみる
実際にこの構成をTerraformでデプロイして、Gatewayに適切にリクエストが送れるか確認してみます!
リポジトリのクローン
まずはリポジトリをクローンします。
git clone https://github.com/yuu551/runtime-to-gateway-for-iam.git
cd runtime-to-gateway-for-iam
Terraformの初期化とデプロイ
Terraformを初期化します。
terraform init
続いて、デプロイ内容を確認します。
terraform plan
Gateway、Runtime、Lambda関数などのリソースが作成されることを確認できましたら、
デプロイを実行します。
terraform apply
確認メッセージが表示されたらyesを入力します。
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
デプロイが完了すると、下記のような出力が表示されます。
Apply complete! Resources: 23 added, 0 changed, 0 destroyed.
Outputs:
gateway_endpoint = "https://xxxxxxxxxx.bedrock-agentcore.us-east-1.amazonaws.com"
runtime_endpoint = "https://yyyyyyyyyy.bedrock-agentcore.us-east-1.amazonaws.com"
これでデプロイ完了です!
コンソールからテスト
デプロイできましたので、今度はコンソール上からリクエストを送って試してみます。
期待値としては、Gatewayに紐付けたLambdaの処理が返却される想定です。
- 足し算のツール
- 掛け算のツール
- 挨拶するツール
- Gatewayによって利用可能になるツール検索ツール
{"prompt": "ツールで何ができるか教えて"}

期待通りツール一覧が返却されました!
今度は足し算のツールが実行できるか確認してみます。
{"prompt": "100 + 12は"}

問題なくツール実行されていますね!ログを見てもツール実行されていました。
{
"message": {
"tool_calls": [
{
"type": "function",
"id": "tooluse_c9qOEPXPS2a6OR8UxN4tfg",
"function": {
"name": "iam-auth-demo-lambda-target___add_numbers",
"arguments": {
"a": 100,
"b": 12
}
}
}
],
"role": "assistant"
},
"index": 0,
"finish_reason": "tool_use"
}
これでRuntime→GatewayがIAM認証で実行できていることを確認できました!
おわりに
mcp-proxy-for-awsを使えば、SigV4署名を意識せずにRuntimeからGatewayを呼び出せるのは便利ですね。
シンプルな構成であれば、Cognito不要でシークレット管理も不要なIAM認証も選択肢に入るかと思います。
一方で、マルチエージェント環境でエージェント毎にツール単位の認可が必要な場合は、M2M認証 + Interceptor/Policyの組み合わせを検討してみてください。
本記事が少しでも参考になりましたら幸いです。
最後までご覧いただきありがとうございましたー!!









