L'architecture multi-tenant est le modele dominant des applications SaaS : une seule instance de l'application sert de multiples clients (tenants) avec leurs propres donnees et configurations. Ce modele offre des avantages considerables en termes de cout et de maintenance, mais il introduit un risque fondamental : la fuite de donnees entre tenants. Si l'isolation entre tenants est defaillante, un client peut acceder aux donnees d'un autre client. Ce guide technique detaille les defis de sécurité du multi-tenant, les stratégies d'isolation, et les méthodes de test pour verifier l'etancheite de votre architecture.
Les modeles d'isolation multi-tenant
Il existe plusieurs modeles d'isolation multi-tenant, chacun avec ses avantages et ses risques de sécurité. Le choix du modele impacte directement le niveau d'isolation, la complexite de l'implementation, et le cout d'exploitation.
Base de donnees partagee avec discrimination par colonne
Schema par tenant
Chaque tenant a son propre schema dans la meme base de donnees. L'application determine le schema a utiliser en fonction du tenant connecte. Ce modele offre une meilleure isolation que la colonne tenant_id car les donnees sont physiquement separees au niveau du schema. Cependant, les risques persistent : une mauvaise gestion de la connexion a la base de donnees peut amener a utiliser le mauvais schema, et les fonctionnalites cross-schema (recherches, rapports agregees) peuvent creer des points de fuite.
Base de donnees par tenant
Chaque tenant a sa propre base de donnees. C'est le modele le plus isole mais aussi le plus couteux a operer. L'isolation est forte car les donnees sont physiquement separees. Les risques residuels sont lies a la gestion des connexions (connection pooling, configuration), aux fonctionnalites de reporting cross-tenant au niveau applicatif, et aux composants partages (cache, file d'attente, stockage de fichiers) qui peuvent creer des canaux de communication entre tenants.
Les vulnérabilités cross-tenant les plus courantes
Fuite via les requetes de base de donnees
Dans le modele de colonne tenant_id, l'oubli du filtre est la cause la plus frequente de fuite cross-tenant. Cela arrive typiquement dans les nouvelles fonctionnalites ou le developpeur oublie d'ajouter le filtre, dans les requetes complexes avec des jointures ou le filtre est present sur la table principale mais pas sur les tables jointes, dans les endpoints d'administration ou le filtre est volontairement omis pour les admins mais la verification du role admin est defaillante, et dans les ORM mal configures ou les scopes par defaut ne sont pas appliques. Un framework comme CASL (authorization library) peut aider a systematiser les filtres d'autorisation, mais il ne couvre pas tous les cas et doit etre correctement configure.
Fuite via le cache
Les systèmes de cache partages (Redis, Memcached) sont une source frequente de fuites cross-tenant. Si les cles de cache n'incluent pas le tenant_id, un tenant peut recevoir des donnees cachees provenant d'un autre tenant. Exemple : le cache contient le résultat de la requete "liste des factures de l'utilisateur X". Si la cle de cache est "factures:user:123" au lieu de "factures:tenant:A:user:123", le meme utilisateur ID sur un autre tenant pourrait recevoir les factures du mauvais tenant.
Fuite via le stockage de fichiers
Les fichiers uploades par les tenants (documents, images, exports) sont souvent stockes dans un bucket partage (S3, Azure Blob). Si les chemins de fichiers sont previsibles ou si les controles d'acces au niveau du fichier ne tiennent pas compte du tenant, un tenant peut acceder aux fichiers d'un autre. Les URLs signees (pre-signed URLs) doivent inclure une verification du tenant au moment de la generation, pas seulement au moment de l'upload.
Fuite via les files d'attente et les événements
Dans les architectures event-driven, les messages dans les files d'attente (RabbitMQ, SQS, Kafka) peuvent contenir des donnees de differents tenants. Si les consumers ne verifient pas le tenant du message, ils peuvent traiter des donnees d'un tenant au nom d'un autre. Les topics ou queues partages sans filtrage par tenant sont un vecteur de fuite souvent oublie.
Fuite via les webhooks et integrations
Les webhooks sortants (notifications vers les systèmes des tenants) doivent inclure uniquement les donnees du tenant destinataire. Une erreur de routage de webhook peut envoyer les donnees d'un tenant vers le système d'un autre. De meme, les integrations avec des services tiers (CRM, ERP) doivent verifier que les donnees echangees appartiennent bien au tenant configure pour cette integration.
Strategies de prevention
La prevention des fuites cross-tenant repose sur plusieurs couches de defense complementaires.
Row-Level Security (RLS)
La Row-Level Security est une fonctionnalite des bases de donnees modernes (PostgreSQL, SQL Server, Oracle) qui applique automatiquement des filtres de lignes en fonction du contexte de la session. En configurant une politique RLS basee sur le tenant_id de l'utilisateur connecte, la base de donnees elle-meme garantit qu'aucune requete ne peut acceder aux donnees d'un autre tenant, meme si le code applicatif oublie le filtre. C'est la couche de defense la plus robuste car elle est independante du code applicatif.
Middleware de tenant
Un middleware centralise qui extrait le tenant_id du contexte de la requete (token JWT, header, sous-domaine) et le propage a toutes les couches de l'application est essentiel. Ce middleware doit etre applique a tous les endpoints sans exception. Le tenant_id ne doit jamais etre pris directement des donnees de la requete (body, query params) mais toujours du contexte d'authentification verifie.
Tests automatisés d'isolation
Comment tester l'isolation multi-tenant
Le test d'isolation multi-tenant est l'un des types de tests de sécurité les plus importants pour les editeurs SaaS, et l'un des plus difficiles a automatisér avec des outils classiques.
La methodologie de test comprend plusieurs phases. Premierement, creer au moins deux comptes sur des tenants differents avec des donnees identifiables (noms, descriptions qui permettent de determiner facilement a quel tenant appartient une donnee). Deuxiemement, cartographier tous les endpoints accessibles et identifiér ceux qui manipulent des identifiants de ressources. Troisiemement, pour chaque endpoint, tenter d'acceder aux ressources du tenant A avec la session du tenant B, en utilisant les identifiants de ressources du tenant A. Quatriemement, verifier egalement les canaux secondaires : cache, fichiers, exports, webhooks, endpoints de recherche et de listing.
Multi-tenant et conformité
Pour un editeur SaaS, la capacité a demontrer l'isolation de ses tenants est un avantage concurrentiel majeur. Les rapports de pentest automatisé avec des preuves de tests d'isolation constituent un element de confiance precieux pour les clients entreprise qui évaluént votre solution.
Bonnes pratiques architecturales
Plusieurs bonnes pratiques architecturales renforcent l'isolation multi-tenant. Utilisez la Row-Level Security comme filet de sécurité au niveau de la base de donnees. Centralisez la gestion du contexte tenant dans un middleware unique plutot que de la distribuer dans chaque handler. Prefiez toutes les cles de cache avec le tenant_id. Separez les buckets de stockage par tenant ou utilisez des politiques d'acces granulaires. Loguez le tenant_id dans chaque trace et chaque log pour faciliter le debugging et l'audit. Testez l'isolation a chaque deploiement avec des tests automatisés et des pentests reguliers.
Questions frequentes
Quel modele d'isolation choisir pour ma plateforme SaaS ?
Le choix depend de vos contraintes. La colonne tenant_id est la plus simple et la moins couteuse mais nécessité une discipline rigoureuse dans le code. Le schema par tenant offre un bon compromis entre isolation et cout. La base par tenant offre la meilleure isolation mais au cout operationnel le plus eleve. Pour la plupart des SaaS en demarrage, la colonne tenant_id avec RLS est le meilleur choix.
La Row-Level Security est-elle suffisante pour garantir l'isolation ?
La RLS est un filet de sécurité extremement puissant mais elle ne couvre que la couche base de donnees. Les fuites via le cache, le stockage de fichiers, les files d'attente, et les integrations ne sont pas couvertes par la RLS. Une stratégie d'isolation complete doit combiner la RLS avec des controles au niveau applicatif pour toutes les couches.
Comment détectér les fuites cross-tenant en production ?
Implementez un monitoring des acces cross-tenant : chaque acces a une ressource doit etre logue avec le tenant_id de l'utilisateur et le tenant_id de la ressource. Une alerte doit se declencher si ces deux valeurs different. Ce monitoring détecté les fuites en production, mais la prevention par les tests est toujours preferable a la détection.
Les microservices rendent-ils l'isolation plus difficile ?
Oui. Dans une architecture microservices, le contexte tenant doit etre propage de service en service via les headers de requete ou les metadata des messages. Chaque service doit verifier l'isolation de maniere independante. La complexite augmente lineairement avec le nombre de services. Un API gateway qui centralise la validation du tenant et le propage aux services downstream peut simplifier cette gestion.
Jordan Fredj, Fondateur Hacksessible -
Testez l'isolation de vos tenants
Les agents IA d'Hacksessible testent systematiquement l'isolation multi-tenant sur chaque endpoint. Verifiez l'etancheite de votre architecture.