Chapitre 38. Kubernetes et conteneurs
Objectifs pédagogiques¶
Configurer la méthode d'authentification Kubernetes de bout en bout et expliquer le rôle des audiences et de la liaison. Comparer les trois modes de consommation dans les pods, et énoncer la conséquence d'une copie hors barrière. Arbitrer entre un Vault dans le cluster et un Vault extérieur. Employer le moteur de secrets Kubernetes. Éviter les erreurs classiques des conteneurs.
Prérequis¶
Chapitre 10 (la méthode Kubernetes et le principe de l'identité déjà présente), chapitre 19 (le moteur de secrets, à ne pas confondre avec elle), chapitre 5 (les frontières de confiance), chapitre 29 (la zone prévue depuis l'architecture cible).
Cours¶
38.1 La méthode d'authentification, en détail¶
Le chapitre 10 en avait donné le principe : le pod possède déjà une identité, le jeton de son compte de service, et Vault la fait valider par le cluster plutôt que de distribuer un secret.
[Laboratoire]
vault auth enable kubernetes
vault write auth/kubernetes/config \
kubernetes_host="https://k8s-astrea.astrea.lab:6443" \
kubernetes_ca_cert=@/etc/vault.d/tls/k8s-ca.pem \
disable_iss_validation=false
vault write auth/kubernetes/role/billing-k8s \
bound_service_account_names="billing" \
bound_service_account_namespaces="billing-prod" \
audience="vault" \
token_policies="billing-kv,billing-db" \
token_ttl=1h token_max_ttl=4h
La liaison est le cœur du contrôle : le rôle n'accepte que ce compte de service, dans ce namespace. Les deux dimensions comptent, et l'oubli de la seconde est l'erreur classique : un rôle lié au seul nom de compte accepte un compte homonyme créé dans n'importe quel namespace, ce qui revient à donner les droits de billing à quiconque peut créer un namespace.
L'audience est le second garde-fou : le jeton présenté doit avoir été émis pour Vault, ce qui empêche qu'un jeton destiné à un autre service soit rejoué ici. Côté pod, cela suppose un volume de jeton projeté demandant explicitement cette audience, et le manifeste doit donc être écrit en conséquence.
Les durées suivent la doctrine du chapitre 12, alignées sur celles de billing hors cluster.
Deux points d'exploitation ferment la configuration. Vault doit pouvoir joindre l'API du cluster pour valider les jetons, ce qui ajoute une ligne à la matrice de flux et une entrée à la frontière où Vault est client. Et l'identité que Vault utilise pour cette validation doit être minimale : le droit de valider des jetons, rien d'autre, avec la même discipline que le compte racine d'un moteur.
38.2 Faire arriver un secret dans un pod : trois voies¶
C'est la question qui occupe réellement les équipes, et les trois réponses n'ont ni la même fraîcheur, ni la même surface, ni le même confort.
| Voie | Fonctionnement | Fraîcheur | Surface | Confort |
|---|---|---|---|---|
| Injecteur | conteneur adjacent qui rend des fichiers par gabarit | naturelle, compatible avec les baux | un conteneur par pod, dépendance au démarrage | annotations à poser |
| Pilote CSI | montage des secrets comme volume éphémère | dépend de la configuration | pas de conteneur adjacent | proche du précédent |
| Opérateur de synchronisation | écrit des Secrets natifs que les pods consomment | problème de synchronisation | le secret quitte la barrière | maximal |
La troisième voie appelle la mise en garde la plus nette. Un Secret Kubernetes est stocké dans le magasin du plan de contrôle, en clair du point de vue de Vault : il est protégé par le chiffrement au repos du cluster s'il est activé, par les droits d'accès de l'API, et par rien d'autre.
La conséquence doit être énoncée sans détour : cette approche copie le secret hors de la barrière et le place sous la responsabilité du modèle de sécurité de Kubernetes. Tout ce que le cursus a construit, révocation qui reprend, durées courtes, imputabilité nominative, s'arrête à la frontière de cette copie. Révoquer un bail côté Vault ne retire pas la valeur déjà écrite ailleurs.
La règle d'arbitrage d'Astrea, consignée : gabarits par injecteur pour les charges qui manipulent des secrets à forte valeur, credentials de base, clés Transit, certificats. Opérateur de synchronisation toléré pour les secrets de configuration à faible sensibilité, avec chiffrement du magasin activé, périmètre écrit et revue trimestrielle. Le confort n'est pas un argument suffisant pour sortir un secret de la barrière, mais il en est un pour les cas où le secret ne le mérite pas.
38.3 Vault dans le cluster ou à l'extérieur¶
Installer Vault dans Kubernetes se fait sans difficulté technique, et la question n'est pas technique. Elle porte sur la frontière de confiance : qui administre le cluster administre ce qui y tourne. Un Vault hébergé dans le cluster qu'il sert place ses secrets, sa mémoire et son stockage sous l'autorité des administrateurs de la plateforme, ce qui est défendable quand ces administrateurs sont déjà les détenteurs légitimes du plus haut privilège, et intenable quand le cluster est mutualisé ou administré par une autre équipe.
S'y ajoutent des considérations d'exploitation qui pèsent lourd. La dépendance circulaire : un cluster qui ne démarre pas sans les secrets que contient le Vault qui tourne dedans est un piège de reprise. Le stockage : Raft exige des volumes persistants au comportement prévisible, ce que tous les clusters n'offrent pas également. La reprise, enfin, dont les sauvegardes, le matériel de scellement et les procédures deviennent tributaires de la plateforme.
Astrea garde Vault en dehors du cluster, décision consignée avec son critère de révision. Le cluster devient donc un consommateur ordinaire, ce qui simplifie l'analyse : la frontière est celle de l'entrée, et le cluster n'obtient que ce que ses rôles accordent.
38.4 Le moteur de secrets Kubernetes¶
Le chapitre 19 a présenté ce moteur en le distinguant de la méthode d'authentification : il ne sert pas aux pods à prouver leur identité, il sert à Vault à fabriquer des accès au cluster.
Son usage devient concret ici. L'outillage d'administration, les tableaux de bord internes et les tâches d'intégration continue ont besoin d'accéder à l'API du cluster, et la pratique par défaut, le fichier de configuration à longue durée copié sur les postes et dans les pipelines, reproduit exactement le constat 6 du chapitre 1, version Kubernetes.
À la place, le moteur remet un jeton de compte de service de quelques minutes, borné à un namespace et à un jeu de droits, tracé par l'audit. Le principe est celui de la partie VI : on ne partage pas un accès, on en fabrique un par usage. Astrea prévoit deux rôles à la migration, un pour l'outillage humain et un pour la CI.
38.5 Docker, Compose et les erreurs qui traversent les plateformes¶
Hors orchestrateur, les mêmes erreurs reviennent, et la première tient à un réflexe : passer les secrets par des variables d'environnement du conteneur. Le chapitre 1 en avait montré la lecture par le système de fichiers virtuel ; le monde des conteneurs y ajoute l'inspection du conteneur, qui affiche la configuration complète à quiconque dispose du socle d'exécution. Un secret passé ainsi se retrouve dans la définition du service, souvent dans un fichier versionné, et dans les journaux d'outillage.
Les patrons acceptables sont ceux que le cursus a déjà construits, transposés : un agent adjacent qui écrit un fichier dans un volume en mémoire, ou une application qui s'authentifie elle-même avec une identité de plateforme. Pour le développement local, la simplicité prime légitimement, mais elle se paie d'une règle : les secrets de développement sont des secrets de développement, jamais des valeurs de production en attendant, et le dépôt ne contient que des exemples explicitement faux.
Un mot enfin sur le chiffrement comme service dans ce contexte. Une application conteneurisée qui chiffre ses données par Transit possède un avantage propre : elle ne détient aucune clé, donc son image, son système de fichiers et ses variables ne contiennent rien à voler. Ce modèle se marie particulièrement bien avec des charges éphémères, dont on ne veut justement pas qu'elles portent des clés.
Exemple : la migration de billing vers le cluster¶
La première charge migrée est le service de facturation, dont la chaîne AppRole du chapitre 13 disparaît au profit de l'identité de plateforme. Le chantier tient en quatre décisions, toutes déjà préparées par le cursus.
Le rôle lie le compte de service au namespace de production, exige l'audience attendue, et porte les mêmes policies que la version hors cluster. L'équipe vérifie en recette ce que la section 38.1 annonçait : un pod du namespace de préproduction utilisant un compte de service homonyme est refusé, et un jeton projeté sans l'audience attendue l'est aussi. Ces deux refus sont consignés comme preuves.
La consommation passe par l'injecteur avec gabarits : les credentials dynamiques arrivent dans un fichier monté en mémoire, renouvelés au rythme du bail. L'équipe applicative demandait l'opérateur de synchronisation, plus simple ; l'arbitrage de la section 38.2 s'applique, et la demande est acceptée pour un autre service, celui des tableaux de bord internes, dont les secrets sont des chaînes de connexion en lecture seule vers une base de recette.
L'identité de Vault vers le cluster reçoit son compte de service dédié, limité à la validation des jetons, et le flux est ajouté à la matrice puis vérifié en recette, refus compris.
La continuité d'identité, enfin, est le détail qui a évité une régression : billing possède une entité depuis le chapitre 13, et le nouvel alias lui est rattaché plutôt que de créer une seconde identité. L'audit continue donc de raconter une seule histoire de part et d'autre de la migration.
Architecture : le cluster comme consommateur¶
zone Vault (10.10.20.0/24) zone k8s-astrea (10.10.40.0/24)
+--------------------------+ +-------------------------------+
| lb-vault-01 :8200 | <------------ | pods : auth/kubernetes/login |
| -> cluster 3 noeuds | (F1) | jeton de compte de service |
| | | audience "vault" |
| | ------------> | API k8s :6443 (TokenReview, |
| | (F4) | moteur de secrets k8s) |
+--------------------------+ +-------------------------------+
Vault reste HORS du cluster : le cluster est un consommateur, pas un hote.
F1 = frontiere d'entree ; F4 = sortie vers les cibles, ou Vault est client (ch. 29)
Deux flux, deux frontieres, une ligne chacune dans la matrice du chapitre 29.
Sécurité : ce que la plateforme change¶
La confiance est déléguée au cluster. En acceptant cette méthode, Vault fait confiance à l'API du cluster pour dire qui est qui. La compromission du plan de contrôle devient donc une compromission des identités qu'il atteste, et l'analyse de risque doit le dire explicitement.
Un Secret natif est une copie hors barrière. Révocation, durées courtes et imputabilité s'arrêtent à cette frontière. La voie de synchronisation se réserve aux valeurs dont la sortie est acceptable.
La liaison sans namespace est une porte ouverte. Qui peut créer un namespace et un compte homonyme obtient les droits associés. Les deux dimensions de liaison, plus l'audience, ne sont pas trois options mais un seul contrôle.
Les images et les définitions de service voyagent. Ce qui est écrit dans un manifeste, une variable d'environnement ou une couche d'image finit dans un registre, un dépôt et des journaux.
Erreurs fréquentes¶
Lier un rôle au seul compte de service. Sans contrainte de namespace, l'homonymie suffit à obtenir les droits (section 38.1).
Ignorer l'audience. Un jeton émis pour un autre service devient rejouable auprès de Vault (section 38.1).
Choisir l'opérateur de synchronisation par confort. Le secret quitte la barrière et le modèle de sécurité change de propriétaire (section 38.2).
Installer Vault dans le cluster qu'il sert sans analyse. Les administrateurs de la plateforme deviennent administrateurs des secrets, et la reprise devient circulaire (section 38.3).
Distribuer des fichiers de configuration du cluster à longue durée. Le constat 6 reconstitué sur une autre plateforme (section 38.4).
Passer les secrets par les variables d'environnement du conteneur. Lisibles par inspection, présents dans les définitions versionnées et les journaux d'outillage (section 38.5).
Créer une seconde identité lors d'une migration. Deux identités pour une application, deux histoires dans l'audit, une imputabilité fendue (Exemple).
Mise en pratique : configurer et arbitrer¶
Sur papier ; réponses commentées en fin de partie.
- Rédigez la configuration complète d'un rôle Kubernetes pour un service de traitement d'images qui tourne dans deux namespaces distincts et doit accéder à un stockage objet via des credentials dynamiques, en justifiant chaque paramètre.
- Une équipe demande l'opérateur de synchronisation pour des clés d'API de prestataires de paiement. Rédigez votre réponse : ce que la copie hors barrière change concrètement, ce que vous proposez à la place, et la condition sous laquelle vous accepteriez.
- Comparez les trois modes de consommation sur cinq critères que vous choisirez, et concluez par une règle d'aiguillage utilisable par une équipe qui n'a pas suivi ce cours.
Questions de compréhension¶
- Détaillez les deux dimensions de la liaison d'un rôle et ce que produit l'oubli de la seconde.
- À quoi sert l'audience, et que suppose-t-elle côté manifeste de pod ?
- Quelle identité Vault utilise-t-il vers le cluster, et quel principe du chapitre 18 s'y applique ?
- Comparez les trois modes de consommation sur la fraîcheur des secrets et la surface d'attaque.
- Énoncez la conséquence exacte d'un secret synchronisé vers un Secret natif.
- Quels arguments plaident contre l'installation de Vault dans le cluster qu'il sert ?
- À quoi sert le moteur de secrets Kubernetes, et quel constat du chapitre 1 traite-t-il ?
- Pourquoi les variables d'environnement de conteneur sont-elles un mauvais transport, et quels patrons les remplacent ?
- Pourquoi le chiffrement comme service se marie-t-il bien avec des charges éphémères ?
Synthèse¶
La méthode Kubernetes réalise la promesse du chapitre 10, aucun secret distribué, à condition de poser correctement ses trois contrôles : liaison au compte de service, liaison au namespace, audience exigée. La consommation dans les pods se décide ensuite entre trois voies dont la comparaison ne se résume pas au confort : les gabarits préservent la fraîcheur et gardent le secret dans la frontière, le pilote offre un compromis, et l'opérateur de synchronisation copie le secret hors de la barrière, où révocation, durées et imputabilité perdent leur prise. L'installation de Vault dans le cluster relève de la même analyse, avec un piège de reprise circulaire en prime. Le moteur de secrets traite enfin le constat 6 sur cette plateforme. Déclenche le TP optionnel (énoncé en partie XV).