Identidade e credenciais do agente
Faça seu servidor auto-hospedado do Claude Managed Agents assinar um token de curta duração que nomeia cada agente, mantenha as credenciais de vault no seu gerenciador de segredos e mantenha os segredos fora dos sandboxes com o gateway de saída.
Esta página mostra como permitir que os sistemas fora do seu servidor confiem em um agente e onde manter as credenciais que seus agentes usam:
- Identidade do agente: Permita que um servidor MCP ou gateway dê a cada agente seu próprio acesso. O servidor assina um token de curta duração que nomeia o agente.
- Gerenciador de segredos: O servidor mantém as credenciais de vault no AWS Secrets Manager, no Google Cloud Secret Manager, no HashiCorp Vault ou no Azure Key Vault.
- Credenciais de variável de ambiente: Permita que os comandos de um agente chamem um serviço enquanto o sandbox mantém apenas um placeholder. O “egress gateway” (gateway de saída) coloca o valor real nas solicitações do agente.
Identidade do agente
Seu servidor pode assinar um “JSON Web Token” (token web JSON), ou JWT, de curta duração que nomeia um agente, e enviá-lo com as chamadas MCP desse agente. O receptor, um servidor MCP ou “gateway” (gateway), verifica o token em relação às chaves públicas que você publica e pode então dar a cada agente seu próprio acesso.
Configurar o emissor
-
Escolha a URL do “issuer” (emissor). Você publica suas chaves públicas nesta URL na etapa 3, e os receptores as buscam nela. Um host web estático funciona. Não use o endereço do seu servidor, porque o servidor não serve as chaves nos caminhos que os receptores buscam. Use uma URL
https://sem caminho nem barra final, em um nome de host que você possa manter. -
Crie a chave de assinatura. Execute estes comandos no nível superior do arquivo extraído:
mkdir -m 700 agent-identity openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out agent-identity/signing-key.pem -
Publique as chaves públicas. Este comando as grava em
issuer-files/.well-known/. Sirvaissuer-filesna raiz do nome de host do emissor, com o tipo de conteúdoapplication/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 -
Dê a chave ao servidor.
- Se o arquivo tiver um diretório
compose, mova o diretório da chave para dentro dele:mv agent-identity compose/agent-identity. - Em
docker-compose.yml, exclua a linhavolumes: *server_mountsdo serviçocma-servere descomente o blocovolumes:abaixo dela. Se você alterou a listax-server-mounts, faça a mesma alteração nesse bloco, porque o serviçocma-servernão lê mais a lista. - No diretório que contém
agent-identity, executesudo chown -R root:root agent-identity, a menos que você use o Docker Desktop no macOS ou Docker rootless.
Execute
kubectl -n cma-server create secret generic cma-agent-identity --from-file=agent-identity/signing-key.pem. Em seguida, definaserver.agentIdentity.secretNamecomocma-agent-identityno arquivo de valores do chart do servidor. - Se o arquivo tiver um diretório
-
Altere o arquivo de configurações. Liste o nome de host do receptor em
mcp.allowed_hostnamese adicione esta seção: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.comCada
audiencenomeia um receptor, como uma URLhttps://. Seusurlssão os prefixos de URL dos servidores MCP que podem receber um token para ele. -
Reinicie o servidor. Na stack do Compose, execute
docker compose up -da partir do diretório do arquivo Compose em vez de reiniciar.
Para manter a chave privada fora de arquivos, use key_secret (seu gerenciador de segredos) ou kms_key (AWS KMS ou Google Cloud KMS). A Referência de configuração descreve ambas as configurações.
Enviar o token a um servidor MCP
O conector MCP descreve os campos da entrada de servidor MCP de um agente. Adicione um campo auth a essa entrada:
mcp_servers:
- type: url
name: tickets
url: https://mcp-gateway.example.com/tickets
auth:
type: agent_token
audience: https://mcp-gateway.example.comPara cada listagem de ferramentas ou chamada de ferramenta, seu servidor assina um novo token. Ele envia o token como Authorization: Bearer <token>, no lugar de uma credencial do vault. Nem o modelo nem o worker o recebem.
Para enviar tanto o token quanto uma credencial de vault, substitua o campo auth por um campo agent_token_header:
mcp_servers:
- type: url
name: tickets
url: https://mcp-gateway.example.com/tickets
agent_token_header:
audience: https://mcp-gateway.example.comA credencial de vault vai no cabeçalho Authorization, como acontece em uma entrada sem nenhum dos dois campos. O token vai em um cabeçalho Agent-Identity-Token, sem o prefixo Bearer.
O SDK não tem os campos auth e agent_token_header. No código do SDK, adicione o campo à entrada do servidor MCP como um campo extra ou envie a solicitação como JSON simples.
Estas páginas mostram como enviar campos extras:
SDK Python · SDK TypeScript · SDK Go · SDK Java · SDK PHP · SDK Ruby
Algumas dessas páginas mostram campos extras apenas no nível superior de uma solicitação, não dentro de uma entrada de lista. Nesse caso, torne o próprio mcp_servers o campo extra. Envie toda a lista dessa forma, com auth ou agent_token_header em sua entrada.
Para interromper os tokens de um agente, remova a entrada do agente ou arquive o agente. Um token já enviado permanece válido até seu exp, no máximo 5 minutos por padrão.
O que o receptor verifica
Faça o receptor aceitar uma solicitação somente se todas estas condições forem atendidas:
- A assinatura é verificada com uma chave do seu conjunto de chaves,
<issuer>/.well-known/jwks.json. A chave correta é aquela cujo ID corresponde aokidno cabeçalho do token. Para uma chave RSA, o algoritmo éRS256. issé igual à URL do seu emissor, eaudé igual ao audience do receptor.expestá no futuro, eiatnão está no futuro.typno cabeçalho do token éagent+jwt, etoken_useéagent.
Em seguida, aplique estas regras:
- Baseie as regras de acesso de cada agente na claim
agent_id, o ID do agente na API. - Aceite um
jtirepetido, porque uma listagem ou chamada pode exigir várias solicitações com o mesmo token. - Faça um gateway chamar cada ferramenta com sua própria credencial e nunca repassar o token.
Com single sign-on, o token de uma chamada de ferramenta também nomeia o chamador que criou a sessão, nas claims actor_sub e actor_iss. actor_sub não significa que o chamador aprovou a chamada. O modelo escolhe cada chamada.
Estes tokens não têm actor_sub:
- O token de uma listagem de ferramentas
- O token de uma chamada de um subagente
- Todos os tokens de uma sessão criada pela chave de API do servidor
Se uma regra depender do chamador, recuse uma chamada de ferramenta que não tenha actor_sub.
Testar o gateway MCP
O comando check-gateway envia tokens válidos e inválidos a um gateway MCP. Forneça ao comando um arquivo de configurações próprio, aqui check-gateway.yaml:
- Copie para o arquivo apenas as seções
mcpeagent_identitydas configurações do servidor, elimits.mcp_call_timeoutse o servidor a definir. - Na cópia, altere
key_filepara o caminho da chave na máquina em que você executa o comando, como./agent-identity/signing-key.pem. Se você moveu o diretório paracompose, esse caminho é./compose/agent-identity/signing-key.pem.
Para -agent, forneça o ID de um agente que o gateway permite. Se a chave pertencer ao root, use sudo.
./cma-server check-gateway -config check-gateway.yaml -agent agent_011CYm1BLqPXpQRk5khsSXrs \
-url https://mcp-gateway.example.com/ticketsO comando imprime uma linha para cada solicitação que envia, com a resposta do gateway. Uma execução bem-sucedida imprime então uma linha que começa com check-gateway: PASS e sai com o código 0. Uma execução com falha informa o que deu errado, em uma linha que começa com check-gateway:, e sai com o código 1.
Gerenciador de segredos
Por padrão, o servidor armazena os segredos das credenciais de vault em seu banco de dados. Com uma seção secret_store, o servidor grava o segredo de cada nova credencial de vault no seu gerenciador de segredos, sob um prefixo de nome que você reserva para isso. O banco de dados mantém apenas uma referência.
Adicione o bloco do seu gerenciador de segredos ao arquivo de configurações:
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/tokenDefina exatamente um dos três métodos de login:
approle: Use-o com o Docker Compose, em um host ou com o Helm chart do servidor. O servidor faz login com um role ID e com um secret ID que ele lê de um arquivo.kubernetes: Use-o somente em uma instalação própria do Kubernetes, cujo pod do servidor tenha um token de service account. O servidor faz login com esse token. O Helm chart do servidor não dá esse token aos pods do servidor, portanto este método não funciona com o chart.token_file: Use-o para qualquer outro método de login do Vault. Execute o Vault Agent ao lado do servidor e faça-o gravar seu token neste arquivo.
Com o Helm chart do servidor, forneça ao servidor o secret ID em um Secret:
- Coloque o secret ID em um Secret no namespace do servidor e nomeie esse Secret em
server.extensionFiles.secretNamedo chart. - Defina
approle.secret_id_filecomo o caminho do secret ID. O chart monta cada chave desse Secret como um arquivo em/run/cma-server/extension-files/, portanto uma chave chamadasecret-idfica em/run/cma-server/extension-files/secret-id.
Para o método kubernetes, vincule a função Kubernetes do Vault ao namespace e à service account do servidor, não ao namespace dos sandboxes, cma.
Conceda acesso
Dê ao servidor uma identidade e restrinja-a ao prefixo. O diretório iam/ do arquivo tem um arquivo para cada gerenciador de segredos:
- AWS Secrets Manager: Substitua os placeholders em
aws-secrets-manager-policy.jsone anexe a política à identidade com a qual o servidor é executado. - Google Cloud Secret Manager: Execute os comandos que estão nos comentários de
gcp-secret-manager-role.yaml. - Azure Key Vault: Uma função do Azure abrange um key vault inteiro, não um prefixo. Portanto, dê à implantação um key vault próprio, que use o controle de acesso baseado em funções do Azure. Substitua
SUBSCRIPTION_IDemazure-key-vault-role.jsone crie uma função personalizada a partir dele. Atribua a função no key vault à identidade com a qual o servidor é executado. - HashiCorp Vault: Substitua os placeholders em
hashicorp-vault-policy.hcle anexe a política à identidade com a qual o servidor é executado.
Na AWS e no Google Cloud, o servidor se autentica da mesma forma que faz para inferência. No Azure Key Vault, ele se autentica com o Microsoft Entra ID, da mesma forma que faz para o Microsoft Foundry.
Verifique a configuração
Execute validate-store antes da primeira inicialização e após qualquer alteração de política. Ele cria, lê e exclui um segredo de teste sob o prefixo, sem iniciar o servidor. Execute o comando onde o servidor é executado, com o ambiente do servidor:
-
Docker Compose: Execute-o no contêiner do servidor. Em Arm, substitua
linux_amd64neste comando porlinux_arm64:docker compose exec cma-server /opt/cma-server/bin/linux_amd64/cma-server validate-store -config /etc/cma-server/config.yaml -
Em um host:
./cma-server validate-store -config /etc/cma-server/config.yaml -
Kubernetes: Execute o mesmo comando como um Job sob a service account do servidor.
Uma execução bem-sucedida termina com uma linha que diz pass e sai com o código 0.
Com o Azure Key Vault, execute esta verificação no seu key vault antes de depender dele.
Limites do gerenciador de segredos
-
Escolha as configurações uma única vez. Após qualquer uma destas alterações, o servidor deixa de encontrar os segredos que gravou antes da alteração:
- Você remove a seção
secret_store. - Você altera
type,prefix,region,project,vault_url,mountounamespace. Os dois últimos são configurações opcionais do HashiCorp Vault. - Você aponta
addresspara outro Vault.
O servidor só volta a encontrar esses segredos quando você restaura os valores antigos.
- Você remove a seção
-
Uma única identidade lê todo o prefixo. Se dois grupos não puderem acessar as credenciais um do outro, dê a cada grupo sua própria implantação. Cada implantação precisa de seu próprio prefixo ou key vault e de sua própria identidade.
Credenciais de variável de ambiente
Com uma credencial de variável de ambiente, os comandos de um agente podem chamar um serviço enquanto o sandbox mantém apenas um placeholder para o segredo. O gateway de saída coloca o valor real nas solicitações aos hosts que a credencial lista.
O gateway, cma-egress, é um proxy no arquivo da versão que fica entre seus sandboxes e a internet. Ele fica desativado por padrão, e seu servidor aceita essas credenciais somente com o gateway ativado.
Com o gateway ativado, dois limites se aplicam aos seus sandboxes:
- Os sandboxes acessam a internet somente por meio do gateway.
- O gateway se conecta apenas aos hosts que você lista na configuração
egress.allowed_hostnamesdo servidor.
Liste nomes de host públicos exatos, sem curingas. Inclua todos os hosts dos quais os comandos dos seus agentes fazem downloads.
Se você criou sua própria imagem de sandbox, inicie o worker por meio de cma-with-egress, como Criar sua própria imagem de sandbox mostra.
Ativar o gateway na stack do Compose
No diretório que contém docker-compose.yml, adicione duas linhas a .env. A primeira lista os hosts aos quais o gateway se conecta, separados por vírgulas. A segunda carrega o arquivo Compose do gateway. Em seguida, inicie a stack:
echo 'CMA_EGRESS__ALLOWED_HOSTNAMES=api.github.com' >> .env
echo 'COMPOSE_FILE=docker-compose.yml:docker-compose.egress.yml' >> .env
docker compose up --build -dSe você também usar outro arquivo Compose, adicione-o à linha COMPOSE_FILE. Uma variável COMPOSE_FILE no seu shell substitui a de .env, então remova a definição da variável do shell.
O arquivo do gateway define as outras configurações egress do servidor, portanto não adicione uma seção egress a compose.config.yaml.
Ativar o gateway no Kubernetes
Estas etapas partem da implantação em Implantar no Kubernetes. Elas usam as variáveis REGISTRY, TAG e PLATFORM dessa página e seus dois arquivos de valores. Execute os comandos a partir do diretório principal do arquivo, com OpenSSL 3.0 ou posterior. O chart do sandbox não oferece o gateway no Azure Kubernetes Service (AKS).
O upgrade do chart do servidor nestas etapas também adiciona uma política de rede sobre os pods dos servidores. Verifique duas das portas que ela abrange antes de começar:
- Porta 9464, a porta de métricas: A política a fecha. Se o Prometheus coletar métricas dessa porta, defina
server.telemetry.prometheus.scraper.namespaceemcma-server-values.yamlcomo o namespace em que o Prometheus é executado. - Porta 8400, a porta da API: A política admite qualquer origem. Se uma política sua limitar quem acessa a porta 8400, esse limite deixa de funcionar. As políticas de rede se somam, portanto uma conexão passa se qualquer uma das políticas a admitir.
Compilar e enviar a imagem do gateway
docker buildx build --platform "$PLATFORM" -f kubernetes/egress/Dockerfile -t "$REGISTRY/cma-egress:$TAG" --push .Criar a autoridade certificadora e a chave do gateway
(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_KEYEm seguida, exclua
egress-ca.key, a chave privada da autoridade certificadora. Qualquer pessoa que a detenha pode se passar por qualquer site perante seus sandboxes. O certificado é válido por 825 dias. Consulte Renovar o certificado.Remover os sandboxes de sessões anteriores
Se o ambiente não executou nenhuma sessão, pule esta etapa. Um sandbox de antes da alteração não consegue iniciar seu worker depois dela. Estes comandos também excluem o workspace de cada sandbox:
kubectl -n cma scale deployment cma-dispatcher --replicas=0 kubectl -n cma delete sandboxwarmpool cma-sandbox kubectl -n cma delete sandboxclaims --allNo Google Kubernetes Engine (GKE), execute também este comando:
kubectl -n cma delete sandboxes --allRepita
kubectl -n cma get sandboxes,pods,pvcaté que ele não encontre nada. Ohelm upgradeda etapa “Ativar o lado dos sandboxes” inicia o dispatcher novamente.Ativar o lado do servidor
Escolha um endereço IPv4 livre no intervalo de Services do cluster para o gateway. A coluna
CLUSTER-IPdekubectl get svc -Amostra endereços nesse intervalo. Adicione isto acma-server-values.yaml. Se o arquivo já tiver um blocoserver, mescle estas linhas nele:egressGateway: enabled: true proxyAddress: 34.118.224.53:3128 # the address that you chose, and port 3128 server: config: egress: allowed_hostnames: - api.github.comEm seguida, execute o upgrade:
helm upgrade cma-server kubernetes/server/chart --namespace cma-server -f cma-server-values.yaml --waitAtivar o lado dos sandboxes
Execute
kubectl -n cma-server get svcpara listar os dois Services do servidor. Em uma nova instalação, eles se chamamcma-serverecma-server-egress.Em
cma-values.yaml, altereegress.modeparagatewaye adicione um blocogatewaysobegress. Dê ao bloco os dois nomes que o comando listou: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 endpointMantenha os outros valores
egressdo arquivo. Para imprimir os endereços e a porta do endpoint da API, executekubectl get endpoints kubernetes -n default. Se a porta não for 443, defina tambémegress.gateway.apiServerPort.helm upgrade cma kubernetes/chart --namespace cma -f cma-values.yaml --waitSe o upgrade parar em um conflito sobre
.spec.replicas, executekubectl -n cma scale deployment cma-dispatcher --replicas=1e, em seguida, execute o upgrade novamente.
Adicionar uma credencial
Crie uma credencial de variável de ambiente como Adicionar uma credencial mostra. Os guias do serviço hospedado dizem que essas credenciais não são suportadas com sandboxes auto-hospedados. Isso descreve o serviço hospedado, não o seu servidor.
Seu servidor adiciona regras próprias. Ele recusa uma solicitação que viole uma delas com um erro 400 que nomeia o campo. Duas dessas regras são:
networkingdeve ter o tipolimited, e todos os hosts emallowed_hostsdevem estar na listaegress.allowed_hostnamesdo servidor.injection_locationdeve ser{"header": true}em JSON e não pode ser omitido.
Depois de adicionar um host à lista do servidor, aplique a alteração. No Docker Compose, execute docker compose up -d. No Kubernetes, execute o comando helm upgrade do servidor e kubectl -n cma-server rollout restart deployment -l anthropic.com/role=server.
Verificar o gateway de saída
Crie uma sessão com o vault da credencial e peça ao agente para executar dois comandos. Este exemplo é para uma credencial chamada GITHUB_TOKEN que lista api.github.com:
printenv GITHUB_TOKEN
curl -sS -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/userO primeiro comando imprime um placeholder que começa com cma_ph_. O segundo imprime o perfil da conta do GitHub do token, porque o gateway substituiu o placeholder pelo token. O gateway recusa uma solicitação a um host que não está na sua lista com um erro 403.
No Kubernetes, se todas as solicitações receberem um erro 503, a rede do seu cluster provavelmente reescreve os endereços dos pods, como faz a opção --masquerade-all do kube-proxy. O gateway distingue os sandboxes pelos endereços de seus pods, portanto esses endereços devem chegar a ele inalterados.
Renovar o certificado
No Kubernetes, renove o certificado enquanto nenhuma sessão estiver em execução. Repita toda a etapa “Criar a autoridade certificadora e a chave do gateway” em Ativar o gateway no Kubernetes. Ela cria a autoridade certificadora e a chave do gateway novamente, portanto você não precisa do arquivo egress-ca.key que excluiu. Faça uma alteração: adicione --dry-run=client -o yaml | kubectl apply -f - ao final de cada uma das quatro linhas que executam kubectl create. Uma linha que termina em --from-file=gateway-key=/dev/stdin, por exemplo, passa então a terminar em --from-file=gateway-key=/dev/stdin --dry-run=client -o yaml | kubectl apply -f -.
Em seguida, reinicie os servidores e o gateway:
kubectl -n cma-server rollout restart deployment -l anthropic.com/role=server
kubectl -n cma rollout restart deployment/cma-egressLimites do gateway de saída
- Cabeçalhos: O gateway coloca um valor apenas em um cabeçalho de solicitação, nunca em uma URL ou em um corpo. Por padrão, o único cabeçalho é
Authorization. Para permitir outros, liste-os junto comAuthorizationemegress.swap_header_names, ou emCMA_EGRESS__SWAP_HEADER_NAMESem.envpara a stack do Compose. - Programas que ignoram variáveis de proxy: Os sandboxes encontram o gateway por meio de
HTTPS_PROXYe variáveis relacionadas. Ferramentas Java como Maven e Gradle não leem essas variáveis, portanto não alcançam nada.
Esta página foi útil?