Règle ExternalCallout

Cette page s'applique à Apigee et à Apigee hybrid.

Consultez la documentation d'Apigee Edge.

icône de la règle

Quoi

La règle ExternalCallout vous permet d'envoyer des requêtes gRPC à votre serveur gRPC afin de mettre en œuvre un comportement personnalisé qu'il n'est pas possible d'obtenir avec les règles Apigee. Dans le code de votre serveur, vous pouvez facilement accéder aux variables de flux d'un proxy et les modifier.

Apigee communique avec un serveur gRPC en utilisant une règle ExternalCallout par l'intermédiaire d'une API. Apigee utilise l'API pour envoyer les variables de flux au serveur gRPC. Dans votre serveur gRPC, vous pouvez lire et modifier (en fonction de la variable) les variables de flux répertoriées sur la page de référence Variables de flux ainsi que certaines variables supplémentaires spécifiées dans le XML de la règle.

Si vous configurez le serveur gRPC avec Apigee et que vous incluez cette stratégie dans un proxy, Apigee traitera les requêtes API comme suit :

  1. Apigee envoie un message contenant les variables de flux à votre serveur gRPC.
  2. Le code de votre serveur gRPC s'exécute et accède aux variables comme indiqué dans le code, puis les modifie. Le serveur gRPC renvoie ensuite une réponse contenant toutes les variables de flux à Apigee.
  3. Apigee lit la réponse du serveur gRPC. Si des variables ont été ajoutées ou modifiées, elles sont mises à jour dans Apigee.

Cette règle est une règle standard qui peut être déployée sur n'importe quel type d'environnement. Pour en savoir plus sur les types de règles et la disponibilité avec chaque type d'environnement, consultez la section Types de règles.

Pour en savoir plus sur l'envoi de requêtes gRPC, consultez les liens suivants :

<ExternalCallout>

Définit une règle ExternalCallout.

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

Cet élément possède les attributs suivants qui sont communs à toutes les règles :

Attribut Par défaut Obligatoire ? Description
name ND Obligatoire

Nom interne de la règle. La valeur de l'attribut name peut contenir des lettres, des chiffres, des espaces, des tirets, des traits de soulignement et des points. Cette valeur ne peut pas dépasser 255 caractères.

Vous pouvez également utiliser l'élément <DisplayName> pour ajouter un libellé à la règle dans l'éditeur de proxy de l'interface utilisateur de gestion avec un nom différent, en langage naturel.

continueOnError faux Facultatif Définissez sur false pour afficher une erreur en cas d'échec d'une règle. Il s'agit du comportement attendu pour la plupart des règles. Définissez sur true pour que l'exécution du flux se poursuive même après l'échec d'une règle. Voir aussi :
enabled true Facultatif Définissez sur true pour appliquer la règle. Définissez sur false pour désactiver la règle. La règle ne sera pas appliquée même si elle reste associée à un flux.
async   faux Obsolète Cet attribut est obsolète.

Le tableau suivant décrit les éléments enfants de <ExternalCallout>.

Élément enfant Obligatoire Description
<TimeoutMs> Obligatoire Délai d'expiration de requête (en millisecondes) pour les requêtes gRPC.
<GrpcConnection> Obligatoire Spécifie le nom d'un objet TargetServer existant en tant que serveur gRPC auquel envoyer des requêtes.
<Configurations> Facultatif Permet de configurer divers aspects de la règle ExternalCallout, y compris les éléments <Property> et <FlowVariable>.

Exemple 1

Des exemples fonctionnels d'ExternalCallout sont disponibles sur la page External Callout Samples sur GitHub.

L'exemple suivant illustre une configuration de règle 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>

L'exemple envoie une requête à un serveur gRPC externe représenté par le TargetServer nommé external-target-server, avec les configurations suivantes :

  • <Property> : permet d'inclure le contenu des requêtes et des réponses dans la requête envoyée au serveur gRPC, mais pas les en-têtes de requête et de réponse.
  • <FlowVariable> : permet d'inclure des variables de flux supplémentaires example1.flow.variable et example2.flow.variable, spécifiées par les éléments FlowVariable, dans la requête envoyée au serveur gRPC.

Exemple 2

Dans l'exemple suivant, l'attribut useTargetUrl de l'élément Audience est défini sur true. Lorsque useTargetUrl est true, le nom d'hôte du serveur cible gRPC est utilisé comme audience. Par exemple, si l'hôte du serveur est my-grpc-server-java.a.run.app, l'audience utilisée sera 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>

Référence d'élément enfant

Les sections suivantes décrivent les éléments enfants de ExternalCallout.

<TimeoutMs>

Délai d'expiration de requête (en millisecondes) pour les requêtes gRPC. <TimeoutMs> doit être un nombre positif.

<GrpcConnection>

L'élément <GrpcConnection> définit le serveur gRPC comme un TargetServer existant, spécifié par l'attribut name. Consultez la page de référence de la ressource TargetServer.

Remarque : Le protocole de TargetServer doit être GRPC.

Par exemple, le code ci-dessous :

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

spécifie le serveur gRPC en tant que TargetServer existant nommé external-target-server.

Utilisez l'élément <Authentication> (décrit plus loin dans cette section) pour générer un jeton OpenID Connect émis par Google afin d'effectuer des appels authentifiés à des services basés sur gRPC, tels que des services personnalisés hébergés dans Cloud Run.

Le tableau suivant décrit les éléments enfants de <GrpcConnection>.

Élément enfant Obligatoire ? Description
Élément <Server> Obligatoire Indique le serveur gRPC.
Élément <Authentication> Facultatif Génère un jeton OpenID Connect émis par Google pour effectuer des appels authentifiés à des services basés sur gRPC, tels que Cloud Run.

Élément <Server>

Indique le serveur gRPC.

Le tableau suivant décrit les attributs de l'élément <Server>.

Attribut Description Par défaut Presence Type
name

Nom d'un objet TargetServer existant en tant que serveur gRPC auquel envoyer des requêtes.

N/A Obligatoire Chaîne

Élément <Authentication>

Génère un jeton OpenID Connect émis par Google pour effectuer des appels authentifiés à des services basés sur gRPC, tels que des services personnalisés hébergés dans Cloud Run. L'utilisation de cet élément nécessite de suivre les étapes de configuration et de déploiement décrites dans la section Utiliser l'authentification Google. Avec une configuration appropriée, la règle crée un jeton d'authentification et l'ajoute à la demande de service.

Cet élément comporte un élément enfant obligatoire : GoogleIDToken.

Par défaut N/A
Obligatoire ? Facultatif.
Type Type complexe
Élément parent <GrpcConnection>
Éléments enfants <GoogleIDToken>

L'élément Authentication utilise la syntaxe suivante :

Syntaxe

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

Exemple

L'exemple suivant montre l'élément 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>
Attributs

Aucune.

Élément enfant <HeaderName>

Par défaut, lorsqu'une configuration d'authentification est présente, Apigee génère un jeton d'authentification et l'injecte dans l'en-tête Authorization du message envoyé au système cible. L'élément HeaderName vous permet de spécifier le nom d'un autre en-tête pour contenir ce jeton de support. Cette fonctionnalité est particulièrement utile lorsque la cible est un service Cloud Run qui utilise l'en-tête X-Serverless-Authorization. L'en-tête Authorization, s'il est présent, est conservé tel quel et est également envoyé dans la requête.

Par défaut N/A
Obligatoire ? Non
Type Chaîne
Élément parent <Authentication>
Éléments enfants Aucun

L'élément HeaderName utilise la syntaxe suivante :

Syntaxe

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

Avec une chaîne statique

Dans cet exemple, le jeton d'authentification généré est ajouté par défaut à un en-tête nommé X-Serverless-Authorization qui est envoyé au système cible. L'en-tête Authorization, s'il est présent, est conservé tel quel et est également envoyé dans la requête.

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

Avec une référence de variable

Dans cet exemple, le jeton d'authentification généré est ajouté par défaut à un en-tête nommé X-Serverless-Authorization qui est envoyé au système cible. Si my-variable a une valeur, celle-ci est utilisée à la place de la chaîne par défaut. L'en-tête Authorization, s'il est présent, est conservé tel quel et est également envoyé dans la requête.

<Authentication>
  <HeaderName ref='my-variable'>X-Serverless-Authorization</HeaderName>
  <GoogleIDToken>
    <Audience>https://cloudrun-hostname.a.run.app</Audience>
  </GoogleIDToken>
</Authentication>
Élément enfant <GoogleIDToken>

Génère des jetons OpenID Connect émis par Google pour effectuer des appels authentifiés à des services Google, tels que des services personnalisés hébergés dans Cloud Run.

Par défaut N/A
Obligatoire ? Obligatoire
Type Chaîne
Élément parent <Authentication>
Éléments enfants <Audience>
<IncludeEmail>

L'élément GoogleIDToken utilise la syntaxe suivante :

Syntaxe

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

Exemple

L'exemple suivant montre l'élément GoogleIDToken :

<Authentication>
  <GoogleIDToken>
      <Audience>https://httpserver0-bar.run.app</Audience>
      <IncludeEmail>true</IncludeEmail>
  </GoogleIDToken>
</Authentication>
Élément enfant <Audience>

Audience du jeton d'authentification généré, comme l'API ou le compte à laquelle ou auquel le jeton accorde l'accès.

Si la valeur de Audience est vide, ref est vide ou correspond à une valeur vide, et useTargetUrl est true, alors "https://" + (nom d'hôte du serveur cible gRPC) est utilisé comme audience. Par exemple, si l'hôte du serveur est my-grpc-server-java.a.run.app, l'audience utilisée sera https://my-grpc-server-java.a.run.app.

La valeur par défaut de useTargetUrl est 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'/>
Par défaut N/A
Obligatoire ? Obligatoire
Type Chaîne
Élément parent <GoogleIDToken>
Éléments enfants Aucune.
Élément enfant <IncludeEmail>

S'il est défini sur true, le jeton d'authentification généré contient les revendications du compte de service email et email_verified.

Par défaut false
Obligatoire ? Facultatif
Type Booléen
Élément parent <GoogleIDToken>
Éléments enfants Aucune.

<Configurations>

L'élément <Configurations> vous permet de configurer divers aspects de la règle ExternalCallout, y compris <Property> et <FlowVariable>.

Le tableau suivant décrit les éléments enfants de <Configurations>.

Élément enfant Obligatoire ? Description
<Property> Obligatoire

Indique si les en-têtes et/ou le contenu des requêtes/réponses seront envoyés au serveur. Les valeurs possibles sont true ou false. La valeur par défaut est false.

<FlowVariable> Obligatoire

Indique les variables de flux supplémentaires à envoyer au serveur.

<Property>

L'élément <Property> indique si les en-têtes et/ou le contenu des requêtes/réponses seront envoyés au serveur. Les valeurs possibles sont true (l'élément est envoyé) ou false (l'élément n'est pas envoyé). La valeur par défaut est false.

Le tableau suivant décrit les attributs de l'élément <Property>.

Attribut Description Par défaut Presence Type
name

Indique le contenu qui sera envoyé au serveur. Les valeurs possibles pour name sont les suivantes :

  • with.request.content
  • with.request.headers
  • with.response.content
  • with.response.headers
N/A Obligatoire Chaîne

<FlowVariable>

L'élément <FlowVariable> indique les variables de flux supplémentaires qui seront envoyées au serveur. La valeur de <FlowVariable> est un préfixe d'une variable, plutôt que le nom complet de la variable. Par exemple , si l'élément est a.b.c, la valeur d'une variable nommée a.b.c sera envoyée au serveur. De même, la valeur d'une variable nommée a.b.c.my-variable sera envoyée au serveur. Toutefois, la valeur d'une variable nommée a.x.another-variable ne sera pas envoyée car elle ne comporte pas le préfixe a.b.c. Voici quelques exemples

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

Informations de référence sur les erreurs

Erreurs de déploiement

Nom de l'erreur Cause
FAILED_PRECONDITION Cette erreur se produit si le compte de service est manquant lorsque le proxy est configuré avec le tag <Authentication>.

Exemple :

Deployment of \"organizations/foo/apis/apiproxy/revisions/1\"
requires a service account identity, but one was not provided
with the request.
PERMISSION_DENIED Cette erreur se produit en cas de problème d'autorisation avec le compte de service si le proxy est configuré avec le tag <Authentication>. Causes possibles :
  • Le compte de service n'existe pas.
  • Le compte de service n'a pas été créé dans le même projet Google Cloud que l'organisation Apigee.
  • Le déployeur dispose de l'autorisation iam.serviceAccounts.actAs sur le compte de service. Pour plus d'informations, voir Autorisations de compte de service.

Erreurs d'exécution

Le tableau ci-dessous décrit les erreurs d'exécution pouvant survenir lors de l'exécution de la stratégie.

Code d'erreur État HTTP Cause
GrpcTlsInitFailed 500

Cette erreur se produit en cas de problèmes d'initialisation de TLS avec le serveur gRPC (problèmes de keystore ou de truststore par exemple).

steps.externalcallout.[error_code] 500

La valeur [error_code] est déterminée par le champ errorCode du message d'erreur. Le champ faultstring du message d'erreur correspond à la chaîne d'erreur de l'erreur.

steps.externalcallout.ExecutionError 500

Cette erreur se produit si une autre exception survient pendant l'exécution de cette règle. L'exception sous-jacente est exposée dans la chaîne d'erreur. Si un problème est survenu avec les identifiants du serveur gRPC, l'erreur ressemble à ceci :

{
  "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"
    }
  }
}

Vous pouvez consulter les journaux du processeur de messages pour obtenir d'autres pointeurs de débogage.

googletoken.EmptyIDTokenAudience 500

<GoogleIDToken> est activé, mais useTargetUrl est défini sur "false" et aucune valeur n'est fournie à <Audience> directement ou via une référence au moment de l'erreur.

steps.externalcallout.ExecutionError

avec une chaîne d'erreur :

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

500

Cette erreur se produit si le proxy d'API est configuré avec l'élément <Authentication>. Causes possibles :

  • Le compte de service déployé avec le proxy :
    • n'existe pas dans votre projet (elle existait lors du déploiement, mais a été supprimée après le déploiement)
    • a été désactivé
    • (Apigee hybrid uniquement) n'a pas attribué le rôle roles/iam.serviceAccountTokenCreator sur le compte de service apigee-runtime.
  • (Apigee hybrid uniquement) L'API IAMCredentials est désactivée dans le projet source du compte de service apigee-runtime.

    Remarque : Pour Apigee hybrid uniquement, consultez le journal du conteneur d'exécution et recherchez externalcallout.ExecutionError pour trouver des messages d'erreur plus détaillés susceptibles de faciliter la résolution du problème.

steps.externalcallout.ExecutionError avec une chaîne d'erreur contenant PERMISSION DENIED.

Par exemple, la chaîne d'erreur se présentera comme suit pour 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

Cette erreur se produit si le proxy d'API est configuré avec l'élément <Authentication>. Causes possibles :

  • Le compte de service proxy existe et est activé, mais il ne dispose pas des autorisations nécessaires pour accéder au service.
  • Le service nécessite une authentification, mais la requête ne contenait pas d'en-tête d'authentification (par exemple, le fichier XML d'authentification n'était pas inclus dans le fichier XML de la règle).

Erreurs diverses

Le tableau ci-dessous décrit divers types d'erreurs. Pour en savoir plus, consultez la cause.

Code d'erreur Cause
ReferencesExistToGrpcServer

Cette erreur se produit si un utilisateur tente de supprimer un serveur cible gRPC, mais que celui-ci est encore utilisé par d'autres règles.

Erreurs

Les variables d'erreur du tableau suivant sont définies par défaut pour toutes les règles. Consultez la section Variables spécifiques aux erreurs liées aux règles.

Variables Lieu Exemples
fault.name="fault_name" fault_name est le nom de l'erreur, tel qu'indiqué dans le tableau Erreurs d'exécution ci-dessus. Le nom d'erreur est la dernière partie du code d'erreur. fault.name correspond à "ExecutionError".
externalcallout.[policy_name].failed policy_name est le nom spécifié par l'utilisateur de la règle qui a provoqué l'erreur. externalcallout.ExternalCallout-1.failed = true

Articles associés