Aller au contenu
English
Compte : non connecté, synchronisation possible Mon apprentissage
Selectionner le thème
English

Images, cloud-init et service de métadonnées

Par mis à jour le

Améliorer cette page

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é.

  • Situer cloud-init dans la préparation d'une machine au démarrage, sans y toucher ensuite (l'écriture pas à pas d'un fichier est l'objet de la leçon suivante).
  • Distinguer ce qui appartient à l'image de ce qui appartient au démarrage.
  • Créer une machine sans adresse publique, et dire par où elle sort pour installer ses paquets.
  • 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.

Aucune connaissance préalable du réseau n'est nécessaire : les deux notions utiles sont définies ici. Un réseau privé est un réseau interne au cloud, sans accès direct depuis Internet : les machines qu'on y rattache s'y parlent par des adresses privées. Une passerelle (gateway) est l'équipement qui relie ce réseau privé à Internet pour que ses machines puissent sortir. Le module Réseau approfondit les deux, dans les leçons sur le réseau privé et ses sous-réseaux et sur les tables de routage et les passerelles.

Pour rejouer la commande de création sans compte cloud, il faut le client scw (version 2.65.1) et l'émulateur Feint 0.13.0 lancé (feint serve dans un terminal, ou le conteneur présenté dans l'installation de Feint), avec scw pointé sur lui par eval "$(feint env scaleway)". Le réseau privé se crée sur place, dans la leçon.

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.

ApprocheCommentCe qu'elle coûte
Image officielle plus configuration au démarragecloud-init installe et configuredémarrage plus long, dépendances externes
Image préparée par vousconstruite en amont, prête à l'emploiun travail de fabrication, et un cycle de mise à jour
Image officielle plus configuration manuellequelqu'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-config
package_update: true
packages:
- nginx
users:
- name: appli
groups: [sudo]
shell: /bin/bash
ssh_authorized_keys:
- ssh-ed25519 AAAA... votre-cle
write_files:
- path: /etc/nginx/conf.d/app.conf
content: |
server { listen 8080; root /var/www/app; }
runcmd:
- systemctl enable --now nginx

Ce fichier YAML, qui commence obligatoirement par #cloud-config, s'appelle le user-data : il crée un utilisateur, installe un paquet, dépose un fichier et lance une commande, le tout sans que personne se connecte à la machine.

Comment créer une machine sans adresse publique ?

Section intitulée « Comment créer une machine sans adresse publique ? »

Une machine qui n'a pas besoin d'être jointe depuis Internet ne doit pas recevoir d'adresse publique. Une adresse publique est la première des trois conditions pour qu'une machine soit exposée (une adresse joignable, un chemin depuis Internet, une règle qui autorise le trafic), comme l'approfondit la leçon sur le réseau privé et ses sous-réseaux : ne pas la donner supprime d'emblée la surface la plus attaquée. Ce que la machine perd en échange, c'est sa sortie : sans adresse publique, elle ne peut plus télécharger ses paquets au démarrage, sauf si le réseau lui offre un chemin.

Chez Scaleway, on demande explicitement l'absence d'adresse avec ip=none. L'argument vaut « aucune adresse publique » dans l'aide de la commande ; dans la console, il s'agit de décocher les cases IPv4 et IPv6 publiques.

Fenêtre de terminal
SRV=$(scw instance server create name=app-privee type=DEV1-S image=ubuntu_jammy \
ip=none zone=fr-par-1 -o json | jq -r .id)

Cette commande ne suffit pas : une machine créée avec ip=none n'a aucune interface réseau privée, donc aucune sortie, même vers un réseau interne. Il faut lui en ajouter une, qui la rattache à un réseau privé. Ce réseau n'existe pas encore : créez-le (le nom lab-amorcage est libre) et gardez son identifiant dans PN.

Fenêtre de terminal
PN=$(scw vpc private-network create name=lab-amorcage -o json | jq -r .id)

La sortie JSON de la commande est l'objet du réseau lui-même, sans enveloppe : le champ id s'y lit directement. L'aide de la version 2.65.1 déclare vpc-id facultatif, et Feint 0.13.0 rattache alors le réseau à un VPC (le réseau virtuel qui contient les réseaux privés) qu'il crée de lui-même. Sur un vrai compte, ce rattachement par défaut n'a pas été rejoué ici : passez vpc-id=<ID_VPC> si la commande le réclame. Rattachez ensuite la machine à ce réseau :

Fenêtre de terminal
scw instance private-nic create server-id="$SRV" private-network-id="$PN" zone=fr-par-1

Avec la version 2.65.1 du client, l'aide de scw instance server create ne propose toujours pas d'argument de réseau privé : la création de l'interface reste donc un second geste. Ces trois commandes se rejouent telles quelles sur Feint 0.13.0, en pointant scw sur l'émulateur. La création du réseau renvoie un identifiant (UUID) de la forme 7337612c-7b4f-4de8-8448-1b4f41d3261e, chaque exécution en donne un autre.

Pour vérifier, relisez la machine avec scw instance server get "$SRV" zone=fr-par-1 : la section Public IPs: ne contient que sa ligne d'en-tête, sans aucune adresse, et la section Private NICs: liste maintenant l'interface rattachée (avec -o json, public_ips vaut [] et public_ip vaut null). Sur un vrai compte, cette machine est facturée tant qu'elle existe. Le nettoyage se fait dans l'ordre inverse de la création : l'interface, la machine, puis le réseau. Un réseau qui porte encore une interface refuse sa suppression (sur Feint : private network still has 1 attached NIC(s)).

Fenêtre de terminal
NIC=$(scw instance private-nic list server-id="$SRV" zone=fr-par-1 -o json | jq -r '.[0].id')
scw instance private-nic delete server-id="$SRV" private-nic-id="$NIC" zone=fr-par-1
scw instance server terminate "$SRV" zone=fr-par-1 with-ip=true with-block=true
scw vpc private-network delete "$PN"

La première commande n'affiche rien : elle range l'identifiant de l'interface dans NIC. La suppression de l'interface répond Private-nic has been successfully deleted., celle de la machine Success., et celle du réseau n'affiche qu'un tiret. L'option with-block=true de terminate retire aussi le disque de la machine. Pour contrôler que rien ne reste, scw instance server list zone=fr-par-1 -o json | jq length et scw vpc private-network list -o json | jq length doivent afficher 0 sur un Feint neuf.

Une Public Gateway est un équipement managé qui relie un réseau privé à Internet : elle traduit les adresses privées des machines vers une adresse publique, et c'est par elle qu'une machine sans adresse publique sort. Pour que la vôtre atteigne Internet, par exemple pour que cloud-init installe des paquets, la passerelle doit être rattachée à ce réseau privé. La leçon sur les tables de routage et les passerelles approfondit ce rattachement, que cette leçon ne réalise pas.

Chez OUTSCALE, la réponse dépend de l'endroit où la machine est créée. Dans un Net, une machine ne reçoit aucune adresse publique par défaut : la propriété MapPublicIpOnLaunch du sous-réseau vaut false par défaut, et ce n'est que si vous la passez à true que les cartes réseau créées dans ce sous-réseau reçoivent une adresse publique. Sinon, on en ajoute une explicitement, avec les actions CreatePublicIp puis LinkPublicIp. Hors Net, dans ce qu'OUTSCALE appelle le Cloud public, la machine reçoit au contraire une adresse publique, sauf si le tag private_only est présent dans son user-data. Vérifiez dans votre compte que ce Cloud public existe encore pour vous : la documentation consultée ne le précise pas pour un compte récent.

Avec Incus, la question ne se pose pas dans ces termes, parce qu'il n'y a pas de notion d'adresse publique. L'instance reçoit une adresse privée du pont géré par Incus, et sa sortie passe par la traduction d'adresses (NAT) de ce pont, l'option ipv4.nat. Cette option vaut false par défaut, mais elle est à true sur un pont créé avec ipv4.address=auto, ce qui est le cas du pont incusbr0 des installations courantes. C'est ce qui permet à la leçon suivante, sur l'écriture d'un user-data, d'installer des paquets depuis une machine qui n'a aucune adresse publique.

Les 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.

NatureQui l'écritCe que c'estDurée de vie
metadatale fournisseuridentifiant, zone, type, nom d'hôtetant que l'instance existe
user-datavousla configuration cloud-init que vous fournissezconservée sur le disque après le boot
vendor-datale fournisseurréglages qu'il impose ou propose par défautidem user-data
identifiants temporairesle fournisseurjeton d'accès lié au rôle de l'instancequelques heures, renouvelé
identité d'instancele fournisseurdocument 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 :

FichierDroitsLisible sans privilège
/var/lib/cloud/instance/user-data.txt-rw------- root:rootnon
/run/cloud-init/instance-data-sensitive.json-rw------- root:rootnon
/run/cloud-init/instance-data.json-rw-r--r-- root:rootoui
/var/lib/cloud/seed/nocloud-net/user-data-rw-r--r-- root:rootoui

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 :

/var/lib/cloud/instance/user-data.txt
# Sans privilège, cloud-init caviarde volontairement sa réponse
cloud-init query userdata

La 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, approfondie dans la leçon sur les identifiants courts : 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 :

ProtectionCe qu'elle casseOù elle se règle
Version durcie du protocolela 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éseaula réponse qui ressortait du serveur vers un conteneur ou un proxymême réglage, côté fournisseur
Rôle le plus étroit possiblel'ampleur des dégâts : un rôle qui ne lit qu'un seul seau limite la fuite à ce seaudans la politique d'accès attachée à l'instance
Blocage depuis les conteneursl'accès des charges non fiables, qui n'ont aucune raison d'interroger l'adressedans 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.

  • 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.
  • Une machine sans adresse publique se demande explicitement chez Scaleway (ip=none), est le comportement par défaut dans un Net OUTSCALE (MapPublicIpOnLaunch à false), et n'existe pas sous cette forme avec Incus, où la sortie passe par le NAT du pont. Dans les clouds, sa sortie passe par une passerelle.
  • 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, et cloud-init query caviarde sa sortie pour un compte ordinaire.
  • Avec la source NoCloud, le seed reste en 0644 et 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, la limite de sauts réseau, un rôle étroit et le blocage depuis les conteneurs, les quatre ensemble.

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

Ce projet vous est utile ?

Les guides, formations, quiz et labs restent gratuits. Si vous les utilisez régulièrement, vous pouvez contribuer à leur maintenance et à leur développement.

Devenir membre de soutien (nouvel onglet) Soutenir une fois (nouvel onglet) En savoir plus

Suivez aussi le projet sur LinkedIn