
Un argument write-only transmet un secret au provider sans jamais le
persister : ni dans le state, ni dans le plan. C'est le pendant, côté
ressource gérée, de ce que ephemeral fait pour les valeurs : la réponse la plus
propre au problème que sensitive ne résout pas. Arrivé en Terraform 1.11,
il ne fonctionne que pour les attributs qu'un provider déclare explicitement
write_only, et son usage a des règles précises qu'on découvre souvent par
l'erreur.
Ce guide traite la syntaxe *_wo et son argument de version, le couple qui est
mutuellement obligatoire, l'alimentation par une valeur éphémère, la
vérification qu'un argument est bien write-only, et la solution quand aucun _wo
n'existe. Les comportements du langage ont été vérifiés sur Terraform v1.15.4.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Ce qu'est un argument write-only, et sa différence avec
sensitive - Le couple
password_wo/password_wo_version, mutuellement obligatoire - Alimenter un write-only par une valeur éphémère
- Vérifier qu'un attribut est write-only, et où s'entraîner
- La solution quand aucun
_won'existe
Prérequis
Section intitulée « Prérequis »- Les données sensibles (sensitive en Terraform)
- Les valeurs éphémères (ephemeral en Terraform)
- Terraform 1.11 ou plus (1.15.x recommandé)
Un argument qui ne touche pas le state
Section intitulée « Un argument qui ne touche pas le state »Un attribut write-only (suffixe _wo par convention) reçoit une valeur que
le provider consomme, mais que Terraform n'écrit ni dans le state ni dans le
plan. C'est un attribut de schéma de provider : il n'existe que si le
provider le déclare. Sur aws_db_instance, c'est password_wo :
resource "aws_db_instance" "db" { # ... password_wo = ephemeral.random_password.db.result password_wo_version = 1}Contrairement à password (persisté), password_wo ne laisse aucune trace
du mot de passe dans le state.
Le couple _wo et _wo_version est mutuellement obligatoire
Section intitulée « Le couple _wo et _wo_version est mutuellement obligatoire »C'est le piège le plus fréquent, et le guide d'origine le sous-estimait.
password_wo et password_wo_version sont mutuellement obligatoires : dans
le provider AWS, chacun porte un RequiredWith sur l'autre. password_wo seul
est refusé au plan. La validation a été ajoutée en provider AWS v5.89.0.
Le rôle de password_wo_version n'est pas un confort : c'est lui qui décide
quand le provider prend en compte une nouvelle valeur. Comme la valeur n'est
pas persistée, Terraform ne peut pas la comparer d'un run à l'autre. Il ne
planifie donc une mise à jour du secret que si le numéro de version change.
Les conflits à connaître
Section intitulée « Les conflits à connaître »Sur aws_db_instance, password_wo est en conflit avec password (le mot
de passe classique persisté) et avec manage_master_user_password (mot
de passe géré par Secrets Manager). Les trois sont mutuellement exclusifs : on
choisit une seule stratégie de mot de passe.
À noter sur les versions du provider AWS : aws_db_instance.password_wo et
aws_secretsmanager_secret_version.secret_string_wo sont arrivés en v5.88.0 ;
la v5.87.0 n'avait apporté que aws_rds_cluster.master_password_wo et
aws_ssm_parameter.value_wo.
Alimenter un write-only par une valeur éphémère
Section intitulée « Alimenter un write-only par une valeur éphémère »La source idéale d'un write-only est une valeur éphémère, elle aussi hors du
state. Une ressource ephemeral "random_password" (provider random >= 3.7)
génère le secret à la volée :
ephemeral "random_password" "db" { length = 24}
resource "aws_db_instance" "db" { password_wo = ephemeral.random_password.db.result password_wo_version = 1}Un argument write-only est l'un des rares contextes où une valeur éphémère est
autorisée. Les sept sont : un argument write-only, un autre bloc ephemeral,
un locals, une variable ephemeral = true, un output de module enfant
ephemeral = true, une configuration de provider, et un provisioner (ou son
bloc connection).
Vérifier qu'un argument est write-only
Section intitulée « Vérifier qu'un argument est write-only »Inutile de fouiller le Registry : terraform providers schema -json expose un
booléen write_only sur chaque attribut :
terraform providers schema -json | jq '.provider_schemas[].resource_schemas.aws_db_instance.block.attributes.password_wo.write_only'C'est aussi la réponse au dépannage « le provider n'expose pas cet argument » : si le booléen n'existe pas, l'attribut n'est pas write-only, et il faut mettre le provider à jour.
Où s'entraîner : aucun provider gratuit, ou presque
Section intitulée « Où s'entraîner : aucun provider gratuit, ou presque »Point d'honnêteté rarement dit : hors fournisseurs cloud, presque aucun
provider n'expose d'attribut write-only. Vérifié par schéma en 1.15.4,
hashicorp/local, null, random, tls, http, time, external,
archive et la ressource intégrée terraform_data n'en exposent aucun. Chez
HashiCorp, seul hashicorp/vault en expose largement
(vault_kv_secret_v2.data_json_wo, etc.). Sans compte cloud ni Vault, on ne peut
donc pas vraiment pratiquer le write-only lui-même, seulement la valeur éphémère
qui l'alimente.
Quand aucun _wo n'existe : ephemeral de bout en bout
Section intitulée « Quand aucun _wo n'existe : ephemeral de bout en bout »Si le provider n'offre pas d'attribut write-only, la transposition en primitives
du langage est le couple variable { ephemeral = true } en entrée et
output { ephemeral = true } en sortie de module enfant. C'est l'exact
équivalent du contrat write-only, et la seule option hors provider compatible.
Un point à ne pas confondre : une variable de module ne peut pas être
write-only. Le write-only est un attribut de schéma de provider, pas une
construction du langage. Pour un secret qui traverse des modules sans être
persisté, c'est ephemeral, pas write-only.
Comment le prouver
Section intitulée « Comment le prouver »Le guide ne doit pas se contenter d'affirmer que le secret « n'apparaît nulle part ». On le constate :
terraform show -json # state : pas de password_woterraform show -json tfplan # plan : pas de password_woUne ressource éphémère ne produit d'ailleurs aucune entrée dans le state
(ni mode: managed, ni mode: data) : son absence est la preuve.
Dépannage
Section intitulée « Dépannage »Ces symptômes touchent au contrat write-only ou à la frontière éphémère.
| Symptôme | Cause | Solution |
|---|---|---|
Invalid use of ephemeral value | Une valeur éphémère dans un attribut persisté (pas _wo) | La router vers un write-only ou un autre contexte éphémère |
Ephemeral value not allowed | Une valeur éphémère exposée dans un output racine | ephemeralasnull(), ou output éphémère en module enfant |
password_wo refusé au plan | password_wo_version manquant (couple obligatoire) | Ajouter password_wo_version |
| Le mot de passe ne change pas | password_wo modifié sans changer la version | Incrémenter password_wo_version |
Conflit sur password_wo | password ou manage_master_user_password aussi défini | Ne garder qu'une stratégie de mot de passe |
L'argument _wo n'existe pas | Provider trop ancien | Mettre à jour le provider (v5.88.0+ pour aws_db_instance) |
Mettre en pratique
Section intitulée « Mettre en pratique »Les arguments write-only transmettent un secret au provider sans jamais le persister dans le state, ce qui répond au reproche le plus sérieux fait à Terraform sur la gestion des secrets. Le lab se joue contre un émulateur AWS local, donc sans compte ni coût, et la validation vérifie l'absence de la valeur dans le state produit.
À retenir
Section intitulée « À retenir »- Un argument write-only (
*_wo) transmet un secret au provider sans le persister ; c'est un attribut de schéma de provider (Terraform 1.11). _woet_wo_versionsont mutuellement obligatoires ;_woseul est refusé.- Oublier d'incrémenter la version ne change pas le secret.
- La source idéale d'un write-only est une valeur éphémère ; il n'y a pas de dérivée persistable d'un secret éphémère.
terraform providers schema -jsonexpose le booléenwrite_only; presque aucun provider gratuit n'en a (saufvault).- Sans
_wo, la transposition estvariable/outputephemeral = true; une variable de module ne peut pas être write-only.
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »Les questions ci-dessous reprennent les confusions les plus fréquentes sur les arguments write-only : le rôle de la version, les conflits, et la source éphémère.
Un secret qui ne touche pas le state
Un attribut write-only (suffixe_wo) reçoit une valeur que le provider consomme, mais que Terraform n'écrit ni dans le state ni dans le plan.resource "aws_db_instance" "db" {
password_wo = ephemeral.random_password.db.result
password_wo_version = 1
}
Un attribut de provider
Contrairement àephemeral, qui est une construction du langage, le write-only est un attribut de schéma de provider : il n'existe que si le provider le déclare. Arrivé en Terraform 1.11.Un couple obligatoire
password_wo et password_wo_version sont mutuellement obligatoires : dans le provider AWS, chacun porte un RequiredWith sur l'autre. password_wo seul est refusé au plan. Validation ajoutée en provider AWS v5.89.0.Le rôle de la version
Comme la valeur n'est pas persistée, Terraform ne peut pas la comparer d'un run à l'autre. Il ne planifie une mise à jour du secret que sipassword_wo_version change.La version pilote le changement
Si vous changez la valeur depassword_wo mais pas password_wo_version, Terraform ne planifie aucune mise à jour : le mot de passe n'est pas changé.Pourquoi
Le provider reçoit bien la nouvelle valeur à chaque opération, mais sans changement de version il n'agit pas. Pour tourner un secret, il faut incrémenterpassword_wo_version.La source idéale : une valeur éphémère
ephemeral "random_password" "db" {
length = 24
}
resource "aws_db_instance" "db" {
password_wo = ephemeral.random_password.db.result
password_wo_version = 1
}
Un contexte autorisé
Un argument write-only est l'un des sept contextes où une valeur éphémère est acceptée (avec un autre blocephemeral, un locals, une variable/output éphémère de module enfant, une config de provider, un provisioner). Il n'y a pas de dérivée persistable d'un secret éphémère : sha256(éphémère) reste refusé.Le schéma du provider
terraform providers schema -json | jq '.provider_schemas[].resource_schemas.aws_db_instance.block.attributes.password_wo.write_only'
Chaque attribut porte un booléen write_only.Le dépannage
Si l'argument n'existe pas dans le schéma, l'attribut n'est pas write-only : il faut mettre le provider à jour (par exemple AWS v5.88.0+ pouraws_db_instance.password_wo).Presque aucun provider gratuit
Vérifié par schéma en 1.15.4 :hashicorp/local, null, random, tls, http, time, external, archive et terraform_data n'exposent aucun attribut write-only.La seule exception HashiCorp
hashicorp/vault en expose largement (vault_kv_secret_v2.data_json_wo, etc.). Sans cloud ni Vault, on ne peut donc pas pratiquer le write-only lui-même, seulement la valeur éphémère (ephemeral random_password) qui l'alimente.La transposition en ephemeral
Si le provider n'offre pas d'attribut_wo, le couple variable { ephemeral = true } en entrée et output { ephemeral = true } en sortie de module enfant fait traverser un secret sans le persister. C'est l'exact équivalent du contrat write-only.La confusion à éviter
Une variable de module ne peut pas être write-only : le write-only est un attribut de schéma de provider, pas une construction du langage. Pour un secret qui traverse des modules, c'estephemeral, pas write-only.Pour aller plus loin
Section intitulée « Pour aller plus loin »- Comprendre le state Terraform : Détaille ce que le state enregistre, la raison d'être des arguments write-only.
- Les backends Terraform : Compare les backends et leur chiffrement, complément d'un secret non persisté.
- Sauvegarder et restaurer le state : Manipule une copie du state sans exposer les valeurs qu'il contient encore.