
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) |
À 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.