Si vous travaillez régulièrement avec des APIs, vous connaissez les difficultés liées à leur sécurisation, leur protection et leur gestion, ainsi qu’à l’élaboration des fonctionnalités de base.
Si vous ne l’avez pas encore fait, vous devriez jeter un coup d’œil à l’API Management.
Pour résumer:
En informatique, l’API management (ou gestion d’APIs) est une discipline qui consiste à exploiter au mieux les APIs sans mettre en péril le système d’information et sans affecter l’expérience utilisateur.
L’API Management, regroupe l’ensemble des procédures, technologies et équipes en charge de la publication sécurisée d’APIs dans une entreprise. Il peut s’agir d’APIs internes au système d’information ou externes destinées à des partenaires.
En d’autres termes, l’API management est un outil de management, comme son nom l’indique, qui permet de gérer la publication, la promotion et la supervision des échanges de données entre un service fournisseur et un service client, au sein d’un environnement sécurisé et évolutif.
Enfin, l’API Management s’appuie sur des plateformes composées d’une passerelle (Gateway), d’une console d’administration et de supervision, d’un portail donnant accès aux développeurs, aux documentations des APIs. Ces systèmes intègrent de plus de fonctionnalités : hybridation, monétisation et streaming.
L’utilisation de la plateforme open source Gravitee.io API Management (repo GitHub) vous permet de concevoir et gérer le cycle de vie de vos APIs. Grâce aux nombreuses Policies riches et puissantes disponibles, vous disposez d’un énorme éventail d’outils et de techniques pour enrichir vos APIs, tels que :
Mais parfois, vos designs deviennent si complexes qu’il est presque impossible de savoir où se situent les problèmes de conception et de configuration lorsqu’ils apparaissent. Pas de panique, le Debug Mode est là pour vous aider. Le Debug Mode est une fonctionnalité qui libère la puissance de l’API Publisher, vous permettant de concevoir une API, de la « shadow » déployer (ne vous inquiétez pas, nous expliquerons plus tard ce qu’est le « shadow deployment ») et de comprendre exactement quelles Policies ont été appliquées à l’appel d’API.
Dans ce blog post, nous allons nous mettre dans la peau d’un éditeur d’API (API Publisher), en examinant une API présentant des comportements étranges. Nous allons parcourir un exemple simple d’API, et étudier non seulement comment utiliser le Debug Mode, mais aussi comment il fonctionne sous le capot.
Je m’appelle Yann Tavernier (pour en savoir plus sur mon parcours, ça se passe ici !) et je suis développeur dans l’équipe APIM chez Gravitee.io. J’ai eu l’occasion de travailler sur le Debug Mode et je suis ravi de vous guider et de vous expliquer cette fonctionnalité !
Avant de nous pencher sur le Debug Mode, nous allons voir un aperçu de tous les concepts et composants clés que nous utiliserons dans cet article.
Nous allons maintenant présenter un simple scénario pour expliquer comment utiliser le Debug Mode.
Tous nos exemples seront réalisés sur une installation locale. Vous pouvez utiliser cette commande pour exécuter APIM 3.17 avec docker-compose
:
cd /tmp && mkdir -p apim && cd apim && curl -L https://raw.githubusercontent.com/gravitee-io/gravitee-docker/master/apim/3.x/docker-compose.yml -o "docker-compose.yml" && export APIM_VERSION=3.17.1 && docker-compose down -v && docker-compose pull && docker-compose up
Pour accéder à l’interface de la console de management, allez à l’adresse suivante: http://localhost:8084
.
Les informations d’identification par défaut sont les suivantes:
admin
admin
Si vous êtes intéressé par un guide plus détaillé, vous pouvez consulter cet article de Ljubica Lazarevic (en anglais) !
Nous allons nous appuyer sur une API appelée « Library backend ». Vous pouvez l’importer grâce à son API Definition ici.
Ce backend sera accessible sur http://localhost:8082/library-backend
et retournera ce jeu de données simulé:
{
"books": [
{
"title": "A tale of two cities",
"author": "Charles Dickens",
"_internalReference": "gio_b1"
},
{
"title": "The Lord of the Rings",
"author": "J.R.R Tolkien",
"_internalReference": "gio_b2"
},
{
"title": "The Hitchhiker's Guide to the Galaxy",
"author": "Douglas Adams",
"_internalReference": "gio_b3"
}
]
}
Nous analyserons ce jeu de données plus tard.
En tant qu’API Publisher, je souhaite concevoir une API, appelée « Library », pour accéder au backend de ma bibliothèque.
Vous pouvez la créer en vous inspirant de la documentation et suivre ce guide étape par étape, ou vous pouvez directement importer l’API Definition résultante.
Tour d’abord, nous devons choisir le type de Plan à utiliser pour mon API. Nous allons choisir deux plans: un plan Keyless, appelé « Free » et un plan Api-Key, appelé « Premium ».
Commençons par concevoir le plan « Free ». Ce plan permets à tout le monde d’accéder à notre API. Pour protéger nos backends, ainsi que pour améliorer les performances, nous voulons gérer la quantité de traffic qui atteindra notre API avec ce plan. Nous limiterons l’accès grâce à la Policy « Rate Limit ». Une chose à noter: comme il s’agit d’un plan Keyless, les applications consommatrices n’ont pas besoin de créer de souscription.
Comme l’API sera accessible au public, nous voudrons dissimuler certaines données privées dans la réponse, le champ _internalReference
. Pour ce faire, nous allons utiliser la JSON to JSON Transformation policy.
Voici la configuration de la JSON to JSON Policy. Son but est de supprimer le champs _internalReference
dans le tableau de books
:
[
{
"operation": "remove",
"spec": {
"books": {
"*": {
"_internalReference": ""
}
}
}
}
]
Déployons l’API (vous pouvez le faire en synchronisant l’API lorsque vous y êtes invité) et appelons là avec un cURL:
L’appel curl http://localhost:8082/library
produira ce résultat:
{
"books": [
{
"title": "A tale of two cities",
"author": "Charles Dickens"
},
{
"title": "The Lord of the Rings",
"author": "J.R.R Tolkien"
},
{
"title": "The Hitchhiker's Guide to the Galaxy",
"author": "Douglas Adams"
}
]
}
Nous avons réussi à dissimuler des données internes et sensibles qui étaient exposées par l’API. Cependant, nos équipes de développeurs pourraient bien avoir besoin d’accéder à ces données à des fins de test. Nous allons créer un plan interne (appelé « Internal » sur les captures d’écran), API-Key plan, pour permettre un accès autorisé aux données, en vérifiant que l’API-Key transmise en tant que header ou query parameter est valide et liée à une application grâce à une souscription. Pour en savoir plus, vous pouvez consulter la documentation sur la façon de configurer un plan.
Rappelez-vous, la suppression de _internalReference
a été faite sur le plan Freemium. Ici, avec le plan Internal, nous conservons les données originales. Nous allons en profiter pour utiliser la Assign Attributes Policy pour ajouter un attribut interne dans le contexte. Cet attribut sera la concaténation de l’ID de l’application suivi de « -internal » et accessible par la clé « internal ».
Pour ce faire, nous avons configuré la Assign Attribute Policy pour ajouter un attribut internal
avec la valeur suivante : {#context.attributes["application"]}-internal
.
Appelons maintenant l’API avec curl http://localhost:8082/library?api-key=7cc755d1-378b-4099-9650-9ee9330be55c
. Le résultat est:
{
"books": [
{
"title": "A tale of two cities",
"author": "Charles Dickens",
"_internalReference": "gio_b1"
},
{
"title": "The Lord of the Rings",
"author": "J.R.R Tolkien",
"_internalReference": "gio_b2"
},
{
"title": "The Hitchhiker's Guide to the Galaxy",
"author": "Douglas Adams",
"_internalReference": "gio_b3"
}
]
}
REMARQUE : Vous avez peut-être remarqué que nous ne pouvons pas voir l’attribut que nous avons défini. En fait, l’attribut ne vit dans la Gateway que le temps de l’appel. Il s’agit d’un comportement de la Policy que nous utilisons, et il est interne à la Gateway.
Enfin, nous allons créer un Flow sur l’API en utilisant à nouveau la JSON to JSON Transformation Policy pour appliquer des remises à un livre en fonction de certaines conditions.
La remise sera appliquée si la réponse est:
"X-Library-Discount":15
internal
n’est pas videPar défaut, la valeur de remise sera celle du header « X-Library-Discount », ou 10% par défaut.
Pour cela, nous allons d’abord configurer la condition de la policy: {(#request.headeers['X-Library-Discount'] != null && #request.headers['X-Library-Discount'].size() > 0) || {#context.attributes['internal'] != null}}
Ensuite, nous allons utiliser cette configuration pour la JSON to JSON Policy:
[
{
"operation": "shift",
"spec": {
"*": "&"
}
},
{
"operation": "default",
"spec": {
"discount": "{#request.headers['X-Library-Discount'] != null ? #request.headers['X-Library-Discount'][0] : 10}%"
}
}
]
L’appel de l’API avec http://localhost:8082/library?api-key=7cc755d1-378b-4099-9650-9ee9330be55c
produira le résultat suivant:
{
"message":"Request failed unintentionally",
"http_status_code":500
}
Nous avons quelques problèmes avec notre dernier flow, mais que s’est-il passé ? Il est difficile de le dire en utilisant simplement cURL ou Postman. Plus la complexité du design de l’API augmente, plus le risque de problèmes augmente également. Comment pouvons-nous éviter de déployer notre API auprès de nos utilisateurs avant d’avoir résolu tous les problèmes en cours ?
L’équipe APIM a créé le Debug Mode pour résoudre ce problème précis.
Le Debug Mode permet d’avoir une compréhension et une vue d’ensemble de ce qui se passe dans la Gateway. Grâce à cette fonctionnalité, nous sommes maintenant en mesure d’envoyer une requête à l’aide de notre client HTTP et de voir exactement quelles Policies ont été exécutées, avec leurs entrées et sorties.
Dans la capture d’écran suivante, vous pouvez voir un exemple de flux de demande examiné à l’aide du Debug Mode :
La requête utilise la même API-Key que précédemment, et nous pouvons voir que le status de réponse est 500 - Internal Server Error
.
Voyons ce que le Debug Mode nous apprends. Le premier élément important de cette fonctionnalité est la timeline. Elle représente chaque Policy qui a été exécutée, sous la forme d’une carte. Une carte est composée de plusieurs éléments:
La timeline représente l’ordre réel d’exécution de vos Policies, qui peut avoir changé par rapport à votre design initial. Vous remarquerez peut-être que l’exécution peut être différente de ce que vous aviez prévu !
Si vous êtes un utilisateur régulier de Gravitee, vous êtes probablement habitué à configurer les Policies et à choisir l’un des scopes suivants: REQUEST
, REQUEST_CONTENT
, RESPONSE
, RESPONSE_CONTENT
. Pour les scopes REQUEST
et RESPONSE
, l’exécution de la Policy n’a aucun accès au « content » (ni en lecture ni en écriture), contrairement à REQUEST_CONTENT
et RESPONSE_CONTENT
.
Nous n’allons pas approfondir ce sujet, mais il est important de noter que la Gateway exécutera d’abord les Policies « headers » (REQUEST
/ RESPONSE
) et ensuite les Policies de « content » (REQUEST_CONTENT
/ RESPONSE_CONTENT
).
Cliquons sur la carte pour explorer les informations qu’elle fournit.
Grâce à la vue différentielle (désolé pour la traduction 😅, pour les habitués de Git, nous appellerons ça un diff), nous pouvons maintenant voir et comprendre comment fonctionne l’Assign Attributes Policy: elle ajoute un attribut dans l’objet Attributes du contexte interne de l’appel.
C’est ici ! Nous pouvons voir deux icônes apparaître sur notre de carte de JSON to JSON Transformation. En regardant la carte, nous constatons que cette erreur ce produit sur le « stage » API > Body.
true
En regardant le diff, nous pouvons voir ce message d’erreur: Request failed unintentionally
. C’est exactement le même message que nous avons eu avec notre appel cURL. Malheureusement, ce message ne nous en apprends pas beaucoup sur l’origine de l’erreur.
Cependant, le point intéressant est le bloc concernant la Condition:
Nous pouvons voir que la condition est invalide. Avec une lecture plus attentive, il semble que nous ayons configuré notre condition avec request.headeers
au lieu de request.headers
.
Alors… comment fonctionne exactement le Debug Mode ? Jetons un coup d’oeil sous le capot.
Lorsque vous envoyez une requête grâce au Debug Mode, l’API Gateway détecte cet événement et commence son traitement.
Elle déploie la version actuelle de votre API dans un état particulier que nous appelons « Shadow Deployment ». Cela signifie simplement que l’API est déployée, mais n’est pas accessible publiquement. Ce déploiement est uniquement utilisé par le Debug Mode, ce qui signifie qu’il n’y a aucun risque que vos clients (ou tout autre utilisateur !) accèdent à cette version de votre API !
Vous n’avez pas besoin de déployer votre API de la manière habituelle pour pouvoir la debugger. Cela peut être très utile lorsque vous effectuez des tests pour trouver la bonne configuration pour une Policy.
Rappelez vous, notre condition contenait une faute de frappe, et nous avons corrigé request.headeers
en request.headers
dans la JSON To JSON Policy.
La réponse est 200 - OK
, et nous pouvons voir la remise appliquée dans le corps de la réponse (champs discount
).
Le Debug Mode peut également nous indiquer si une Policy ne s’est pas exécutée en raison d’une condition non remplie.
Si nous appelons l’API sans API-Key ou sans header X-Library-Discount
, la JSON to JSON Policy ne sera pas appliquées, comme vous pouvez le voir sur la timeline:
Nous venons de voir un exemple simple d’APIs défaillantes avec des problèmes de configuration de Policy, et de la manière de la dépanner avec le Debug Mode. Nous avons pu voir et parcourir les flows pour comprendre ce qui se passait réellement et ce qui causait le problème. On a également examiné comment le Debug Mode fonctionne sous le capot.
Nous serions ravis de connaître votre avis et de savoir comment vous utilisez le Debug Mode. Si le sujet vous intéresse et que vous avez des questions, n’hésitez pas à rejoindre notre forum communautaire. L’équipe se fera un plaisir de discuter avec vous !
Elles sont passées où les femmes dans la tech ? Entre le manque de représentation…
Dans cette vidéo, on interview Nicolas Grekas, contributeur clé de Symfony, pour discuter de sa…
Comment trouver son job dans la tech ? Marie a la réponse ! Grâce à…
Adobe, l'empire créatif, et pas des moindres ! Belle ascension de la part de ces…
Est-ce plus simple de créer des morceaux avec les outils de Musique Assistée par Ordinateur…