Voici plusieurs méthodes pour authentifier les microservices entre eux, de la plus simple — mais aussi la moins sûre et la moins maintenable — jusqu'aux architectures recommandées.

Une architecture en microservices repose entièrement sur des services qui s'invoquent mutuellement. Mais comment garantir la sécurité de ces échanges et s'assurer que seuls vos propres services peuvent appeler chacun d'eux ? Comment s'authentifier ?
Avec les applications web, le procédé est connu : l'utilisateur saisit ses identifiants, le navigateur les transmet au service, qui renvoie un jeton de session l'authentifiant pendant une certaine durée. Mais dans le cas d'un microservice, aucun humain n'est là pour saisir un mot de passe ou une clé d'authentification multifacteur.
Je vais décrire ici la marche à suivre, en me concentrant sur des serveurs exécutés sur les services Google Cloud Platform tels que Cloud Run ou Google Kubernetes Engine (GKE). Les services clients peuvent se trouver sur GCP, on-premises ou sur AWS.
Ce qui m'a poussé à écrire cet article, c'est qu'API Gateway et Cloud Endpoints sont des technologies en pleine évolution, dotées de solides capacités d'authentification, mais aussi de limites tant l'une par rapport à l'autre que face aux services concurrents. Les façons d'authentifier des microservices entre eux sont nombreuses. Je commencerai par la plus simple — mais la moins sûre et la moins maintenable — pour aller jusqu'aux architectures recommandées.
Par souci de clarté, je me concentrerai sur les microservices dont vous maîtrisez les deux extrémités, mais les mêmes principes s'appliquent lorsque le service client est externe à votre organisation.
Les bases : en-têtes, clés et proxys
Bien qu'il existe des manières plus ou moins complexes de procéder, l'authentification entre services exige une conception très soignée. Voici les grandes lignes.
- Le client utilise une clé secrète pour signer un jeton.
- Le format standard pour le transmettre est le JSON Web Token.
- Le jeton est placé dans un en-tête HTTP Authorization de la manière suivante :
Authorization: Bearer <JWT>où correspond au jeton encodé en base64.
- Le serveur valide ce jeton en interrogeant un service. Autre option : un reverse proxy reçoit la requête et, avant de la transmettre au serveur réel, valide le jeton en interrogeant un service.
- Sur GCP, ce service est fourni par la plateforme.
Cet article présente plusieurs façons de procéder, en partant des approches simples et peu sûres pour aller vers des solutions plus abouties.
Trop simple : les " clés API " auto-gérées
Une solution basique, souvent retenue par ceux qui ne maîtrisent pas l'ensemble des technologies disponibles, s'inspire de ce que font les utilisateurs humains lorsqu'ils se connectent avec un nom d'utilisateur et un mot de passe : on stocke une chaîne secrète dans le service client — une " clé API " faisant office de justificatif d'identité — puis on la valide côté serveur.
APIKEY=Microservice1:78eb9a45897fLimites
Cette approche n'est pas sécurisée.
Fuites de clés
Les clés fuitent par bien plus de canaux qu'on ne l'imagine.
Pour éviter cela, ne stockez pas de secrets dans Git ou tout autre système de gestion de code source — il est trop facile de les exposer par accident. Privilégiez plutôt un service de gestion de secrets comme Google Cloud Secret Manager ou Hashicorp Vault. Le problème reste néanmoins entier : le service client devra stocker des identifiants pour accéder au gestionnaire de secrets.
Gestion des clés
Vous devrez développer une base de données côté serveur pour stocker ces clés, ainsi qu'une couche pour vérifier qu'une clé reçue est correcte. Vous ne voudrez pas non plus que les clés fuitent depuis cette couche : le client ne doit donc pas transmettre la clé API elle-même, mais uniquement un hash, que le serveur compare à un hash stocké de la clé. La maintenance de l'ensemble est coûteuse. Et peu sûre, car vous n'êtes pas en mesure de mobiliser l'expertise et les efforts nécessaires pour combler toutes les failles possibles. Les systèmes de sécurité doivent, dans la mesure du possible, être confiés à des experts.
Rotation
Les fuites étant inévitables, la bonne pratique consiste à effectuer fréquemment une rotation des clés : en créer une nouvelle et invalider l'ancienne après une certaine durée. Cela impose d'automatiser, côté client, un mécanisme qui demande une nouvelle clé (en authentifiant cette demande avec l'ancienne clé !). Et côté serveur, il faut un mécanisme capable de générer de nouvelles clés à la demande et d'invalider l'ancienne à une date précise.
Et ce genre de chose se révèle toujours plus compliqué qu'il n'y paraît : par exemple, vous voudrez probablement plafonner le nombre de versions valides d'une clé à un instant donné, car disposer de deux versions valides est nécessaire à la rotation, mais en avoir une centaine, c'est une fuite annoncée.
Clés de comptes de service du fournisseur cloud
Pourquoi implémenter soi-même les mécanismes de hachage, de validation, de rotation et d'expiration ? Mieux vaut créer un compte de service, puis télécharger un fichier de clé depuis Google Cloud Identity and Access Management (IAM). Vous pouvez créer une clé depuis la page Compte de service.


Téléchargez le JSON et veillez à définir une date d'expiration — une nouvelle fonctionnalité Google Cloud. Le JSON ressemble à ceci. (Pas d'inquiétude, j'ai soigneusement caviardé le texte 😁, et la clé est déjà désactivée !)
{ "type": "service_account", "project_id": "myproject", "private_key_id": "ded9d97108b…..5cfd179e95e0e1", "private_key": " — — -BEGIN PRIVATE KEY — — -\nMIIEvKIBADABNBg….QDA6woGjE4Q — — -END PRIVATE KEY — — -\n", "client_email": "[email protected]", "client_id": "106482...4210366919", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/kubeflowpipeline%40joshua-playground.iam.gserviceaccount.com"}Limite
Plutôt séduisant, n'est-ce pas ? Mais (vous l'aurez deviné), cette méthode n'offre pas non plus toute la sécurité ni le confort attendus.
Comme pour les clés API maison, le fichier de clé du compte de service peut fuiter : il faut donc le faire tourner. Google vous aide à garantir que les clés expirent et fournit des API pour en obtenir une nouvelle, mais encore faut-il exploiter ces possibilités.
Plus loin, nous expliquerons comment se passer totalement de fichier de clé en intégrant le compte de service directement dans vos applications clientes. Mais voyons d'abord comment exploiter le compte de service, que ce soit via le fichier de clé ou via la version intégrée.
Authentification dans le code applicatif
Pour s'authentifier, le service client utilise son compte de service.
Cela passe par OpenID Connect (OIDC), qui transmet des JSON Web Tokens (JWT) signés. Ces jetons ne sont valides que pour une courte durée — quelques heures, pas des semaines — ce qui limite le risque en cas de fuite.
Vous pouvez le faire au niveau de votre propre code, à l'aide de bibliothèques logicielles côté client et côté serveur.
- D'abord, le client crée un jeton JWT de demande d'accès et le signe en s'appuyant sur une bibliothèque logicielle et la clé du compte de service.
- Il utilise ensuite ce jeton pour demander un autre jeton — un jeton d'accès — au serveur d'authentification Google. Ce dernier vérifie que le compte de service a bien signé le JWT de demande d'accès, puis renvoie le jeton d'accès qui en atteste.
- Le client utilise ce jeton d'accès pour appeler votre microservice.
- Votre microservice s'appuie sur une bibliothèque logicielle pour vérifier que le jeton d'accès est bien validé et signé par le service Google.
Le flux est similaire à celui-ci, à ceci près que le service invoqué est votre propre microservice et non une API Google.

Limite
Couplage avec votre serveur
Cette solution implique du code à l'intérieur de votre serveur. Comme vous pouvez avoir plusieurs microservices aux mêmes besoins, cela revient à maintenir et à sécuriser cette couche d'authentification dans plusieurs bases de code.
Plus loin, nous verrons comment éviter d'insérer ce code dans votre application. Mais voyons d'abord comment se passer totalement de fichiers de clé.
Comptes de service intégrés : GCP
Si vous déployez le service client sur GCP, n'utilisez pas de clé de compte de service. Lancez plutôt le service avec le compte de service souhaité directement intégré.
Par exemple, pour une instance Google Compute Engine (GCE), vous pouvez utiliser :
gcloud compute instances create [INSTANCE_NAME] --service-account [SERVICE_ACCOUNT_EMAIL] ...pour spécifier le compte de service ; le principe est le même pour Cloud Run et les autres services GCP depuis lesquels votre microservice client peut en invoquer d'autres.
Plus de risque de fuite de fichier de clé, puisqu'il n'y en a aucun. À la place, le serveur de métadonnées génère un jeton d'instance signé qui atteste l'identité du compte de service. (Et la requête vers le serveur de métadonnées ne quitte jamais l'instance physique sur laquelle la VM s'exécute.)
Sur Kubernetes
Kubernetes possède son propre système de comptes de service, qui s'inscrit dans un mécanisme d'authentification qui lui est spécifique. Ce système est distinct de la couche IAM de GCP : si votre service client tourne sur Google Kubernetes Engine, utilisez Workload Identity pour associer un compte de service GCP IAM à votre couche Kubernetes. Workload Identity intercepte et relaie de manière transparente tous les appels de GKE vers les API GCP, en les enrichissant du jeton d'accès.
Si votre client est sur Elastic Kubernetes Service d'AWS, vous pouvez également attribuer un rôle IAM pour participer aux flux GCP, comme expliqué dans la section suivante.
Rôles intégrés : AWS et Workload Identity Federation
Si le service client est sur AWS, impossible de le lancer avec un compte de service GCP, mais vous pouvez le lancer avec son équivalent AWS, le Role. Vous lancez votre Lambda avec un rôle d'exécution, ou votre instance EC2 avec un rôle (encapsulé dans un " Instance Profile ").
GCP ne peut pas faire confiance à ce rôle directement : vous utilisez donc Workload Identity Federation (WIF) comme passerelle entre AWS et GCP (article).
Voici le déroulement :
- D'abord, le service client sur AWS utilise son rôle pour signer un jeton (jeton 1).
- Il utilise le jeton 1 pour en demander un autre (jeton 2) signé par AWS IAM.
- Il utilise le jeton 2 pour demander à GCP WIF de signer un jeton d'accès (jeton 3). Google WIF a été préconfiguré pour faire confiance au rôle AWS donné, et puisqu'AWS a certifié que la demande émane de ce rôle, WIF signe et renvoie le jeton d'accès (jeton 3).
- Le service client utilise désormais le jeton 3 exactement comme un service client basé sur GCP utiliserait un jeton d'accès ; le flux se poursuit ensuite à l'identique.

Cela paraît compliqué, mais évite d'envoyer ces chaînes secrètes hautement susceptibles de fuiter aux quatre coins d'internet — ici, vers un autre cloud.
Authentification depuis Google vers un workload AWS
Cet article porte essentiellement sur les services exécutés sur Google, mais gtoken mérite ici une brève mention. Il fait l'inverse de Workload Identity Federation : il authentifie un workload GKE pour interroger les API AWS en lui attribuant une identité AWS temporaire le temps de l'invocation.
Proxy d'authentification : API Gateway
Comme évoqué plus haut, nous restons toutefois limités par le fait que c'est votre propre code applicatif qui effectue l'étape finale, à savoir vérifier que la signature provient bien du principal autorisé par Google. Mieux vaut, dans la mesure du possible, s'appuyer sur des systèmes éprouvés et industrialisés conçus par des experts en sécurité.
Penchez-vous donc sur API Gateway pour disposer d'une couche d'authentification service-à-service robuste et configurable, dont vous n'aurez pas à assurer la maintenance.
Le service fonctionne comme un proxy. Il expose une adresse publique et s'intercale entre le client et votre service serverless sur Cloud Run, Cloud Functions ou App Engine. Il prend en charge la réception du jeton et l'invocation des services Google pour authentifier la requête, avant de la transmettre à votre backend serverless. Pour sécuriser le lien entre l'API Gateway et le backend, Google insère un en-tête spécial qu'il contrôle et qu'aucun attaquant ne peut ajouter.
Limite
API Gateway ne fonctionne cependant pas avec GKE, car il est étroitement intégré aux interfaces exposées par les services serverless gérés par Google.
Proxy d'authentification : Cloud Endpoint
Alors comment s'authentifier pour GKE tout en sécurisant le lien entre la couche d'authentification et votre service backend ? Vous utilisez pour cela Extensible Service Proxy avec Google Cloud Endpoints : un service un peu plus ancien, dont API Gateway s'inspire et qu'il prolonge.
ESP (aujourd'hui en v2) est un conteneur qui expose une adresse publique et authentifie les requêtes. Pour l'utiliser avec GKE, déployez-le en tant que pod dans votre cluster. (Soit dit en passant, même si la documentation indique que seuls les clusters récents VPC-native/IP alias sont pris en charge, cela fonctionne également avec les anciens clusters basés sur les routes.)
Le lien entre ESPv2 et vos services Kubernetes à l'intérieur du cluster doit lui aussi être sécurisé. Vous pouvez le faire au niveau de la couche réseau du cluster en n'exposant aucune adresse publique en dehors de l'ESP, ou recourir à des solutions plus poussées comme le mutual TLS ou Istio Security.
Pour aller encore plus loin, déployez ESPv2 en sidecar : le proxy et votre application (Kubernetes Deployment) cohabitent ainsi dans l'espace " localhost " sécurisé d'un même pod. (Ce n'est pas le mode de déploiement principal d'ESPv2, mais il est pris en charge via cette recette YAML partagée sur le compte GitHub officiel de Google Cloud.)
Pour conclure : sécurisez vos microservices !
Vous ne pouvez pas laisser n'importe qui appeler vos API. Le problème se réglait autrefois par des frontières réseau, ou dans le cloud, par des VPC. Mais les architectures modernes intègrent des comptes cloud différents, plusieurs fournisseurs cloud et des systèmes hors cloud. Et même au sein d'un VPC, vous voulez une couche de sécurité supplémentaire ciblant précisément le lien client-serveur : chaque extrémité doit faire confiance à l'autre.
Pour y parvenir, le défi est le suivant :
- S'authentifier sans laisser traîner des fichiers sensibles susceptibles de fuiter.
- Déléguer l'authentification à des services de confiance ; ne jamais coupler l'authentification au code applicatif.
Dans cet article, j'ai décrit plusieurs façons d'y parvenir, en renforçant progressivement la sécurité et la maintenabilité, mais en exigeant aussi la maîtrise d'un plus grand nombre de technologies. L'investissement dans cet apprentissage en vaut largement la peine — il revient bien moins cher qu'une cyberattaque !