Loïc BoninLB
← Veille

ia / securite

Agent IAM : sécuriser l'identité de vos agents en production

11 juillet 2026·5 min de lecture


Introduction à l'Agent IAM

Quand votre agent appelle un serveur MCP, invoque une API tierce, ou délègue une tâche à un sous-agent, une question simple se pose rarement assez tôt : quelle identité présente-t-il réellement, et qui peut la vérifier ? La plupart des architectures d'agents que l'on construit aujourd'hui héritent encore des réflexes du monde des microservices — une clé API partagée, un jeton statique, un compte de service générique. Ce modèle craque dès qu'un agent devient autonome, persistant, et capable d'agir au nom d'un utilisateur ou d'un autre agent.

Cet article aborde l'Agent IAM comme une brique d'infrastructure à prendre en compte et concevoir dès l'architecture.

Pourquoi un agent n'est pas une simple clé API

Dans une architecture de microservices classique, deux répliques du même service sont interchangeables : elles exécutent le même code, sans état, et partager une identité de service entre elles ne pose pas de problème de fond. Un agent IA casse cette hypothèse. Deux instances du même agent, déployées à partir du même code, peuvent développer des comportements différents selon leur contexte, leur mémoire accumulée et l'historique de leurs interactions.

Cette différence a une conséquence directe sur la conception de l'identité : deux répliques Kubernetes d'un même agent ne devraient pas partager la même identité cryptographique, contrairement à ce qu'on ferait pour un microservice stateless. Chaque instance d'agent doit pouvoir être identifiée, tracée et révoquée individuellement au niveau de l'instance elle-même.

SPIFFE/SPIRE : un standard prometteur

Avant d'aller plus loin, un petit détour définitionnel s'impose, car ces sigles reviennent partout dans les discussions sur la sécurité cloud-native.

SPIFFE (Secure Production Identity Framework For Everyone) n'est pas un logiciel, mais une spécification : elle décrit un format d'identité et des règles pour l'attribuer à une charge de travail (un "workload"), qu'il s'agisse d'un conteneur, d'un service, ou aujourd'hui d'un agent IA. C'est l'équivalent d'un standard de format de carte d'identité, sans préciser qui la délivre concrètement.

SPIRE est l'implémentation de référence qui rend SPIFFE concret : c'est le "service d'état civil" qui émet réellement ces identités, sous forme de certificats, et qui les renouvelle automatiquement.

Dans la pratique la plus courante aujourd'hui, on ne déploie pas SPIRE directement : on passe par un service mesh comme Istio, qui intègre SPIFFE en arrière-plan pour simplifier la gestion réseau dans Kubernetes. C'est là que le bémol apparaît. Quand un pod démarre sous Istio, le service mesh échange automatiquement le jeton du compte de service Kubernetes du pod contre un certificat SPIFFE, sous une forme du type : spiffe://mondomaine.io/agent/support-client/instance-global

Le point à bien comprendre ici : cette identité est rattachée au compte de service Kubernetes (instance-global), pas au pod individuel. Concrètement, si vous déployez quatre répliques du même agent pour répartir la charge, les quatre pods reçoivent exactement la même identité SPIFFE :

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mon-domaine-agent
spec:
replicas: 4
template:
spec:
serviceAccountName: mon-domaine-agent-sa
# Les 4 pods reçoivent tous la même identité :
# spiffe://mondomaine.io/agent/support-client/instance-global

Pour un microservice classique, sans état et sans comportement variable, ce n'est pas un problème : les quatre répliques font strictement la même chose, alors autant qu'elles partagent la même identité. Le souci, c'est que ce n'est plus vrai pour un agent. Reprenons l'exemple de l'agent de trading évoqué plus haut : si les quatre répliques partagent la même identité SPIFFE, impossible de savoir, une fois l'incident détecté, laquelle des quatre instances a réellement pris la décision problématique. Du point de vue des logs et de l'audit, les quatre pods sont indiscernables.

Plusieurs plateformes ont déjà industrialisé une solution pour corriger ce défaut, avec des approches légèrement différentes.

Google Cloud IAM Agent Identity attribue une identité SPIFFE unique à chaque agent individuel déployé, et non plus au niveau du compte de service partagé par toutes les répliques. Concrètement, chaque agent reçoit son propre identifiant, mappé sur la ressource cloud précise qui l'héberge, et un certificat renouvelé automatiquement toutes les 24 heures. La documentation officielle est explicite sur ce point : "contrairement aux comptes de service, les identités d'agent ne sont pas partagées par plusieurs charges de travail par défaut, ne peuvent pas être empruntées, et ne permettent pas aux développeurs de générer des clés à longue durée de vie". Un mécanisme de "token binding" va plus loin : chaque jeton d'accès est cryptographiquement lié au certificat unique de l'agent qui l'a demandé, ce qui rend un jeton volé inutilisable sans posséder aussi la clé privée correspondante (une protection que ne permet pas une clé API classique). Google distingue par ailleurs deux modes d'action: l'agent peut agir avec sa propre autorité (sa propre identité), ou avec une autorité déléguée par l'utilisateur via un flux OAuth dédié.

Ping Identity a annoncé une approche complémentaire avec Agent IAM Core, dont le principe directeur diffère légèrement : plutôt que de sécuriser uniquement la connexion initiale de l'agent (comme le fait un IAM traditionnel), la plateforme déplace la frontière de sécurité vers le moment de l'action elle-même. Chaque agent est enregistré comme une identité de premier ordre, rattachée à un propriétaire humain, et chaque action qu'il entreprend est évaluée en temps réel selon le contexte, la politique en vigueur et un score de risque et non seulement au moment où l'agent s'authentifie. En bref, l'outil applique une délégation explicite plutôt qu'une usurpation d'identité.

Le vrai clivage aujourd'hui n'est donc plus une "identité unique par instance possible ou pas", mais plutôt quand est-ce qu'on aura une construction standard bien défini respecté par les differents acteurs.

MCP : sécuriser les appels d'outils

Une fois la question de l'identité de workload posée, reste un problème plus quotidien pour un développeur : comment contrôler ce qu'un agent peut faire concrètement quand il appelle un outil, par exemple un serveur MCP (Model Context Protocol) ?

MCP s'appuie sur OAuth 2.1, le même protocole qui sécurise déjà une grande partie du web moderne.

Le principe général d'implémentation côté serveur MCP se décompose en quatre étapes :

  1. Exposer les métadonnées OAuth du serveur — un endpoint .well-known/oauth-protected-resource qui indique où se trouve le serveur d'autorisation, pour que n'importe quel client MCP puisse découvrir automatiquement comment s'authentifier.
  2. Rediriger vers le serveur d'autorisation — le client (votre agent) est redirigé vers l'IdP configuré, avec PKCE activé pour éviter l'interception du code d'autorisation.
  3. Valider les jetons côté serveur — chaque appel d'outil MCP doit vérifier la signature du JWT reçu, son expiration, et l'audience (aud) pour s'assurer que le jeton a bien été émis pour ce serveur précis.
  4. Appliquer des permissions par scope — chaque outil exposé par le serveur MCP est associé à un ou plusieurs scopes OAuth, pour qu'un agent avec un jeton à faible privilège ne puisse pas invoquer un outil sensible.

Voici un exemple simplifié de middleware de validation JWT pour un serveur MCP :

javascript
import { jwtVerify, createRemoteJWKSet } from "jose";
 
// createRemoteJWKSet gère automatiquement le cache et la rotation des clés,
// avec une limite de fréquence de récupération (cooldown) intégrée.
const JWKS = createRemoteJWKSet(
new URL("https://votre-idp.com/.well-known/jwks.json"),
);
 
async function mcpAuthMiddleware(req, res, next) {
const token = req.headers.authorization?.replace("Bearer ", "");
if (!token) {
return res.status(401).json({ error: "missing_token" });
}
 
try {
const { payload } = await jwtVerify(token, JWKS, {
issuer: "https://votre-idp.com",
audience: "mcp-server-support-client",
algorithms: ["RS256"],
clockTolerance: 30, // tolérance de 30s pour les décalages d'horloge
});
 
// Vérification du scope requis par l'outil appelé
const requiredScope = req.mcpTool?.requiredScope;
const scopes = payload.scope?.split(" ") || [];
if (requiredScope && !scopes.includes(requiredScope)) {
return res.status(403).json({ error: "insufficient_scope" });
}
 
req.agentIdentity = payload;
next();
} catch (err) {
return res.status(401).json({ error: "invalid_or_expired_token" });
}
}

Ce squelette illustre le principe central : chaque appel d'outil passe par une vérification d'identité et de scope avant exécution, jamais après. C'est exactement le même réflexe de sécurité qu'on applique à une API REST classique, simplement transposé au contexte des appels d'outils agentiques.

La délégation : agir au nom d'un utilisateur ou d'un autre agent

Un agent qui agit pour le compte d'un utilisateur, par exemple, un assistant qui consulte votre boîte mail ou modifie un document en votre nom, ne doit jamais stocker votre mot de passe ni recevoir un accès permanent à votre compte. C'est le rôle du flux OAuth 2.0 On-Behalf-Of (OBO), déjà bien connu dans le monde des applications d'entreprise, et désormais adapté aux architectures d'agents.

Le principe : votre application obtient un jeton initial représentant l'utilisateur, puis l'échange auprès du serveur d'autorisation contre un second jeton, plus restreint, destiné spécifiquement à l'agent. L'agent n'a alors accès qu'à ce que ce jeton dérivé autorise, jamais à l'intégralité des droits de l'utilisateur d'origine. Ce mécanisme devient particulièrement important dès qu'un agent délègue lui-même une sous-tâche à un autre agent : chaque niveau de délégation devrait réduire le périmètre d'accès, jamais l'élargir.

Cette logique de jetons est une bonne protection contre un scénario de compromission en cascade : si un sous-agent est compromis, l'attaquant n'hérite que d'un sous-ensemble restreint des droits initiaux, pas de l'identité complète de l'utilisateur.

En pratique

En pratique, sécuriser l'identité de vos agents revient à appliquer cinq réflexes dès la conception de l'architecture, (en utilisant des bibliothèques et non tout réécrire), plutôt qu'à les ajouter après un premier incident :

  • Attribuer une identité unique et vérifiable à chaque instance d'agent, pas à chaque déploiement.
  • Limiter systématiquement les scopes à ce dont l'agent a réellement besoin pour la tâche en cours, jamais plus.
  • Préférer des jetons à courte durée de vie, renouvelés automatiquement, plutôt que des clés API statiques.
  • Valider systématiquement la signature, l'expiration et l'audience de chaque jeton avant d'exécuter un outil.
  • Réduire le périmètre d'accès à chaque niveau de délégation, jamais l'inverse.

Ce dernier point rejoint un principe que vous avez peut-être déjà croisé sous une autre forme : le gate d'approbation humaine (write_approval) que propose Hermes Agent avant d'écrire en mémoire est un bon exemple de contrôle applicatif complémentaire à l'identité protocolaire: l'un vérifie qui agit, l'autre vérifie ce qui est écrit. Les deux couches sont nécessaires, et aucune ne remplace l'autre.

Conclusion

L'identité d'un agent IA n'est pas qu'un sujet de conformité à cocher pour un audit de sécurité : c'est une brique d'infrastructure, au même titre que l'authentification de vos microservices. La différence tient à la nature même des agents, non déterministes, potentiellement persistants, capables de déléguer à leur tour. Traiter leur identité avec les réflexes qu'on appliquait déjà aux clés API et aux comptes de service ne suffit plus : SPIFFE/SPIRE pour l'identité cryptographique, OAuth 2.1 pour l'autorisation des appels d'outils, et des jetons dérivés à portée décroissante pour la délégation forment aujourd'hui la base technique la plus solide pour construire des agents que l'on peut réellement faire confiance à grande échelle.

Sources et ressources utiles :


IABonnes pratiquesAgent