Идентификация агентов и учётные данные
Настройте самостоятельно размещённый сервер Claude Managed Agents так, чтобы он подписывал краткосрочный токен с именем каждого агента, храните учётные данные хранилища в своём менеджере секретов и не допускайте секреты в песочницы с помощью шлюза исходящего трафика.
На этой странице показано, как позволить системам за пределами вашего сервера доверять агенту и где хранить учётные данные, которые используют ваши агенты:
- Идентификация агентов: позвольте серверу или шлюзу MCP предоставлять каждому агенту собственный доступ. Сервер подписывает краткосрочный токен с именем агента.
- Менеджер секретов: сервер хранит учётные данные хранилища в AWS Secrets Manager, Google Cloud Secret Manager, HashiCorp Vault или Azure Key Vault.
- Учётные данные в переменных окружения: позвольте командам агента обращаться к сервису, в то время как песочница содержит лишь заполнитель. Шлюз исходящего трафика подставляет реальное значение в запросы агента.
Идентификация агентов
Ваш сервер может подписывать краткосрочный JSON Web Token (JWT), который указывает агента, и отправлять его вместе с вызовами MCP этого агента. Получатель — сервер или шлюз MCP — проверяет токен по открытым ключам, которые вы публикуете, и затем может предоставить каждому агенту собственный доступ.
Настройка издателя
-
Выберите URL издателя. На шаге 3 вы публикуете по этому URL свои открытые ключи, а получатели загружают их с него. Подойдёт статический веб-хостинг. Не используйте адрес вашего сервера, потому что сервер не отдаёт ключи по путям, которые запрашивают получатели. Используйте URL
https://без пути и завершающей косой черты, на имени хоста, которое вы сможете сохранить за собой. -
Создайте ключ подписи. Выполните эти команды в верхнем каталоге распакованного архива:
mkdir -m 700 agent-identity openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out agent-identity/signing-key.pem -
Опубликуйте открытые ключи. Эта команда записывает их в
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 -
Передайте серверу ключ.
- Если в архиве есть каталог
compose, переместите в него каталог ключа:mv agent-identity compose/agent-identity. - В
docker-compose.ymlудалите строкуvolumes: *server_mountsсервисаcma-serverи раскомментируйте блокvolumes:под ней. Если вы изменили списокx-server-mounts, внесите то же изменение в этот блок, потому что сервисcma-serverбольше не читает этот список. - В каталоге, где находится
agent-identity, выполнитеsudo chown -R root:root agent-identity, если только вы не используете Docker Desktop на macOS или rootless Docker.
Выполните
kubectl -n cma-server create secret generic cma-agent-identity --from-file=agent-identity/signing-key.pem. Затем задайте дляserver.agentIdentity.secretNameзначениеcma-agent-identityв файле значений чарта сервера. - Если в архиве есть каталог
-
Измените файл настроек. Укажите имя хоста получателя в
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указывает одного получателя в виде URLhttps://. Егоurls— это префиксы URL серверов MCP, которые могут получать токен для него. -
Перезапустите сервер. В стеке Compose вместо перезапуска выполните
docker compose up -dиз каталога Compose-файла.
Чтобы не хранить закрытый ключ в файлах, используйте 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, как и для записи без обоих этих полей. Токен передаётся в заголовке 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. Нужный ключ — тот, идентификатор которого совпадает сkidв заголовке токена. Для ключа RSA алгоритм —RS256. issравен URL вашего издателя, аaudравен audience получателя.expнаходится в будущем, аiatне находится в будущем.typв заголовке токена равенagent+jwt, аtoken_useравенagent.
Затем применяйте следующие правила:
- Стройте правила доступа для каждого агента на основе утверждения
agent_id— идентификатора агента в API. - Принимайте повторяющийся
jti, потому что одно получение списка или вызов может включать несколько запросов с одним и тем же токеном. - Шлюз должен вызывать каждый инструмент с собственными учётными данными и никогда не передавать токен дальше.
При использовании единого входа токен вызова инструмента также указывает вызывающую сторону, создавшую сессию, в утверждениях actor_sub и actor_iss. actor_sub не означает, что вызывающая сторона одобрила вызов. Каждый вызов выбирает модель.
Эти токены не имеют actor_sub:
- Токен получения списка инструментов
- Токен вызова субагента
- Все токены сессии, созданной с помощью ключа API сервера
Если правило зависит от вызывающей стороны, отклоняйте вызов инструмента, у которого нет actor_sub.
Проверка шлюза MCP
Команда check-gateway отправляет шлюзу MCP действительные и недействительные токены. Передайте команде отдельный файл настроек, здесь check-gateway.yaml:
- Скопируйте в файл только разделы
mcpиagent_identityнастроек сервера, а такжеlimits.mcp_call_timeout, если сервер его задаёт. - В копии измените
key_fileна путь к ключу на машине, где вы запускаете команду, например./agent-identity/signing-key.pem. Если вы переместили каталог вcompose, это./compose/agent-identity/signing-key.pem.
Для -agent укажите идентификатор агента, которому шлюз разрешает доступ. Если ключ принадлежит 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.
Менеджер секретов
По умолчанию сервер хранит секреты учётных данных хранилища в своей базе данных. При наличии раздела secret_store сервер записывает секрет каждых новых учётных данных хранилища в ваш менеджер секретов под префиксом имени, который вы для этого резервируете. В базе данных хранится только ссылка.
Добавьте блок для вашего менеджера секретов в файл настроек:
secret_store:
type: aws_secrets_manager
region: us-east-1
prefix: cma-server/prod/secret_store:
type: gcp_secret_manager
project: my-project # the project ID, not its number
prefix: cma-server-prod--secret_store:
type: azure_key_vault
vault_url: https://my-vault.vault.azure.net
prefix: cma-server-prod--secret_store:
type: hashicorp_vault
address: https://vault.internal:8200
prefix: cma-server/prod/
approle:
role_id: <role-id>
secret_id_file: /run/vault/secret-id
#kubernetes: { role: cma-server }
#token_file: /run/vault/tokenЗадайте ровно один из трёх методов входа:
approle: используйте его с Docker Compose, на хосте или с Helm-чартом сервера. Сервер входит с помощью идентификатора роли и идентификатора секрета, который он читает из файла.kubernetes: используйте его только в собственной установке Kubernetes, в которой у пода сервера есть токен сервисной учётной записи. Сервер входит с помощью этого токена. Helm-чарт сервера не выдаёт подам сервера такой токен, поэтому этот метод не работает с чартом.token_file: используйте его для любого другого метода входа в Vault. Запустите Vault Agent рядом с сервером и настройте его так, чтобы он записывал свой токен в этот файл.
При использовании Helm-чарта сервера передайте серверу идентификатор секрета в Secret:
- Поместите идентификатор секрета в Secret в пространстве имён сервера и укажите имя этого Secret в
server.extensionFiles.secretNameчарта. - Задайте для
approle.secret_id_fileпуть к идентификатору секрета. Чарт монтирует каждый ключ этого Secret как файл в/run/cma-server/extension-files/, поэтому ключ с именемsecret-idнаходится по пути/run/cma-server/extension-files/secret-id.
Для метода kubernetes привяжите роль Kubernetes в Vault к пространству имён и сервисной учётной записи сервера, а не к пространству имён песочниц, cma.
Предоставление доступа
Выделите серверу одно удостоверение и ограничьте его префиксом. В каталоге iam/ архива есть файл для каждого менеджера секретов:
- AWS Secrets Manager: замените заполнители в
aws-secrets-manager-policy.jsonи прикрепите политику к удостоверению, от имени которого работает сервер. - Google Cloud Secret Manager: выполните команды из комментариев в
gcp-secret-manager-role.yaml. - Azure Key Vault: роль Azure охватывает всё хранилище ключей, а не префикс. Поэтому выделите развёртыванию собственное хранилище ключей, использующее управление доступом на основе ролей Azure. Замените
SUBSCRIPTION_IDвazure-key-vault-role.jsonи создайте на его основе пользовательскую роль. Назначьте эту роль в хранилище ключей удостоверению, от имени которого работает сервер. - 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.
Сервер снова найдёт эти секреты, только когда вы восстановите старые значения.
- Вы удаляете раздел
-
Одно удостоверение читает весь префикс. Если две группы не должны иметь доступа к учётным данным друг друга, выделите каждой группе собственное развёртывание. Каждому развёртыванию нужен собственный префикс или хранилище ключей и собственное удостоверение.
Учётные данные в переменных окружения
С помощью учётных данных в переменной окружения команды агента могут обращаться к сервису, в то время как песочница содержит лишь заполнитель вместо секрета. «Egress gateway» (шлюз исходящего трафика) подставляет реальное значение в запросы к хостам, перечисленным в учётных данных.
Шлюз, cma-egress, — это прокси из архива релиза, который находится между вашими песочницами и интернетом. По умолчанию он выключен, и ваш сервер принимает такие учётные данные, только если шлюз включён.
При включённом шлюзе к вашим песочницам применяются два ограничения:
- Песочницы выходят в интернет только через шлюз.
- Шлюз подключается только к хостам, перечисленным вами в настройке сервера
egress.allowed_hostnames.
Указывайте точные публичные имена хостов, без подстановочных знаков. Включите все хосты, с которых команды ваших агентов что-либо загружают.
Если вы собрали собственный образ песочницы, запускайте воркер через cma-with-egress, как показано в разделе Сборка собственного образа песочницы.
Включение шлюза в стеке 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. Переменная COMPOSE_FILE в вашей оболочке переопределяет переменную в .env, поэтому сбросьте переменную оболочки.
Файл шлюза задаёт остальные настройки egress сервера, поэтому не добавляйте раздел egress в compose.config.yaml.
Включение шлюза в Kubernetes
Эти шаги начинаются с развёртывания из раздела Развёртывание в Kubernetes. В них используются переменные REGISTRY, TAG и PLATFORM с той страницы и два её файла значений. Выполняйте команды из верхнего каталога архива, используя OpenSSL 3.0 или новее. Чарт песочниц не предоставляет шлюз в Azure Kubernetes Service (AKS).
Обновление чарта сервера в этих шагах также добавляет сетевую политику для подов серверов. Прежде чем начать, проверьте два из охватываемых ею портов:
- Порт 9464, порт метрик: политика закрывает его. Если Prometheus собирает метрики с этого порта, задайте в
cma-server-values.yamlдляserver.telemetry.prometheus.scraper.namespaceпространство имён, в котором работает Prometheus. - Порт 8400, порт API: политика открывает его для любых источников. Если ваша собственная политика ограничивает доступ к порту 8400, это ограничение перестаёт работать. Сетевые политики суммируются, поэтому соединение проходит, если его разрешает хотя бы одна политика.
Соберите и отправьте образ шлюза
docker buildx build --platform "$PLATFORM" -f kubernetes/egress/Dockerfile -t "$REGISTRY/cma-egress:$TAG" --push .Создайте центр сертификации и ключ шлюза
(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— закрытый ключ центра сертификации. Любой, кто владеет им, может выдавать себя за любой веб-сайт перед вашими песочницами. Сертификат действителен 825 дней. См. раздел Обновление сертификата.Удалите песочницы предыдущих сессий
Если в окружении не запускалось ни одной сессии, пропустите этот шаг. Песочница, созданная до изменения, после него не сможет запустить свой воркер. Эти команды также удаляют рабочее пространство каждой песочницы:
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на шаге «Включите сторону песочниц» снова запускает диспетчер.Включите сторону сервера
Выберите для шлюза свободный адрес IPv4 в диапазоне Service кластера. Столбец
CLUSTER-IPкомандыkubectl get svc -Aпоказывает адреса из этого диапазона. Добавьте следующее в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Включите сторону песочниц
Выполните
kubectl -n cma-server get svc, чтобы вывести два объекта Service сервера. При новой установке они называютсяcma-serverиcma-server-egress.В
cma-values.yamlизменитеegress.modeнаgatewayи добавьте блокgatewayвegress. Укажите в блоке два имени, которые вывела команда: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должен быть{"header": true}в JSON и не может быть опущен.
После добавления хоста в список сервера примените изменение. В 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, вероятно, сеть вашего кластера переписывает адреса подов, как это делает параметр --masquerade-all kube-proxy. Шлюз различает песочницы по адресам их подов, поэтому эти адреса должны доходить до него без изменений.
Обновление сертификата
В Kubernetes обновляйте сертификат, когда не выполняется ни одна сессия. Повторите весь шаг «Создайте центр сертификации и ключ шлюза» в разделе Включение шлюза в Kubernetes. Он заново создаёт центр сертификации и ключ шлюза, поэтому удалённый вами файл egress-ca.key не понадобится. Внесите одно изменение: добавьте --dry-run=client -o yaml | kubectl apply -f - в конец каждой из четырёх строк, выполняющих kubectl create. Например, строка, которая заканчивается на --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или вCMA_EGRESS__SWAP_HEADER_NAMESв.envдля стека Compose. - Программы, игнорирующие переменные прокси: песочницы находят шлюз через
HTTPS_PROXYи связанные переменные. Инструменты Java, такие как Maven и Gradle, не читают эти переменные, поэтому ничего не могут достичь.
Эта страница была полезной?