Passer

Surconsommation de tokens dans HashiCorp Vault : anticiper et remédier les chutes de performance

Le nombre de tokens dans un cluster Hashicorp Vault et la fréquence de leur génération sont deux indicateurs essentiels de l’état du service fourni par Vault. Un grand nombre de requêtes envoyées à un cluster Vault partagé par des milliers de consommateurs entraînera nécessairement une augmentation significative du nombre de tokens. L’utilisation de méthodes d’authentification sans spécifier de durée de vie (TTL) ou avec des TTL longs et non maîtrisés affecte directement les performances du cluster. HashiCorp Vault offre une liste de métriques et d’outils permettant de surveiller efficacement le service Vault, ainsi que des limites pour renforcer le contrôle de la consommation par les utilisateurs.

Cet article requiert une connaissance approfondie de Hashicorp Vault afin de profiter pleinement des diverses solutions abordées, voyons cela ensemble dans les sections suivantes.

Authentification sur HashiCorp Vault

Le mécanisme d’authentification sur Vault se fait par l’intermédiaire d’un jeton (« token »), qui peut être généré avec une méthode d’authentification préconfigurée sur Vault.

Il existe des paramètres communs pour ces méthodes d’authentification, que l’on peut configurer, notamment token_ttl et token_type :

  • token_ttl représente la durée de vie d’un token avant son expiration (par défaut 32 jours).
  • token_type peut être soit un token batch soit un token de service (par défaut c’est un token service).

Lorsqu’un cluster Vault est partagé entre plusieurs clients, le nombre de tokens actifs continue d’augmenter, ce qui remplit progressivement le stockage. Cela peut entraîner une dégradation des performances, se manifestant par des temps de réponse plus longs, voire une interruption totale du service pour les utilisateurs.

Génération de token avec HashiCorp Vault

Pour récupérer un secret sur Vault, chaque utilisateur a besoin d’un token. Dans un cluster avec des milliers de clients qui effectuent des opérations telles que la lecture, la création, la modification ou la suppression de secrets, le nombre de tokens peut devenir très important.

Un client peut être soit un humain soit un automate ; ces derniers  sont généralement responsables d’une génération de trafic importante sur un cluster Vault, nécessitant donc un nombre important de tokens.

HashiCorp recommande de ne pas dépasser le seuil de 256 000 tokens actifs sur un cluster Vault.

Dans une grande organisation, il est facile d’atteindre  et dépasser cette limite, car chaque client ne voit que sa consommation, qui lui paraît normale à son échelle.

Pour simplifier, prenons un cluster avec 1 000 clients, chacun possédant 5 applications accédant à Vault toutes les 15 minutes pour récupérer un secret (dans le monde réel, il peut y avoir des appels par minute pour plusieurs secrets). Supposons également que le TTL est celui par défaut (32 jours). 

Pour le premier appel, nous aurons 1 000 * 5 = 5 000 tokens actifs. Ces 5 000 tokens restent valides pendant 32 jours. Pour le deuxième appel, le nombre de tokens actifs passe à 10 000. Après une journée d’activité, soient  96 appels (1 appel / 15 min équivaut à 96 appels / 24h), nous aurons 480 000 (96 appels * 5 000 applications) tokens actifs sur le cluster. En maintenant ce TTL et cette activité, le cluster Vault va gérer ce nombre important de tokens ainsi que les autres opérations en parallèle, ce qui va provoquer une forte dégradation de sa  performance.

Signes révélateurs d’une dégradation de performance sur un cluster HashiCorp Vault 

Pour ce type de consommation, une dégradation de performance peut se manifester sous plusieurs aspects : 

  • Augmentation des temps de réponse, que ce soit interne au cluster ou aux requêtes client.
  • Augmentation des consommations système (CPU, RAM, lecture/écriture disque).
  • Perte de synchronisation entre les nœuds du cluster pouvant entraîner une perte du quorum.
  • Pour la version Enterprise, perte de synchronisation avec le cluster de Disaster Recovery.

Causes racines de dégradation de performance sur un cluster HashiCorp Vault

Cette dégradation de performance est principalement causée par le grand nombre de tokens actifs générés. Parmi les facteurs contribuant à maintenir un nombre élevé de tokens actifs, on peut notamment citer l’implémentation par les clients d’un TTL trop long ou mal adapté à leurs besoins . Par exemple, si 20 000 tokens sont générés avec un TTL de 12 heures pour un usage  unique, ils viennent alors  s’ajouter aux autres tokens générés et aux opérations en cours pendant 12 heures. En revanche, si ces mêmes 20 000 tokens étaient générés avec un TTL de 5 minutes, ils ne seraient rapidement plus présents dans le cluster après cette période.

Comme nous l’avons mentionné plus haut, si un utilisateur ne spécifie pas de TTL lors de la définition d’une méthode d’authentification, Vault utilise un paramètre par défaut de 32 jours.

Les utilisateurs ne prévoient souvent ni la réutilisation ni la révocation de leurs tokens dans leur code et applications. L’usage  habituellement observé est plutôt la génération d’un token, son utilisation, puis la génération d’un nouveau , et ainsi de suite, ce qui contribue à accumuler encore plus de tokens.

Parmi les opérations impactées par cette dégradation, on peut citer  la révocation des tokens arrivés à expiration. Vault continue de créer de nouveaux tokens, sans pouvoir révoquer les tokens expirés.

D’après mon expérience suite à un incident sur un cluster Vault utilisé par 900 clients et plus de 10 000 applications, j’ai constaté qu’un temps de réponse important, dépassant une seconde, survient à partir d’environ 1 000 000 de tokens actifs, des fonctionnalités sont perdues après environ 2 500 000 tokens actifs, et un arrêt presque complet du cluster survient après environ 4 000 000 de tokens actifs. Ces chiffres sont approximatifs et dépendent des capacités des infrastructures qui hébergent le cluster Vault (processeurs, mémoire, disque, latence).

Rétablissement de la performance d’un cluster HashiCorp Vault

Actions immédiates

Il est crucial de détecter les clients à l’origine d’un grand nombre de création de tokens pour :

  • Examiner la possibilité de révoquer les tokens disponibles mais non utilisés.
  • Réviser le TTL mis en place et essayer de le réduire au maximum.
  • Changer le type de token : passer de service à batch pour alléger la charge sur le cluster.
  • En dernier recours, envisager de bloquer les clients surconsommateurs afin de maintenir un service stable pour le reste des utilisateurs et minimiser l’impact sur les performances.

Actions moyen terme 

  • Mettre en place des règles Sentinel dans le but de :
  1. Rendre obligatoire la spécification du TTL lors de la définition de la méthode d’authentification. 
  2. Imposer l’utilisation exclusive de tokens batch au lieu de tokens de service pour certains namespaces.
  • Configuration d’un TTL par défaut dans le fichier de configuration de Vault pour remplacer celui de 32 jours.
  • Définition d’une valeur de TTL_max dans le fichier de configuration, garantissant que c’est bien cette dernière qui sera appliquée par Vault, même si un client définit un TTL supérieur.
  • Encouragement des clients à adopter l’agent Vault pour gérer l’auto-authentification et le renouvellement des tokens.
  • Sensibilisation des clients à la réutilisation du même token pendant toute sa durée de vie, et à l’utilisation de l’option de renouvellement ou de révocation après utilisation.

Actions à long terme 

  •  Mise en place de l’agent proxy par les administrateurs de Vault :
  1. Utilisation du proxy Vault comme couche intermédiaire pour gérer la réutilisation et le renouvellement des tokens.
  2. Activation de la gestion du cache pour la lecture des secrets (à partir de la version 1.16 de Vault). Cette fonctionnalité est activée par le paramètre cache_static_secrets dans le fichier de configuration de Vault :

Le gain de ces actions peut être décisif ; considérons de nouveau le premier exemple avec 1 000 clients, chacun ayant 5 applications accédant à Vault toutes les 15 minutes pour récupérer un secret avec un token au TTL de 32 jours, on obtient alors 1 000 * 5 = 5 000 tokens actifs à l’issue du premier appel. Lors des appels suivants, le proxy Vault renverra les tokens existants, ce qui signifie que nous n’aurons toujours que  5 000 tokens actifs pendant 24 heures grâce au TTL_max prédéfini, au lieu des 480 000 tokens actifs pendant 32 jours si nous avions interfacé directement le client avec le backend Vault et avec le TTL par défaut.

  • Une documentation doit être élaborée pour orienter les clients à utiliser l’URL du proxy-Vault au lieu de celle de Vault directement.
  • Il est également crucial de sécuriser la solution en mettant en place des quotas configurables par le fournisseur Vault pour la version Enterprise. Il existe deux quotas à implémenter pour contrôler la consommation des clients :
  1. Le premier quota est le rate-limit, qui permet de configurer le nombre de requêtes à traiter par namespace ou par chemin d’accès aux secrets.
  2. La deuxième fonctionnalité est le lease-count, qui limite le nombre de tokens générés par les clients ou au niveau global du cluster. Cette fonctionnalité empêche la création massive de tokens, qu’elle soit intentionnelle ou non.
  • La mise en place d’une solution de supervision est primordiale pour un cluster Vault partagé entre plusieurs clients. Vault fournit une panoplie de métriques que l’on peut activer au niveau du service Vault et collecter dans une solution d’Observabilité (Prometheus, Datadog, Dynatrace, etc.). Parmi les métriques qui aideront à identifier la surcharge du cluster par des tokens, on peut superviser les suivantes :
  1. vault.token.count : jauge reflétant le nombre de tokens de service actifs sur un cluster Vault. On peut obtenir la somme de tokens pour le cluster global ou par namespace.
  2. vault.token.creation : compteur enregistrant chaque token créé, avec des détails tels que le type de token, le client, la méthode d’authentification, le chemin de création du token et le TTL.
  3. vault.token.count.by_auth : compteur donnant le nombre de tokens générés par méthode d’authentification, ce qui simplifie la détection des divergences dans la création de tokens par méthode d’authentification.
  4. vault.token.count.by_ttl : compteur permettant de détecter les TTL élevés et travailler avec les clients pour les réduire dans leur namespace.
  • Il est également possible d’implémenter des métriques pour surveiller la performance de fonctionnement du cluster :
  1. vault.core.handle_login_request : temps de réponse pour les requêtes de login.
  2. vault.core.handle_request : temps de réponse pour les requêtes autres que de login.
  3. vault.core.in_flight_requests : compteur du nombre de requêtes en cours.
  4. vault.autopilot.failure_tolerance : indicateur de tolérance aux pannes sans perte du quorum, déduit à partir du nombre de nœuds actuellement sains pouvant échouer.

En utilisant ces métriques, il est possible de  mieux gérer et optimiser l’utilisation de Vault, assurant ainsi une performance stable et une répartition équitable des ressources entre les clients.

Conclusion

Dans un environnement de production à grande échelle et avec un produit proposé en tant que service, les administrateurs de ce service doivent se protéger contre tous les scénarios possibles de dysfonctionnement ou de panne. Cela implique la mise en place de limites strictes pour éviter les surcharges.

La mise en place d’un système d’alerte capable de surveiller l’état global du cluster et de signaler les anomalies au niveau du cluster ou des clients est primordiale.

Des règles Sentinel doivent être établies pour bloquer certains types d’opérations ou imposer des conditions aux requêtes envoyées au Vault. Il est également crucial de calculer avec précision la charge que le cluster peut supporter avant de devenir non fonctionnel.

Il est nécessaire de préparer des documents d’utilisation contenant les bonnes pratiques spécifiques à l’organisation, des ressources d’apprentissage, des scénarios de consommation et les recommandations de l’éditeur. En outre, il est important de prendre en compte les cas spécifiques qui nécessitent une attention particulière. Ces cas peuvent être discutés lors des réunions ou des workshops afin de les traiter de manière appropriée.