Aller au contenu

Chapitre 11. Les policies

Objectifs pédagogiques

Expliquer le modèle d'autorisation. Écrire des policies correctes, capabilities et jokers compris. Régler définitivement le piège KV v2. Employer le templating d'identité. Tester des droits sans tricher. Organiser les policies d'une organisation et reconnaître les chemins d'escalade. Situer Sentinel et les control groups.

Prérequis

Chapitre 4 pour l'évaluation dans le cycle de requête, chapitre 9 pour l'API réelle de KV v2, chapitre 10 pour les rôles qui attachent.

Cours

11.1 Le modèle

Quatre règles gouvernent tout. Un token porte une liste de policies, attachées par le rôle et complétées par son identité. Une requête est autorisée si au moins une règle d'au moins une de ces policies accorde la capability requise sur le chemin demandé : les policies s'additionnent. Exception unique : la capability deny, qui l'emporte sur toute autorisation concurrente. Et en l'absence de règle applicable, refus : aucune policy ne porte ce défaut, il tient à l'absence même de permission.

Deux policies existent d'office. root n'a pas de contenu à lire : c'est le laissez-passer intégral, dont le chapitre 8 a réglé le sort. default, attachée automatiquement à presque tous les tokens, contient le minimum vital d'un token envers lui-même : se consulter, se renouveler, se révoquer, accéder à son cubbyhole. Sa lecture est un bon exercice de grammaire.

11.2 La grammaire

Une policy est un document HCL fait de blocs path portant des capabilities.

path "secret/data/billing/prod/*" {
  capabilities = ["read"]
}

Les jokers. Deux, aux sémantiques distinctes. Le glob *, uniquement en fin de motif, absorbe tout le reste du chemin, segments suivants compris. Le joker + vaut pour exactement un segment, n'importe où : secret/data/+/prod/db couvre toutes les applications pour le seul objet db de la production. Le premier découpe des sous-arbres, le second exprime des motifs transverses. Aucun n'est une expression régulière ; la tentation d'en écrire signale une arborescence à repenser.

Les capabilities. read pour lire. create et update pour écrire, la première valant pour un chemin qui n'existe pas encore : comme le client ignore souvent lequel des deux cas s'applique, la pratique les accorde ensemble sur les préfixes d'écriture. patch pour la modification partielle, une écriture moindre accordable sans l'écriture pleine. delete pour supprimer. list pour énumérer : capability à part entière et non sous-produit de read, parce que connaître l'inventaire des chemins d'autrui est déjà une information. sudo pour les chemins protégés, une courte liste d'endpoints sensibles qui exigent cette marque en plus de la capability d'opération. deny pour l'interdiction prioritaire, unique règle soustractive du modèle, dont l'usage propre est l'exception chirurgicale à l'intérieur d'un préfixe accordé.

La correspondance avec l'API. La capability requise est déterminée par l'opération HTTP réelle : GET exige read, POST et PUT exigent create ou update, DELETE exige delete, LIST exige list, PATCH exige patch. Devant un 403, la question est donc : quelle requête cette commande émet-elle, sur quel chemin réel ?

Pour la complétude : les blocs acceptent des paramètres de finesse supplémentaire, qui contraignent les paramètres autorisés, interdits ou exigés d'une requête. Outil de précision à manier avec parcimonie, car il couple la policy au schéma de l'endpoint.

11.3 KV v2 : le piège récolté

Un administrateur pressé écrit la policy « lecture des secrets de billing » :

path "secret/billing/*" {
  capabilities = ["read", "list"]
}

Résultat : 403 sur toutes les lectures. vault kv get secret/billing/prod/db émet GET /v1/secret/data/billing/prod/db ; le chemin réel contient data/, la policy ne le mentionne pas, aucune règle ne s'applique. La CLI masque le préfixe ; le moteur d'autorisation ne voit que les chemins réels.

La forme correcte, qui est mot pour mot la policy billing-kv du fil rouge :

# billing-kv -- lecture des secrets de production de l'application billing
path "secret/data/billing/prod/*" {
  capabilities = ["read"]
}
path "secret/metadata/billing/prod/*" {
  capabilities = ["list", "read"]
}

Le second bloc n'est pas décoratif : list permet d'énumérer le préfixe, read de consulter l'état des versions sans lire les valeurs. Une identité purement machine, qui connaît ses chemins par configuration, peut s'en passer entièrement, au prix d'une énumération qui échouera pour elle, ce qui n'est pas un bogue mais la policy qui travaille.

Réflexe définitif : toute policy KV v2 se pense en deux familles de chemins et s'écrit sur les deux, ou sur une seule, mais en le sachant.

11.4 Le templating d'identité

Les policies acceptent des paramètres résolus à l'évaluation, tirés de l'identité de l'appelant :

# Un espace personnel par entite, sans une policy par personne
path "secret/data/users/{{identity.entity.name}}/*" {
  capabilities = ["create", "read", "update", "delete"]
}
path "secret/metadata/users/{{identity.entity.name}}/*" {
  capabilities = ["list", "read"]
}

Une seule policy, et chaque identité n'atteint que son sous-arbre. D'autres champs sont disponibles : identifiant d'entité, métadonnées d'alias, groupes. Discipline d'usage : le templating sert les motifs réguliers ; dès que la logique devient conditionnelle, c'est l'arborescence ou l'architecture des groupes qu'il faut revoir.

11.5 Tester sans tricher

L'erreur de méthode la plus répandue : valider une policy avec un token d'administrateur. Tout fonctionne, et rien n'est validé.

La discipline est outillée. vault policy fmt normalise, vault policy write publie, vault policy read relit, et le fichier vit dans un dépôt de version, revu comme du code. Puis le test réel : émettre un token portant la seule policy à valider, vault token create -policy=billing-kv -ttl=10m, et jouer sous ce token la grille de cas : la lecture qui doit réussir, la lecture voisine qui doit échouer, l'écriture qui doit échouer. Le refus attendu fait partie du test.

Deux outils accélèrent le diagnostic. vault token capabilities <chemin> répond, pour le token courant, à la question du 403. Et la CLI offre, depuis la version 1.9, l'option -output-policy, qui affiche la policy minimale qu'une commande requerrait : l'outil pour construire au moindre privilège à partir des gestes réels.

11.6 L'architecture des policies

Une policy bien écrite dans un ensemble mal pensé reste une dette. Trois règles d'organisation : une policy par rôle fonctionnel, nommée par son consommateur et son objet, attachée par les rôles et les groupes et jamais à la main sur des tokens isolés ; des policies courtes, dix lignes qui se relisent valant mieux qu'un monolithe ; l'ensemble versionné et revu comme du code.

La matrice du fil rouge :

Policy Contenu Portée par
billing-kv lecture des secrets de production de billing rôle AppRole billing, puis billing-k8s
ci-deploy écriture en préproduction, rien en production rôle ci-billing
ops-backup lecture de l'endpoint de snapshot et de l'état de santé groupe externe ops
ops-audit gestion des dispositifs d'audit, avec sudo groupe externe ops
billing-db réservée pour la partie VI, déclarée vide et commentée rôle billing
admin administration, sans lecture des valeurs groupe des administrateurs

ops-backup mérite un mot : l'équipe de sauvegarde sauvegarde du chiffré, la barrière fait le reste. Aucune de ses règles ne lit un secret.

Le raffinement d'admin. La version bootstrap du chapitre 8 couvrait les secrets en toutes capabilities : nécessaire à l'amorçage, indéfendable en régime permanent. La version raffinée sépare administrer la structure et lire les valeurs : admin conserve la gestion du serveur, des méthodes, de l'identité et l'inventaire des secrets par secret/metadata/*, mais perd secret/data/*. L'administrateur voit qu'un secret existe, ses versions, sa configuration ; il n'en lit plus les valeurs. Les cas légitimes de lecture humaine passent par des policies dédiées, temporaires et tracées.

Le chemin d'escalade. Conséquence du modèle, à garder à chaque revue : qui peut écrire les policies peut s'écrire tous les droits. L'écriture sur les chemins de policies, c'est la policy root avec une étape de plus ; et qui peut modifier les rôles d'authentification peut attacher n'importe quelle policy à ses propres logins. Ces chemins n'appartiennent qu'à admin, leur usage se surveille, et aucune policy applicative n'en approche.

11.7 Enterprise : Sentinel et control groups

L'édition Community s'arrête aux capabilities sur des chemins. L'édition Enterprise ajoute deux étages. Les policies Sentinel expriment des conditions riches en langage dédié, attachées aux tokens et identités ou aux endpoints, et peuvent conditionner l'accès à l'heure, à l'origine réseau, au facteur MFA présenté. Les control groups ajoutent l'approbation à la demande : une requête sur un chemin protégé est suspendue jusqu'à validation par des approbateurs désignés, ce qui est exactement l'outil des cas légitimes de lecture humaine évoqués plus haut.

Exemple : la journée du raffinement d'admin

La nouvelle version d'admin est publiée, et le test de non-régression passe au premier essai : sous un token admin fraîchement émis, la lecture d'une valeur de production échoue désormais.

Mais la relecture de l'audit du mois écoulé montre trois lectures de valeurs de production sous des tokens admin. Toutes trois s'expliquent, deux dépannages et une vérification après rotation, et aucune n'était rattachée à un ticket.

La décision qui suit est la bonne conclusion du chapitre : une policy debug-billing-prod, lecture seule, durée de trente minutes, émise à la demande et journalisée avec référence d'incident, remplace l'accès permanent que personne n'assumait avoir. Le moindre privilège n'a rien retiré : il a rendu explicite ce qui était invisible.

Sécurité : les policies comme code et comme cible

Versionnées, revues, testées. Le dépôt de policies est le registre du pouvoir. Toute modification y est une revue à deux, et tout écart entre le dépôt et l'état réel est un incident de dérive.

Le rayon d'explosion se décide ici. Le client compromis obtient exactement ce que les policies accordent. Chaque joker trop haut placé, chaque list d'entraînement, chaque capability accordée au cas où est un cadeau différé. La revue périodique cherche ce qui peut être retiré.

Les chemins du pouvoir. Écriture des policies, gestion des rôles d'authentification, administration de l'audit : les trois familles qui permettent de s'élever, de se déguiser ou de s'effacer.

deny n'est pas une architecture. L'interdiction prioritaire sert l'exception documentée. Une forêt de deny rattrapant des accords trop larges est une arborescence à refondre.

Erreurs fréquentes

Oublier data/ sur KV v2. L'erreur numéro un de l'écosystème : la policy sur secret/billing/* n'autorise rien (section 11.3).

Croire que * s'arrête au segment. Le glob final absorbe tout le sous-arbre ; c'est + qui vaut pour un segment (section 11.2).

Accorder update sans create. La première écriture d'un chemin neuf exige create : un rôle qui n'a que l'un des deux échoue de façon intermittente (section 11.2).

Oublier list, ou l'accorder partout. Sans lui les énumérations échouent et l'on soupçonne à tort la policy de lecture ; partout, l'inventaire des secrets devient public interne (section 11.2).

Valider avec un token root. Tout passe, rien n'est prouvé (section 11.5).

Attacher des policies à la main sur des tokens. Cela crée des droits orphelins, hors rôles et hors revue (section 11.6).

Laisser traîner l'écriture des policies. Chaque revue commence par : qui peut modifier les droits aujourd'hui ? La réponse doit tenir sur une ligne (section 11.6).

Mise en pratique : trois policies sur papier

Écrivez les trois policies en HCL exact. Réponses commentées en fin de partie ; gardez vos brouillons, le TP 4 les fera vivre.

  1. ops-audit : gérer les dispositifs d'audit, sachant que ce chemin est protégé, et lire l'état de santé. Rien d'autre.
  2. lecteur-preprod : tout lire et énumérer sous les secrets de préproduction de billing, sans aucun droit d'écriture ni de suppression, les deux familles de chemins comprises.
  3. billing-kv-restreinte : identique à billing-kv, mais le sous-arbre secret/data/billing/prod/interne/* doit être inaccessible même si une autre policy du même token l'accordait.

Questions de compréhension

  1. Énoncez les quatre règles du modèle d'autorisation et ce qu'elles impliquent pour le cumul de policies.
  2. Que contient default, à quoi sert-elle, et pourquoi sa lecture est-elle un bon exercice ?
  3. Distinguez * et +, avec un exemple où chacun est le bon choix.
  4. Expliquez create contre update, et pourquoi on les accorde ensemble.
  5. Pourquoi list est-elle une capability à part entière, et où s'accorde-t-elle pour KV v2 ?
  6. Que fait sudo, sur quels chemins, et quel est l'exemple canonique du fil rouge ?
  7. Déroulez le diagnostic complet du 403 avec une policy écrite sans data/.
  8. Décrivez la méthode de test d'une policy, et pourquoi les refus attendus en font partie.
  9. Identifiez les chemins d'escalade et ce que Sentinel et les control groups ajoutent en édition Enterprise.

Synthèse

L'autorisation tient en un modèle, rien par défaut, l'union des policies du token, deny souverain, et une grammaire : des blocs path aux jokers précis, des capabilities dont chacune a son sens, et une correspondance directe avec les opérations HTTP réelles qui règle le piège KV v2. Autour, une discipline : le templating pour les motifs réguliers, le test sous un token dédié avec ses refus attendus, des policies courtes et versionnées, une par rôle fonctionnel, et la garde des chemins du pouvoir, car qui écrit les policies écrit tout. Le fil rouge a sa matrice, et admin a perdu la lecture des valeurs. Déclenche le TP 4 (énoncé en partie XV).