AgentCore GatewayがAWS WAFをサポートしたのでレートベースルールとBot Controlを試してみた
はじめに
2026年6月29日、AWS WAFがAmazon Bedrock AgentCore Gatewayをサポートするリソースとして追加されました。
これにより、AgentCore GatewayのMCPエンドポイントに対してREGIONALスコープのウェブACLを関連付けられるようになります。レートベースルールによる流量制御に加え、Bot Controlマネージドルールによるボット分類も適用可能です。
今回は以下の3点を検証しました。
- レートベースルールによるブロック(403)
- Bot Controlマネージドルール(COMMONレベル)によるラベル付与
- AI Traffic Monetizationによる402 Payment Required(CloudFront経由、参考情報)
検証環境
| 項目 | 値 |
|---|---|
| リージョン | us-east-1 |
| Lambda Runtime | Python 3.12 |
| AgentCore Gateway Authorizer | NONE |
| AgentCore Gateway Protocol | MCP |
| WAF (REGIONAL) | Rate-based 100req/60s, Block |
AgentCore Gateway + REGIONAL ウェブACL でレートベースルールを検証する
Gateway と Lambda Target の構築
AgentCore Gatewayを作成し、バックエンドとしてLambda関数(MCPツール)を登録します。Gateway経由で tools/call を呼び出す構成です。認証は検証用のためNONEとしています。
Gateway + Lambda Target 構築手順(CLI)
Lambda関数のハンドラーコードは以下です。MCPの tools/call リクエストを受け取り、挨拶メッセージを返すシンプルなツールです。
import json
def handler(event, context):
method = event.get("method", "")
params = event.get("params", {})
if method == "tools/call":
tool_name = params.get("name", "")
arguments = params.get("arguments", {})
if tool_name == "hello":
name = arguments.get("name", "World")
return {
"content": [{"type": "text", "text": f"Hello, {name}!"}]
}
elif method == "tools/list":
return {
"tools": [{
"name": "hello",
"description": "Returns a greeting message",
"inputSchema": {
"type": "object",
"properties": {"name": {"type": "string", "description": "Name to greet"}},
"required": []
}
}]
}
return {"content": [{"type": "text", "text": "Hello, World!"}]}
Gateway用のIAMロールを作成し、Lambdaを呼び出す権限を付与します。
# Gateway 用 IAM ロール作成(信頼ポリシー: bedrock-agentcore.amazonaws.com)
aws iam create-role \
--role-name agentcore-waf-demo-gateway-role \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "bedrock-agentcore.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}'
# Lambda 呼び出し権限を付与
aws iam put-role-policy \
--role-name agentcore-waf-demo-gateway-role \
--policy-name lambda-invoke \
--policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:ACCOUNT_ID:function:agentcore-waf-demo-hello"
}]
}'
AgentCore Gatewayを作成します。
aws bedrock-agentcore-control create-gateway \
--name agentcore-waf-demo \
--role-arn arn:aws:iam::ACCOUNT_ID:role/agentcore-waf-demo-gateway-role \
--protocol-type MCP \
--authorizer-type NONE \
--exception-level DEBUG \
--region us-east-1
Gatewayにツールターゲットを登録します。
aws bedrock-agentcore-control create-gateway-target \
--gateway-identifier GATEWAY_ID \
--name hello-tool \
--credential-provider-configurations '[{"credentialProviderType":"GATEWAY_IAM_ROLE"}]' \
--target-configuration '{
"mcp": {
"lambda": {
"lambdaArn": "arn:aws:lambda:us-east-1:ACCOUNT_ID:function:agentcore-waf-demo-hello",
"toolSchema": {
"inlinePayload": [{
"name": "hello",
"description": "Returns a greeting message",
"inputSchema": {
"type": "object",
"properties": {"name": {"type": "string", "description": "Name to greet"}},
"required": []
}
}]
}
}
}
}' \
--region us-east-1
Gatewayの動作確認です。
$ curl -s -X POST "https://GATEWAY_ID.gateway.bedrock-agentcore.us-east-1.amazonaws.com/mcp" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":"1","method":"tools/call","params":{"name":"hello-tool___hello","arguments":{"name":"World"}}}'
{"jsonrpc":"2.0","id":"2","result":{"content":[{"type":"text","text":"Hello, World!"}]}}
WAF レートベースルールの設定と関連付け
REGIONALスコープのウェブACLを作成し、60秒あたり100リクエストを超えたIPをブロックするレートベースルールを設定します。
aws wafv2 create-web-acl \
--name agentcore-waf-demo-acl \
--scope REGIONAL \
--default-action '{"Allow":{}}' \
--rules '[{
"Name": "RateLimit100PerMinute",
"Priority": 0,
"Statement": {
"RateBasedStatement": {
"Limit": 100,
"EvaluationWindowSec": 60,
"AggregateKeyType": "IP"
}
},
"Action": {"Block": {}},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "RateLimit100PerMinute"
}
}]' \
--visibility-config '{
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "agentcore-waf-demo-acl"
}' \
--region us-east-1
ウェブACLをAgentCore Gatewayに関連付けます。
aws wafv2 associate-web-acl \
--web-acl-arn arn:aws:wafv2:us-east-1:ACCOUNT_ID:regional/webacl/agentcore-waf-demo-acl/ACL_ID \
--resource-arn arn:aws:bedrock-agentcore:us-east-1:ACCOUNT_ID:gateway/GATEWAY_ID \
--region us-east-1
バーストリクエストで Block を確認する
200リクエスト(10並列)を送信し、レートルールの動作を確認します。
# 200リクエストを10並列で送信
for i in $(seq 1 200); do
curl -s -o /dev/null -w "req=$i status=%{http_code}\n" \
-X POST "$GATEWAY_URL" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":"1","method":"tools/call","params":{"name":"hello-tool___hello","arguments":{"name":"World"}}}' &
[ $((i % 10)) -eq 0 ] && wait
done
wait
結果は以下のとおりです。閾値(100req/60s)の超過後、WAFのレート評価が反映されたタイミングでBlockが開始され、403 Forbiddenが返却されました。
ステータス分布:
200 OK: 196件
403 Forbidden: 3件
000 (エラー): 1件
今回の検証では、閾値超過の検知からブロック開始まで数秒程度のラグが見られたため、超過直後の数リクエストは通過しました(試行ごとにブロック件数は変動します)。バースト完了直後に単発リクエストを送信すると403が返り、レートウィンドウ経過後は200に復帰しました。
Bot Controlマネージドルールとの組み合わせ
同じREGIONALウェブACLにBot Controlマネージドルール(COMMONレベル)をCountモードで追加し、MCPエンドポイントへのリクエストに対してBot Controlの分類ラベルが付与されるか確認しました。
curlでリクエストを送信した際のWAFログを確認すると、httpSourceNameがAGENTCOREとして記録されており、WAFログ上でもAgentCore Gateway由来のリクエストとして扱われていることを確認できます。
{
"httpSourceName": "AGENTCORE",
"httpSourceId": "784693731708-agentcore-waf-demo-kacmy90fj8",
"labels": [
{"name": "awswaf:managed:aws:bot-control:bot:category:http_library"},
{"name": "awswaf:managed:aws:bot-control:bot:name:curl"},
{"name": "awswaf:managed:aws:bot-control:bot:unverified"},
{"name": "awswaf:managed:aws:bot-control:signal:non_browser_user_agent"}
]
}
Bot Controlによる分類ラベル(http_library、bot:name:curl、unverifiedなど)が付与されています。curlによるリクエストは、HTTPライブラリカテゴリのcurlとして検出され、unverified(未検証)およびnon_browser_user_agentのラベルが付与されました。Bot Control v4.0以降のWeb Bot Auth(WBA)と組み合わせることで、WBAで検証可能なリクエストに付与されるラベルを条件に許可し、検証できないリクエストをブロックする構成も考えられます。
CloudFront 経由で AgentCore Gateway へのリクエストに Monetize を適用する
2026年6月時点で、AI Traffic Monetizationは公式ドキュメントに「AI traffic monetization is available globally with Amazon CloudFront」と記載されておりCLOUDFRONTスコープ限定です。AgentCore GatewayはREGIONALウェブACLのみ関連付け可能なため、現時点ではCloudFrontを前段に配置する構成が必要です。
REGIONALスコープのウェブACLにMonetizeアクションを設定しようとすると、以下のエラーが返ります。
An error occurred (WAFInvalidOperationException):
Monetization is not available for regional resources.
Use CloudFront scope to configure monetization.
CloudFront ディストリビューションの作成
AgentCore Gatewayのエンドポイントをカスタムオリジンとして設定します。ポイントは以下の3点です。
- オリジンプロトコル:
https-only(Gateway側がHTTPSのみ受付) - Origin Request Policy:
AllViewerExceptHostHeader(Hostヘッダーを除くすべてのヘッダーを転送) - Cache Policy:
CachingDisabled(すべてのリクエストでキャッシュを無効化)
CloudFront ディストリビューション作成コマンド
aws cloudfront create-distribution \
--distribution-config '{
"CallerReference": "agentcore-waf-demo-cf",
"Origins": {
"Quantity": 1,
"Items": [{
"Id": "agentcore-gateway",
"DomainName": "GATEWAY_ID.gateway.bedrock-agentcore.us-east-1.amazonaws.com",
"CustomOriginConfig": {
"HTTPPort": 80,
"HTTPSPort": 443,
"OriginProtocolPolicy": "https-only",
"OriginSslProtocols": {"Quantity": 1, "Items": ["TLSv1.2"]}
}
}]
},
"DefaultCacheBehavior": {
"TargetOriginId": "agentcore-gateway",
"ViewerProtocolPolicy": "https-only",
"AllowedMethods": {"Quantity": 7, "Items": ["GET","HEAD","OPTIONS","PUT","POST","PATCH","DELETE"], "CachedMethods": {"Quantity": 2, "Items": ["GET","HEAD"]}},
"CachePolicyId": "4135ea2d-6df8-44a3-9df3-4b5a84be39ad",
"OriginRequestPolicyId": "b689b0a8-53d0-40ab-baf2-68738e2966ac",
"Compress": true
},
"Enabled": true,
"Comment": "AgentCore Gateway WAF Monetize demo"
}'
b689b0a8-53d0-40ab-baf2-68738e2966ac: AWSマネージドポリシーAllViewerExceptHostHeader4135ea2d-6df8-44a3-9df3-4b5a84be39ad: AWSマネージドポリシーCachingDisabled
CLOUDFRONT ウェブACL + Monetize の設定
CLOUDFRONTスコープのウェブACLを作成し、Monetizeアクションを設定します。設定手順の詳細は前回記事を参照してください。
今回は決済ネットワークにBase Sepolia(テストネット)、通貨はUSDC、金額は0.001を指定しました。
作成したウェブACLをCloudFrontディストリビューションに関連付けます。
aws wafv2 associate-web-acl \
--web-acl-arn arn:aws:wafv2:us-east-1:ACCOUNT_ID:global/webacl/agentcore-waf-monetize-acl/ACL_ID \
--resource-arn arn:aws:cloudfront::ACCOUNT_ID:distribution/DISTRIBUTION_ID \
--region us-east-1
402 Payment Required の確認
AgentCore GatewayをオリジンとしたCloudFrontディストリビューションのURLへリクエストを送信します。
$ curl -s -D - -X POST "https://DISTRIBUTION_DOMAIN.cloudfront.net/mcp" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":"1","method":"tools/list","params":{}}'
HTTP/2 402
payment-required: eyJhY2Nlc...(base64)
HTTP 402 Payment Requiredが返却されました。payment-required ヘッダーにbase64エンコードされたprice manifestが含まれています。デコードすると以下の内容です。
{
"accepts": [
{
"amount": "1000",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"extra": {
"name": "USDC",
"version": "2"
},
"maxTimeoutSeconds": 300,
"network": "eip155:84532",
"payTo": "0x8501aaba3a0670dd35a4894c9be3216b1a4b6404",
"scheme": "exact"
}
],
"error": "PAYMENT-SIGNATURE header is required",
"resource": {
"url": "https://DISTRIBUTION_DOMAIN.cloudfront.net/mcp"
},
"x402Version": 2
}
manifestの内容を確認します。
| フィールド | 値 | 説明 |
|---|---|---|
network |
eip155:84532 |
Base Sepolia テストネット |
asset |
0x036CbD53842c5426634e7929541eC2318f3dCF7e |
USDC コントラクトアドレス |
amount |
1000 |
0.001 USDC(USDC は decimals=6 のため 1000 = 0.001) |
scheme |
exact |
正確な金額の支払いを要求 |
maxTimeoutSeconds |
300 |
支払い確認の最大待機時間 |
x402Version |
2 |
x402 プロトコルバージョン |
クライアントはmanifestに基づいて支払いを行い、有効なPAYMENT-SIGNATUREヘッダーを付与して再リクエストすることで、支払い検証に成功した場合にアクセスが許可される想定です。
まとめ
AWS WAFがAmazon Bedrock AgentCore Gatewayをサポートしたことで、AgentCore GatewayのMCPエンドポイントにREGIONALスコープのウェブACLを関連付けられるようになりました。
今回の検証では、レートベースルールによる403 Forbiddenのブロックと、Bot Controlマネージドルールによるボット分類ラベルの付与を確認しました。MCPエンドポイントに対して過剰なリクエストの抑制やBot Controlの分類結果を活用した制御を行いたい場合は、AWS WAFを選択肢として検討できそうです。









