AWS API Gateway : un tour d’horizon

Véritable avant-poste de votre Système d’Information, les APIs relient les différents composants de vos architectures.

Qu’il s’agisse d’une API technique, utilisée exclusivement en interne, ou bien d’une API publique, utilisée par vos clients à travers le web et vos applications mobiles, la bonne conception de votre API Gateway est un élément fondamental de votre architecture cloud.

La création, la gestion et le déploiement de telles API Gateways, peuvent être de véritables challenges pour les ingénieurs. Heureusement, AWS propose via le service AWS API Gateway, une offre intégralement managée, avec une tarification avantageuse, à la requête, pour aider votre entreprise à relever ces défis.

Dans cet article, nous explorerons en profondeur ce service, en détaillant ses fonctionnalités, ses avantages, mais également ses limitations actuelles, ainsi que les différentes solutions permettant d’y remédier.

Choisir l’API Gateway adaptée à ses besoins

AWS API Gateway (APIGW) propose trois modes de déploiement :

  • EDGE
  • REGIONAL
  • PRIVATE

Dans tous les cas, après avoir créé une APIGW, vous obtenez un API endpoint unique. Il s’agit d’un hostname similaire à :

<api-id>.execute-api.<region>.amazonaws.com

Commençons tout d'abord par le type EDGE. Il s'agit du mode proposé par défaut lors du déploiement d'une nouvelle APIGW.

Ce type vous permet de bénéficier du réseau des points de présence (PoP) Cloud Front.

Les requêtes sont redirigées vers le point de présence le plus proche, permettant ainsi une distribution mondiale de votre API, tout en garantissant des temps de réponse ultrarapides pour les utilisateurs finaux, et ce, indépendamment de leurs emplacements géographiques.

Cela en fait donc un choix judicieux pour les charges de travail distribuées à grande échelle.

Le type REGIONAL correspond à une APIGW publique.

Ce qui signifie, que l’endpoint de votre API sera exposé publiquement sur Internet.

Si vous souhaitez créer une APIGW publiquement accessible pour votre application mobile, il s'agit de la bonne option.

À noter, que même si cet endpoint est public, il est toujours possible d'en restreindre l'accès via une ressource policy, des API Keys voire en utilisant une fonction lambda Authorizer, pour s'assurer, par exemple, que seules les requêtes authentifiées par token seront traitées. Nous aborderons ce point dans la dernière section de l’article.

Le type PRIVATE correspond comme son nom l'indique, à une APIGW privée non exposée sur internet.

Dans ce cas, l’endpoint de l'APIGW est accessible uniquement depuis le réseau AWS, via un vpc endpoint (vpce) pour le service execute-api.

Si vous souhaitez mettre en place une APIGW technique, qui sera appelée exclusivement en interne depuis vos VPC, vous pouvez utiliser ce mode de déploiement.

Un Domain Name custom pour son API publique

Il est fort probable, que vous souhaitiez utiliser votre propre nom de domaine en lieu et place de <api-id>.execute-api.<region>.amazonaws.com.

Pour les APIGW publiques, AWS propose de créer un Custom Domain Name.

Cette option vous permettra d'appeler votre API, via un FQDN comme :  api.my-company.com.

Pour enregistrer un nouveau Custom Domain Name, AWS vous demandera de lier ce domaine à son certificat qui devra impérativement être stocké dans AWS Certificate Manager (ACM).

À noter que si votre certificat pour ce domaine n'a pas été délivré par Amazon, il est toujours possible de créer un certificat de type "importé" dans ACM ; dans ce cas, il vous sera demandé de fournir le certificat et sa clé privée.

Une fois le domaine enregistré et validé, vous pourrez le lier à une APIGW et à un stage.

La dernière étape consiste à créer un enregistrement DNS pour rediriger le Custom Domain Name vers <api-id>.execute-api.<region>.amazonaws.com.

Cette opération peut être effectuée avec Route 53, si votre DNS public est également géré par AWS.

Un Custom Domain Name peut être utilisé par plusieurs APIGW publiques.

Il est par ailleurs possible de définir des règles fondées sur les paths des requêtes pour effectuer des redirections vers différents API/Stages.

Cela permet de facilement gérer le routage vers plusieurs APIGW en fonction de vos différents environnements (test, QA, production, etc.).

Un Domain Name Custom pour son API Privée

La méthode est quelque peu différente pour les APIGW privées.

Effectivement, les Custom Domain Names, ne sont malheureusement disponibles que pour les APIGW publiques et ne fonctionnent pas avec les APIGW privées.

Vous pouvez créer un Custom Domain Name et l'attacher à votre APIGW privée, mais cela n'aura aucun effet et ne permettra pas de rediriger vos requêtes vers votre API.

Heureusement, une solution de contournement existe, mais demandera quelques coups de clé à molette supplémentaires 🔧.

Mais pas de panique, nous sommes là 👷 pour vous guider.

Network Load Balancer et Application Load balancer à la rescousse

Nous pouvons créer un Application Load Balancer (ALB) ou bien un Network Load Balancer (NLB) avec pour cibles les trois adresses IP des Elastic Network Interfaces (ENI) associées au VPC endpoint du service execute-api.

Il est ensuite possible d'associer à notre Load Balancer un certificat sourcé depuis ACM. Enfin, il suffit de créer un CNAME dans Route 53 pour résoudre par exemple api.internal.my-company.com vers le nom DNS du Load Balancer.

Le diagramme suivant résume la présente solution :


Et le MTLS ?

Vous faites bien de poser la question 🙋, car c'est une des limites de la solution précédente.

Actuellement, les Load Balancers AWS ne prennent pas en charge le MTLS (Mutual TLS), c'est-à-dire le fait de vérifier côté serveur la présence d'un certificat client.

Si vos standards de sécurité vous obligent à mettre en place du MTLS, vous n'avez pas d'autre alternative que de mettre en place en self-managed, un reverse proxy tel que Nginx, qui vous permettra d'avoir accès à une plus grande liberté de configuration et d'activer le MTLS pour les flux entrants.

Un dernier mot sur le MTLS. Il est possible de demander à votre APIGW de présenter un certificat client lorsqu'elle appelle votre backend.

Quelques déceptions à ce niveau, puisque nous constatons que :

  • Le certificat client de l'APIGW n'est pas géré dans ACM mais dans le service APIGW en lui-même (ce qui peut complexifier vos process de renouvellement).
  • Le certificat client est un simple certificat autosigné généré par le service 🤦🏻‍♀️. Impossible donc d'utiliser sa propre PKI (via AWS Certificate Manager Private CA par exemple).
  • Enfin, si vous utilisez un certificat privé côté backend, AWS APIGW ne sera pas en mesure de le vérifier, puisqu'à ce jour, aucune fonctionnalité ne permet d’ajouter à son APIGW le certificat de son Autorité de Certification 😬.

Créer du lien entre les comptes AWS

Une fois l'APIGW créée, vous ne trouverez pas d'ENI permettant d'accéder directement à votre APIGW, comme c'est le cas pour d'autres services managés comme MSK ou Redshift par exemple.

AWS APIGW est un service intégralement géré par AWS, et les serveurs de l'APIGW ne sont pas instanciés dans votre compte, mais dans un compte détenu par AWS et dédié à ce service.

Vous pouvez trouver ici, la liste des comptes AWS qui hébergent vos APIGW en fonction de la région que vous utilisez.

Ainsi, une requête entrante, suit le schéma suivant :

Votre compte AWS → Compte AWS du service APIGW → Retour dans votre compte AWS

Ce scénario cross-accounts, utilise la technologie AWS Private Link. À noter que pour APIGW, vous verrez parfois le terme de VPC Link à la place, mais il s'agit du même concept.

En résumé, Private Link fonctionne de la manière suivante :

(Illustration extraite de la documentation AWS Private Link)

  • Un Service Provider propose à ses clients un service managé reposant sur les ressources instanciées dans son compte AWS.
  • Un Service Consumer souhaite utiliser depuis son compte le service du provider.
  • Le Service Provider met en place un Network Load Balancer en amont de ses ressources compute et associe ce NLB à un VPC service endpoint.
  • Le Service Consumer peut ensuite créer un vpc-endpoint en spécifiant l'ARN du service endpoint créé précédemment par le provider
  • Le Service Provider accepte la demande du consumer et celui-ci peut dès lors utiliser le service

Sous le capot, AWS APIGW utilise ce système pour que vous puissiez joindre une APIGW privée.

Le Service provider est un des comptes AWS pour APIGW et le vpc endpoint et celui créé pour le service execute-api.

En revanche, lorsque le trafic doit revenir dans votre compte, la situation s'inverse, et vous devenez, pour APIGW, un Service Provider.

C'est pourquoi, si vous souhaitez que votre APIGW cible une ressource dans votre VPC (par exemple un cluster EKS), il vous faudra créer un NLB et l'associer dans le service APIGW en tant que VPC Link.

De cette manière, le pont sera construit entre les différents comptes.

Gardez toutefois en tête cette limitation importante du service APIGW :

  • le NLB utilisé comme VPC Link doit impérativement se trouver dans le compte où vous avez instancié votre APIGW.

Cela peut être problématique si vous avez créé une Landing Zone complexe et que vous utilisez deux comptes AWS différents pour votre APIGW et votre backend (EC2, EKS etc.).

Dans ce cas, pas d'autre choix que de recréer un autre VPC Link pour gérer le cross-account (oui ça commence à faire beaucoup 😋)

Cela donnerait schématiquement :


Et la sécurité dans tout ça ?

AWS APIGW permet une intégration native avec AWS Web Application Firewall (WAF). De cette manière, vous pouvez bloquer en amont les requêtes malicieuses (injections SQL, attaques XSS, query string excentriques, voire tentatives d'accès à certains paths tels que /admin ) — votre backend vous en remerciera 😇.

Vous bénéficiez également d'une protection DDoS via AWS Shield.

Enfin, l'endpoint de votre APIGW, qu'elle soit publique ou privée, peut aussi être protégé par une IAM Ressource Policy.

Il est donc possible de bloquer certaines adresses IP, certains paths et dans le cas d'une APIGW privée, autoriser uniquement le trafic provenant de votre VPC.

À noter qu’AWS ne vous facturera pas les requêtes bloquées par votre policy IAM.

Lambda Authorizer

Vous pouvez utiliser une Lambda AWS comme Authorizer pour votre APIGW.

Dès lors, il sera possible d'appeler en coupure de certains paths de votre API cette Lambda. La fonction peut avoir accès aux headers de la requête et il vous sera possible de programmer votre propre logique métier pour authentifier/autoriser les requêtes entrantes.

APIGW propose de plus un système de cache pour éviter d'avoir à exécuter la lambda à chaque fois qu'un utilisateur déjà autorisé par la lambda refait un appel.

Un dernier élément important est de veiller à maintenir des performances optimales pour notre système.

Effectivement, AWS Lambda, du fait de sa nature serverless ne fait pas exception aux problématiques de "Cold Start”.

C'est-à-dire, que lors de la première invocation de votre lambda, ou après une période d’inactivité, une latence sera observée puisque AWS devra démarrer un nouvel environnement d'exécution pour y lancer votre code.

Bien sûr, des solutions existent pour limiter l'impact du Cold Start.

Tout d’abord quelques bonnes pratiques à suivre lors du développement de votre Lambda :

  • réduire au maximum la taille du package zip qui contient votre code
  • dans la mesure du possible, limiter le nombre de librairies externes
  • placer l'instanciation des connecteurs de bases de données en dehors de la fonction handler (effectivement, tout le code en dehors du handler est exécuté une seule fois, lors de la création de l'environnement d'exécution, tandis que le code présent dans la fonction handler sera quant à lui exécuté à chaque appel).

Et côté infrastructure, vous pouvez utiliser ces quelques astuces :

  • Provisioned Concurrency : grâce à cette fonctionnalité, il vous sera possible d'indiquer à AWS que vous souhaitez avoir, à tout moment, un certain nombre d'environnements d'exécution en phase hot. Ce qui signifie que AWS se chargera de veiller à démarrer vos environnements d'exécution en amont, avant même de devoir traiter une requête, afin de ne pas être impacté par de possibles latences.

Mais comment définir le nombre idéal d'environnements provisionnés ? Dans la mesure où l'activité de votre API et donc le nombre d'appels à votre Lambda Authorizer peut varier fortement en fonction des horaires ou d’autres évènements extérieurs, il peut être complexe de mettre à jour ce paramètre pour éviter de payer inutilement pour des ressources inutilisées ou au contraire, pour éviter de sous-provisionner son infrastructure.

Heureusement, AWS met à notre disposition une mise à l'échelle automatique du nombre d'environnements provisionnés.

Vous permettant de définir une capacité minimale et maximale ainsi qu'un objectif cible en pourcentage (par exemple 80%).

De cette manière, AWS veillera à augmenter ou à réduire le nombre d'environnements provisionnés afin que le nombre d'environnements utilisés corresponde au pourcentage défini (dans notre exemple, AWS s'arrangera pour garder un taux d'utilisation des environnements provisionnés de 80%).

Dernière astuce, n'oubliez pas de définir une Reserved Concurrency pour votre lambda Authorizer.

Ce paramètre, qui agit au niveau du compte AWS, permet de réserver un nombre maximum d'exécutions d’une fonction lambda.

Il permet deux choses :

  • vous assurer que votre quota d'exécution ne sera pas mangé par un autre lambda qui serait sursollicitée.
  • vous assurer que votre lambda ne pourra pas être appelée infiniment de manière incontrôlée. Effectivement, ce paramètre agit comme une borne supérieure, au-delà duquel il n'est plus possible de créer des exécutions supplémentaires de votre Lambda

Conclusion

J’espère que cet article vous aura permis de mieux appréhender les bonnes pratiques, lorsqu’il s’agit de bâtir les fondations d’une APIGW.

L’intégralité de cette architecture peut être déployée en IaaC grâce à des outils comme Terraform.

AWS APIGW offre une intégration complète avec l’écosystème AWS et présente de nombreux avantages, cependant, le service n’est pas exempt de défauts, notamment lorsqu’il s’agit de la question des quotas.

On soulignera que le nombre maximal de routes par APIGW est de 300 par défaut. Ce quota peut être augmenté, cependant, actuellement la hard limite est de 600 routes. Ceci pourra s’avérer être problématique, si vous souhaitez instancier une APIGW centralisant l’accès à l’intégralité des API de vos microservices.

A noter que d’autres solutions concurrentes, comme Kong, ne sont pas soumises à de telles contraintes.

Nous avons choisi de ne pas aborder le mécanisme de publication des différentes ressources et méthodes d’une API dans cet article. Sachez toutefois qu’il est également possible d’adopter un workflow GitOps, en générant un fichier OpenAPI qui sera utilisé par votre outillage IaaC pour créer un nouveau déploiement de votre APIGW et ainsi intégrer les nouvelles versions de votre parc applicatif.