Claude Platform Docs
Managed Agentsエンタープライズ設定

エージェントアイデンティティと認証情報

セルフホスト型のClaude Managed Agentsサーバーに、各エージェントを識別する有効期間の短いトークンへ署名させ、ボールトの認証情報をシークレットマネージャーに保管し、エグレスゲートウェイでシークレットをサンドボックスの外に保ちます。

このページでは、サーバーの外部にあるシステムがエージェントを信頼できるようにする方法と、エージェントが使用する認証情報の保管場所を示します:

  • エージェントアイデンティティ:MCPサーバーまたはゲートウェイが、各エージェントに個別のアクセス権を付与できるようにします。サーバーがエージェントを識別する有効期間の短いトークンに署名します。
  • シークレットマネージャー:サーバーは、ボールトの認証情報をAWS Secrets Manager、Google Cloud Secret Manager、HashiCorp Vault、またはAzure Key Vaultに保管します。
  • 環境変数の認証情報:サンドボックスがプレースホルダーのみを保持した状態で、エージェントのコマンドがサービスを呼び出せるようにします。「egress gateway」(エグレスゲートウェイ)が実際の値をエージェントのリクエストに挿入します。

エージェントアイデンティティ

サーバーは、エージェントを識別する有効期間の短い「JSON Web Token」(JSONウェブトークン)、すなわちJWTに署名し、そのエージェントのMCP呼び出しとともに送信できます。受信側(MCPサーバーまたはゲートウェイ)は、あなたが公開する公開鍵を使ってトークンを検証し、その後、各エージェントに個別のアクセス権を付与できます。

発行者を設定する

  1. 「issuer」(発行者)のURLを選択します。 手順3でこのURLに公開鍵を公開し、受信側はこのURLから公開鍵を取得します。静的なWebホストで問題ありません。サーバーは受信側が取得するパスで鍵を配信しないため、サーバーのアドレスは使用しないでください。パスや末尾のスラッシュのないhttps:// URLを、今後も維持できるホスト名で使用してください。

  2. 署名鍵を作成します。 展開したアーカイブの最上位ディレクトリで次のコマンドを実行します:

    mkdir -m 700 agent-identity
    openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out agent-identity/signing-key.pem
  3. 公開鍵を公開します。 このコマンドは公開鍵をissuer-files/.well-known/に書き込みます。issuer-filesを発行者のホスト名のルートに、コンテンツタイプapplication/jsonで配信してください。

    CMA_AGENT_IDENTITY__ISSUER=https://agents.example.com \
    CMA_AGENT_IDENTITY__KEY_FILE=./agent-identity/signing-key.pem \
      ./cma-server export-issuer -out issuer-files
  4. サーバーに鍵を渡します。

    1. アーカイブにcomposeディレクトリがある場合は、鍵のディレクトリをその中に移動します:mv agent-identity compose/agent-identity。
    2. docker-compose.ymlで、cma-serverサービスのvolumes: *server_mounts行を削除し、その下にあるvolumes:ブロックのコメントを解除します。x-server-mountsリストを変更した場合は、cma-serverサービスがそのリストを読み取らなくなるため、そのブロックでも同じ変更を行ってください。
    3. macOS上のDocker Desktopまたはrootless Dockerを使用している場合を除き、agent-identityがあるディレクトリでsudo chown -R root:root agent-identityを実行します。
  5. 設定ファイルを変更します。 受信側のホスト名をmcp.allowed_hostnamesに記載し、次のセクションを追加します:

    agent_identity:
      issuer: https://agents.example.com
      key_file: /run/cma-server/agent-identity/signing-key.pem
      direct:
        audiences:
          - audience: https://mcp-gateway.example.com
            urls:
              - https://mcp-gateway.example.com

    各audienceは、1つの受信側をhttps:// URLとして指定します。そのurlsは、そのaudience向けのトークンを受け取ることができるMCPサーバーのURLプレフィックスです。

  6. サーバーを再起動します。 Composeスタックでは、再起動の代わりにComposeファイルのディレクトリからdocker compose up -dを実行します。

秘密鍵をファイルに置かないようにするには、key_secret(シークレットマネージャー)またはkms_key(AWS KMSまたはGoogle Cloud KMS)を使用します。設定リファレンスで、両方の設定について説明しています。

MCPサーバーにトークンを送信する

MCPコネクタでは、エージェントのMCPサーバーエントリのフィールドについて説明しています。そのエントリにauthフィールドを追加します:

mcp_servers:
  - type: url
    name: tickets
    url: https://mcp-gateway.example.com/tickets
    auth:
      type: agent_token
      audience: https://mcp-gateway.example.com

ツールの一覧取得またはツール呼び出しのたびに、サーバーは新しいトークンに署名します。トークンは、ボールトの認証情報の代わりにAuthorization: Bearer <token>として送信されます。モデルもワーカーもこのトークンを受け取りません。

トークンとボールト認証情報の両方を送信するには、authフィールドをagent_token_headerフィールドに置き換えます:

mcp_servers:
  - type: url
    name: tickets
    url: https://mcp-gateway.example.com/tickets
    agent_token_header:
      audience: https://mcp-gateway.example.com

ボールト認証情報は、どちらのフィールドもないエントリの場合と同様に、Authorizationヘッダーに入れて送信されます。トークンはBearerプレフィックスなしでAgent-Identity-Tokenヘッダーに入れて送信されます。

SDKにはauthフィールドとagent_token_headerフィールドがありません。SDKのコードでは、フィールドをMCPサーバーエントリに追加フィールドとして追加するか、リクエストをプレーンなJSONとして送信してください。

追加フィールドの送信方法は、以下のページに記載されています:

Python SDK · TypeScript SDK · Go SDK · Java SDK · PHP SDK · Ruby SDK

これらのページの中には、追加フィールドをリストのエントリ内ではなく、リクエストの最上位レベルでのみ示しているものがあります。その場合は、mcp_servers自体を追加フィールドにします。エントリにauthまたはagent_token_headerを含めて、リスト全体をその方法で送信してください。

エージェントのトークンを停止するには、エージェントからエントリを削除するか、エージェントをアーカイブします。すでに送信されたトークンは、そのexpまで有効なままです(デフォルトでは最大5分)。

受信側が検証する内容

次のすべてが満たされる場合にのみ、受信側がリクエストを受け入れるようにしてください:

  • キーセット<issuer>/.well-known/jwks.json内の鍵で署名が検証されること。正しい鍵は、IDがトークンヘッダーのkidと一致する鍵です。RSA鍵の場合、アルゴリズムはRS256です。
  • issが発行者URLと等しく、audが受信側のaudienceと等しいこと。
  • expが未来の時刻であり、iatが未来の時刻ではないこと。
  • トークンヘッダーのtypがagent+jwtであり、token_useがagentであること。

次に、以下のルールを適用してください:

  • 各エージェントのアクセスルールは、API上のエージェントのIDであるagent_idクレームに基づいて設定してください。
  • 1回の一覧取得または呼び出しで、同じトークンを使って複数のリクエストが行われることがあるため、繰り返されるjtiを受け入れてください。
  • ゲートウェイには各ツールをそのツール自身の認証情報で呼び出させ、トークンは決して転送しないようにしてください。

シングルサインオンを使用すると、ツール呼び出しのトークンには、セッションを作成した呼び出し元もactor_subクレームとactor_issクレームで記載されます。actor_subは、呼び出し元がその呼び出しを承認したことを意味しません。各呼び出しはモデルが選択します。

次のトークンにはactor_subがありません:

  • ツールの一覧取得のトークン
  • サブエージェントの呼び出しのトークン
  • サーバーのAPIキーで作成されたセッションのすべてのトークン

ルールが呼び出し元に依存する場合は、actor_subのないツール呼び出しを拒否してください。

MCPゲートウェイをテストする

check-gatewayコマンドは、MCPゲートウェイに有効なトークンと無効なトークンを送信します。コマンドに専用の設定ファイル(ここではcheck-gateway.yaml)を渡します:

  1. サーバーの設定のうち、mcpセクションとagent_identityセクションのみをファイルにコピーし、サーバーがlimits.mcp_call_timeoutを設定している場合はそれもコピーします。
  2. コピーで、key_fileを、コマンドを実行するマシン上の鍵のパス(./agent-identity/signing-key.pemなど)に変更します。ディレクトリをcomposeに移動した場合は、./compose/agent-identity/signing-key.pemになります。

-agentには、ゲートウェイが許可するエージェントのIDを指定します。rootが鍵を所有している場合はsudoを使用します。

./cma-server check-gateway -config check-gateway.yaml -agent agent_011CYm1BLqPXpQRk5khsSXrs \
  -url https://mcp-gateway.example.com/tickets

このコマンドは、送信するリクエストごとに1行を、ゲートウェイの応答とともに出力します。成功した実行は、その後check-gateway: PASSで始まる行を出力し、コード0で終了します。失敗した実行は、check-gateway:で始まる行に問題の内容を示し、コード1で終了します。

シークレットマネージャー

デフォルトでは、サーバーはボールトの認証情報のシークレットをデータベースに保存します。secret_storeセクションを設定すると、サーバーは新しいボールト認証情報それぞれのシークレットを、そのために予約した名前プレフィックスの下で、シークレットマネージャーに書き込みます。データベースには参照のみが保持されます。

使用するシークレットマネージャーのブロックを設定ファイルに追加します:

secret_store:
  type: aws_secrets_manager
  region: us-east-1
  prefix: cma-server/prod/

アクセスを付与する

サーバーに1つのアイデンティティを付与し、そのアクセス範囲をプレフィックスに限定します。アーカイブのiam/ディレクトリには、シークレットマネージャーごとのファイルがあります:

  • AWS Secrets Manager: aws-secrets-manager-policy.json内のプレースホルダーを置き換え、サーバーが実行されるアイデンティティにポリシーをアタッチします。
  • Google Cloud Secret Manager: gcp-secret-manager-role.yamlのコメントにあるコマンドを実行します。
  • Azure Key Vault: Azureのロールはプレフィックスではなくキーボールト全体を対象とするため、Azureのロールベースのアクセス制御を使用する、デプロイメント専用のキーボールトを用意してください。azure-key-vault-role.json内のSUBSCRIPTION_IDを置き換え、そこからカスタムロールを作成します。キーボールトに対するそのロールを、サーバーが実行されるアイデンティティに割り当てます。
  • HashiCorp Vault: hashicorp-vault-policy.hcl内のプレースホルダーを置き換え、サーバーが実行されるアイデンティティにポリシーをアタッチします。

AWSとGoogle Cloudに対しては、サーバーは推論の場合と同じ方法で認証します。Azure Key Vaultに対しては、Microsoft Foundryの場合と同様に、Microsoft Entra IDで認証します。

セットアップを確認する

最初の起動前と、ポリシーを変更した後には、validate-storeを実行してください。このコマンドは、サーバーを起動せずに、プレフィックスの下でテストシークレットを作成、読み取り、削除します。コマンドは、サーバーが実行される場所で、サーバーの環境を使って実行してください:

  • Docker Compose: サーバーのコンテナ内で実行します。Armでは、このコマンドのlinux_amd64をlinux_arm64に置き換えてください:

    docker compose exec cma-server /opt/cma-server/bin/linux_amd64/cma-server validate-store -config /etc/cma-server/config.yaml
  • ホスト上:

    ./cma-server validate-store -config /etc/cma-server/config.yaml
  • Kubernetes: 同じコマンドを、サーバーのサービスアカウントでJobとして実行します。

成功した実行はpassと書かれた行で終わり、コード0で終了します。

Azure Key Vaultを使用する場合は、利用を開始する前に、キーボールトに対してこのチェックを実行してください。

シークレットマネージャーの制限事項

  • 設定は一度だけ選択してください。 次のいずれかの変更を行うと、サーバーは変更前に書き込んだシークレットを見つけられなくなります:

    • secret_storeセクションを削除する。
    • type、prefix、region、project、vault_url、mount、またはnamespaceを変更する。最後の2つは、HashiCorp Vaultのオプション設定です。
    • addressを別のVaultに向ける。

    古い値を元に戻した場合にのみ、サーバーはそれらのシークレットを再び見つけられます。

  • 1つのアイデンティティがプレフィックス全体を読み取ります。 2つのグループが互いの認証情報にアクセスできてはならない場合は、各グループに独自のデプロイメントを用意してください。各デプロイメントには、独自のプレフィックスまたはキーボールトと独自のアイデンティティが必要です。

環境変数の認証情報

環境変数の認証情報を使用すると、サンドボックスがシークレットのプレースホルダーのみを保持した状態で、エージェントのコマンドがサービスを呼び出せます。エグレスゲートウェイは、認証情報に記載されたホストへのリクエストに実際の値を挿入します。

ゲートウェイcma-egressは、リリースアーカイブに含まれるプロキシで、サンドボックスとインターネットの間に位置します。ゲートウェイはデフォルトでは無効であり、サーバーはゲートウェイが有効な場合にのみこれらの認証情報を受け付けます。

ゲートウェイを有効にすると、サンドボックスに2つの制限が適用されます:

  • サンドボックスはゲートウェイ経由でのみインターネットにアクセスします。
  • ゲートウェイは、サーバーのegress.allowed_hostnames設定に記載したホストにのみ接続します。

ワイルドカードを使わず、正確なパブリックホスト名を記載してください。エージェントのコマンドがダウンロード元とするすべてのホストを含めてください。

独自のサンドボックスイメージを構築した場合は、独自のサンドボックスイメージを構築するに示すとおり、cma-with-egressを介してワーカーを起動してください。

Composeスタックでゲートウェイを有効にする

docker-compose.ymlがあるディレクトリから、.envに2行を追加します。1行目には、ゲートウェイの接続先となるホストをカンマで区切って記載します。2行目は、ゲートウェイのComposeファイルを読み込みます。その後、スタックを起動します:

echo 'CMA_EGRESS__ALLOWED_HOSTNAMES=api.github.com' >> .env
echo 'COMPOSE_FILE=docker-compose.yml:docker-compose.egress.yml' >> .env
docker compose up --build -d

別のComposeファイルも使用している場合は、COMPOSE_FILEの行に追加してください。シェルのCOMPOSE_FILE変数は.env内の変数より優先されるため、シェルの変数の設定を解除してください。

ゲートウェイのファイルがサーバーのその他のegress設定を行うため、compose.config.yamlにegressセクションを追加しないでください。

Kubernetesでゲートウェイを有効にする

これらの手順は、Kubernetesにデプロイするのデプロイを出発点とします。そのページのREGISTRY、TAG、PLATFORM変数と、2つのvaluesファイルを使用します。コマンドは、OpenSSL 3.0以降を使用して、アーカイブの最上位ディレクトリから実行してください。サンドボックスチャートは、Azure Kubernetes Service(AKS)ではゲートウェイを提供しません。

これらの手順でのサーバーチャートのアップグレードでは、サーバーのPodに対するネットワークポリシーも追加されます。開始する前に、このポリシーが対象とするポートのうち2つを確認してください:

  • ポート9464(メトリクスのポート): ポリシーはこのポートを閉じます。Prometheusがそのポートをスクレイプする場合は、cma-server-values.yamlでserver.telemetry.prometheus.scraper.namespaceを、Prometheusが実行される名前空間に設定してください。
  • ポート8400(APIのポート): ポリシーはすべての送信元を許可します。独自のポリシーでポート8400にアクセスできる送信元を制限している場合、その制限は機能しなくなります。ネットワークポリシーは加算的に適用されるため、いずれか1つのポリシーが許可すれば接続は通過します。
  1. ゲートウェイのイメージをビルドしてプッシュする

    docker buildx build --platform "$PLATFORM" -f kubernetes/egress/Dockerfile -t "$REGISTRY/cma-egress:$TAG" --push .
  2. 認証局とゲートウェイの鍵を作成する

    (umask 077 && openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -days 825 \
      -subj "/CN=cma-server egress gateway" \
      -addext "basicConstraints=critical,CA:TRUE,pathlen:0" \
      -addext "keyUsage=critical,keyCertSign,cRLSign" \
      -keyout egress-ca.key -out egress-ca.crt)
    kubectl -n cma create secret tls cma-egress-ca --cert=egress-ca.crt --key=egress-ca.key
    kubectl -n cma-server create configmap cma-egress-ca --from-file=ca.crt=egress-ca.crt
    GATEWAY_KEY=$(openssl rand -hex 32)
    printf %s "$GATEWAY_KEY" | kubectl -n cma create secret generic cma-egress-gateway-key --from-file=gateway-key=/dev/stdin
    printf %s "$GATEWAY_KEY" | kubectl -n cma-server create secret generic cma-egress-gateway-key --from-file=gateway-key=/dev/stdin
    unset GATEWAY_KEY

    その後、認証局の秘密鍵であるegress-ca.keyを削除します。これを保持する者は誰でも、サンドボックスに対して任意のWebサイトになりすますことができます。証明書の有効期間は825日です。証明書を更新するを参照してください。

  3. 以前のセッションのサンドボックスを削除する

    環境でセッションを一度も実行していない場合は、この手順をスキップしてください。変更前のサンドボックスは、変更後にワーカーを起動できません。これらのコマンドは、各サンドボックスのワークスペースも削除します:

    kubectl -n cma scale deployment cma-dispatcher --replicas=0
    kubectl -n cma delete sandboxwarmpool cma-sandbox
    kubectl -n cma delete sandboxclaims --all

    Google Kubernetes Engine(GKE)では、次のコマンドも実行してください:

    kubectl -n cma delete sandboxes --all

    kubectl -n cma get sandboxes,pods,pvcが何も見つけなくなるまで繰り返します。「サンドボックス側を有効にする」の手順のhelm upgradeで、ディスパッチャーが再び起動します。

  4. サーバー側を有効にする

    クラスターのServiceの範囲内で、ゲートウェイ用の空いているIPv4アドレスを選択します。kubectl get svc -AのCLUSTER-IP列に、その範囲内のアドレスが表示されます。次の内容をcma-server-values.yamlに追加します。ファイルにすでにserverブロックがある場合は、これらの行をそこにマージしてください:

    egressGateway:
      enabled: true
      proxyAddress: 34.118.224.53:3128   # the address that you chose, and port 3128
    server:
      config:
        egress:
          allowed_hostnames:
            - api.github.com

    その後、アップグレードを実行します:

    helm upgrade cma-server kubernetes/server/chart --namespace cma-server -f cma-server-values.yaml --wait
  5. サンドボックス側を有効にする

    kubectl -n cma-server get svcを実行して、サーバーの2つのServiceを一覧表示します。新規インストールでは、それらの名前はcma-serverとcma-server-egressです。

    cma-values.yamlで、egress.modeをgatewayに変更し、egressの下にgatewayブロックを追加します。ブロックには、コマンドが一覧表示した2つの名前を指定します:

    egress:
      mode: gateway
      gateway:
        serviceIP: 34.118.224.53   # the address that you chose
        serverService: cma-server
        serverEgressService: cma-server-egress
        apiServerCIDRs:
          - 203.0.113.10/32        # the cluster's API endpoint

    ファイルのその他のegressの値はそのまま残してください。APIエンドポイントのアドレスとポートを表示するには、kubectl get endpoints kubernetes -n defaultを実行します。ポートが443でない場合は、egress.gateway.apiServerPortも設定してください。

    helm upgrade cma kubernetes/chart --namespace cma -f cma-values.yaml --wait

    アップグレードが.spec.replicasに関する競合で停止した場合は、kubectl -n cma scale deployment cma-dispatcher --replicas=1を実行してから、アップグレードを再度実行してください。

認証情報を追加する

認証情報を追加するに示すとおりに、環境変数の認証情報を作成します。ホスト型のガイドでは、これらの認証情報はセルフホスト型サンドボックスではサポートされていないとされています。これはあなたのサーバーではなくホスト型サービスについての説明です。

サーバーは独自のルールを追加します。いずれかのルールに違反するリクエストは、該当するフィールド名を示す400エラーで拒否されます。そのうち2つのルールを以下に示します:

  • networkingはタイプlimitedである必要があり、allowed_hosts内のすべてのホストがサーバーのegress.allowed_hostnamesリストに含まれている必要があります。
  • injection_locationはJSONで{"header": true}である必要があり、省略できません。

サーバーのリストにホストを追加した後、変更を適用します。Docker Composeでは、docker compose up -dを実行します。Kubernetesでは、サーバーのhelm upgradeコマンドとkubectl -n cma-server rollout restart deployment -l anthropic.com/role=serverを実行します。

エグレスゲートウェイを確認する

認証情報のボールトを使用してセッションを作成し、エージェントに2つのコマンドを実行するよう依頼します。この例は、api.github.comを記載したGITHUB_TOKENという名前の認証情報の場合です:

printenv GITHUB_TOKEN
curl -sS -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/user

最初のコマンドは、cma_ph_で始まるプレースホルダーを出力します。2番目のコマンドは、ゲートウェイがプレースホルダーをトークンに置き換えたため、トークンのGitHubアカウントのプロフィールを出力します。ゲートウェイは、リストにないホストへのリクエストを403エラーで拒否します。

Kubernetesで、すべてのリクエストが503エラーになる場合は、kube-proxyの--masquerade-allオプションのように、クラスターのネットワークがPodのアドレスを書き換えている可能性があります。ゲートウェイはPodのアドレスによってサンドボックスを区別するため、それらのアドレスが変更されずにゲートウェイに届く必要があります。

証明書を更新する

Kubernetesでは、セッションが実行されていない間に証明書を更新してください。Kubernetesでゲートウェイを有効にするの「認証局とゲートウェイの鍵を作成する」の手順全体を繰り返します。この手順で認証局とゲートウェイの鍵が再度作成されるため、削除したegress-ca.keyファイルは必要ありません。変更点は1つだけです。kubectl createを実行する4行それぞれの末尾に--dry-run=client -o yaml | kubectl apply -f -を追加します。たとえば、--from-file=gateway-key=/dev/stdinで終わる行は、--from-file=gateway-key=/dev/stdin --dry-run=client -o yaml | kubectl apply -f -で終わるようになります。

その後、サーバーとゲートウェイを再起動します:

kubectl -n cma-server rollout restart deployment -l anthropic.com/role=server
kubectl -n cma rollout restart deployment/cma-egress

エグレスゲートウェイの制限事項

  • ヘッダー: ゲートウェイは値をリクエストヘッダーにのみ挿入し、URLやボディには決して挿入しません。デフォルトでは、対象のヘッダーはAuthorizationのみです。他のヘッダーを許可するには、Authorizationと合わせてegress.swap_header_namesに記載するか、Composeスタックの場合は.envのCMA_EGRESS__SWAP_HEADER_NAMESに記載してください。
  • プロキシ変数を無視するプログラム: サンドボックスはHTTPS_PROXYなどの関連変数を通じてゲートウェイを見つけます。MavenやGradleなどのJavaツールはこれらの変数を読み取らないため、これらのツールはどこにもアクセスできません。

このページは役に立ちましたか?