Aller au contenu
Infrastructure as Code medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Ressources éphémères Terraform

14 min de lecture

logo terraform

Le bloc ephemeral crée des ressources temporaires que Terraform ne stocke jamais dans le state ni dans le plan. Contrairement à sensitive = true qui masque l’affichage mais conserve la valeur dans le state, une ressource éphémère existe uniquement pendant l’opération Terraform en cours. Elle est ouverte au début, éventuellement renouvelée, puis fermée. Le cas d’usage principal : générer un mot de passe ou récupérer un secret pour le passer à un argument write-only, sans laisser de trace.

  • Déclarer une ressource éphémère : syntaxe du bloc ephemeral
  • Comprendre le lifecycle : open → renew → close
  • Savoir où les utiliser : contextes autorisés et interdits
  • Déclarer une variable éphémère : ephemeral = true sur une variable
  • Utiliser les meta-arguments : count, for_each, precondition

Pensez à une note autocollante que vous lisez puis détruisez :

# Valeur classique : stockée dans un fichier
with open("state.json", "w") as f:
json.dump({"password": "S3cr3t!"}, f) # reste sur le disque
# Valeur éphémère : en mémoire seulement
password = generate_password()
use_password(password)
del password # disparue, jamais écrite sur disque

ephemeral c’est la variable locale qui n’est jamais sérialisée. Terraform la crée en mémoire, l’utilise pendant l’opération, puis la libère. Aucun fichier (state, plan, logs) ne contient cette valeur.

Avec sensitive = true, un mot de passe reste lisible dans le state :

Fenêtre de terminal
terraform show -json | python3 -c "
import sys, json
d = json.load(sys.stdin)
for k, v in d['values']['outputs'].items():
print(f'{k}: {v[\"value\"]}')
"
db_password: S3cr3t!P@ssw0rd

Le state est le fichier que Terraform utilise pour suivre l’état de votre infrastructure. Toute personne ayant accès au state (fichier local, bucket S3, workspace HCP Terraform) voit le secret en clair. Les ressources éphémères résolvent ce problème : Terraform ne les écrit tout simplement pas dans le state.

La syntaxe ressemble à un bloc resource, mais avec le mot-clé ephemeral :

ephemeral "random_password" "db_password" {
length = 16
override_special = "!#$%&*()-_=+[]{}<>:?"
}

On référence la valeur avec ephemeral.<TYPE>.<NOM>.<ATTRIBUT> :

ephemeral.random_password.db_password.result

Contrairement aux ressources classiques (create → read → update → delete), une ressource éphémère suit un cycle différent :

PhaseMomentCe qui se passe
openDébut du plan ou de l’applyLe provider crée la valeur temporaire
renewSi la ressource a un TTLLe provider renouvelle le bail avant expiration
closeFin de l’opération TerraformLe provider libère la ressource, Terraform oublie la valeur

En pratique, vous verrez ce cycle dans la sortie Terraform :

ephemeral.random_password.db_password: Opening...
ephemeral.random_password.db_password: Opening complete after 0s
ephemeral.random_password.db_password: Closing...
ephemeral.random_password.db_password: Closing complete after 1s

Terraform restreint l’usage des valeurs éphémères à des contextes qui ne persistent pas les données :

Contexte autoriséExemple
Arguments write-only d’un resourcepassword_wo = ephemeral.random_password.db.result
Autre bloc ephemeralUn ephemeral qui référence un autre ephemeral
localslocal.conn = "user:${ephemeral.random_password.db.result}@host"
Variables ephemeral = truePasser une valeur éphémère en entrée d’un module
Configuration d’un providerCredentials éphémères dans un bloc provider
Provisionerslocal-exec qui utilise la valeur pendant l’apply
Contexte interditPourquoi
Attributs classiques d’un resourceTerraform les stockerait dans le state
Outputs du module racine (sans ephemeral = true)La valeur serait persistée
Bloc dataLe résultat est stocké dans le state

Cet exemple utilise uniquement le provider random, testable localement sans infrastructure cloud.

Créez versions.tf :

terraform {
required_version = ">= 1.11.0"
required_providers {
random = {
source = "hashicorp/random"
version = "~> 3.0"
}
null = {
source = "hashicorp/null"
version = "~> 3.0"
}
}
}

Créez variables.tf :

variable "password_length" {
description = "Longueur du mot de passe éphémère"
type = number
default = 16
}

Créez main.tf :

ephemeral "random_password" "db_password" {
length = var.password_length
override_special = "!#$%&*()-_=+[]{}<>:?"
}
locals {
db_connection = "postgres://admin:${ephemeral.random_password.db_password.result}@db:5432"
}
resource "null_resource" "use_ephemeral" {
triggers = {
always = timestamp()
}
provisioner "local-exec" {
command = "echo 'Password length: ${var.password_length} — connection configured'"
}
}
Fenêtre de terminal
terraform init
terraform plan

Vous verrez le lifecycle éphémère dans la sortie :

ephemeral.random_password.db_password: Opening...
ephemeral.random_password.db_password: Opening complete after 0s
ephemeral.random_password.db_password: Closing...
ephemeral.random_password.db_password: Closing complete after 1s

Appliquez et vérifiez l’absence dans le state :

Fenêtre de terminal
terraform apply -auto-approve
terraform show -json | python3 -c "
import sys, json
d = json.load(sys.stdin)
outputs = d.get('values', {}).get('outputs', {})
for k, v in outputs.items():
print(f'{k}: {v[\"value\"]}')
"
password_length: 16

Le mot de passe éphémère n’apparaît nulle part dans le state. Seul password_length, qui est une variable normale, est stocké.

Depuis Terraform 1.11, vous pouvez déclarer une variable comme éphémère avec ephemeral = true :

variable "api_token" {
description = "Token d'API temporaire"
type = string
sensitive = true
ephemeral = true
}

Une variable éphémère :

  • n’est pas stockée dans le state ni dans le plan ;
  • ne peut être utilisée que dans les contextes autorisés (write-only, locals, provider config, etc.) ;
  • se combine naturellement avec sensitive = true pour masquer aussi l’affichage CLI.

Dans un module enfant, vous pouvez déclarer un output éphémère :

modules/credentials/outputs.tf
output "db_password" {
description = "Mot de passe éphémère pour la base"
value = ephemeral.random_password.db.result
ephemeral = true
}

Le module parent peut alors utiliser module.credentials.db_password dans un contexte éphémère (write-only, provider config, etc.).

Les blocs ephemeral supportent les mêmes meta-arguments que les blocs resource :

Meta-argumentUsage avec ephemeral
countCréer N instances éphémères
for_eachItérer sur un ensemble de clés
depends_onForcer l’ordre avec d’autres ressources
providerChoisir un alias de provider
lifecycleprecondition et postcondition uniquement
variable "environments" {
type = set(string)
default = ["dev", "staging", "prod"]
}
ephemeral "random_password" "per_env" {
for_each = var.environments
length = 20
override_special = "!#$%&*()-_=+[]{}<>:?"
}

Chaque environnement obtient son propre mot de passe éphémère, accessible via ephemeral.random_password.per_env["dev"].result.

ephemeral "random_password" "validated" {
length = var.password_length
override_special = "!#$%&*()-_=+[]{}<>:?"
lifecycle {
precondition {
condition = var.password_length >= 12
error_message = "Le mot de passe doit faire au moins 12 caractères."
}
}
}
ConceptBloc resource classiqueBloc ephemeral
Stocké dans le stateOuiNon
Stocké dans le planOuiNon
Lifecyclecreate → read → update → deleteopen → renew → close
Référenceresource_type.name.attrephemeral.type.name.attr
Meta-argumentsTouscount, for_each, depends_on, provider, lifecycle (precondition/postcondition)

1. Préférer ephemeral à sensitive pour les secrets dynamiques

Section intitulée « 1. Préférer ephemeral à sensitive pour les secrets dynamiques »

Si le secret est généré pendant l’opération Terraform (mot de passe, token, certificat), utilisez une ressource éphémère plutôt qu’une resource classique avec sensitive = true.

2. Combiner sensitive + ephemeral sur les variables d’entrée

Section intitulée « 2. Combiner sensitive + ephemeral sur les variables d’entrée »

Pour un secret passé par l’utilisateur ou le CI/CD, déclarez la variable avec les deux attributs :

variable "vault_token" {
type = string
sensitive = true
ephemeral = true
}

3. Utiliser les valeurs éphémères avec les arguments write-only

Section intitulée « 3. Utiliser les valeurs éphémères avec les arguments write-only »

Le pattern complet est : ephemeral génère la valeur → write-only la transmet au provider → rien n’est stocké. La page suivante détaille ce mécanisme.

4. Ne pas contourner les restrictions de référence

Section intitulée « 4. Ne pas contourner les restrictions de référence »

Si Terraform refuse d’utiliser une valeur éphémère dans un attribut de ressource, c’est pour une bonne raison : cet attribut serait persisté dans le state. Trouvez l’argument write-only correspondant ou repensez l’architecture.

SymptômeCause probableSolution
Invalid use of ephemeral valueValeur éphémère dans un attribut de ressource classiqueUtiliser un argument write-only ou un provisioner
Ephemeral output not allowedOutput ephemeral = true dans le module racineDéplacer dans un module enfant ou supprimer ephemeral
Le lifecycle n’affiche pas renewLa ressource éphémère n’a pas de TTLNormal pour random_password — le renew concerne les connexions temporaires
Provider does not support ephemeral resourcesVersion du provider trop ancienneMettre à jour le provider (random ≥ 3.7.0 pour ephemeral "random_password")
  1. ephemeral crée des ressources temporaires qui n’existent que pendant l’opération Terraform en cours.
  2. Le lifecycle est différent des ressources classiques : open → renew → close au lieu de create → update → delete.
  3. Les valeurs éphémères ne peuvent être utilisées que dans des contextes qui ne persistent pas : write-only, locals, provider config, provisioners.
  4. Les variables éphémères (ephemeral = true) permettent de passer un secret en entrée sans qu’il soit stocké dans le state.
  5. Les outputs éphémères ne fonctionnent que dans les modules enfants, pas dans le module racine.

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn