Chapitre 19. Les moteurs dynamiques en pratique
Objectifs pédagogiques¶
Configurer le moteur Database pour PostgreSQL de bout en bout. Expliquer les trois types de credentials AWS et leurs propriétés de révocation. Situer Azure et GCP et leurs pièges de quotas. Remplacer des clés SSH partagées par des certificats signés courts. Situer RabbitMQ et le moteur Kubernetes. Solder le constat 6 de l'état des lieux.
Prérequis¶
Chapitre 18 (le modèle, que ce chapitre ne répète pas), chapitre 13 (la chaîne AppRole de billing), chapitre 11 (les policies, enrichies des nouveaux chemins).
Cours¶
19.1 Database : PostgreSQL de bout en bout¶
Le moteur Database est le vaisseau amiral du modèle : un plugin par famille de bases, une mécanique commune, la fabrique du chapitre 18 en SQL.
La connexion. D'abord le compte racine côté base : l'administratrice crée vault-mgr selon la discipline de 18.4, capable de gérer des rôles, pas superutilisateur. Puis la déclaration côté Vault.
[Laboratoire]
vault secrets enable database
vault write database/config/pg-billing \
plugin_name=postgresql-database-plugin \
connection_url="postgresql://{{username}}:{{password}}@db-pg-01.astrea.lab:5432/billing?sslmode=verify-full" \
username="vault-mgr" \
password="valeur-initiale-a-faire-tourner" \
allowed_roles="billing-app,billing-batch"
Trois détails sont des décisions. Le gabarit d'identifiants dans l'URL : ils ne sont pas écrits en dur mais vivent dans des champs dédiés, ce qui permettra la rotation sans toucher à la configuration. La vérification TLS complète vers la base : le moteur envoie des mots de passe fraîchement créés, et une session en clair ruinerait la fabrique. La liste fermée des rôles autorisés : jamais un joker, qui permettrait à tout créateur de rôle futur d'emprunter ce compte racine.
La configuration vérifie la connexion à l'écriture, puis vient le geste d'hygiène de 18.4, immédiatement.
[Laboratoire]
La valeur initiale, qui a transité par un terminal, est morte. Le compte de secours de l'administratrice, hors Vault, a été vérifié avant.
Le rôle dynamique. La politique côté base, écrite dans le rôle.
[Laboratoire]
vault write database/roles/billing-app \
db_name=pg-billing \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; \
GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA billing TO \"{{name}}\";" \
revocation_statements="REVOKE ALL ON ALL TABLES IN SCHEMA billing FROM \"{{name}}\"; DROP ROLE IF EXISTS \"{{name}}\";" \
default_ttl=1h \
max_ttl=24h
Lecture ligne à ligne, car tout y est. Les gabarits de nom, de mot de passe et d'échéance sont les valeurs que Vault génère et injecte ; une politique de mots de passe nommée peut être imposée sur la connexion pour les cibles à contraintes. La clause d'échéance est la ceinture et les bretelles : la base elle-même refusera le compte après l'heure, même si Vault, en panne, n'a pas pu exécuter la révocation. C'est le cas non nominal de 18.3, traité dans le SQL.
Les droits accordés sont la lecture et l'écriture sur le schéma applicatif, rien d'autre. Pas de définition de structure, et surtout le compte dynamique ne possède aucun objet : un rôle propriétaire de tables ne peut pas être supprimé proprement, et la révocation échouerait. Les comptes fabriqués consomment le schéma, ils ne le construisent pas.
Les instructions de révocation sont explicites, et le nettoyage est notre SQL, relu comme une policy. Les durées, enfin, alignent le bail sur le token de billing, avec un plafond de vingt-quatre heures sous celui du montage.
La consommation. Côté application, une lecture.
[Laboratoire]
vault read database/creds/billing-app
# username: v-approle-billing-a-x7Kf3q..., password: ..., lease_id: database/creds/billing-app/...,
# lease_duration: 1h, renewable: true
Côté base, la preuve que tout le chapitre 18 est vrai : le compte existe avec son échéance renseignée, les journaux montrent des connexions sous ce nom unique, et une révocation de bail le fait disparaître dans la seconde.
La policy qui autorise cette lecture est billing-db, réservée depuis la partie IV et activée aujourd'hui.
Le détail compte : lire des credentials dynamiques est une lecture. Le chemin fabrique, mais l'API reste un read, et la capability le dit.
Le rôle statique géré. Pour le traitement nocturne, selon la grille de 18.5. Le compte existe, créé par l'administratrice, et Vault en prend le mot de passe en gérance.
[Laboratoire]
vault write database/static-roles/billing-batch \
db_name=pg-billing \
username="billing_batch" \
rotation_period=86400
vault read database/static-creds/billing-batch
# password courant, last_vault_rotation, ttl avant prochaine rotation
Deux chemins, deux modèles, jusque dans les noms : l'un fabrique, l'autre distribue la valeur courante d'un compte que Vault fait tourner. La prise en gérance change immédiatement le mot de passe, et l'ancien, connu de l'administratrice, meurt.
Note de version : depuis la version 1.15, la rotation des rôles statiques sait aussi se programmer par une expression calendaire avec fenêtre de tolérance. Tourner à trois heures du matin, après la fenêtre du traitement, vaut mieux que toutes les vingt-quatre heures depuis la prise en gérance.
Le worker lit ce chemin sous une policy dédiée d'une règle. Un statique géré redevient un secret partagé si dix consommateurs le lisent : il se traite comme un compte à consommateur unique.
19.2 AWS : trois types de credentials, trois contrats¶
Le moteur AWS illustre le mieux que le type de credential est un contrat de révocation. La configuration suit le schéma familier : un compte racine au périmètre minimal, sa rotation avec la même irréversibilité, des rôles. La nouveauté est le type de credential, avec trois valeurs.
Utilisateur IAM : Vault crée un utilisateur réel avec une clé d'accès. Révocable à tout instant, mais lourd, avec des objets créés et détruits, des quotas de compte et une propagation de quelques secondes.
Rôle assumé : Vault obtient des credentials temporaires auprès du service de jetons. Légers, rapides, sans objet à nettoyer, et non révocables : ils expirent d'eux-mêmes et ne peuvent pas être rappelés avant l'heure. Révoquer le bail côté Vault ne reprend rien côté cloud.
Jeton de fédération : mêmes propriétés d'expiration, pour des cas d'intégration particuliers, avec des exigences élargies sur le compte racine.
La règle de choix découle des contrats. Le rôle assumé par défaut, le plus propre, avec des durées courtes précisément parce que la révocation n'existe pas : la durée est la seule défense. L'utilisateur IAM quand la révocabilité immédiate est une exigence du modèle de menace, en payant le poids.
19.3 Azure et GCP : le même modèle, des pièges de quotas¶
Le modèle ne change pas, les pièges sont locaux.
Azure crée des identités de service éphémères, ou fait tourner les secrets d'identités existantes, ce qui est le statique géré version cloud. Les objets créés mettent quelques secondes à se propager dans l'annuaire, et les applications doivent tolérer ce délai au premier usage.
GCP offre deux formes. Des jetons d'accès de courte durée, sans objet créé, non révocables avant l'heure. Ou des clés de comptes de service, révocables mais soumises au quota dur de dix clés par compte de service : un rôle mal dimensionné qui génère des clés plus vite qu'elles n'expirent sature le quota et bloque toute la chaîne. La préférence va aux jetons ; les clés se réservent aux consommateurs qui l'exigent, avec un calcul de quota écrit au dossier.
19.4 SSH : les certificats signés courts¶
Le dernier constat de l'état des lieux est la clé privée d'astreinte, partagée par l'équipe, présente sur les postes, jamais tournée. La tentation à écarter d'abord est de la ranger dans KV : un secret partagé versionné reste un secret partagé, avec la même absence d'imputabilité, la même éternité, la même révocation impossible.
La bonne réponse change de modèle, exactement comme au chapitre 17 : une autorité de certification SSH. Les hôtes font confiance à une clé publique d'autorité, une fois. Les personnes font signer leur propre clé pour quelques minutes.
[Laboratoire]
vault secrets enable -path=ssh ssh
vault write ssh/config/ca generate_signing_key=true
vault write ssh/roles/admin-ssh - <<'JSON'
{
"key_type": "ca",
"algorithm_signer": "rsa-sha2-256",
"allow_user_certificates": true,
"allowed_users": "astreinte",
"default_user": "astreinte",
"allowed_extensions": "permit-pty",
"default_extensions": { "permit-pty": "" },
"ttl": "30m",
"max_ttl": "1h"
}
JSON
Le rôle est la politique : signer uniquement des certificats d'utilisateur, pour le seul principal que les serveurs connaissent, avec l'extension qui autorise une session interactive. Sans elle, le certificat est valide mais n'ouvre pas de terminal, l'échec le plus déroutant du moteur. Trente minutes par défaut. L'algorithme de signature moderne est imposé dans le rôle, les OpenSSH récents refusant les signatures anciennes.
Côté hôtes, un déploiement une fois, par la gestion de configuration.
[Production]
# La cle PUBLIQUE de l'autorite -- endpoint non authentifie, fait pour ca
curl -s https://vault.astrea.lab:8200/v1/ssh/public_key \
-o /etc/ssh/trusted-user-ca-keys.pem
# Dans /etc/ssh/sshd_config :
# TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem
Et côté personne, le rituel d'astreinte devient une signature.
[Laboratoire]
vault write -field=signed_key ssh/sign/admin-ssh \
public_key=@$HOME/.ssh/id_ed25519.pub > $HOME/.ssh/id_ed25519-cert.pub
ssh astreinte@app-billing-01.astrea.lab # le client presente cle + certificat
Ce qui change, constat par constat. La clé privée de la personne n'a jamais quitté son poste : elle a envoyé sa clé publique et reçu un certificat, le motif du chapitre 17 à l'identique. Le certificat vaut trente minutes, donc la fenêtre de compromission est l'intervention et non la carrière de la clé. Chaque signature est une ligne d'audit nominative, et le certificat porte un identifiant que le serveur journalise à la connexion : la question « qui s'est connecté en astreinte cette nuit » a une réponse des deux côtés. Enfin la révocation d'urgence ne consiste plus à changer une clé sur trente serveurs : on retire à une personne le droit de faire signer, et ses certificats meurent seuls dans la demi-heure.
Le constat 6 est soldé par le même principe que le 5 : on ne partage pas un secret, on distribue une confiance.
Deux mentions complètent la carte. Le moteur sait aussi signer des certificats d'hôtes, ce qui fait disparaître l'acceptation aveugle des empreintes au premier contact. Et un mode à mots de passe à usage unique existe, vérifié par un assistant installé sur chaque hôte : plus intrusif, utile dans des contextes sans certificats, à connaître sans en faire le premier choix.
19.5 RabbitMQ, et la famille¶
Le moteur RabbitMQ ferme la démonstration côté middleware : une connexion à l'API de gestion du broker avec son compte racine dédié, des rôles qui projettent des permissions par hôte virtuel, et un chemin qui fabrique des utilisateurs éphémères détruits au bail.
Rien de neuf conceptuellement, et c'est le message. La famille des moteurs dynamiques s'allonge à chaque version, et se lit désormais d'un regard, par quatre questions : où est le compte racine, que disent les instructions de création, quel est le contrat de révocation, quelles sont les durées. Elles se posent à n'importe quel moteur, y compris ceux qui n'existent pas encore.
19.6 Kubernetes : des jetons de service éphémères¶
Note de version : depuis la version 1.11, Vault propose un moteur de secrets Kubernetes, à ne pas confondre avec la méthode d'authentification du chapitre 10. La distinction tient en une phrase : la méthode permet aux pods de prouver leur identité à Vault, le moteur permet à Vault de fabriquer des accès à Kubernetes.
Le moteur émet à la demande des jetons de comptes de service à courte durée, et sait créer le compte de service et ses liaisons le temps du bail. Le cas d'usage type est celui qu'Astrea rencontrera à la migration : l'outillage d'administration et la CI ont besoin d'accès au cluster, et la pratique par défaut, le fichier de configuration longue durée distribué aux personnes et aux pipelines, est le constat 6 version Kubernetes. À la place, un jeton de dix minutes, borné à un namespace, tracé. Le chapitre 38 branchera ce moteur sur l'architecture cible.
Exemple : le jour où le mot de passe de la base a cessé d'exister¶
La bascule de billing, consignée, aboutissement d'un fil tendu depuis le chapitre 1.
Préproduction. L'application, qui lisait le statique migré au chapitre 9, lit désormais le chemin de credentials dynamiques au démarrage et renouvelle son bail avec son token. Le code du chantier AppRole n'a presque pas bougé : un chemin a changé. Recette : les journaux de la base montrent des comptes distincts par instance, l'imputabilité descendue jusqu'à la base, et une révocation de test fait tomber une connexion dans la seconde.
Production. Elle suit le jour même. Le traitement nocturne passe sur le statique géré le soir même, rotation programmée après sa fenêtre.
Le geste final. Le secret statique de la base est détruit selon le cycle du chapitre 9. Il n'existe plus. Il n'a pas été mieux caché, mieux tourné, mieux gouverné : il a disparu en tant que catégorie. Les constats 1 et 2 ne sont plus corrigés, ils sont sans objet : chaque environnement, chaque instance, chaque heure a le sien, fabriqué.
Au registre, l'architecte note la dette restante du domaine : le compte de secours de l'administratrice, scellé sous enveloppe, à tester au prochain exercice trimestriel.
Architecture : les flux du domaine base de données¶
app-billing-01 (instance API) db-pg-01 (PostgreSQL)
token AppRole [billing-kv, billing-db]
| ^
| 1. read database/creds/billing-app | 3. connexions SQL
v | (compte unique, VALID UNTIL)
vault-core-01 ------- 2. CREATE ROLE "v-approle-..." --+
| (compte vault-mgr, TLS verify-full)
| 4. expiration/revocation du bail
+------------------ REVOKE ... ; DROP ROLE ------>
traitement nocturne --- read database/static-creds/billing-batch (rotation 03h10)
vault lease revoke -prefix database/creds/billing-app/ <-- bouton d'urgence du domaine
Sécurité : les points durs du chapitre¶
Les chemins de configuration sont des chemins de pouvoir. Qui écrit les configurations et les rôles décide de ce que la fabrique produit, jusqu'aux droits accordés dans la base. Écriture réservée, alarmée, revue, et liste fermée des rôles autorisés pour qu'un rôle créé par erreur ne puisse pas s'adosser à la connexion.
La liaison moteur-cible se protège comme une frontière. Vérification TLS complète vers la base, TLS vers les API cloud et le broker : le moteur transporte des secrets neufs, et une session en clair ruinerait la fabrique.
Les contrats de révocation se connaissent avant l'incident. Un credential temporaire ne se rappelle pas ; un utilisateur IAM ou un rôle PostgreSQL, si. Le plan de réponse note, moteur par moteur, ce que la révocation reprend vraiment, et là où elle ne reprend rien, les durées courtes sont la seule ligne.
L'ancre de confiance SSH se distribue avec intégrité. La clé publique de l'autorité, déployée sur tous les hôtes, est le nouveau point dur : qui peut la remplacer fait accepter ses propres certificats partout. Elle se déploie par la gestion de configuration, et son remplacement est une procédure.
Les quotas des cibles entrent dans le dimensionnement. Dix clés par compte de service, des quotas IAM, la charge de création sur la base : la fabrique se calibre en durée, taille de flotte et fréquence, et se supervise.
Erreurs fréquentes¶
Écrire les identifiants en dur dans l'URL de connexion. La chaîne fonctionne, et la rotation du compte racine ne peut plus opérer : le mot de passe est fossilisé dans la configuration (section 19.1).
Autoriser tous les rôles sur une connexion. Tout rôle futur, y compris créé par erreur, peut s'adosser au compte racine. La liste est fermée, nominative, revue (section 19.1).
Des comptes dynamiques propriétaires d'objets. À l'échéance, la suppression échoue, les baux se coincent, les orphelins s'accumulent. Le DDL appartient aux migrations applicatives, sous une autre identité (section 19.1).
Oublier la clause d'échéance côté base. La révocation repose alors entièrement sur la disponibilité de Vault à l'heure dite. La ceinture et les bretelles (section 19.1).
Dix consommateurs sur un statique géré. L'imputabilité s'évapore et la rotation casse dix services à la fois. Un compte géré, un consommateur (section 19.1).
Des durées longues sur des credentials irrévocables, pour compenser. C'est l'inverse : moins un credential se révoque, plus court il doit vivre (sections 19.2, 19.3).
Signer des certificats SSH sans l'extension de session, ou pour un compte tout-puissant. Le premier donne des connexions qui semblent marcher sans shell ; le second recrée le compte partagé avec une meilleure cryptographie (section 19.4).
Ranger la clé SSH partagée dans KV et clore le ticket. Le constat 6 mieux rangé n'est pas résolu : même clé, même partage, même éternité. Le changement est de modèle, pas d'emplacement (section 19.4).
Mise en pratique : concevoir sur trois cibles¶
Sur papier ; réponses commentées en fin de partie.
- L'équipe data obtient une base PostgreSQL en lecture pour ses analystes, avec des connexions interactives de moins de deux heures via un outil qui sait relire ses credentials. Rédigez la configuration complète : compte côté base, connexion, rôle avec ses instructions SQL, durées, policy, en justifiant chaque durée.
- Établissez le plan de migration du parc SSH vers les certificats : ordre des opérations, période de coexistence, tests, et le critère qui autorise la suppression de l'ancienne clé d'astreinte.
- Un audit relève des comptes fabriqués présents sur la base sans bail correspondant dans Vault. Donnez les deux causes possibles, le diagnostic qui les départage, et le traitement de chacune, y compris le rôle de la révocation forcée et son prix.
Questions de compréhension¶
- Pourquoi le gabarit d'identifiants dans l'URL de connexion est-il indispensable, et que fossilise son absence ?
- Que fait la clause d'échéance dans les instructions de création, et quel cas non nominal traite-t-elle ?
- Pourquoi les comptes dynamiques ne doivent-ils posséder aucun objet dans la base, et que se passe-t-il sinon ?
- Distinguez les deux familles de chemins de credentials : ce que chacune remet, ce que Vault fait derrière, et la règle du consommateur unique.
- Comparez les trois types de credentials AWS sous l'angle du contrat de révocation, et donnez la règle de choix.
- Quel est le piège de quota du moteur GCP, et quelle préférence en découle ?
- Pourquoi ranger la clé SSH partagée dans KV ne résout-il rien, et que change le modèle par autorité sur les quatre défauts du constat 6 ?
- Quel échec déroutant l'absence d'extension de session produit-elle, et où se corrige-t-il ?
- Distinguez la méthode d'authentification Kubernetes du moteur de secrets Kubernetes, et donnez le cas d'usage type du second.
Synthèse¶
Six moteurs, une seule grammaire. PostgreSQL a donné la version complète : une connexion templée et chiffrée dont le compte racine tourne dès la mise en service, un rôle dont le SQL est la policy côté base, une policy d'une règle, et le statique géré pour le traitement nocturne qui ne peut pas mieux. Les clouds ont appris la leçon des contrats : le rôle assumé est propre mais irrévocable, donc court ; l'utilisateur IAM est révocable mais lourd ; les quotas entrent dans le dimensionnement. SSH a soldé le dernier constat par le principe du chapitre 17 : on ne partage pas un secret, on distribue une confiance. Et la famille entière se lit par quatre questions, valables pour les moteurs qui n'existent pas encore. Déclenche le TP 8 (énoncé en partie XV).