AWS Security Hub CSPM に追加された Amazon Bedrock AgentCore のコントロール [BedrockAgentCore.1] を検証してみた

記事タイトルとURLをコピーする

アイキャッチ

こんにちは。日本スピッツを飼っている深瀬です。白モフに日々癒されています。

2026 年 4 月 22 日のアップデートで、AWS Security Hub CSPM に Amazon Bedrock AgentCore(以下、AgentCore) を対象とした新しい CSPM コントロールが追加されました。本記事では、そのうちの 1 つである [BedrockAgentCore.1] に焦点を当て、実際にコントロールが検出される状態を作り、修正して Compliance Status が PASSED になるまでの流れを検証します。

AgentCore を初めて触る方にも参考になるよう、ランタイムの作成からクリーンアップまでの手順を一通り記載しています。

BedrockAgentCore.1 とは

[BedrockAgentCore.1] Bedrock AgentCore runtimes should be configured with VPC network mode

項目 内容
カテゴリ Protect > Secure access management > Resource not publicly accessible
重要度 High
リソースタイプ AWS::BedrockAgentCore::Runtime
AWS Config ルール bedrockagentcore-runtime-private-network-required
トリガータイプ 変更トリガー(Change triggered)

このコントロールは、AgentCore ランタイムのネットワークモードが PUBLIC に設定されている場合に FAILED を返します。

PUBLIC モードではランタイムがインターネットに直接公開され、攻撃対象領域が広がります。VPC モードにすればトラフィックをプライベートネットワーク内に閉じ込め、セキュリティグループやネットワーク ACL といった制御を適用できるほか、VPC フローログでトラフィックの監視・記録も行えます。

なお、PUBLIC モードでもエージェントの呼び出しには IAM 権限が必要なため、誰でもアクセスできるわけではありません。主なリスクはランタイムからの通信がパブリックネットワークを経由する点です。VPC モードにすることで、これらの通信をプライベートネットワーク内に閉じ、ネットワークレベルのセキュリティ制御を適用できるようになります。

参考

検証の全体像

今回の検証は以下の流れで進めます。

  1. AgentCore CLI のセットアップ
  2. PUBLIC モードでランタイムをデプロイ
  3. Security Hub CSPM で FAILED を確認
  4. VPC モードに変更して再デプロイ
  5. Security Hub CSPM で PASSED を確認
  6. クリーンアップ

前提条件

  • AWS アカウント(AWS CLI の認証情報が設定済み)
  • Node.js 20 以上
  • Python 3.10 以上
  • AWS CDK がインストール済み(npm install -g aws-cdk
  • Amazon Bedrock で Anthropic Claude Sonnet のモデルアクセスが有効
  • Security Hub CSPM が有効化されている
  • AWS Config が有効化されている(対象リソースの記録が有効)

検証環境について

今回は WSL2(Ubuntu) 上で検証を行いました。AgentCore CLI は内部で AWS CDK を使用するため、Linux 環境の方がトラブルが少なくおすすめです。

WSL2 上で以下のようにセットアップしました。

$ node -v
v22.22.0
$ python3 --version
Python 3.10.12
$ cdk --version
2.1120.0 (build acefbf8)

手順 1: AgentCore CLI のインストール

AgentCore CLI は、AI エージェントのプロジェクト作成・ローカル開発・デプロイ・呼び出しを一貫して行える コマンドラインツールです。内部では AWS CDK を使って CloudFormation リソースをデプロイします。Strands Agents、LangChain/LangGraph、Google ADK、OpenAI Agents といった主要なエージェントフレームワークに対応しています。

npm でグローバルインストールします。

npm install -g @aws/agentcore

インストールを確認します。

agentcore --help

主なコマンドは以下のとおりです。

コマンド 概要
agentcore create 新しいエージェントプロジェクトを作成
agentcore dev ローカル開発サーバーを起動(ホットリロード対応)
agentcore deploy AWS CDK 経由で AgentCore Runtime にデプロイ
agentcore invoke デプロイ済みエージェントを呼び出し
agentcore status デプロイ済みリソースの状態を確認
agentcore remove プロジェクトからリソースを削除

参考

手順 2: PUBLIC モードでエージェントをデプロイ

まず、Security Hub CSPM で FAILED が検出される状態を意図的に作ります。

エージェントプロジェクトの作成

agentcore create --name SecurityHubTest --framework Strands --protocol HTTP --model-provider Bedrock --memory none

以下のようなプロジェクト構成が生成されます。

SecurityHubTest/
  agentcore/
    agentcore.json        # プロジェクト・エージェント設定
    aws-targets.json      # AWS アカウント・リージョン設定
    .env.local            # ローカル環境変数
  app/
    SecurityHubTest/
      main.py             # エージェントのエントリーポイント
      pyproject.toml      # Python 依存関係
  README.md

ネットワークモードの確認

AgentCore CLI でデフォルトのままデプロイすると、ネットワークモードは PUBLIC になります。agentcore/agentcore.json を確認すると、ネットワーク設定が以下のようになっているはずです。

{
  "$schema": "https://schema.agentcore.aws.dev/v1/agentcore.json",
  "name": "SecurityHubTest",
  "version": 1,
  "managedBy": "CDK",
  "tags": {
    "agentcore:created-by": "agentcore-cli",
    "agentcore:project-name": "SecurityHubTest"
  },
  "runtimes": [
    {
      "name": "SecurityHubTest",
      "build": "CodeZip",
      "entrypoint": "main.py",
      "codeLocation": "app/SecurityHubTest/",
      "runtimeVersion": "PYTHON_3_14",
      "networkMode": "PUBLIC",
      "protocol": "HTTP"
    }
  ],
  "memories": [],
  "credentials": [],
  "evaluators": [],
  "onlineEvalConfigs": [],
  "agentCoreGateways": [],
  "policyEngines": []
}

補足: agentcore.json の構成はバージョンによって異なる場合があります。ネットワークモードに関する設定箇所を確認してください。

ローカルテスト

デプロイ前に、エージェントがローカルで正しく動作するか確認しておきます。

cd SecurityHubTest
agentcore dev

agentcore dev を実行すると、ローカル開発サーバーが起動し、http://localhost:8081 で Chat UI が開きます。Windows 側のブラウザからアクセスして、チャット画面でエージェントの動作を確認できます。

Chat UIの画像 図1: AgentCore dev の Chat UI 画面

なお、--logs オプションを付けるとログ出力モードになり、Chat UI は起動しません。この場合は別のターミナルから agentcore dev "Hello, tell me a joke" でプロンプトを送信します。

# ターミナル 1: ログモードでサーバー起動
agentcore dev --logs

# ターミナル 2: プロンプトを送信
cd ~/SecurityHubTest
agentcore dev "Hello, tell me a joke"
$ agentcore dev "Hello, tell me a joke"
Here's a joke for you:

Why don't scientists trust atoms?

Because they make up everything! 😄

Would you like to hear another one?

どちらの方法でもエージェントの応答が返ってくれば OK です。

デプロイ

AgentCore CLI は内部で AWS CDK を使用しますが、デプロイ先のリージョンで CDK ブートストラップが済んでいないとエラーになる場合があります。初回は先に手動でブートストラップを実行しておきましょう。

cdk bootstrap aws://$(aws sts get-caller-identity --query Account --output text)/ap-northeast-1

ブートストラップが完了したら、デプロイを実行します。

agentcore deploy

デプロイが完了すると、AgentCore Runtime が PUBLIC モードで作成されます。 デプロイ結果 図2: PUBLIC モードでのデプロイ結果

動作確認

デプロイしたエージェントが動作することを確認します。

agentcore invoke "Hello, tell me a joke"
$ agentcore invoke "Hello, tell me a joke"
Here's a joke for you:

Why don't scientists trust atoms?

Because they make up everything! 😄

Would you like to hear another one?

手順 3: Security Hub CSPM で FAILED を確認

ランタイムが PUBLIC モードで作成されたので、Security Hub CSPM のコントロール評価で FAILED が検出されるはずです。

AWS Config ルールの確認

まず、AWS Config 側でルールが評価されていることを確認します。Security Hub CSPM 経由で作成される Config ルールは securityhub- プレフィックスとランダムなサフィックスが付くため、以下のコマンドでルール名を確認します。

aws configservice describe-config-rules \
  --query 'ConfigRules[?contains(ConfigRuleName, `bedrockagentcore-runtime-private-network-required`)].ConfigRuleName'

取得したルール名を使って、コンプライアンス状態を確認します。

aws configservice get-compliance-details-by-config-rule \
  --config-rule-name securityhub-bedrockagentcore-runtime-private-network-required-XXXXXXXX \
  --compliance-types NON_COMPLIANT

NON_COMPLIANT のリソースとして、先ほど作成したランタイムが表示されるはずです。

{
    "EvaluationResults": [
        {
            "EvaluationResultIdentifier": {
                "EvaluationResultQualifier": {
                    "ConfigRuleName": "securityhub-bedrockagentcore-runtime-private-network-required-XXXXXXXX",
                    "ResourceType": "AWS::BedrockAgentCore::Runtime",
                    "ResourceId": "SecurityHubTest_SecurityHubTest-XXXXXXXX",
                    "EvaluationMode": "DETECTIVE"
                },
                "OrderingTimestamp": "2026-04-30T16:18:16.424000+09:00"
            },
            "ComplianceType": "NON_COMPLIANT",
            "ResultRecordedTime": "2026-04-30T16:18:30.764000+09:00",
            "ConfigRuleInvokedTime": "2026-04-30T16:18:22.328000+09:00"
        }
    ]
}

注意: AWS Config の評価は変更トリガー型ですが、反映までに数分かかる場合があります。

Security Hub CSPM コンソールでの確認

  1. AWS マネジメントコンソールで Security Hub CSPM を開きます
  2. 左メニューから Findings(検出結果)を選択します
  3. フィルターに以下を追加します
    • Title: Bedrock
  4. 該当のランタイムリソースに対する FAILED の検出結果が表示されることを確認します

Security Hub CSPM 図3: Security Hub CSPM で FAILED が検出された状態

検出結果の詳細には、以下のような情報が含まれます。

  • Severity: HIGH
  • Compliance Status: FAILED
  • Resource Type: AwsBedrockAgentCoreRuntime

参考

手順 4: VPC モードに変更して再デプロイ

VPC の準備

VPC モードに切り替えるには、事前に VPC・サブネット・セキュリティグループを用意する必要があります。既存の VPC を使用するか、新規に作成してください。

ポイントは以下のとおりです。

  • プライベートサブネット: 異なる AZ に最低 2 つ用意(サポートされている AZ を確認)
  • セキュリティグループ: 必要な通信のみを許可するルールを設定
  • NAT ゲートウェイ(必要な場合): エージェントが外部 API を呼び出す場合はプライベートサブネットから NAT ゲートウェイ経由でインターネットアクセスを確保

AgentCore ランタイムはプライベートサブネットに配置され、Amazon Bedrock API や外部 MCP サーバーへの通信は NAT ゲートウェイ → インターネットゲートウェイ経由で行います。

今回は検証用に以下の CloudFormation テンプレートで VPC 環境を作成しました。

テンプレートとデプロイ手順

AWSTemplateFormatVersion: '2010-09-09'
Description: VPC for AgentCore Runtime (BedrockAgentCore.1 verification)

Parameters:
  ProjectName:
    Type: String
    Default: agentcore-vpc-test

Resources:
  # VPC
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-vpc

  # プライベートサブネット(2 AZ)
  PrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: !Select [0, !GetAZs '']
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-private-1

  PrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24
      AvailabilityZone: !Select [1, !GetAZs '']
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-private-2

  # パブリックサブネット(NAT ゲートウェイ用)
  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.0.0/24
      AvailabilityZone: !Select [0, !GetAZs '']
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-public

  # インターネットゲートウェイ
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-igw

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  # NAT ゲートウェイ
  NatEIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc

  NatGateway:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt NatEIP.AllocationId
      SubnetId: !Ref PublicSubnet
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-nat

  # ルートテーブル(パブリック)
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-public-rt

  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  # ルートテーブル(プライベート)
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-private-rt

  PrivateRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGateway

  PrivateSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1
      RouteTableId: !Ref PrivateRouteTable

  PrivateSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet2
      RouteTableId: !Ref PrivateRouteTable

  # セキュリティグループ
  AgentCoreSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for AgentCore Runtime
      VpcId: !Ref VPC
      SecurityGroupEgress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
          Description: HTTPS outbound for AWS APIs and external services
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-sg

  # VPC フローログ
  FlowLogLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /vpc/${ProjectName}-flow-logs
      RetentionInDays: 14

  FlowLogRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${ProjectName}-flow-log-role
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: vpc-flow-logs.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: FlowLogPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                  - logs:DescribeLogGroups
                  - logs:DescribeLogStreams
                Resource: '*'

  VpcFlowLog:
    Type: AWS::EC2::FlowLog
    Properties:
      ResourceId: !Ref VPC
      ResourceType: VPC
      TrafficType: ALL
      LogDestinationType: cloud-watch-logs
      LogGroupName: !Ref FlowLogLogGroup
      DeliverLogsPermissionArn: !GetAtt FlowLogRole.Arn
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-flow-log

Outputs:
  VpcId:
    Value: !Ref VPC
  PrivateSubnet1Id:
    Value: !Ref PrivateSubnet1
  PrivateSubnet2Id:
    Value: !Ref PrivateSubnet2
  SecurityGroupId:
    Value: !Ref AgentCoreSecurityGroup

以下のコマンドでスタックを作成します。

aws cloudformation deploy \
  --template-file vpc-for-agentcore.yaml \
  --stack-name agentcore-vpc-test \
  --capabilities CAPABILITY_NAMED_IAM

作成後、Outputs からサブネット ID とセキュリティグループ ID を取得します。

aws cloudformation describe-stacks \
  --stack-name agentcore-vpc-test \
  --query 'Stacks[0].Outputs'

注意: NAT ゲートウェイは時間課金が発生します。検証が終わったら忘れずにスタックを削除してください。

参考 - Configure Amazon Bedrock AgentCore Runtime and tools for VPC

agentcore.json の編集

agentcore/agentcore.json のネットワーク設定を VPC モードに変更します。

{
  "agents": [
    {
      "name": "SecurityHubTest",
      "networkMode": "VPC",
      "networkConfig": {
        "subnets": ["subnet-xxxxxxxx", "subnet-yyyyyyyy"],
        "securityGroups": ["sg-zzzzzzzz"]
      },
      ...
    }
  ]
}

補足: 設定のキー名は AgentCore CLI のバージョンによって異なる場合があります。agentcore validate で設定ファイルの構文チェックができます。

再デプロイ

agentcore deploy

デプロイが完了すると、ランタイムのネットワークモードが VPC に更新されます。 図4: VPC モードでの再デプロイ結果

動作確認

VPC モードでもエージェントが正常に動作することを確認します。

agentcore invoke "Hello, tell me a joke"

VPC モードの場合、以下のように Warning が表示されます。エージェントから応答が返ってくれば、VPC 構成が正しく機能しています。

⠋ Invoking agent...
Warning: This agent uses VPC network mode. Ensure your VPC endpoints are configured for invocation.

Here's a joke for you:

Why don't scientists trust atoms?

Because they make up everything! 😄

Would you like to hear another one?

手順 5: Security Hub CSPM で PASSED を確認

Security Hub CSPM コンソールでの確認

  1. Security Hub CSPM の Findings を開きます
  2. フィルターを以下に変更します
    • Title: Bedrock
  3. 該当のランタイムリソースの Compliance Status が PASSED に変わっていることを確認します(Workflow Status は RESOLVED になります) 図5: Security Hub CSPM で Compliance Status が PASSED、Workflow Status が RESOLVED に変わった状態

注意: Security Hub CSPM の検出結果が更新されるまでに時間がかかる場合があります。

手順 6: クリーンアップ

検証が完了したら、作成したリソースを削除します。

agentcore remove
agentcore deploy

agentcore remove でエージェントの設定を削除し、agentcore deploy で CloudFormation スタックを削除します。

VPC 環境も CloudFormation で作成した場合は、以下のコマンドでスタックを削除します。

aws cloudformation delete-stack --stack-name agentcore-vpc-test
aws cloudformation wait stack-delete-complete --stack-name agentcore-vpc-test

注意: AgentCore が作成した ENI(Elastic Network Interface)は、エージェント削除後も最大 8 時間 VPC 内に残る場合があります。ENI が残っている間はスタックの削除が失敗するため、時間を置いてから再実行するか、手動で ENI をデタッチ・削除してください。

NAT ゲートウェイは時間課金が発生するため、検証が終わったら速やかに削除してください。

まとめ

今回は、Security Hub CSPM に新しく追加された [BedrockAgentCore.1] コントロールを実際に検証しました。

  • AgentCore ランタイムを PUBLIC モードでデプロイすると、Security Hub CSPM で FAILED として検出される
  • VPC モードに変更して再デプロイすると、Compliance Status が PASSED に変わる(Workflow Status は RESOLVED

VPC モードへの切り替えは事前に VPC・サブネット・セキュリティグループの準備が必要です。本番環境では最初から VPC モードで構成することをおすすめします。

留意事項: VPC 構成について

今回の検証では、AgentCore CLI が生成するデフォルトのエージェントコードが外部の MCP サーバー(mcp.exa.ai)に接続するため、NAT ゲートウェイを使用したインターネットアクセスありの構成としました。 本番環境でエージェントが外部サービスへの接続を必要としない場合は、NAT ゲートウェイを作成せず、VPC エンドポイント(AWS PrivateLink)のみの構成を推奨します。VPC エンドポイントを使用すれば、Bedrock API や CloudWatch Logs などの AWS サービスへの通信がすべて AWS ネットワーク内で完結し、よりセキュアかつコスト効率の良い構成になります。

AgentCore Runtime で必要となる VPC エンドポイントについては、VPC endpoint configuration を参照してください。

また、AgentCore Runtime と組み込みツールをパブリックサブネットに接続してもインターネットアクセスは提供されません。インターネット接続が必要な場合は、必ず NAT ゲートウェイを備えたプライベートサブネットを使用してください。

参考リンク

深瀬 義貴 (記事一覧)

クロスインダストリー第1本部

キャンプがしたいです。