Table des matières :
- API Gateway vs reverse proxy vs Ingress : responsabilités réelles (et anti-patterns)
- Authentification et autorisation : JWT/OAuth2, OIDC, mTLS, et la séparation authN/authZ
- Rate limiting : modèles (token bucket), dimensionnement et pièges de production
- Routage des microservices : règles L7, versioning, canary et résilience (timeouts/retries)
- Observabilité au gateway : logs structurés, métriques, traces et corrélation incident
- Intégrer un API Gateway dans un écosystème PrestaShop : cas d’usage, limites du cœur et checklist prod
API Gateway vs reverse proxy vs Ingress : responsabilités réelles (et anti-patterns)
Un API Gateway n’est pas “juste un Nginx devant des services”. C’est un plan de contrôle L7 qui centralise des décisions de sécurité et de trafic (authN/authZ, quotas, transformations, routage, observabilité) et qui doit rester stateless autant que possible. Le reverse proxy classique (Nginx/HAProxy) se contente souvent de terminer le TLS, de faire du load‑balancing et d’appliquer quelques ACL ; l’Ingress Kubernetes délègue une partie de ces fonctions, mais n’impose pas une politique applicative homogène.
Pour clarifier rapidement les responsabilités (et éviter de “mettre le mauvais outil au mauvais endroit”), voici une vue synthétique :
| Brique | Couche | Bon usage typique | À éviter |
|---|---|---|---|
| Reverse proxy (Nginx/HAProxy) | L4/L7 | TLS, LB, compression, règles simples, protection basique | Politiques IAM complexes, décisions métier |
| Ingress (Kubernetes) | L7 (entrée cluster) | Exposer des services K8s, routage HTTP simple, certificats, intégration K8s | Gouvernance multi-teams sans conventions, authZ fine par ressource |
| API Gateway | L7 “policy first” | AuthN/AuthZ centralisée, rate limiting, routage avancé, versioning, observabilité, contrats d’accès | Agrégation lourde, orchestration de workflows, dépendances stateful |
La confusion la plus courante : mettre toute la logique métier dans le gateway (ex. enrichissements lourds, appels en cascade, agrégations de données). C’est un anti-pattern : vous recréez un monolithe au point d’entrée, vous augmentez la latence P99 et vous transformez la passerelle en SPOF fonctionnel. L’API Gateway doit appliquer des politiques transverses et router vite ; l’agrégation, si nécessaire, se fait plutôt via un BFF (Backend For Frontend) par canal (web, mobile, POS), versionné comme un service.
Un bon test mental : si votre gateway “connaît” la structure d’un panier, calcule des promos, ou appelle 4 services pour composer une réponse, vous êtes déjà en train de déplacer le domaine métier au mauvais endroit. En revanche, s’il valide l’identité, applique des limites, impose des timeouts, corrèle des traces, et route vers le bon upstream, il est dans son rôle.
Dans un contexte e-commerce, y compris quand le cœur reste un monolithe (typiquement PrestaShop 9.x), la passerelle prend son sens dès que vous branchez des briques : recherche, ERP, paiement, pricing, inventaire. Vous avez déjà des exemples de “microservices de facto” avec une recherche externalisée (voir l’article sur Meilisearch) ou une couche d’intégration ERP (voir Intégration ERP : API, connecteurs et donnée unique en temps réel). L’API Gateway est le point unique où vous imposez les mêmes exigences à tous ces flux.
Point d’attention “production” souvent sous-estimé : la passerelle devient une surface d’attaque et une pièce d’infrastructure critique. Cela implique des pratiques d’exploitation comparables à celles d’un frontal web (gestion des certificats, mises à jour, règles de sécurité, supervision) — et des tests réalistes, notamment en charge.
Pré-requis et périmètre d’exemples : les extraits ci-dessous sont réalistes sur Kubernetes 1.30, Redis 7.2, et un gateway de type Kong Gateway 3.6 / Envoy 1.31 / Traefik Proxy 3.2. Côté boutique, les intégrations sont illustrées avec PrestaShop 9.1 (Symfony 6.4) et PHP 8.3. Toute modification de gateway en production implique un risque de coupure : prévoyez un déploiement blue/green et des tests de charge (cf. PrestaShop performance : monitoring, tests de charge et runbooks soldes).
Authentification et autorisation : JWT/OAuth2, OIDC, mTLS, et la séparation authN/authZ
Le minimum viable “propre” au niveau de la gateway, c’est : authentifier le client (authN) puis autoriser l’action (authZ) sur une ressource. Dans la pratique, l’authN se fait via un IdP (Keycloak, Auth0, Azure AD, etc.) en OAuth2/OIDC, et le gateway valide des tokens JWT sans appeler l’IdP à chaque requête (sinon vous ajoutez une dépendance de disponibilité). Le RFC 7519 rappelle la définition canonique : “JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties.” (RFC 7519, Abstract) — ce côté “compact” explique pourquoi c’est devenu un standard de facto sur des APIs.
Pour OAuth2, gardez en tête ce que dit le RFC 6749 : “The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service…” (RFC 6749, Abstract). Traduction opérationnelle : OAuth2 n’est pas un “système de login”, c’est un cadre d’obtention d’accès limité. En front web, on parle souvent OIDC (couche identité au-dessus d’OAuth2) ; en machine-to-machine, on est sur client credentials + scopes. Le gateway doit surtout : (1) valider la signature (JWKS), (2) vérifier iss/aud/exp/nbf, (3) normaliser les claims (ex. sub, scope, roles), et (4) transmettre un contexte minimal en headers signés en interne si vos services ne parlent pas JWT.
Quelques détails qui font la différence en prod (et qui expliquent beaucoup de “401 mystérieux”) :
- Cache JWKS + rotation : si votre IdP rotate ses clés, gérez correctement
kidet un cache avec expiration raisonnable. Trop court = charge IdP inutile ; trop long = erreurs lors de rotation. - Clock skew : vérifiez
exp/nbfavec une tolérance (ex. 30–60s) et assurez-vous que NTP est sain sur tous les nœuds ; sinon, un décalage d’horloge suffit à invalider des tokens valides. - Audience stricte : un même IdP peut servir plusieurs APIs ; refuser un token dont
audn’est pas la vôtre évite des confusions (ou des abus) entre environnements. - Deny-by-default : si une route n’est pas explicitement ouverte (ex. healthchecks internes), elle doit exiger authN/authZ.
Sur des flux sensibles (backoffice, endpoints admin, webhooks paiement), le JWT seul n’est pas une garantie suffisante : mettez du mTLS entre gateway et upstream (ou au moins sur les segments critiques) et segmentez par réseaux/ACL. L’objectif est de réduire l’impact d’un token volé (rejeu depuis un réseau non autorisé). Pour les shops PrestaShop, c’est cohérent avec une stratégie plus globale de durcissement : WAF + journalisation + protection de l’API d’admin (voir Sécurité PrestaShop : protéger API backoffice, WAF et journalisation SIEM et Sécurité PrestaShop : mises à jour, SSL et durcissement .htaccess).
Mini-scenario réaliste : un prestataire logistique appelle /api/orders/export. Vous lui donnez un client_id OAuth dédié + scopes lecture uniquement, et vous forcez :
- IP allowlist (si possible),
- mTLS (si le prestataire sait le faire),
- quotas spécifiques,
- et une trace d’audit (qui a exporté quoi, quand).
Vous réduisez d’un coup le risque de fuite et vous facilitez l’investigation en cas d’incident (ce qui est très concret côté RGPD : minimisation des données, et capacité à expliquer les accès).
Exemple (Envoy 1.31) : validation JWT au gateway et propagation d’un header x-user-id (attention : ne jamais laisser le client le définir).
# envoy.yaml (extrait)
http_filters:
- name: envoy.filters.http.jwt_authn
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
providers:
oidc:
issuer: "https://idp.example.com/realms/shop"
remote_jwks:
http_uri:
uri: "https://idp.example.com/realms/shop/protocol/openid-connect/certs"
cluster: jwks_cluster
timeout: 2s
forward: true
rules:
- match: { prefix: "/api/" }
requires: { provider_name: "oidc" }
- name: envoy.filters.http.lua
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
inline_code: |
function envoy_on_request(handle)
local jwt_sub = handle:headers():get("x-jwt-sub")
if jwt_sub ~= nil then
handle:headers():add("x-user-id", jwt_sub)
end
end
Rate limiting : modèles (token bucket), dimensionnement et pièges de production
Le rate limiting au niveau API Gateway vise deux objectifs distincts : (1) protéger l’infra (CPU, DB, IO) et (2) protéger le métier (anti-fraude, anti-scraping, limites contractuelles par client). Les implémentations sérieuses utilisent un modèle type token bucket (capacité + débit de refill), parfois combiné à un “burst” temporaire. Le point clé pour une boutique : vos endpoints n’ont pas le même coût. /api/orders (écriture DB, locks, webhooks) n’a rien à voir avec /api/products (cacheable). Un quota uniforme est une erreur de design.
Une méthode simple (et utile) pour dimensionner sans “deviner” :
- Classez les routes par coût (faible / moyen / élevé) selon DB writes, verrous, appels tiers, CPU.
- Mesurez (même approximativement) le coût P95 et l’impact DB (ex. requêtes/s, locks).
- Fixez des plafonds par route, puis déclinez par client (public, partenaire, ERP, admin).
- Validez en tests de charge : votre limite doit protéger sans casser les usages légitimes.
Exemple de grille pragmatique (à adapter) :
| Route | Type | Coût | Quota de départ conseillé |
|---|---|---|---|
/api/products |
GET | faible | plus élevé (et cache HTTP si possible) |
/api/search |
GET | moyen | modéré + anti-bot |
/api/orders |
POST | élevé | faible + idempotence |
/api/erp/* |
PATCH/POST | variable | élevé mais borné + fenêtres |
Évitez le rate limiting “en mémoire” sur un cluster horizontal : vous obtiendrez des limites incohérentes selon le pod/instance. En pratique, vous externalisez l’état dans Redis (ou un datastore équivalent), et vous acceptez un compromis CAP : soit une limite stricte (latence + coût), soit une limite “approximative” (meilleure perf). Sur un e-commerce, la stratégie la plus robuste est : par route + par identité + par IP, avec des plafonds différents selon client_id/plan. Pour les endpoints publics, couplez avec du bot management/WAF en amont si vous avez un budget ; sinon, un rate limiting L7 bien fait reste un excellent filet.
Cas concret : une intégration ERP qui pousse 50k mises à jour stock/prix pendant un import. Si vous limitez à 10 rps global, vous explosez le SLA de synchronisation ; si vous n’avez aucun quota, vous pouvez saturer MySQL et faire tomber le front. La solution pragmatique : (a) une route dédiée /api/erp/*, (b) un client OAuth dédié (scopes restreints), (c) un quota élevé mais borné + backpressure, et (d) une fenêtre de maintenance/CI pour les imports. Ça s’aligne avec les problématiques de concurrence sur stock (voir Performance e-commerce : prévenir la concurrence sur les stocks avec Redis).
Exemple (Kong Gateway 3.6) : quotas différents par consumer + burst court. En prod, stockez l’état dans Redis, pas dans le node.
# Plugin rate-limiting (extraits conceptuels)
kong plugin enable rate-limiting \
--config minute=600 \
--config policy=redis \
--config redis_host=redis \
--config redis_port=6379
# Variante par route critique (checkout / paiement)
kong plugin enable rate-limiting --route checkout \
--config second=20 --config minute=600 \
--config fault_tolerant=false
Deux pièges fréquents : (1) fault_tolerant=true qui laisse passer si Redis est down (vous perdez votre garde-fou précisément quand l’infra souffre), (2) ne pas renvoyer des headers explicites (RateLimit-Limit, RateLimit-Remaining, Retry-After). Documentez-les : côté clients (modules, ERP, partenaires) ça évite des tempêtes de retries mal réglés.
Autre piège “métier” : un rate limiting qui renvoie 429 mais déclenche un retry immédiat côté client (sans backoff) empire l’incident. Assurez-vous que vos intégrations respectent Retry-After et appliquent un backoff exponentiel, surtout sur des opérations coûteuses (checkout, création commande).
Référence utile : l’OWASP API Security Top 10 souligne que l’absence de limitation et de monitoring facilite les attaques d’énumération et de brute force (voir OWASP, “API Security Top 10”). Ce n’est pas “théorique” : sur un backoffice exposé, ça devient un incident.
Routage des microservices : règles L7, versioning, canary et résilience (timeouts/retries)
Le routage d’un API Gateway moderne se joue au niveau HTTP : path, host, headers, méthodes, query params, et parfois contenu (moins recommandé). Les patterns utiles :
- Path-based routing :
/api/catalog/*→ service catalogue,/api/search/*→ service recherche. - Header-based routing :
X-Api-Version: 2→ v2, sinon v1 (pratique pour des migrations progressives). - Host-based routing :
api.example.comvsadmin-api.example.compour isoler surfaces d’attaque.
Pour un environnement PrestaShop qui commence à se “microservice-iser”, un schéma propre consiste à isoler : (1) les APIs publiques (front/PWA), (2) les APIs partenaires (ERP, transporteurs), (3) les APIs internes (admin). La génération d’URLs et les routes côté PrestaShop ne sont pas toujours homogènes entre legacy et Symfony ; la passerelle peut uniformiser, mais attention aux redirections et à la canonicalisation (utile si vous exposez des endpoints SEO/SSR) — voir Génération d’URL PrestaShop : Link, routes Symfony et legacylink.
Sur le versioning, gardez une règle simple : ne cassez pas vos consommateurs.
- Version dans l’URL (
/v1/…) : simple et explicite, mais peut multiplier les routes et les docs. - Version par header : pratique pour canary/migration, mais nécessite une bonne discipline côté clients (et attention au cache si vous cachez).
- Version par media type : plus “REST puriste”, mais souvent trop complexe pour des équipes produit.
La partie que beaucoup sous-estiment : timeouts, retries et circuit breaking. Un gateway qui “retry” par défaut sur des POST non idempotents est un générateur de doublons (commandes, paiements). Définissez une politique par méthode : retries uniquement sur GET/HEAD, ou sur POST explicitement idempotents via Idempotency-Key. Fixez des timeouts courts au gateway (ex. 2–5s sur lecture), et laissez les services gérer des traitements async via files (Kafka/Rabbit) quand ça dépasse. Si vous utilisez HAProxy en frontal L4/L7, vous pouvez combiner : HAProxy pour le très haut débit et la terminaison TLS, API Gateway pour la politique applicative (voir HAProxy 3.2 : déploiement systemd, configuration frontend/backend, ACL).
Micro-scenario “checkout” (classique en e-commerce) : votre PSP met parfois 3–8 secondes à répondre (3DS/SCA, latence réseau, dépendance externe). Si le gateway a un timeout à 2s et que le front retry automatiquement, vous pouvez générer :
- double tentative de paiement,
- incohérences de statut commande,
- ou “commande fantôme” en backoffice.
La solution n’est pas “augmenter tous les timeouts”. C’est de traiter au cas par cas :
- timeouts plus longs uniquement sur les routes PSP,
- idempotency sur création de paiement/commande,
- et un circuit breaker qui protège votre infra si l’amont se dégrade.
Exemple (Traefik Proxy 3.2) : canary simple par header, utile pour déployer une v2 du service “search” sans impacter tout le trafic.
# dynamic.yml (extrait)
http:
routers:
search-v1:
rule: "PathPrefix(`/api/search`) && HeadersRegexp(`X-Canary`,`^$`)"
service: search-v1
search-v2:
rule: "PathPrefix(`/api/search`) && Headers(`X-Canary`,`1`)"
service: search-v2
services:
search-v1:
loadBalancer:
servers: [{ url: "http://search-v1:8080" }]
search-v2:
loadBalancer:
servers: [{ url: "http://search-v2:8080" }]
Le canary “par header” marche bien en dev/QA et pour des clients internes. En prod grand public, préférez un split par pourcentage (weighted routing) ou par cohorte (hash utilisateur) pour éviter de casser l’expérience d’un client au milieu d’un parcours (ex. panier → paiement). Et si votre checkout est sensible, testez-le comme un flux complet : le tunnel de commande est le premier endroit où un routage approximatif se transforme en perte de CA (voir Contrôle PrestaShop post-modification : checklist tunnel de commande et règles panier).
Observabilité au gateway : logs structurés, métriques, traces et corrélation incident
Sans observabilité, votre API Gateway devient un “black box” : c’est lui qui refuse, qui rate-limit, qui time-out, et vos équipes vont blâmer au hasard le service amont. Le minimum : logs structurés JSON (avec request_id, trace_id, client_id, route, upstream, status, latency_ms, bytes_in/out), des métriques (RPS, P50/P95/P99, erreurs 4xx/5xx, rate-limit hits), et du tracing distribué (OpenTelemetry). Le gateway doit générer ou propager un identifiant de corrélation (traceparent W3C) et le passer aux services.
Un point très concret pour les équipes : au moment d’un incident, vous voulez pouvoir répondre en quelques minutes à :
- “Quelles routes explosent en P99 ?”
- “Est-ce du 5xx upstream (service) ou du 4xx gateway (policy) ?”
- “Quel consumer/
client_idfait le trafic ?” - “La hausse est-elle géographique (un partenaire) ou globale (bots) ?”
Côté stack, vous pouvez rester pragmatique : métriques Prometheus → dashboards Grafana, logs → Logstash/Elastic, monitoring infra via Netdata. Des ressources internes existent déjà pour industrialiser ça : Grafana sur Ubuntu : installation APT et configuration initiale, Logstash : plugins Input, Filter, Output pour Elasticsearch et Kafka, et Netdata monitoring : surveiller AWS, Kubernetes, bases de données et serveurs web.
Sur un e-commerce, surveillez spécifiquement les métriques “métier-proxy” : taux de 401/403 (auth), taux de 429 (rate limiting), et timeouts upstream. Un pic de 429 peut être un bot, un bug client, ou une régression qui déclenche des retries agressifs. Un pic de 401 peut venir d’une rotation de clés JWKS ou d’un décalage d’horloge (NTP) qui invalide nbf/exp. Documentez des runbooks : “429 sur /api/checkout → vérifier quotas + Redis + trafic par consumer”, “401 global → vérifier JWKS cache + issuer/aud”. Cette approche runbook est la seule façon d’éviter des incidents qui se répètent.
Pour les logs, évitez le piège RGPD/PCI : ne loggez ni PAN (cartes), ni CVV, ni secrets, ni tokens complets. Masquez (redact) les headers Authorization, cookies, et paramètres sensibles. Si vous automatisez des tâches (webhooks, exports) gardez une trace d’audit exploitable mais minimale (voir Automatisation PrestaShop : sécurité RGPD, moindre privilège et journaux d’audit).
Astuce simple mais efficace : logguez aussi un champ “reason” quand le gateway bloque (ex. auth_missing, jwt_invalid_aud, rate_limited_consumer, body_too_large). Ça réduit énormément le temps de diagnostic, surtout quand plusieurs équipes (web, ERP, data) partagent la même passerelle.
Intégrer un API Gateway dans un écosystème PrestaShop : cas d’usage, limites du cœur et checklist prod
PrestaShop (même en 9.x) reste majoritairement un cœur monolithique : vous ne “transformez” pas l’application en microservices en posant un gateway. En revanche, vous pouvez externaliser progressivement : recherche, catalogue enrichi, pricing, ERP, PSP, PIM, etc. Un exemple concret : exposer une API dédiée à l’automatisation (MCP/webservices) derrière la passerelle avec authentification forte, scopes, et quotas (voir PrestaShop MCP Server : installation, webservices et gestion produits). L’intérêt n’est pas “l’architecture”, c’est de reprendre le contrôle sur qui appelle quoi, combien de fois, et avec quelle traçabilité.
Dans la vraie vie PrestaShop, vous avez souvent un mix :
- modules qui appellent des APIs tierces (transport, paiement, avis),
- partenaires qui appellent vos APIs (ERP, BI, marketplace),
- et des scripts internes (imports/export, tâches cron).
Le gateway devient alors l’endroit où vous standardisez : un schéma d’auth (clients OAuth/keys), des quotas, des IP allowlists, des formats de logs, et une politique de timeouts. Résultat : moins de comportements “hors contrat” et des incidents plus faciles à diagnostiquer.
Sur la partie performance, n’attendez pas du gateway qu’il compense un backend lent. Il peut mettre en cache des réponses GET (selon produit), compresser, et protéger ; mais si PHP-FPM ou MySQL saturent, vous aurez des 504. Avant de pousser du trafic derrière une passerelle, stabilisez votre socle : PHP-FPM/OPcache, DB, et cache serveur (voir Performance PrestaShop : benchmarks et optimisation PHP-FPM, OPCache, MySQL et Cache PrestaShop : Varnish, Redis, Memcached et OPcache côté serveur). Dans beaucoup d’architectures, Varnish reste pertinent pour le cache HTTP public, et l’API Gateway s’occupe des APIs authentifiées et du routage.
Checklist prod (sans folklore) :
- TLS : TLS 1.2+ minimum, HSTS, rotation certs automatisée, politique cipher cohérente.
- AuthN/AuthZ : validation JWT stricte, scopes par route, mTLS sur flux critiques, deny-by-default.
- Rate limiting : par consumer + route + IP, stockage distribué (Redis),
Retry-After. - Résilience : timeouts courts, retries uniquement idempotents, limites de taille (
max_body_size), protection slowloris. - Observabilité : logs JSON redacted, métriques P99 et 4xx/5xx/429, tracing OTel, dashboards + alerting.
- Déploiement : blue/green, config as code, validation (lint), tests de non-régression sur checkout.
Ajout utile “terrain” : faites un inventaire des dépendances externes (PSP, ERP distant, moteur de recherche managé). Une passerelle met en évidence les fragilités (timeouts, latences, erreurs 5xx) ; si un upstream est instable, vous aurez besoin de stratégies dédiées (circuit breaker, files async, dégradations contrôlées).
Si vous hébergez sur des environnements mutualisés ou des DB managées avec contraintes (latence, limites connexions), le gateway va rendre vos symptômes plus visibles (timeouts, saturation). Traitez la cause : dimensionnement DB, pool connexions, et limites OS (voir par exemple PrestaShop 9 : corriger l’erreur « too many open files » et Erreurs base de données OVHcloud : diagnostic et solutions d’hébergement Web). Le bon usage d’un API Gateway n’est pas d’ajouter une couche : c’est d’ajouter un contrat d’accès à vos microservices, et de le rendre mesurable, testable, et auditable.
