AgentCore GatewayがAWS WAFをサポートしたのでレートベースルールとBot Controlを試してみた

AgentCore GatewayがAWS WAFをサポートしたのでレートベースルールとBot Controlを試してみた

AWS WAFがAmazon Bedrock AgentCore Gatewayをサポートしました。REGIONALウェブACLを関連付けることで、MCPエンドポイントに対してWAFの各種ルールを適用できます。本記事ではレートベースルールとBot Controlマネージドルールの動作を検証しました。
2026.06.30

はじめに

2026年6月29日、AWS WAFがAmazon Bedrock AgentCore Gatewayをサポートするリソースとして追加されました。

https://aws.amazon.com/jp/about-aws/whats-new/2026/06/aws-waf-amazon-bedrock-agentcore/

これにより、AgentCore GatewayのMCPエンドポイントに対してREGIONALスコープのウェブACLを関連付けられるようになります。レートベースルールによる流量制御に加え、Bot Controlマネージドルールによるボット分類も適用可能です。

今回は以下の3点を検証しました。

  • レートベースルールによるブロック(403)
  • Bot Controlマネージドルール(COMMONレベル)によるラベル付与
  • AI Traffic Monetizationによる402 Payment Required(CloudFront経由、参考情報)

https://docs.aws.amazon.com/waf/latest/developerguide/waf-ai-traffic-monetization.html

検証環境

項目
リージョン 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の分類ラベルが付与されるか確認しました。

https://dev.classmethod.jp/articles/aws-waf-web-bot-auth-wba-support/

curlでリクエストを送信した際のWAFログを確認すると、httpSourceNameAGENTCOREとして記録されており、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_librarybot:name:curlunverifiedなど)が付与されています。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マネージドポリシー AllViewerExceptHostHeader
  • 4135ea2d-6df8-44a3-9df3-4b5a84be39ad: AWSマネージドポリシー CachingDisabled

CLOUDFRONT ウェブACL + Monetize の設定

CLOUDFRONTスコープのウェブACLを作成し、Monetizeアクションを設定します。設定手順の詳細は前回記事を参照してください。

https://dev.classmethod.jp/articles/aws-waf-ai-traffic-monetization-402-evaluation/

今回は決済ネットワークに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を選択肢として検討できそうです。

参考リンク

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事