Aller au contenu
Infrastructure as Code medium

Valeurs éphémères Terraform : le secret hors du state

15 min de lecture

logo terraform

Une valeur éphémère existe pendant une opération Terraform, puis disparaît : elle n'est jamais écrite dans le state ni dans le plan. C'est la seule réponse réelle au problème que sensitive ne résout pas, puisque sensitive laisse la valeur en clair dans l'état. Le déclarer est simple ; les pièges sont dans la règle d'or (jamais dans un attribut persisté) et dans les deux erreurs que le module racine renvoie.

Ce guide part de la base, le bloc ephemeral, puis traite les contextes autorisés, ephemeralasnull(), les variables éphémères et la preuve. L'éphémère est arrivé en Terraform 1.10, et tout ce guide tourne dès cette version, sur 1.15.4 (vérifié) avec random >= 3.7 pour ephemeral "random_password".

  • Déclarer une valeur éphémère avec le bloc ephemeral
  • La règle d'or : jamais dans un attribut persisté
  • Les contextes autorisés, et les deux erreurs du module racine
  • ephemeralasnull() pour exposer sans fuiter
  • Les variables et outputs éphémères, et comment le prouver
  • Les données sensibles (sensitive en Terraform)
  • Terraform 1.10 ou plus (1.15.x recommandé), et random >= 3.7

Un bloc ephemeral produit une valeur générée à la volée, jamais persistée. On la référence par ephemeral.<TYPE>.<NOM>.<ATTR> :

ephemeral "random_password" "session" {
length = 24
}

ephemeral.random_password.session.result est disponible pendant le run, mais n'apparaît nulle part dans le state. Contrairement à un random_password ordinaire, dont le result est stocké en clair dans l'état, l'éphémère ne laisse aucune trace sur le disque. Son cycle de vie se déroule en open / renew / close pendant l'opération, invisible dans l'état.

La règle d'or : jamais dans un attribut persisté

Section intitulée « La règle d'or : jamais dans un attribut persisté »

Une valeur éphémère ne peut aller que dans des contextes éphémères. La lui faire toucher un attribut persisté lève une erreur nette :

resource "local_file" "fuite" {
content = ephemeral.random_password.session.result # interdit
}
Error: Invalid use of ephemeral value

Le détail du message est explicite : « Ephemeral values are not valid for "content", because it is not a write-only attribute and must be persisted to state. » Les contextes autorisés, au nombre de sept, sont : un argument write-only d'une ressource, un autre bloc ephemeral, un local consommé uniquement en contexte éphémère, une variable ephemeral = true, une configuration de provider, un provisioner (et sa configuration de connexion), et un output éphémère de module enfant.

Au niveau racine, un output ne peut pas porter d'éphémère, et cela se manifeste de deux façons distinctes, à ne pas confondre :

  • déclarer un output ephemeral = true à la racine renvoie Ephemeral output not allowed : « Ephemeral outputs are not allowed in context of a root module » ;
  • exposer dans un output racine ordinaire une valeur dérivée d'un éphémère, même sa simple longueur, renvoie Ephemeral value not allowed.

C'est ce second cas que l'on rencontre en premier, dès qu'on essaie d'afficher un éphémère « pour voir ». La sensibilité éphémère se propage : length(ephemeral...) est encore éphémère.

Comment, alors, exposer quelque chose au root sans casser le run ? La fonction ephemeralasnull() rend null toute valeur éphémère hors contexte éphémère :

output "session_masquee" {
value = ephemeralasnull(ephemeral.random_password.session.result)
}

L'output vaut null. Ce n'est pas un affichage du secret, c'est sa neutre mise à l'écart : la valeur éphémère ne franchit pas la frontière du state. Sur une valeur non éphémère, ephemeralasnull() renvoie la valeur telle quelle, ce qui en fait aussi un bon révélateur : un null prouve que l'entrée était bien éphémère.

Depuis Terraform 1.10, une variable peut être ephemeral = true : sa valeur alimente le run mais n'est jamais persistée. Un output de module enfant peut l'être aussi, pour faire remonter un éphémère vers le module appelant sans jamais l'écrire.

variable "jeton_api" {
type = string
ephemeral = true
}

La preuve utile ne se lit pas dans les seuls values.outputs : une valeur éphémère ne peut de toute façon jamais s'y trouver, donc le contrôle passerait même sans rien avoir fait d'éphémère. La bonne preuve porte sur l'intégralité du state et sur le plan converti en JSON :

Fenêtre de terminal
terraform show -json | jq '[.values.root_module.resources[].address]'

L'éphémère n'apparaît nulle part dans cette liste, là où un random_password ordinaire y figure avec son result en clair. C'est le contraste qui prouve qu'une valeur a bien été tenue hors du state.

Ces symptômes viennent tous de la frontière entre éphémère et persisté.

SymptômeCauseSolution
Invalid use of ephemeral valueUn éphémère dans un attribut persistéLe déplacer vers un contexte éphémère (write-only, provider, local éphémère)
Ephemeral value not allowedUn output racine dérive d'un éphémèreL'envelopper dans ephemeralasnull(), ou ne pas l'exposer
Ephemeral output not allowedUn output racine déclaré ephemeral = trueRéserver les outputs éphémères aux modules enfants
ephemeral "random_password" inconnuProvider random trop ancienExiger random >= 3.7.0
Un secret apparaît dans le stateUne ressource ordinaire au lieu d'éphémèrePasser le bloc en ephemeral
  1. Une valeur éphémère n'est jamais écrite dans le state ni le plan.
  2. Elle ne va que dans un contexte éphémère ; ailleurs, Invalid use of ephemeral value.
  3. Le module racine renvoie deux erreurs distinctes : Ephemeral output not allowed et Ephemeral value not allowed.
  4. ephemeralasnull() expose une valeur éphémère en null, sans la fuiter.
  5. Variables et outputs éphémères datent de 1.10 ; ephemeral "random_password" demande random >= 3.7.
  6. La preuve porte sur tout le state, pas sur les seuls outputs.

Les questions ci-dessous reprennent les confusions les plus fréquentes sur les valeurs éphémères : la différence avec sensitive, la règle d'or, et ephemeralasnull().

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn