AgentCore Gateway/Identity の VPC エグレスをネットワーク屋目線で読み解く
AgentCore Gateway と Identity が VPC エグレスをサポートしたという発表が出ていました(2026年4月24日 AWS What’s New)。これまでマネージド側に居た AgentCore から、お客様 VPC のプライベートリソースに直接到達できるようになったというものです。
「VPC エグレス対応しました」と書かれていると、つい PrivateLink か NAT 経由かと想像してしまうのですが、ドキュメントを読み込むと裏で動いているのは VPC Lattice の Resource Gateway でした。普段 Lattice をあまり触らない人にも面白い構成だったので、自分なりに経路を追って整理しておきます。
何が新しいのか
AgentCore は Bedrock の AI エージェント向けマネージド基盤で、Gateway はエージェントが呼び出すツール(MCP サーバーや API)を集約するコンポーネント、Identity は外部 IdP との OAuth トークンのやりとりを担当するコンポーネントです。両方ともこれまではマネージドサービスのアカウント側で動いていて、お客様 VPC のリソースには到達できませんでした。
つまり、社内 VPC で動いている MCP サーバーや、Keycloak のような自前 IdP を AgentCore から使いたい場合、いったんパブリックに公開する必要がありました。エンタープライズ用途では受け入れにくい制約です。
今回のアップデートで、Gateway ターゲットと Identity の認証情報プロバイダーに privateEndpoint という設定が追加され、お客様 VPC 内のプライベートエンドポイントへ直接到達できるようになりました。
中身は VPC Lattice
公式ドキュメントには以下のように書かれています(Connect to private resources in your VPC using VPC Lattice)。
Private connectivity is established using Amazon VPC Lattice resource gateways and resource configurations.
つまり経路は VPC Lattice の Resource Gateway と Resource Configuration を使って張られます。Lattice の Resource Gateway は VPC 内に配置される ネットワークの入口(ENI ベース) で、Resource Configuration が「その入口の先にある具体的なリソース(DNS 名 / IP)」を表現します。AgentCore のサービスネットワークがその Resource Configuration と関連付けされることで、AgentCore から VPC 内へトラフィックが流れ込む構造になっています。
登場人物を整理しておきます。
| コンポーネント | 役割 | どこに作られるか |
|---|---|---|
| Resource Gateway | お客様 VPC への入口(ENI を消費) | お客様アカウントの VPC 内 |
| Resource Configuration | 入口の先のリソース定義(DNS/IP) | マネージド型では AgentCore サービスアカウント、セルフ管理型ではお客様アカウント |
| Service Network Resource Association | AgentCore のサービスネットワークと Resource Configuration を結びつける | AgentCore が常に管理 |
ここがこのアップデートの肝で、PrivateLink 的な「サービス側に作るエンドポイント」ではなく、お客様 VPC 側に Lattice の入口を立てて、AgentCore のサービスネットワークから association する という方向で作られています。
マネージド型とセルフマネージド型
privateEndpoint には2つのモードがあります。マネージド型(managedVpcResource)とセルフマネージド型(selfManagedLatticeResource)です。違いを表にまとめます。
| 観点 | マネージド型 | セルフマネージド型 |
|---|---|---|
| Resource Gateway / Configuration の作成 | AgentCore が代行 | 自分で作る |
| 必要な権限 | EC2 系 + iam:CreateServiceLinkedRole | 上記 + vpc-lattice:* 一式 |
| クロスアカウント | 非対応 | AWS RAM 経由で対応 |
| Lattice 料金 | データ処理料のみ(GB 単位) | サービスネットワーク関連付けの時間料金 + データ処理料 |
| 可視性 | お客様アカウントに見えるのは Resource Gateway(ENI ラッパー)のみ。Resource Configuration は AgentCore サービスアカウント側 | 全部見える |
| IP 消費 | サブネットあたり 1 IP | サブネットあたり 1 IP(他サービスネットワークにも紐づける場合は ENI あたり追加 IP) |
公式ドキュメントの比較表に、マネージド型のガバナンス可視性についてこう書かれていました。
The only resource in your account is a resource gateway, which is effectively a network interface (ENI) in your VPC. This is a read-only resource fully managed by Amazon Bedrock AgentCore — you cannot modify, configure, or interact with it.
要するにマネージド型を選ぶと、お客様 VPC に「触れない ENI」が一つ生えるだけで、Lattice 側の細かいリソースは全部見えないようになっています。SCP で vpc-lattice:* を絞っている組織でも使い始められるよう、Lattice をあくまで内部実装として隠す 設計になっているのが分かります。
逆にセルフマネージド型は、自分で aws vpc-lattice create-resource-gateway と aws vpc-lattice create-resource-configuration を叩いて作り、その ARN を AgentCore に渡す形です。クロスアカウントが必要な場合(ハブアカウントの Gateway から各サービスアカウントの私設 API を呼ぶ等)は、こちらを選んで AWS RAM で共有することになります。
マネージド型での Gateway ターゲット作成
ターゲット作成のリクエスト本体はこうなります(gateway-vpc-egress.html より)。
{
"name": "my-private-mcp-target",
"privateEndpoint": {
"managedVpcResource": {
"vpcIdentifier": "vpc-0abc123def456",
"subnetIds": ["subnet-0abc123", "subnet-0def456"],
"endpointIpAddressType": "IPV4",
"securityGroupIds": ["sg-0abc123def"]
}
},
"targetConfiguration": {
"mcp": {
"mcpServer": {
"endpoint": "https://my-mcp-server.internal.example.com/mcp"
}
}
}
}
vpcIdentifier / subnetIds / endpointIpAddressType が必須、セキュリティグループは省略すると VPC のデフォルト SG が使われます。
ターゲットを作成すると status: CREATING になり、Lattice リソースの準備とサービスネットワーク関連付けが終わると READY になります。読み取り API のレスポンスには privateEndpointManagedResources が返ってきて、そこに AgentCore が代理で作った Resource Gateway の ARN が入っています。
{
"status": "READY",
"privateEndpointManagedResources": [
{
"domain": "my-server.internal.example.com",
"resourceGatewayArn": "arn:aws:vpc-lattice:us-east-1:123456789012:resourcegateway/rgw-abc123"
}
]
}
VPC や サブネット、SG、IP タイプの設定が同じターゲットを複数作ると、AgentCore は 同じ Resource Gateway を再利用 します。逆に最後のターゲットを消すと Resource Gateway も削除されます。Lattice ENI のお代わりは増えない設計で、無駄に IP を食わずに済むのは個人的にありがたい挙動です。
なお、サービスリンクロール AWSServiceRoleForBedrockAgentCoreGatewayNetwork が初回のターゲット作成時に自動作成されます。このロールは BedrockAgentCoreGatewayManaged: true のタグが付いた Resource Gateway しか触れない作りで、自分で作った Lattice リソースを横から消されない安全装置になっています。
Routing Domain と SNI のトリックが面白い
routingDomain というオプションがあって、ここが個人的に一番唸ったポイントです。
公式ドキュメントの記述です(Route traffic through an intermediate domain)。
When using a routing domain, the domain you specify for your target (in the MCP endpoint URL or OpenAPI server URL) should be the actual DNS name of your resource. The
routingDomainis a separate domain that AgentCore uses to set up the VPC Lattice resource configuration. At invocation time, AgentCore routes traffic through the routing domain but sends requests with the actual target domain as the TLS SNI hostname, so your resource receives requests addressed to its actual domain.
VPC Lattice の Resource Configuration は DNS で経路を解決する ので、複数のプライベート API Gateway を一つの VPC エンドポイントの裏に集約したいような場合、API ごとに Resource Configuration を作るとリソースが膨らみます。routingDomain を使うと、Lattice の経路解決には共通の中継ドメイン(VPCE の DNS 名や内部 ALB の DNS 名)を使い、TLS の SNI には実際のターゲットドメインを乗せて送ってくれます。
つまり、
- AgentCore は Lattice 生成の DNS 名を引いて Resource Gateway に到達
- Resource Gateway → 中継ドメイン(VPCE / ALB)にトラフィックが入る
- SNI は本来のターゲットドメインなので、中継先で正しい仮想ホストへルーティングされる
という流れで、Resource Configuration 数を減らしつつ複数のバックエンドに振り分けできます。ネットワーク的には地味ですが、Lattice の DNS 経路解決と TLS SNI を分離する発想がきれいで、設計の自由度が一気に上がります。
プライベート CA を使っている場合は ALB で受ける
プライベート CA で発行した証明書を使っているサーバーには、AgentCore は直接繋げません。公式の言い回しは正直で、こうあります。
VPC egress requires your target endpoint to have a publicly trusted TLS certificate.
回避策として案内されているのが、内部 ALB を前段に立てる構成です。ターゲット URL は ACM のパブリック証明書のドメイン(例: my-server.my-company.com)にして、routingDomain を内部 ALB の DNS 名に設定。ALB のリスナールールで Host ヘッダ変換を入れて、内部のプライベートドメインへ書き換えてからバックエンドに転送、という段取りです。
[AgentCore]
│ (TLS SNI: my-server.my-company.com)
▼ (Lattice 経由で ALB へ)
[内部 ALB] ── ACM 証明書で TLS 終端
│ (Host ヘッダを my-server.my-company.internal に書き換え)
▼
[バックエンド(プライベート CA)]
ALB の Host ヘッダ変換は最近サポートされた listener rule の機能で、これと組み合わせると「外向きにはパブリック ACM、内向きにはプライベート CA のまま」というハイブリッドな運用が成立します。ネットワーク屋的にはこのワークアラウンドが綺麗にハマる気持ちよさがあります。
Identity 側はどう変わるのか
Identity 側でも同じ privateEndpoint ブロックが使えるようになっていて、用途は2つあります(identity-private-idp.html)。
- インバウンド JWT 認可: AgentCore Runtime や Gateway が受信した JWT を検証する際、IdP の OIDC ディスカバリ URL や JWKS エンドポイントを叩きに行く先がプライベート IdP(社内 Keycloak 等)の場合
- アウトバウンド OAuth 認証: AgentCore Identity がアクセストークンを取得しに行く
tokenEndpointがプライベートにある場合
例えば Runtime 作成時のオーソライザ設定にこう書きます。
{
"agentRuntimeName": "my-runtime",
"authorizerConfiguration": {
"customJWTAuthorizer": {
"discoveryUrl": "https://idp.internal.example.com/.well-known/openid-configuration",
"allowedAudiences": ["my-agent-audience"],
"allowedClients": ["my-client-id"],
"privateEndpoint": {
"managedVpcResource": {
"vpcIdentifier": "vpc-0abc123def456",
"subnetIds": ["subnet-0abc123", "subnet-0def456"],
"endpointIpAddressType": "IPV4",
"securityGroupIds": ["sg-0abc123def"]
}
}
}
}
}
裏で動いている仕組みは Gateway と同じく VPC Lattice で、サービスリンクロールも AWSServiceRoleForBedrockAgentCoreIdentity という別物になっているだけです。Keycloak / PingFederate / 任意の OIDC 互換 IdP がプライベートのまま使えるので、データレジデンシ要件が厳しい組織にとっては待ち望んでいたピースだと思います。
ちなみに自分の環境(AWS CLI 2.34.35)ではまだ Identity 側の privateEndpoint は CLI 側に降りてきていませんでした。CHANGELOG を見ると Identity 側の対応は AWS CLI 2.34.37 で入っています(“Added support for configuring identity providers and inbound authorizers within a private VPC for AWS Bedrock AgentCore”)。Gateway 側は AWS CLI 2.34.22 からです。リリース時期が微妙にずれているので、Identity 側も触りたい人は CLI を 2.34.37 以上に上げる必要があります。
CLI で --private-endpoint が使えることだけ確認
実機で MCP サーバーを VPC に立てて検証するには時間がかかるので、今回は CLI が新しいパラメータを受けつけるところまで確認しました。AWS CLI バージョンは 2.34.35、リージョンは ap-northeast-1 です。
$ aws --version
aws-cli/2.34.35 Python/3.14.4 Darwin/25.4.0 source/arm64
$ aws bedrock-agentcore-control create-gateway-target help | grep -A2 "private-endpoint"
[--private-endpoint <value>]
--cli-input-json | --cli-input-yaml]
[--generate-cli-skeleton <value>]
ヘルプに --private-endpoint が出ていて、tagged union として managedVpcResource か selfManagedLatticeResource のどちらかを取る、と説明されていました。スケルトン生成を使えば JSON テンプレートも出せます。
$ aws bedrock-agentcore-control create-gateway-target \
--generate-cli-skeleton input | jq '.privateEndpoint'
{
"selfManagedLatticeResource": {
"resourceConfigurationIdentifier": ""
},
"managedVpcResource": {
"vpcIdentifier": "",
"subnetIds": [""],
"securityGroupIds": [""],
"endpointIpAddressType": "IPV4",
"routingDomain": "",
"tags": {
"KEY_VALUE": ""
}
}
}
ペイロードの形が完全にドキュメントと一致しているのが確認できました。なお Identity の privateEndpoint を試そうとすると 2.34.35 ではフィールド未対応で弾かれるので、Identity 側を触る場合は事前に CLI を上げておく必要があります。
実機で Resource Gateway が生えるところまで追いたかったのですが、AgentCore Gateway 自体の作成と MCP サーバーの準備が要るので、今回は文献調査と CLI の挙動確認まで。後日 EKS 上に MCP サーバーを立てて、Resource Gateway の ENI が実際に何個生えるか・サブネットあたり 1 IP の挙動どおりかを追う記事を別で書こうと思います。
ハマりそうなポイント
ドキュメントを読んでいて、ネットワーク屋として気になった注意点を並べておきます。
- インバウンド認可は
NO_AUTH不可:privateEndpointを付けたターゲットは、interceptor Lambda を別途設定しない限りインバウンドにNO_AUTHを選べません。プライベートに繋ぐなら認可は必須、というポリシーで、これは妥当な設計だと思います - DNS TTL に注意: VPC Lattice は IP ベースルーティングなので、ターゲットドメインの DNS TTL を短めにしておかないと、ローリングデプロイ時に IP が変わったときに繋がらなくなる可能性がある、と注意書きがあります
- API Gateway は別経路: API Gateway ターゲット(プライベート REST API)には現状
privateEndpointが直接使えず、OpenAPI 仕様としてエクスポートして OpenAPI ターゲットにroutingDomainで VPCE を指定する、という遠回りになります - リージョン: 東京を含む14リージョンで提供。GovCloud と中国は対象外
所感
「マネージドサービスから VPC 内のリソースに繋ぐ」と聞くと PrivateLink を想像してしまいますが、PrivateLink はサービス提供側が出口を作る構造なので、AgentCore のように「お客様側でホストしたいリソース(自前 MCP サーバーや Keycloak)に繋ぎに行く」用途には向きません。今回 VPC Lattice の Resource Gateway を採用したことで、お客様 VPC 側に入口を立てる方向で構築でき、SCP / IAM の制約も内部実装として隠せるようになっています。
routingDomain と SNI の組み合わせや、複数ターゲットでの Resource Gateway 共有など、ネットワーク設計の余地が思ったより広いアップデートでした。AI エージェントを社内システムにつなぐ要件は今後さらに増えていきそうなので、Lattice の動きをきちんと押さえておくと後で楽できると思います。