Claude Platform Docs
Managed Agents企業設定

代理身分與憑證

讓您自行託管的 Claude Managed Agents 伺服器簽署一個標示每個代理的短期權杖,將 vault 憑證保存在您的密鑰管理器中,並透過輸出閘道讓密鑰不進入沙箱。

本頁說明如何讓您伺服器以外的系統信任代理,以及將代理使用的憑證保存在何處:

  • 代理身分:讓 MCP 伺服器或閘道為每個代理提供各自的存取權限。伺服器會簽署一個標示代理的短期權杖。
  • 密鑰管理器:伺服器將 vault 憑證保存在 AWS Secrets Manager、Google Cloud Secret Manager、HashiCorp Vault 或 Azure Key Vault 中。
  • 環境變數憑證:讓代理的命令在沙箱僅持有預留位置值的情況下呼叫服務。「egress gateway」(輸出閘道)會將實際值放入代理的請求中。

代理身分

您的伺服器可以簽署一個標示代理的短期「JSON Web Token」(JSON 網路權杖),即 JWT,並將其隨該代理的 MCP 呼叫一併傳送。接收方(MCP 伺服器或閘道)會依據您發布的公開金鑰檢查該權杖,然後即可為每個代理提供各自的存取權限。

設定簽發者

  1. 選擇簽發者 URL。 您會在步驟 3 中於此 URL 發布公開金鑰,接收方會從此 URL 擷取這些金鑰。靜態網站主機即可使用。請勿使用您伺服器的位址,因為伺服器不會在接收方擷取的路徑上提供金鑰。請使用不含路徑或結尾斜線的 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. 在包含 agent-identity 的目錄中,執行 sudo chown -R root:root agent-identity,除非您在 macOS 上使用 Docker Desktop 或使用 rootless Docker。
  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 以 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> 的形式傳送權杖,取代保管庫憑證。模型和 worker 都不會收到該權杖。

若要同時傳送權杖和保管庫憑證,請以 agent_token_header 欄位取代 auth 欄位:

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

保管庫憑證會放在 Authorization 標頭中,與未包含這兩個欄位的項目相同。權杖會放在 Agent-Identity-Token 標頭中,且不含 Bearer 前綴。

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。

然後套用以下規則:

  • 請以 agent_id 宣告(即代理在 API 中的 ID)作為每個代理存取規則的依據。
  • 請接受重複的 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

該命令會為其傳送的每個請求印出一行,並附上閘道的回應。通過的執行接著會印出以 check-gateway: PASS 開頭的一行,並以代碼 0 結束。失敗的執行會在以 check-gateway: 開頭的一行中說明出錯之處,並以代碼 1 結束。

密鑰管理器

根據預設,伺服器會將 vault 憑證的密鑰儲存在其資料庫中。若有 secret_store 區段,伺服器會將每個新 vault 憑證的密鑰寫入您的密鑰管理器,並使用您為其保留的名稱前綴。資料庫僅保留一個參照。

將您密鑰管理器的區塊新增至設定檔:

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

授與存取權

為伺服器提供單一身分,並將其限制在該前綴。封存的 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 Entra ID 進行驗證,與 Microsoft Foundry 相同。

檢查設定

請在首次啟動前以及任何原則變更後執行 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。後兩者是選用的 HashiCorp Vault 設定。
    • 您將 address 指向另一個 Vault。

    只有在您還原舊值後,伺服器才會再次找到這些密鑰。

  • 單一身分可讀取整個前綴。 如果兩個群組不得存取彼此的憑證,請為每個群組提供各自的部署。每個部署都需要各自的前綴或金鑰保存庫和各自的身分。

環境變數憑證

透過環境變數憑證,代理的命令可以在沙箱僅持有密鑰預留位置值的情況下呼叫服務。出口閘道會將實際值放入傳送至憑證所列主機的請求中。

該閘道 cma-egress 是發行封存中的一個代理伺服器,位於您的沙箱與網際網路之間。它預設為關閉,且您的伺服器僅在閘道開啟時才接受這些憑證。

開啟閘道後,您的沙箱會受到兩項限制:

  • 沙箱僅能透過閘道連線至網際網路。
  • 閘道僅會連線至您在伺服器 egress.allowed_hostnames 設定中列出的主機。

請列出確切的公開主機名稱,不使用萬用字元。請包含您代理的命令會從中下載內容的每個主機。

如果您建置了自己的沙箱映像檔,請透過 cma-with-egress 啟動 worker,如建置您自己的沙箱映像檔所示。

在 Compose 堆疊中開啟閘道

在包含 docker-compose.yml 的目錄中,於 .env 新增兩行。第一行列出閘道會連線的主機,以逗號分隔。第二行會載入閘道的 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 這一行。Shell 中的 COMPOSE_FILE 變數會覆寫 .env 中的變數,因此請取消設定 shell 中的該變數。

閘道的檔案會設定伺服器的其他 egress 設定,因此請勿在 compose.config.yaml 中新增 egress 區段。

在 Kubernetes 上開啟閘道

這些步驟以在 Kubernetes 上部署中的部署為起點。它們使用該頁面的 REGISTRY、TAG 和 PLATFORM 變數及其兩個 values 檔案。請在封存的最上層目錄中,以 OpenSSL 3.0 或更新版本執行這些命令。沙箱 chart 在 Azure Kubernetes Service (AKS) 上不提供閘道。

這些步驟中伺服器 chart 的升級也會在伺服器的 pod 上新增一個網路原則。開始之前,請檢查它涵蓋的其中兩個連接埠:

  • 連接埠 9464(指標連接埠): 該原則會關閉此連接埠。如果 Prometheus 會抓取該連接埠,請在 cma-server-values.yaml 中將 server.telemetry.prometheus.scraper.namespace 設為 Prometheus 執行所在的命名空間。
  • 連接埠 8400(API 的連接埠): 該原則會允許所有來源。如果您自己的原則限制了誰能連線至連接埠 8400,該限制將會失效。網路原則會累加,因此只要任何一個原則允許某個連線,該連線就能通過。
  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,也就是「certificate authority」(憑證授權單位)的私密金鑰。任何持有它的人,都可以對您的沙箱冒充任何網站。該憑證的有效期為 825 天。請參閱更新憑證。

  3. 移除先前工作階段的沙箱

    如果該環境尚未執行任何工作階段,請略過此步驟。變更之前建立的沙箱在變更之後無法啟動其 worker。這些命令也會刪除每個沙箱的工作區:

    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 會再次啟動 dispatcher。

  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 以列出伺服器的兩個 Service。在新安裝中,它們的名稱為 cma-server 和 cma-server-egress。

    在 cma-values.yaml 中,將 egress.mode 變更為 gateway,並在 egress 下新增 gateway 區塊。在該區塊中填入該命令列出的兩個名稱:

    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 錯誤拒絕違反規則的請求。其中兩條規則如下:

  • 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。

檢查輸出閘道

使用該憑證的保管庫建立工作階段,並要求代理執行兩個命令。此範例適用於名為 GITHUB_TOKEN 且列出 api.github.com 的憑證:

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

第一個命令會印出以 cma_ph_ 開頭的預留位置值。第二個命令會印出該權杖所屬 GitHub 帳戶的個人資料,因為閘道已將預留位置值替換為權杖。閘道會以 403 錯誤拒絕傳送至不在您清單上之主機的請求。

在 Kubernetes 上,如果每個請求都收到 503 錯誤,您叢集的網路可能會改寫 pod 的位址,就像 kube-proxy 的 --masquerade-all 選項所做的那樣。閘道會依據 pod 的位址區分沙箱,因此這些位址必須在未經變更的情況下到達閘道。

更新憑證

在 Kubernetes 上,請在沒有任何工作階段執行時更新憑證。重複在 Kubernetes 上開啟閘道中的整個「建立憑證授權單位和閘道金鑰」步驟。該步驟會再次建立憑證授權單位和閘道金鑰,因此您不需要已刪除的 egress-ca.key 檔案。請做一項變更:在執行 kubectl create 的四行中,於每一行的結尾加上 --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 工具不會讀取這些變數,因此這些工具無法連線到任何地方。

這個頁面有幫助嗎?