Claude Platform Docs
Managed AgentsConfiguración empresarial

Identidad y credenciales del agente

Haz que tu servidor autoalojado de Claude Managed Agents firme un token de corta duración que nombre a cada agente, guarda las credenciales de vault en tu gestor de secretos y mantén los secretos fuera de los sandboxes con el gateway de salida.

Esta página muestra cómo permitir que los sistemas fuera de tu servidor confíen en un agente y dónde guardar las credenciales que usan tus agentes:

  • Identidad del agente: Permite que un servidor MCP o un gateway le dé a cada agente su propio acceso. El servidor firma un token de corta duración que nombra al agente.
  • Gestor de secretos: El servidor guarda las credenciales de vault en AWS Secrets Manager, Google Cloud Secret Manager, HashiCorp Vault o Azure Key Vault.
  • Credenciales de variables de entorno: Permite que los comandos de un agente llamen a un servicio mientras el sandbox contiene solo un marcador de posición. El “egress gateway” (gateway de salida) coloca el valor real en las solicitudes del agente.

Identidad del agente

Tu servidor puede firmar un “JSON Web Token” (token web JSON), o JWT, de corta duración que nombre a un agente, y enviarlo con las llamadas MCP de ese agente. El receptor, un servidor MCP o un “gateway” (puerta de enlace), verifica el token con las claves públicas que publicas y, a continuación, puede darle a cada agente su propio acceso.

Configura el emisor

  1. Elige la URL del emisor. Publicas tus claves públicas en esta URL en el paso 3, y los receptores las obtienen desde ella. Un host web estático funciona. No uses la dirección de tu servidor, porque el servidor no sirve las claves en las rutas que obtienen los receptores. Usa una URL https:// sin ruta ni barra final, en un nombre de host que puedas conservar.

  2. Crea la clave de firma. Ejecuta estos comandos en el directorio superior del archivo extraído:

    mkdir -m 700 agent-identity
    openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out agent-identity/signing-key.pem
  3. Publica las claves públicas. Este comando las escribe en issuer-files/.well-known/. Sirve issuer-files en la raíz del nombre de host del emisor, con el tipo de contenido 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. Dale la clave al servidor.

    1. Si el archivo tiene un directorio compose, mueve el directorio de la clave dentro de él: mv agent-identity compose/agent-identity.
    2. En docker-compose.yml, elimina la línea volumes: *server_mounts del servicio cma-server y quita el comentario del bloque volumes: que está debajo. Si cambiaste la lista x-server-mounts, haz el mismo cambio en ese bloque, porque el servicio cma-server ya no lee la lista.
    3. En el directorio que contiene agent-identity, ejecuta sudo chown -R root:root agent-identity, a menos que uses Docker Desktop en macOS o Docker sin root.
  5. Modifica el archivo de configuración. Incluye el nombre de host del receptor en mcp.allowed_hostnames y agrega esta sección:

    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

    Cada audience nombra a un receptor, como una URL https://. Sus urls son los prefijos de URL de los servidores MCP que pueden recibir un token para él.

  6. Reinicia el servidor. En el stack de Compose, ejecuta docker compose up -d desde el directorio del archivo de Compose en lugar de reiniciar.

Para mantener la clave privada fuera de los archivos, usa key_secret (tu gestor de secretos) o kms_key (AWS KMS o Google Cloud KMS). Referencia de configuración describe ambas configuraciones.

Envía el token a un servidor MCP

Conector MCP describe los campos de la entrada del servidor MCP de un agente. Agrega un campo auth a esa entrada:

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

Para cada listado de herramientas o llamada a herramienta, tu servidor firma un token nuevo. Envía el token como Authorization: Bearer <token>, en lugar de una credencial del vault. Ni el modelo ni el worker lo reciben.

Para enviar tanto el token como una credencial de bóveda, reemplaza el campo auth por un 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.com

La credencial de bóveda va en el encabezado Authorization, como ocurre con una entrada que no tiene ninguno de los dos campos. El token va en un encabezado Agent-Identity-Token, sin el prefijo Bearer.

El SDK no tiene los campos auth y agent_token_header. En el código del SDK, agrega el campo a la entrada del servidor MCP como un campo adicional, o envía la solicitud como JSON simple.

Estas páginas muestran cómo enviar campos adicionales:

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

Algunas de esas páginas muestran campos adicionales solo en el nivel superior de una solicitud, no dentro de una entrada de lista. En ese caso, haz que mcp_servers sea el campo adicional. Envía toda la lista de esa forma, con auth o agent_token_header en su entrada.

Para detener los tokens de un agente, elimina la entrada del agente o archiva el agente. Un token ya enviado sigue siendo válido hasta su exp, como máximo 5 minutos de forma predeterminada.

Qué verifica el receptor

Haz que el receptor acepte una solicitud solo si se cumplen todas estas condiciones:

  • La firma se verifica con una clave de tu conjunto de claves, <issuer>/.well-known/jwks.json. La clave correcta es aquella cuyo ID coincide con kid en el encabezado del token. Para una clave RSA, el algoritmo es RS256.
  • iss es igual a la URL de tu emisor, y aud es igual a la audiencia del receptor.
  • exp está en el futuro, y iat no está en el futuro.
  • typ en el encabezado del token es agent+jwt, y token_use es agent.

Luego aplica estas reglas:

  • Basa las reglas de acceso de cada agente en el claim agent_id, el ID del agente en la API.
  • Acepta un jti repetido, porque un listado o una llamada puede requerir varias solicitudes con el mismo token.
  • Haz que un gateway llame a cada herramienta con su propia credencial y que nunca reenvíe el token.

Con el inicio de sesión único, el token de una llamada a herramienta también nombra al autor de la llamada que creó la sesión, en los claims actor_sub y actor_iss. actor_sub no significa que el autor de la llamada haya aprobado la llamada. El modelo elige cada llamada.

Estos tokens no tienen actor_sub:

  • El token de un listado de herramientas
  • El token de una llamada de un subagente
  • Todos los tokens de una sesión creada con la clave de API del servidor

Si una regla depende del autor de la llamada, rechaza una llamada a herramienta que no tenga actor_sub.

Prueba el gateway MCP

El comando check-gateway envía a un gateway MCP tokens válidos e inválidos. Dale al comando un archivo de configuración propio, aquí check-gateway.yaml:

  1. Copia en el archivo solo las secciones mcp y agent_identity de la configuración del servidor, y limits.mcp_call_timeout si el servidor lo establece.
  2. En la copia, cambia key_file a la ruta de la clave en la máquina donde ejecutas el comando, como ./agent-identity/signing-key.pem. Si moviste el directorio dentro de compose, la ruta es ./compose/agent-identity/signing-key.pem.

Para -agent, indica el ID de un agente que el gateway permita. Si root es el propietario de la clave, usa sudo.

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

El comando imprime una línea por cada solicitud que envía, con la respuesta del gateway. Una ejecución correcta imprime luego una línea que comienza con check-gateway: PASS y sale con el código 0. Una ejecución fallida indica qué salió mal, en una línea que comienza con check-gateway:, y sale con el código 1.

Gestor de secretos

De forma predeterminada, el servidor almacena los secretos de las credenciales de vault en su base de datos. Con una sección secret_store, el servidor escribe el secreto de cada nueva credencial de vault en tu gestor de secretos, con un prefijo de nombre que reservas para ello. La base de datos guarda solo una referencia.

Agrega el bloque de tu gestor de secretos al archivo de configuración:

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

Conceder acceso

Dale al servidor una identidad y limítala al prefijo. El directorio iam/ del archivo tiene un archivo para cada gestor de secretos:

  • AWS Secrets Manager: Reemplaza los marcadores de posición en aws-secrets-manager-policy.json y adjunta la política a la identidad con la que se ejecuta el servidor.
  • Google Cloud Secret Manager: Ejecuta los comandos de los comentarios de gcp-secret-manager-role.yaml.
  • Azure Key Vault: Un rol de Azure abarca todo un key vault, no un prefijo. Así que dale a la implementación un key vault propio, uno que use el control de acceso basado en roles de Azure. Reemplaza SUBSCRIPTION_ID en azure-key-vault-role.json y crea un rol personalizado a partir de él. Asigna el rol en el key vault a la identidad con la que se ejecuta el servidor.
  • HashiCorp Vault: Reemplaza los marcadores de posición en hashicorp-vault-policy.hcl y adjunta la política a la identidad con la que se ejecuta el servidor.

Ante AWS y Google Cloud, el servidor se autentica igual que para la inferencia. Ante Azure Key Vault, se autentica con Microsoft Entra ID, igual que para Microsoft Foundry.

Comprobar la configuración

Ejecuta validate-store antes del primer inicio y después de cualquier cambio de política. Crea, lee y elimina un secreto de prueba bajo el prefijo, sin iniciar el servidor. Ejecuta el comando donde se ejecuta el servidor, con el entorno del servidor:

  • Docker Compose: Ejecútalo en el contenedor del servidor. En Arm, reemplaza linux_amd64 en este comando por linux_arm64:

    docker compose exec cma-server /opt/cma-server/bin/linux_amd64/cma-server validate-store -config /etc/cma-server/config.yaml
  • En un host:

    ./cma-server validate-store -config /etc/cma-server/config.yaml
  • Kubernetes: Ejecuta el mismo comando como un Job con la cuenta de servicio del servidor.

Una ejecución correcta termina con una línea que dice pass y sale con el código 0.

Con Azure Key Vault, ejecuta esta comprobación contra tu key vault antes de confiar en él.

Límites del gestor de secretos

  • Elige la configuración una sola vez. Después de cualquiera de estos cambios, el servidor deja de encontrar los secretos que escribió antes del cambio:

    • Eliminas la sección secret_store.
    • Cambias type, prefix, region, project, vault_url, mount o namespace. Los dos últimos son configuraciones opcionales de HashiCorp Vault.
    • Diriges address a otro Vault.

    El servidor vuelve a encontrar esos secretos solo cuando restauras los valores anteriores.

  • Una identidad lee todo el prefijo. Si dos grupos no deben poder acceder a las credenciales del otro, dale a cada grupo su propia implementación. Cada implementación necesita su propio prefijo o key vault y su propia identidad.

Credenciales de variables de entorno

Con una credencial de variable de entorno, los comandos de un agente pueden llamar a un servicio mientras el sandbox contiene solo un marcador de posición para el secreto. El gateway de salida coloca el valor real en las solicitudes a los hosts que la credencial enumera.

El gateway, cma-egress, es un proxy incluido en el archivo de la versión que se sitúa entre tus sandboxes e internet. Está desactivado de forma predeterminada, y tu servidor acepta estas credenciales solo con el gateway activado.

Con el gateway activado, se aplican dos límites a tus sandboxes:

  • Los sandboxes llegan a internet solo a través del gateway.
  • El gateway se conecta solo a los hosts que enumeras en la configuración egress.allowed_hostnames del servidor.

Enumera nombres de host públicos exactos, sin comodines. Incluye todos los hosts desde los que descargan los comandos de tus agentes.

Si creaste tu propia imagen de sandbox, inicia el worker mediante cma-with-egress, como se muestra en Crea tu propia imagen de sandbox.

Activa el gateway en el stack de Compose

Desde el directorio que contiene docker-compose.yml, agrega dos líneas a .env. La primera enumera los hosts a los que se conecta el gateway, separados por comas. La segunda carga el archivo de Compose del gateway. Luego inicia el 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 -d

Si también usas otro archivo de Compose, agrégalo a la línea COMPOSE_FILE. Una variable COMPOSE_FILE en tu shell anula la de .env, así que elimina la variable del shell.

El archivo del gateway establece las demás configuraciones egress del servidor, así que no agregues una sección egress a compose.config.yaml.

Activa el gateway en Kubernetes

Estos pasos parten de la implementación de Implementa en Kubernetes. Usan las variables REGISTRY, TAG y PLATFORM de esa página y sus dos archivos de valores. Ejecuta los comandos desde el directorio superior del archivo, con OpenSSL 3.0 o posterior. El chart del sandbox no ofrece el gateway en Azure Kubernetes Service (AKS).

La actualización del chart del servidor en estos pasos también agrega una política de red sobre los pods de los servidores. Revisa dos de los puertos que cubre antes de empezar:

  • Puerto 9464, el puerto de métricas: La política lo cierra. Si Prometheus recopila métricas de ese puerto, establece server.telemetry.prometheus.scraper.namespace en cma-server-values.yaml en el namespace en el que se ejecuta Prometheus.
  • Puerto 8400, el puerto de la API: La política admite cualquier origen. Si una política propia limita quién llega al puerto 8400, ese límite deja de funcionar. Las políticas de red se suman, así que una conexión pasa si cualquier política la admite.
  1. Compila y sube la imagen del gateway

    docker buildx build --platform "$PLATFORM" -f kubernetes/egress/Dockerfile -t "$REGISTRY/cma-egress:$TAG" --push .
  2. Crea la autoridad de certificación y la clave del 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_KEY

    Luego elimina egress-ca.key, la clave privada de la autoridad de certificación. Cualquiera que la tenga puede suplantar cualquier sitio web ante tus sandboxes. El certificado es válido durante 825 días. Consulta Renueva el certificado.

  3. Elimina los sandboxes de sesiones anteriores

    Si el entorno no ha ejecutado ninguna sesión, omite este paso. Un sandbox de antes del cambio no puede iniciar su worker después. Estos comandos también eliminan el espacio de trabajo de cada sandbox:

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

    En Google Kubernetes Engine (GKE), ejecuta también este comando:

    kubectl -n cma delete sandboxes --all

    Repite kubectl -n cma get sandboxes,pods,pvc hasta que no encuentre nada. El helm upgrade del paso “Activa el lado de los sandboxes” vuelve a iniciar el dispatcher.

  4. Activa el lado del servidor

    Elige una dirección IPv4 libre en el rango de Service del clúster para el gateway. La columna CLUSTER-IP de kubectl get svc -A muestra direcciones de ese rango. Agrega esto a cma-server-values.yaml. Si el archivo ya tiene un bloque server, combina estas líneas en él:

    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

    Luego ejecuta la actualización:

    helm upgrade cma-server kubernetes/server/chart --namespace cma-server -f cma-server-values.yaml --wait
  5. Activa el lado de los sandboxes

    Ejecuta kubectl -n cma-server get svc para enumerar los dos Services del servidor. En una instalación nueva, se llaman cma-server y cma-server-egress.

    En cma-values.yaml, cambia egress.mode a gateway y agrega un bloque gateway debajo de egress. Indica en el bloque los dos nombres que enumeró el comando:

    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

    Conserva los demás valores egress del archivo. Para imprimir las direcciones y el puerto del endpoint de la API, ejecuta kubectl get endpoints kubernetes -n default. Si el puerto no es 443, establece también egress.gateway.apiServerPort.

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

    Si la actualización se detiene por un conflicto sobre .spec.replicas, ejecuta kubectl -n cma scale deployment cma-dispatcher --replicas=1 y luego vuelve a ejecutar la actualización.

Agrega una credencial

Crea una credencial de variable de entorno como se muestra en Agrega una credencial. Las guías del servicio alojado indican que estas credenciales no son compatibles con sandboxes autoalojados. Eso describe el servicio alojado, no tu servidor.

Tu servidor agrega reglas propias. Rechaza una solicitud que incumpla alguna con un error 400 que nombra el campo. A continuación se indican dos de esas reglas:

  • networking debe tener el tipo limited, y cada host en allowed_hosts debe estar en la lista egress.allowed_hostnames del servidor.
  • injection_location debe ser {"header": true} en JSON, y no se puede omitir.

Después de agregar un host a la lista del servidor, aplica el cambio. En Docker Compose, ejecuta docker compose up -d. En Kubernetes, ejecuta el comando helm upgrade del servidor y kubectl -n cma-server rollout restart deployment -l anthropic.com/role=server.

Verifica el gateway de salida

Crea una sesión con el vault de la credencial y pídele al agente que ejecute dos comandos. Este ejemplo es para una credencial llamada GITHUB_TOKEN que enumera api.github.com:

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

El primer comando imprime un marcador de posición que comienza con cma_ph_. El segundo imprime el perfil de la cuenta de GitHub del token, porque el gateway reemplazó el marcador de posición por el token. El gateway rechaza una solicitud a un host que no está en tu lista con un error 403.

En Kubernetes, si todas las solicitudes reciben un error 503, probablemente la red de tu clúster reescribe las direcciones de los pods, como lo hace la opción --masquerade-all de kube-proxy. El gateway distingue los sandboxes por las direcciones de sus pods, así que esas direcciones deben llegarle sin cambios.

Renueva el certificado

En Kubernetes, renueva el certificado mientras no se ejecute ninguna sesión. Repite todo el paso “Crea la autoridad de certificación y la clave del gateway” de Activa el gateway en Kubernetes. Ese paso vuelve a crear la autoridad de certificación y la clave del gateway, así que no necesitas el archivo egress-ca.key que eliminaste. Haz un cambio: agrega --dry-run=client -o yaml | kubectl apply -f - al final de cada una de las cuatro líneas que ejecutan kubectl create. Por ejemplo, una línea que termina en --from-file=gateway-key=/dev/stdin termina entonces en --from-file=gateway-key=/dev/stdin --dry-run=client -o yaml | kubectl apply -f -.

Luego reinicia los servidores y el gateway:

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

Límites del gateway de salida

  • Encabezados: El gateway coloca un valor solo en un encabezado de solicitud, nunca en una URL ni en un cuerpo. De forma predeterminada, el único encabezado es Authorization. Para permitir otros, enuméralos junto con Authorization en egress.swap_header_names, o en CMA_EGRESS__SWAP_HEADER_NAMES en .env para el stack de Compose.
  • Programas que ignoran las variables de proxy: Los sandboxes encuentran el gateway mediante HTTPS_PROXY y variables relacionadas. Las herramientas de Java como Maven y Gradle no leen esas variables, así que no llegan a nada.

¿Te resultó útil esta página?