Política ExternalCallout

Esta página se aplica a Apigee y Apigee Hybrid.

Consulta la documentación de Apigee Edge.

Icono de política

Qué

La política ExternalCallout te permite enviar solicitudes gRPC a tu servidor gRPC para implementar un comportamiento personalizado que no admiten las políticas de Apigee. En el código de tu servidor, puedes acceder y modificar fácilmente las variables de flujo dentro del flujo de un proxy.

Apigee se comunica con un servidor gRPC a través de una política ExternalCallout mediante una API. Apigee usa la API para enviar variables de flujo al servidor gRPC. En tu servidor gRPC, puedes leer (y, según la variable, modificar) las variables de flujo que se indican en la página de referencia Variables de flujo, así como las variables adicionales que especifiques en el XML de la política.

Si configuras el servidor gRPC con Apigee e incluyes esta política en un proxy, Apigee gestionará las solicitudes de API de la siguiente manera:

  1. Apigee envía un mensaje que contiene las variables de flujo a tu servidor gRPC.
  2. Se ejecuta el código del servidor gRPC, que accede a las variables y las modifica según se definen en el código. A continuación, el servidor gRPC envía una respuesta que contiene todas las variables de flujo a Apigee.
  3. Apigee lee la respuesta de tu servidor gRPC. Si se añade alguna variable o se modifica alguna variable de flujo modificable, se actualiza en Apigee.

Esta política es una política estándar y se puede implementar en cualquier tipo de entorno. Para obtener información sobre los tipos de políticas y la disponibilidad de cada tipo de entorno, consulta Tipos de políticas.

Para obtener más información sobre cómo enviar solicitudes gRPC, consulta los siguientes enlaces:

<ExternalCallout>

Define una política ExternalCallout.

<ExternalCallout async="true" continueOnError="true" enabled="true" name="EC">

Este elemento tiene los siguientes atributos, que son comunes a todas las políticas:

Atributo Predeterminado ¿Es obligatorio? Descripción
name N/A Obligatorio

El nombre interno de la política. El valor del atributo name puede contener letras, números, espacios, guiones, guiones bajos y puntos. Este valor no puede superar los 255 caracteres.

Opcionalmente, usa el elemento <DisplayName> para etiquetar la política en el editor de proxy de la interfaz de gestión con un nombre diferente en lenguaje natural.

continueOnError falso Opcional Asigna el valor false para devolver un error cuando falle una política. Este es el comportamiento esperado de la mayoría de las políticas. Asigna el valor true para que la ejecución del flujo continúe incluso después de que falle una política. Consulta también:
enabled true Opcional Asigna el valor true para aplicar la política. Selecciona false para desactivar la política. La política no se aplicará aunque siga adjunta a un flujo.
async   falso Obsoleto Este atributo está obsoleto.

En la siguiente tabla se describen los elementos secundarios de <ExternalCallout>.

Elemento secundario Obligatorio Descripción
<TimeoutMs> Obligatorio Tiempo de espera de la solicitud en milisegundos para las solicitudes gRPC.
<GrpcConnection> Obligatorio Especifica el nombre de un TargetServer que ya exista para que sea el servidor gRPC al que se envíen las solicitudes.
<Configurations> Opcional Te permite configurar varios aspectos de la política ExternalCallout, incluidos los elementos <Property> y <FlowVariable>.

Ejemplo 1

Puedes consultar ejemplos prácticos de ExternalCallout en External Callout Samples (Ejemplos de ExternalCallout) en GitHub.

En el siguiente ejemplo se muestra una configuración de política ExternalCallout.

<ExternalCallout enabled="true" continueOnError="false" name="ExternalCallout-1">
  <DisplayName>External Callout 1</DisplayName>
  <TimeoutMs>5000</TimeoutMs>
  <GrpcConnection>
    <Server name="external-target-server"/>
  </GrpcConnection>
  <Configurations>
    <Property name="with.request.content">true</Property>
    <Property name="with.request.headers">false</Property>
    <Property name="with.response.content">true</Property>
    <Property name="with.response.headers">false</Property>
    <FlowVariable>example1.flow.variable</FlowVariable>
    <FlowVariable>example2.flow.variable</FlowVariable>
  </Configurations>
<ExternalCallout>

En el ejemplo se envía una solicitud a un servidor gRPC externo representado por el TargetServer llamado external-target-server, con las siguientes configuraciones:

  • <Property>: incluye el contenido de la solicitud y la respuesta, pero no los encabezados de la solicitud y la respuesta, en la solicitud enviada al servidor gRPC.
  • <FlowVariable>: Incluye variables de flujo adicionales example1.flow.variable y example2.flow.variable, especificadas por los elementos FlowVariable, en la solicitud enviada al servidor gRPC.

Ejemplo 2

En el ejemplo siguiente, el atributo useTargetUrl del elemento Audience se ha definido como true. Cuando useTargetUrl es true, el nombre de host del servidor de destino de gRPC se usa como audiencia. Por ejemplo, si el host del servidor es my-grpc-server-java.a.run.app, la audiencia utilizada será https://my-grpc-server-java.a.run.app.

<ExternalCallout continueOnError="false" enabled="true" name="External-Callout-1">
  <DisplayName>External-Callout-1</DisplayName>
  <GrpcConnection>
    <Server name="cloud_run_server_name"/>
    <Authentication>
      <GoogleIDToken>
        <Audience useTargetUrl="true"/>
      </GoogleIDToken>
    </Authentication>
  </GrpcConnection>
  <TimeoutMs>5000</TimeoutMs>
  <Configurations>
    <Property name="with.request.content">true</Property>
    <Property name="with.request.headers">true</Property>
    <Property name="with.response.content">true</Property>
    <Property name="with.response.headers">true</Property>
    <FlowVariable>example.flow.variable</FlowVariable>
    <FlowVariable>another.flow.variable</FlowVariable>
  </Configurations>
</ExternalCallout>

Referencia de elemento secundario

En las siguientes secciones se describen los elementos secundarios de ExternalCallout.

<TimeoutMs>

Tiempo de espera de la solicitud en milisegundos para las solicitudes gRPC. <TimeoutMs> debe ser un número positivo.

<GrpcConnection>

El elemento <GrpcConnection> define el servidor gRPC como un TargetServer existente, especificado por el atributo name. Consulta la página de referencia del recurso TargetServer.

Nota: El protocolo de TargetServer debe ser GRPC.

Por ejemplo, el siguiente código

<GrpcConnection>
  <Server name="external-target-server"/>
</GrpcConnection>

especifica que el servidor gRPC es un TargetServer llamado external-target-server.

Usa el elemento <Authentication> (descrito más adelante en esta sección) para generar un token OpenID Connect emitido por Google para hacer llamadas autenticadas a servicios basados en gRPC, como los servicios personalizados alojados en Cloud Run.

En la siguiente tabla se describen los elementos secundarios de <GrpcConnection>.

Elemento secundario ¿Es obligatorio? Descripción
Elemento <Server> Obligatorio Especifica el servidor gRPC.
Elemento <Authentication> Optional Genera un token OpenID Connect emitido por Google para hacer llamadas autenticadas a servicios basados en gRPC, como Cloud Run.

Elemento <Server>

Especifica el servidor gRPC.

En la siguiente tabla se describen los atributos del elemento <Server>.

Atributo Descripción Predeterminado Presencia Tipo
name

Nombre de un TargetServer que será el servidor gRPC al que se enviarán las solicitudes.

N/A Obligatorio Cadena

Elemento <Authentication>

Genera un token OpenID Connect emitido por Google para hacer llamadas autenticadas a servicios basados en gRPC, como servicios personalizados alojados en Cloud Run. Para usar este elemento, debes seguir los pasos de configuración e implementación que se describen en el artículo Usar la autenticación de Google. Si la configuración es correcta, la política crea un token de autenticación y lo añade a la solicitud de servicio.

Este elemento tiene un elemento secundario obligatorio: GoogleIDToken.

Predeterminado N/A
¿Es obligatorio? Opcional.
Tipo Tipo complejo
Elemento principal <GrpcConnection>
Elementos secundarios <GoogleIDToken>

El elemento Authentication utiliza la siguiente sintaxis:

Sintaxis

<ExternalCallout>
...
  <GrpcConnection>
    <Server name="cloud_run_server_name"/>
    <Authentication>
      <HeaderName ref="FLOW_VARIABLE">STRING</HeaderName>
      <GoogleIDToken>
         <Audience ref="variable-1">STRING</Audience>
         <IncludeEmail ref="variable-2">BOOLEAN</IncludeEmail>
      </GoogleIDToken>
    </Authentication>
  </GrpcConnection>
</ExternalCallout>

Ejemplo

En el siguiente ejemplo se muestra el elemento GoogleIDToken:

<ExternalCallout continueOnError="false" enabled="true" name="External-Callout-1">
  <DisplayName>External-Callout-1</DisplayName>
  <GrpcConnection>
     <Server name="cloud_run_server_name"/>
     <Authentication>
        <HeaderName ref='my-variable'>X-Serverless-Authorization</HeaderName>
        <GoogleIDToken>
           <Audience>https://cloudrun-hostname.a.run.app</Audience>
        </GoogleIDToken>
     </Authentication>
  </GrpcConnection>
  <TimeoutMs>5000</TimeoutMs>
  <Configurations>
    <Property name="with.request.content">true</Property>
    <Property name="with.request.headers">true</Property>
    <Property name="with.response.content">true</Property>
    <Property name="with.response.headers">true</Property>
    <FlowVariable>example.flow.variable</FlowVariable>
    <FlowVariable>another.flow.variable</FlowVariable>
  </Configurations>
</ExternalCallout>
Atributos

Ninguno

Elemento secundario <HeaderName>

De forma predeterminada, cuando hay una configuración de autenticación, Apigee genera un token de portador y lo inserta en el encabezado Authorization del mensaje enviado al sistema de destino. El elemento HeaderName le permite especificar el nombre de otro encabezado para contener ese token de portador. Esta función es especialmente útil cuando el destino es un servicio de Cloud Run que usa la cabecera X-Serverless-Authorization. El encabezado Authorization, si está presente, no se modifica y también se envía en la solicitud.

Predeterminado N/A
¿Es obligatorio? No
Tipo Cadena
Elemento principal <Authentication>
Elementos secundarios Ninguno

El elemento HeaderName utiliza la siguiente sintaxis:

Sintaxis

<ExternalCallout>
...
  <Authentication>
    <HeaderName ref="FLOW_VARIABLE">STRING</HeaderName>
    <GoogleIDToken>
    ... 
    </GoogleIDToken>
  </Authentication>
  ...
</ExternalCallout>

Con una cadena estática

En este ejemplo, el token de portador generado se añade de forma predeterminada a un encabezado llamado X-Serverless-Authorization que se envía al sistema de destino. El encabezado Authorization, si está presente, se deja sin modificar y también se envía en la solicitud.

<Authentication>
  <HeaderName>X-Serverless-Authorization</HeaderName>
  <GoogleIDToken>
    <Audience>https://cloudrun-hostname.a.run.app</Audience>
  </GoogleIDToken>
</Authentication>

Con referencia variable

En este ejemplo, el token de portador generado se añade de forma predeterminada a un encabezado llamado X-Serverless-Authorization que se envía al sistema de destino. Si my-variable tiene un valor, se usará ese valor en lugar de la cadena predeterminada. El encabezado Authorization, si está presente, se deja sin modificar y también se envía en la solicitud.

<Authentication>
  <HeaderName ref='my-variable'>X-Serverless-Authorization</HeaderName>
  <GoogleIDToken>
    <Audience>https://cloudrun-hostname.a.run.app</Audience>
  </GoogleIDToken>
</Authentication>
Elemento secundario <GoogleIDToken>

Genera tokens de OpenID Connect emitidos por Google para hacer llamadas autenticadas a servicios de Google, como servicios personalizados alojados en Cloud Run.

Predeterminado N/A
¿Es obligatorio? Obligatorio
Tipo Cadena
Elemento principal <Authentication>
Elementos secundarios <Audience>
<IncludeEmail>

El elemento GoogleIDToken utiliza la siguiente sintaxis:

Sintaxis

<ExternalCallout>
...
  <GrpcConnection>
    <Server name="cloud_run_server_name"/>
    <Authentication>
      <GoogleIDToken>
        <Audience ref="context-variable" useTargetUrl='BOOLEAN'>STRING</Audience>
        <IncludeEmail ref="context-variable">BOOLEAN</IncludeEmail>
      </GoogleIDToken>
    </Authentication>
  </GrpcConnection>
</ExternalCallout>

Ejemplo

En el siguiente ejemplo se muestra el elemento GoogleIDToken:

<Authentication>
  <GoogleIDToken>
      <Audience>https://httpserver0-bar.run.app</Audience>
      <IncludeEmail>true</IncludeEmail>
  </GoogleIDToken>
</Authentication>
Elemento secundario <Audience>

La audiencia del token de autenticación generado, como la API o la cuenta a la que el token concede acceso.

Si el valor de Audience está vacío, ref está vacío o se resuelve en un valor vacío y useTargetUrl es true, se usa "https://" + (nombre de host del servidor de destino de gRPC) como audiencia. Por ejemplo, si el host del servidor es my-grpc-server-java.a.run.app, la audiencia utilizada será https://my-grpc-server-java.a.run.app.

De forma predeterminada, useTargetUrl es false.

<Audience>explicit-audience-value-here</Audience>

or:

<Audience ref='variable-name-here'/>

or:

<Audience ref='variable-name-here' useTargetUrl='true'/>

or:

<Audience useTargetUrl='true'/>
Predeterminado N/A
¿Es obligatorio? Obligatorio
Tipo Cadena
Elemento principal <GoogleIDToken>
Elementos secundarios Ninguno
Elemento secundario <IncludeEmail>

Si se define como true, el token de autenticación generado contendrá las reclamaciones email y email_verified de la cuenta de servicio.

Predeterminado falso
¿Es obligatorio? Opcional
Tipo Booleano
Elemento principal <GoogleIDToken>
Elementos secundarios Ninguno

<Configurations>

El elemento <Configurations> le permite configurar varios aspectos de la política ExternalCallout, como <Property> y <FlowVariable>.

En la siguiente tabla se describen los elementos secundarios de <Configurations>.

Elemento secundario ¿Es obligatorio? Descripción
<Property> Obligatorio

Especifica si se enviarán al servidor los encabezados y/o el contenido de la solicitud o la respuesta. Los valores posibles son true o false. El valor predeterminado es false.

<FlowVariable> Obligatorio

Especifica qué variables de flujo adicionales se deben enviar al servidor.

<Property>

El elemento <Property> especifica si se enviarán al servidor los encabezados y/o el contenido de la solicitud o la respuesta. Los valores posibles son true (el artículo se enviará) o false (el artículo no se enviará). El valor predeterminado es false.

En la siguiente tabla se describen los atributos del elemento <Property>.

Atributo Descripción Predeterminado Presencia Tipo
name

Especifica el contenido que se enviará al servidor. Los valores posibles de name son:

  • with.request.content
  • with.request.headers
  • with.response.content
  • with.response.headers
N/A Obligatorio Cadena

<FlowVariable>

El elemento <FlowVariable> especifica qué variables de flujo adicionales se enviarán al servidor. El valor de <FlowVariable> es un prefijo de una variable, no el nombre completo de la variable. Por ejemplo , si el elemento es a.b.c, se enviará al servidor el valor de una variable llamada a.b.c. Del mismo modo, el valor de una variable llamada a.b.c.my-variable se enviará al servidor. Sin embargo, no se enviará el valor de una variable llamada a.x.another-variable porque no tiene el prefijo a.b.c. Aquí tienes algunos ejemplos:

<Configurations>
  <FlowVariable>a.b.c</FlowVariable>
  <FlowVariable>d.e.f</FlowVariable>
</Configurations>

Referencia de errores

Errores de implementación

Nombre del error Causa
FAILED_PRECONDITION Este error se produce si falta la cuenta de servicio cuando el proxy se configura con la etiqueta <Authentication>.

Por ejemplo:

Deployment of \"organizations/foo/apis/apiproxy/revisions/1\"
requires a service account identity, but one was not provided
with the request.
PERMISSION_DENIED Este error se produce si hay un problema de permisos con la cuenta de servicio si el proxy se configura con la etiqueta <Authentication>. Posibles causas:
  • La cuenta de servicio no existe.
  • La cuenta de servicio no se ha creado en el mismo proyecto de Google Cloud que la organización de Apigee.
  • El usuario que realiza el despliegue tiene el permiso iam.serviceAccounts.actAs en la cuenta de servicio. Para obtener más información, consulta el artículo Acerca de los permisos de las cuentas de servicio.

Errores de tiempo de ejecución

En la siguiente tabla se describen los errores de tiempo de ejecución, que pueden producirse cuando se ejecuta la política.

Código de fallo Estado de HTTP Causa
GrpcTlsInitFailed 500

Este error se producirá si hay algún problema al inicializar TLS con el servidor gRPC (por ejemplo, problemas con el almacén de claves o el almacén de confianza).

steps.externalcallout.[error_code] 500

[error_code] se determina mediante el campo errorCode del mensaje Fault. La cadena de error del error será el campo faultstring del mensaje de error.

steps.externalcallout.ExecutionError 500

Este error se producirá si se produce alguna otra excepción durante la ejecución de esta política. La excepción subyacente se expondrá en faultstring. Si ha habido un problema con las credenciales del servidor gRPC, el error será similar a este:

{
  "fault": {
    "faultstring": "Encountered the following exception while sending the gRPC request or
     processing the response: [io.grpc.StatusRuntimeException: UNAVAILABLE: Credentials failed
     to obtain metadata].",
    "detail": {
      "errorcode": "steps.externalcallout.ExecutionError"
    }
  }
}

Puedes consultar los registros del MP para obtener más información sobre la depuración.

googletoken.EmptyIDTokenAudience 500

<GoogleIDToken> está habilitado, pero useTargetUrl tiene el valor "false" y no se ha proporcionado ningún valor para <Audience>, ni directamente ni mediante una referencia en el momento del error.

steps.externalcallout.ExecutionError

con la cadena de error:

Encountered the following exception while sending the gRPC request or processing the response: [io.grpc.StatusRuntimeException: UNAVAILABLE: Credentials failed to obtain metadata]

500

Este error se produce si el proxy de API se configura con el elemento <Authentication>. Posibles motivos:

  • La cuenta de servicio implementada con el proxy:
    • no existe en tu proyecto (existía cuando se desplegó, pero se eliminó después del despliegue)
    • se ha inhabilitado
    • (Solo Apigee hybrid) no ha concedido el rol roles/iam.serviceAccountTokenCreator en la cuenta de servicio apigee-runtime.
  • (Solo Apigee hybrid) La API IAMCredentials está inhabilitada en el proyecto de origen de la cuenta de servicio apigee-runtime.

    Nota: Solo en Apigee hybrid, consulta el registro del contenedor de tiempo de ejecución y busca externalcallout.ExecutionError para encontrar mensajes de error más detallados que puedan ayudarte a depurar el problema.

steps.externalcallout.ExecutionError con faultstring que contiene PERMISSION DENIED.

Por ejemplo, el elemento faultstring tendrá el siguiente aspecto en Cloud Run:

Encountered the following exception while sending the gRPC request or processing the response: [io.grpc.StatusRuntimeException: PERMISSION_DENIED: HTTP status code 403 …]

500

Este error se produce si el proxy de API se configura con el elemento <Authentication>. Posibles motivos:

  • La cuenta de servicio proxy existe y está habilitada, pero no tiene los permisos adecuados para acceder al servicio.
  • El servicio requiere autenticación, pero la solicitud no incluía un encabezado de autenticación (por ejemplo, el XML de autenticación no se incluyó en el XML de la política).

Errores varios

En la siguiente tabla se describen errores varios. Consulta la causa para obtener más información.

Código de fallo Causa
ReferencesExistToGrpcServer

Este error se producirá si un usuario intenta eliminar un servidor de destino de gRPC, pero el servidor sigue usándose en otras políticas.

Fallas

Las variables de error de la siguiente tabla se definen de forma predeterminada en todas las políticas. Consulta las variables específicas de los errores de las políticas.

Variables Dónde Ejemplos
fault.name="fault_name" fault_name es el nombre del error, tal como se indica en la tabla de errores de tiempo de ejecución de arriba. El nombre del error es la última parte del código de error. fault.name coincide con "ExecutionError".
externalcallout.[policy_name].failed policy_name es el nombre de la política especificado por el usuario que ha provocado el error. externalcallout.ExternalCallout-1.failed = true

Temas relacionados