Aller au contenu

Auditer la couverture réelle du mTLS service mesh

Auditer la couverture réelle du mTLS service mesh

Section intitulée « Auditer la couverture réelle du mTLS service mesh »

Un service mesh promet du chiffrement mutuel entre services, des autorisations réseau fines et une trace de chaque appel. La promesse tient, mais seulement à l’intérieur du périmètre effectivement intercepté, identifié et soumis à une politique restrictive. Le compromis central est brutal : on gagne une couche de contrôle homogène sans modifier le code, on paie une infrastructure d’identité, de routage et d’exploitation qui ne tolère pas l’approximation.

→ Lire l’explication complète de la marmotte

Le mTLS (mutual Transport Layer Security, sécurité de la couche transport avec authentification réciproque) chiffre un flux et impose que client et serveur présentent chacun un certificat. Dans Istio, un proxy Envoy est généralement injecté à côté de chaque charge applicative. Dans Linkerd, le proxy Linkerd joue le même rôle. Les processus applicatifs continuent souvent à parler en HTTP (Hypertext Transfer Protocol) local, tandis que les proxies établissent le canal chiffré.

Cette architecture apporte trois propriétés distinctes, qu’il faut cesser de mélanger :

  1. Confidentialité et intégrité du flux intercepté : un acteur placé sur le réseau du cluster ne lit ni ne modifie silencieusement le trafic protégé, sous réserve d’algorithmes et de versions maintenus.
  2. Authentification de la charge distante : l’identité provient normalement du compte de service Kubernetes associé à la charge, puis est portée par un certificat de charge. Ce n’est pas l’identité humaine, ni l’identité métier complète.
  3. Contrôle d’accès au niveau du trafic : une politique peut autoriser service-a à joindre service-b sur un port, une méthode ou une route, selon les capacités du mesh et du protocole observé.

La propriété ne porte donc pas sur « tous les services ». Elle porte sur les connexions qui traversent deux proxies configurés, dont les identités sont émises et validées correctement, et auxquelles une politique applicable interdit effectivement le reste. Une slide qui résume cela par « zero trust dans Kubernetes » fait gagner du temps en réunion, puis en fait perdre beaucoup pendant l’incident.

Le mode permissif est le piège classique. Istio peut accepter simultanément du trafic chiffré mutuellement et du trafic non chiffré afin de permettre une migration. Ce mode est défendable pendant une bascule contrôlée, avec une date de sortie et une mesure de trafic résiduel. Le laisser indéfiniment revient à installer une serrure qui accepte aussi les portes sans serrure. Une politique PeerAuthentication stricte doit devenir la norme dès que la couverture est démontrée.

Le mesh ne remplace pas les contrôles décrits dans l’architecture cybersécurité. Il ne décide pas si un appel métier est légitime au regard d’un dossier, d’un tenant ou d’une délégation. Il authentifie une charge et contraint un chemin réseau. L’autorisation métier reste dans l’application ou dans un composant d’autorisation dédié. De même, il ne corrige pas un compte de service Kubernetes trop puissant, sujet à traiter dans la gouvernance de la plateforme, pas dans un manifeste de mesh décoré de labels.

Le trafic sortant est le premier angle mort. Un proxy peut chiffrer le flux entre une charge et une passerelle de sortie, appelée egress gateway. Après cette passerelle, la protection dépend du protocole, de la validation du certificat distant et de la politique appliquée. Un appel vers une interface externe en HTTPS (HTTP Secure) garde son chiffrement TLS (Transport Layer Security) applicatif, mais le mesh ne crée pas magiquement une identité mutuelle chez le fournisseur externe.

Sans registre explicite des destinations sortantes, beaucoup de déploiements laissent les proxies joindre toute adresse accessible. Cette configuration rend l’observabilité bavarde, pas la sortie contrôlée. Une charge compromise peut alors exfiltrer vers un nom de domaine quelconque via HTTPS, ou contourner une passerelle en utilisant une adresse IP. Le chiffrement ne distingue pas une mise à jour légitime d’une fuite bien emballée.

La règle à retenir est nette : interdire par défaut les sorties directes, déclarer les destinations externes attendues, puis forcer leur passage par une passerelle de sortie lorsque le mesh le permet. Cette passerelle doit journaliser le nom demandé, l’identité source, la décision et le résultat. Pour les partenaires qui exigent un certificat client, stocker la clé dans un mécanisme de secrets gouverné, limiter sa lecture au composant de sortie et planifier sa rotation. Une clé client déposée en variable d’environnement dans chaque charge est une forme de distribution de tracts, avec moins de papier.

La seconde fuite est plus banale : une charge non injectée. L’injection automatique repose souvent sur un label de namespace, tel que istio-injection=enabled, ou sur un mécanisme d’admission. Une exception de namespace, un déploiement avec injection désactivée, un proxy en échec de démarrage ou un workload particulier suffisent à sortir du périmètre. Les tâches éphémères, jobs, opérateurs et outils de diagnostic sont fréquemment oubliés, précisément parce qu’ils semblent temporaires. En sécurité, « temporaire » est un mot qui a une espérance de vie étonnante.

Un service sans proxy peut appeler un autre service si les politiques réseau Kubernetes et les règles du mesh ne ferment pas cette voie. Le mTLS ne protège alors rien sur ce segment. La réponse n’est pas de multiplier les exceptions dans le mesh : combiner une politique de réseau Kubernetes restrictive avec le mode mTLS strict. La première bloque les chemins non prévus au niveau IP (Internet Protocol) et port, le second impose l’authentification cryptographique aux chemins autorisés.

Politiques d’autorisation : refuser par défaut ou ne rien protéger

Section intitulée « Politiques d’autorisation : refuser par défaut ou ne rien protéger »

Les politiques d’autorisation du mesh sont évaluées par le proxy destinataire. Une règle qui autorise une identité source donnée n’a de sens que si cette identité ne peut pas être usurpée depuis un flux non chiffré. D’où l’ordre obligatoire : activer mTLS strict, puis déployer les autorisations. Déployer l’autorisation avant de supprimer le trafic non chiffré peut laisser une règle fondée sur une identité absente ou ambiguë.

La politique doit commencer par un refus implicite ou explicite pour chaque charge sensible. Dans Istio, l’absence d’AuthorizationPolicy n’est pas une posture « prudente », c’est généralement une ouverture totale au trafic que le routage rend possible. Il faut ensuite autoriser par couple source, destination et port, puis ajouter méthode et chemin HTTP seulement quand le protocole est réellement décodé.

Les règles HTTP ne s’appliquent pas à du trafic chiffré de bout en bout que le proxy ne termine pas, ni à un protocole opaque. Dans ce cas, l’autorisation se limite à l’identité de source et au port. Présenter un filtrage de routes HTTP comme un contrôle universel est une erreur de conception, pas une nuance de syntaxe YAML. Les données transportées restent aussi visibles par l’application destinataire : le mesh ne protège pas contre un service légitime mais compromis.

L’identité de charge dépend du compte de service Kubernetes. Changer ce compte, réutiliser le même compte entre applications ou accorder la possibilité de créer des charges avec ce compte change immédiatement le périmètre de confiance. La sécurité du mesh dépend donc du contrôle d’admission, du RBAC (Role-Based Access Control, contrôle d’accès fondé sur les rôles) Kubernetes et de la protection des jetons de compte de service. Le lien avec IAM dans le cloud est direct : une identité de machine n’est pas moins critique parce qu’elle n’a pas de photo dans un annuaire.

Audit de couverture mTLS : mesurer le trafic, pas les manifestes

Section intitulée « Audit de couverture mTLS : mesurer le trafic, pas les manifestes »

L’audit doit comparer quatre inventaires : charges attendues, charges réellement exécutées, proxies effectivement présents et flux réellement observés. Un manifeste déclaré ne prouve rien. Un label de namespace ne prouve presque rien. Une connexion acceptée en mTLS strict avec une identité attendue commence à prouver quelque chose.

Commencer par exporter la liste des pods actifs, leur compte de service, les namespaces et l’état d’injection. Recouper cette liste avec les déploiements, jobs planifiés, daemonsets et opérateurs. Toute charge réseau sans proxy doit être classée : hors périmètre assumé, exemptée temporairement avec échéance, ou anomalie. L’absence de classification est une anomalie, même si l’application « marche très bien ».

Vérifier ensuite la posture par namespace et par charge :

  • une politique mTLS stricte couvre les destinations internes ;
  • les politiques d’autorisation ont un refus par défaut, puis des autorisations nominatives ;
  • les services exposés utilisent des comptes de service dédiés ;
  • les exceptions permissives sont limitées, datées et observées ;
  • les destinations externes déclarées correspondent aux appels détectés ;
  • les flux directs vers Internet, les adresses IP brutes et les résolutions de noms anormales déclenchent une alerte.

Les métriques de proxy permettent de mesurer les connexions chiffrées, les refus et les destinations. Les traces distribuées révèlent les dépendances, mais ne suffisent pas : un flux bloqué ou hors mesh ne produit pas forcément une trace exploitable. Conserver aussi les journaux de décision des proxies et de la passerelle de sortie. L’observabilité sans politique de rétention ni corrélation d’identité produit une décharge de données, ce qui est une façon très chère de ne pas savoir.

Tester enfin depuis une charge de validation placée dans un namespace ordinaire : tentative d’appel vers une destination non autorisée, vers une charge sans proxy, vers une adresse externe non déclarée et vers un service autorisé. Chaque résultat attendu doit être observé dans les métriques et les journaux. Les tests de chemin interdit comptent autant que les tests fonctionnels, car un contrôle absent réussit généralement avec une stabilité remarquable.

La commande suivante liste les pods en cours d’exécution et cherche le conteneur proxy istio-proxy. Elle ne remplace pas l’inventaire applicatif, mais elle détecte immédiatement une partie des charges sorties du mesh.

Fenêtre de terminal
# Requiert kubectl, jq et des droits de lecture sur tous les namespaces.
# Affiche namespace, pod, compte de service et présence du proxy Istio.
kubectl get pods -A \
--field-selector=status.phase=Running \
-o json |
jq -r '
.items[]
| {
namespace: .metadata.namespace,
pod: .metadata.name,
serviceAccount: .spec.serviceAccountName,
injected: ([.spec.containers[].name] | index("istio-proxy") != null)
}
| select(.injected == false)
| "\(.namespace)\t\(.pod)\tserviceAccount=\(.serviceAccount)\tSANS_PROXY"
'

Toute ligne produite doit recevoir un traitement explicite. Les composants de plan de contrôle, les agents de nœud ou certains jobs d’administration peuvent être exclus, mais une exclusion doit être documentée avec sa justification, son propriétaire et sa date de révision. Ne pas injecter un proxy dans certains composants est parfois requis. Ne pas savoir lesquels ne l’est jamais.

L’audit doit être exécuté après chaque changement de politique, de version du mesh, de modèle de déploiement ou de mécanisme d’injection. Les mises à jour de proxy sont aussi un sujet d’exploitation : maintenir la compatibilité avec les versions Kubernetes, suivre les vulnérabilités des images et déployer progressivement. La rotation automatique des certificats réduit le risque de clé longue durée, mais ne révoque pas instantanément les sessions déjà établies ni une charge compromise qui possède encore une identité valide.

Exploitation : autorité de certification, rotation et reprise

Section intitulée « Exploitation : autorité de certification, rotation et reprise »

Le mesh repose sur une autorité de certification interne qui émet les certificats des charges. Protéger sa clé racine et ses clés intermédiaires est non négociable. Une clé d’autorité exportable dans un secret Kubernetes accessible à trop de comptes transforme la chaîne de confiance en décoration cryptographique. Selon les exigences, ancrer les clés d’autorité dans un HSM (Hardware Security Module, module matériel de sécurité) ou dans un service de gestion de clés avec contrôle d’accès, journalisation et rotation.

La durée de vie courte des certificats limite l’exposition d’une clé de charge volée, mais accroît la dépendance au plan de contrôle. Tester la rotation en charge, l’indisponibilité temporaire de l’autorité et le redémarrage des proxies. Un proxy ne doit pas tomber parce qu’il ne peut pas renouveler immédiatement son certificat, mais il ne doit pas non plus continuer indéfiniment avec une identité expirée.

Sauvegarder la configuration du mesh, les politiques, les ancres de confiance et les paramètres de l’autorité. Une restauration qui recrée une nouvelle autorité sans plan de transition casse les relations de confiance existantes. Une restauration qui réimporte sans contrôle une clé d’autorité compromise les rétablit toutes. Le plan de reprise doit préciser la procédure de remplacement de l’autorité, de redéploiement des proxies, de rotation des certificats et de validation des flux. Le mesh fournit le mécanisme ; la discipline d’exploitation doit venir d’ailleurs.

Sans audit de couverture, la posture affichée reste une hypothèse : personne ne peut établir, à un instant donné, quelles connexions étaient réellement chiffrées et authentifiées. Lors d’une investigation, l’analyse du périmètre compromis devient impossible à borner, puisque rien ne distingue un flux protégé d’un flux resté en clair faute de proxy. Les attestations de conformité s’appuient alors sur des manifestes et des labels, éléments qu’un déploiement dérogatoire ou un job planifié contredit sans alerte. La dette s’accumule aussi côté exploitation : les exceptions non datées se figent, les comptes de service partagés brouillent l’attribution des appels, et chaque montée de version du mesh se fait sans référence de comparaison. La remédiation coûte davantage plus tard, car il faut reconstituer l’inventaire des flux avant de durcir quoi que ce soit.

Un service mesh ajoute un programme de contrôle auprès de chaque application qui communique sur le réseau. Quand une application appelle une autre application, les deux programmes vérifient leur identité à l’aide de certificats, puis créent une communication chiffrée. Le certificat est délivré par une autorité interne, qui décide quelles identités peuvent recevoir un certificat.

Le système peut aussi appliquer des règles : telle application a le droit de joindre telle autre, sur tel port ou pour telle requête. Il enregistre les appels, les refus et parfois les erreurs. Cela aide à voir les dépendances réelles entre applications.

La protection ne fonctionne que si les deux applications passent par ce système. Une application installée sans le programme de contrôle peut envoyer du trafic sans cette vérification. Une sortie vers Internet peut également quitter le périmètre protégé : le service mesh peut surveiller et filtrer cette sortie, mais il ne contrôle pas automatiquement le serveur externe.

Les règles doivent commencer par refuser les accès non prévus. Si elles autorisent tout par défaut, le chiffrement cache le trafic mais ne limite pas les communications. Il faut donc vérifier régulièrement quelles applications sont couvertes, quels appels sont autorisés et quelles sorties existent. Il faut aussi protéger les clés qui servent à créer les certificats, tester leur renouvellement et préparer la reprise après une panne.

À lire aussi

Pages voisines

: les deux pages se citent l’une l’autre.