Une machine qu'on configure à la main après son démarrage est une machine qu'on ne saura pas recréer. Cette leçon montre comment préparer une instance au moment où elle démarre, avec une image système et un fichier de configuration lu par cloud-init, puis comment elle obtient des identifiants temporaires auprès du service de métadonnées. Elle montre aussi, mesures à l'appui, ce que cette configuration de démarrage laisse derrière elle sur le disque, parce que c'est le point où l'on se croit à tort protégé.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Préparer une machine au démarrage avec cloud-init, sans y toucher ensuite.
- Distinguer ce qui appartient à l'image de ce qui appartient au démarrage.
- Vérifier ce que cloud-init conserve sur le disque, et qui peut le lire.
- Protéger le service de métadonnées, cible d'une classe d'attaques connue.
L'image, et la préparation au démarrage
Section intitulée « L'image, et la préparation au démarrage »Une image est le disque de départ de votre machine. Trois façons de faire cohabitent, et le choix a des conséquences sur la sécurité comme sur le temps de démarrage.
| Approche | Comment | Ce qu'elle coûte |
|---|---|---|
| Image officielle plus configuration au démarrage | cloud-init installe et configure | démarrage plus long, dépendances externes |
| Image préparée par vous | construite en amont, prête à l'emploi | un travail de fabrication, et un cycle de mise à jour |
| Image officielle plus configuration manuelle | quelqu'un se connecte et installe | à éviter : rien n'est reproductible |
La troisième ligne mérite son avertissement. Une machine configurée à la main est une machine que personne ne saura recréer à l'identique, y compris celui qui l'a faite. Le jour où elle tombe, l'incident dure le temps de retrouver ce qui avait été installé, et cette durée ne se budgète pas.
cloud-init est le mécanisme standard, présent sur pratiquement toutes les images Linux officielles, quel que soit le fournisseur. Il lit une configuration que vous fournissez à la création et l'applique au premier démarrage.
#cloud-configpackage_update: truepackages: - nginxusers: - name: appli groups: [sudo] shell: /bin/bash ssh_authorized_keys: - ssh-ed25519 AAAA... votre-clewrite_files: - path: /etc/nginx/conf.d/app.conf content: | server { listen 8080; root /var/www/app; }runcmd: - systemctl enable --now nginxLes cinq natures de données qu'une instance reçoit au démarrage
Section intitulée « Les cinq natures de données qu'une instance reçoit au démarrage »Parler de « métadonnées » au singulier fait perdre la distinction qui compte pour la sécurité. Une instance reçoit cinq choses différentes, qui n'ont ni la même origine, ni la même durée de vie, ni les mêmes droits de lecture.
| Nature | Qui l'écrit | Ce que c'est | Durée de vie |
|---|---|---|---|
| metadata | le fournisseur | identifiant, zone, type, nom d'hôte | tant que l'instance existe |
| user-data | vous | la configuration cloud-init que vous fournissez | conservée sur le disque après le boot |
| vendor-data | le fournisseur | réglages qu'il impose ou propose par défaut | idem user-data |
| identifiants temporaires | le fournisseur | jeton d'accès lié au rôle de l'instance | quelques heures, renouvelé |
| identité d'instance | le fournisseur | document signé prouvant « je suis cette instance » | à la demande |
La ligne à retenir est la deuxième. Les identifiants temporaires expirent, pas votre user-data : il reste lisible sur le disque, dans le même état qu'au moment de la création de la machine. C'est la seule des cinq natures que vous écrivez, et la seule qui ne se révoque pas.
Que garde cloud-init sur le disque après le premier démarrage ?
Section intitulée « Que garde cloud-init sur le disque après le premier démarrage ? »cloud-init conserve votre user-data en clair sur le disque, définitivement, et tout ce qu'il conserve n'est pas protégé de la même façon. Mesuré le 20 septembre 2026 sur deux machines virtuelles fraîchement démarrées, AlmaLinux 10.2 avec cloud-init 24.4 et Debian 13 avec cloud-init 25.1.4, toutes deux sur la source de données NoCloud :
| Fichier | Droits | Lisible sans privilège |
|---|---|---|
/var/lib/cloud/instance/user-data.txt | -rw------- root:root | non |
/run/cloud-init/instance-data-sensitive.json | -rw------- root:root | non |
/run/cloud-init/instance-data.json | -rw-r--r-- root:root | oui |
/var/lib/cloud/seed/nocloud-net/user-data | -rw-r--r-- root:root | oui |
Les deux premières lignes montrent que cloud-init fait son travail : le
user-data recopié dans /var/lib/cloud/instance/ est en 0600, et la
variante sensible de l'inventaire aussi. La commande cloud-init query
applique la même règle et refuse de servir un compte ordinaire :
# Sans privilège, cloud-init caviarde volontairement sa réponsecloud-init query userdataLa quatrième ligne annule cette protection. Avec la source de données
NoCloud, celle que vous obtenez avec libvirt, Incus, Proxmox ou une clé USB,
le fichier d'amorçage reste sur le disque en 0644 : n'importe quel compte
local relit l'intégralité du user-data, y compris ce que cloud-init s'est
donné la peine de protéger deux répertoires plus loin. Sur un cloud public qui
sert ses données par le service de métadonnées, il n'y a pas de seed sur le
disque et cette ligne disparaît, mais les trois autres restent vraies.
Le service de métadonnées : ce que votre machine sait d'elle-même
Section intitulée « Le service de métadonnées : ce que votre machine sait d'elle-même »Chaque machine du cloud peut interroger une adresse locale spéciale qui lui répond sur sa propre configuration, et, surtout, lui remet des identifiants temporaires. C'est le mécanisme qui rend possible l'identité attachée à la ressource décrite dans le principe API-first : l'application n'embarque aucun mot de passe, elle demande un jeton au moment de s'en servir.
Cette adresse est locale au serveur physique : elle n'est pas routée depuis l'extérieur, elle ne répond qu'aux processus de la machine elle-même, et la réponse lui est propre. C'est justement ce qui en fait une cible : tout ce qui parvient à émettre une requête depuis la machine parle au service de métadonnées avec les droits de la machine.
Comment protéger le service de métadonnées d'un détournement SSRF ?
Section intitulée « Comment protéger le service de métadonnées d'un détournement SSRF ? »La menace principale est la falsification de requête côté serveur, ou SSRF. Une application qui accepte une URL fournie par l'utilisateur et va la chercher peut être détournée pour interroger l'adresse de métadonnées et renvoyer le jeton dans sa réponse. Des compromissions majeures ont eu exactement cette cause, et aucune n'a demandé d'accès préalable à la machine.
Quatre protections, à appliquer ensemble plutôt qu'à choisir :
| Protection | Ce qu'elle casse | Où elle se règle |
|---|---|---|
| Version durcie du protocole | la requête simple qui suffisait à lire le jeton : il faut d'abord obtenir un jeton de session par une requête préalable | à la création de l'instance, puis rendue obligatoire par politique |
| Limite de sauts réseau | la réponse qui ressortait du serveur vers un conteneur ou un proxy | même réglage, côté fournisseur |
| Rôle le plus étroit possible | l'ampleur des dégâts : un rôle qui ne lit qu'un seul seau limite la fuite à ce seau | dans la politique d'accès attachée à l'instance |
| Blocage depuis les conteneurs | l'accès des charges non fiables, qui n'ont aucune raison d'interroger l'adresse | dans l'orchestrateur, la plupart offrent le réglage |
Le contrôle est immédiat, et il se fait depuis la machine : une requête vers l'adresse de métadonnées sans jeton de session préalable doit être refusée si la version durcie est bien imposée. Si elle répond, le réglage n'est pas appliqué, quelle que soit la case cochée dans la console.
À retenir
Section intitulée « À retenir »- L'image porte ce qui est stable, le démarrage porte ce qui est propre à la machine. Mélanger les deux produit une image qu'on ne sait plus reconstruire.
- cloud-init conserve votre user-data en clair sur le disque, dans
/var/lib/cloud/instance/user-data.txt, bien après le premier démarrage. - Les droits sont corrects là où cloud-init les pose,
0600, etcloud-init querycaviarde sa sortie pour un compte ordinaire. - Avec la source NoCloud, le seed reste en
0644et rend le user-data lisible par tout compte local. Vérifiez-le, ne le supposez pas. - Un secret dans user-data est un secret publié : il part dans les sauvegardes et les images dérivées. Utilisez un rôle d'instance et un gestionnaire de secrets.
- Le service de métadonnées se protège par la version durcie du protocole, un rôle étroit et le blocage depuis les conteneurs, les trois ensemble.