
Les arguments write-only permettent de passer un secret à un provider Terraform sans que cette valeur soit jamais stockée dans le state ou le plan. C’est le dernier maillon de la chaîne de protection des données sensibles : une ressource éphémère génère ou récupère le secret, puis un argument write-only le transmet au provider lors de chaque opération. Terraform envoie la valeur au provider mais ne la conserve nulle part.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Déclarer un argument write-only :
password_wosur une ressource - Comprendre le mécanisme de version :
_wo_versionpour déclencher les mises à jour - Combiner ephemeral + write-only : zéro secret dans le state
- Connaître le cycle complet : générer → stocker → récupérer → utiliser
Prérequis
Section intitulée « Prérequis »- Ressources éphémères comprises (ressources éphémères Terraform)
- sensitive compris (sensitive : masquer les valeurs)
- Terraform ≥ 1.11 installé (installer Terraform)
L’idée derrière les arguments write-only
Section intitulée « L’idée derrière les arguments write-only »Pensez à un coffre-fort avec une fente de dépôt :
# Argument classique : Terraform lit et écritstate["password"] = "S3cr3t!" # stocké dans le statecurrent = state.get("password") # relu au plan suivant
# Argument write-only : Terraform écrit, mais ne stocke jamaisprovider.set_password("S3cr3t!") # envoyé au provider# rien dans le state — Terraform ne peut pas relire la valeurUn argument write-only c’est une fente de dépôt : vous glissez la valeur, le provider la reçoit et l’utilise, mais personne ne peut la récupérer après. Terraform envoie la valeur à chaque opération parce qu’il ne la stocke pas.
Le problème résolu
Section intitulée « Le problème résolu »Avec une resource classique, même marquée sensitive = true, le mot de passe d’une base de données se retrouve dans le state :
resource "aws_db_instance" "main" { instance_class = "db.t3.micro" engine = "postgres" username = "admin" password = var.db_password # ← stocké dans le state}Après un terraform apply, la valeur de password est lisible en clair dans terraform.tfstate. L’argument password_wo remplace ce comportement : le provider reçoit la valeur, mais Terraform ne la stocke jamais.
Déclarer un argument write-only
Section intitulée « Déclarer un argument write-only »Les providers indiquent dans le Terraform Registry quels arguments sont write-only. Par exemple, la ressource aws_db_instance expose password_wo :
resource "aws_db_instance" "example" { identifier = "my-database" instance_class = "db.t3.micro" allocated_storage = 5 engine = "postgres" username = "admin" skip_final_snapshot = true
password_wo = "MonMotDePasse!" password_wo_version = 1}Deux points importants :
password_woaccepte la valeur du mot de passe. Terraform l’envoie au provider à chaque opération (plan, apply), mais ne la stocke ni dans le state ni dans le plan.password_wo_versionest un entier que Terraform stocke dans le state. Il sert à déclencher une mise à jour du mot de passe quand vous l’incrémentez.
Le mécanisme de version
Section intitulée « Le mécanisme de version »Terraform ne stocke pas la valeur d’un argument write-only. Conséquence : il ne peut pas détecter si cette valeur a changé. Sans l’argument de version, Terraform enverrait toujours la même disposition au provider sans savoir qu’il faut déclencher une mise à jour.
Le pattern est simple :
-
Déclarer :
password_wo = <valeur>etpassword_wo_version = 1. -
Mettre à jour : changer la valeur et incrémenter la version à
2. -
Appliquer : Terraform détecte le changement de version dans le state et demande au provider d’appliquer la nouvelle valeur.
resource "aws_db_instance" "example" { # ... password_wo = "NouveauMotDePasse!" password_wo_version = 2}Terraform voit que password_wo_version est passée de 1 à 2 dans le state. Il inclut la modification dans le plan et envoie la nouvelle valeur password_wo au provider AWS lors de l’apply.
Combiner ephemeral et write-only
Section intitulée « Combiner ephemeral et write-only »Le pattern recommandé utilise une ressource éphémère pour générer le secret, puis le transmet via l’argument write-only :
ephemeral "random_password" "db_password" { length = 16 override_special = "!#$%&*()-_=+[]{}<>:?"}
resource "aws_db_instance" "example" { identifier = "my-database" instance_class = "db.t3.micro" allocated_storage = 5 engine = "postgres" username = "admin" skip_final_snapshot = true
password_wo = ephemeral.random_password.db_password.result password_wo_version = 1}Avec ce pattern, aucune trace du mot de passe :
ephemeral "random_password"génère un mot de passe temporaire, jamais stocké dans le state ;password_wole transmet au provider AWS, qui l’utilise pour créer l’instance RDS ;- Terraform oublie la valeur dès que l’opération est terminée.
Exemple complet : AWS Secrets Manager
Section intitulée « Exemple complet : AWS Secrets Manager »En production, vous ne voulez pas seulement générer un mot de passe : vous voulez aussi le stocker dans un coffre pour que les applications puissent le récupérer. Le cycle complet avec AWS Secrets Manager :
# 1. Générer un mot de passe éphémèreephemeral "random_password" "db_password" { length = 16 override_special = "!#$%&*()-_=+[]{}<>:?"}
# 2. Stocker dans Secrets Manager (write-only aussi)resource "aws_secretsmanager_secret" "db_password" { name = "my-app/db-password"}
resource "aws_secretsmanager_secret_version" "db_password" { secret_id = aws_secretsmanager_secret.db_password.id secret_string_wo = ephemeral.random_password.db_password.result secret_string_wo_version = 1}
# 3. Récupérer le secret via une ressource éphémèreephemeral "aws_secretsmanager_secret_version" "db_password" { secret_id = aws_secretsmanager_secret_version.db_password.secret_id}
# 4. Utiliser comme argument write-only sur l'instance RDSresource "aws_db_instance" "example" { identifier = "my-database" instance_class = "db.t3.micro" allocated_storage = 5 engine = "postgres" username = "admin" skip_final_snapshot = true
password_wo = ephemeral.aws_secretsmanager_secret_version.db_password.secret_string password_wo_version = aws_secretsmanager_secret_version.db_password.secret_string_wo_version}Ce qui se passe dans le state
Section intitulée « Ce qui se passe dans le state »Après un terraform apply sur cette configuration :
| Ressource | Dans le state ? | Contient le mot de passe ? |
|---|---|---|
aws_secretsmanager_secret | Oui | Non (juste le nom et l’ARN) |
aws_secretsmanager_secret_version | Oui | Non (secret_string_wo est write-only) |
aws_db_instance | Oui | Non (password_wo est write-only) |
ephemeral "random_password" | Non | — |
ephemeral "aws_secretsmanager_secret_version" | Non | — |
Le mot de passe n’apparaît nulle part dans les artefacts Terraform.
Providers et arguments write-only connus
Section intitulée « Providers et arguments write-only connus »L’implémentation est spécifique à chaque provider. Voici les arguments write-only les plus courants :
| Provider | Ressource | Argument write-only | Argument version |
|---|---|---|---|
aws | aws_db_instance | password_wo | password_wo_version |
aws | aws_secretsmanager_secret_version | secret_string_wo | secret_string_wo_version |
azurerm | azurerm_key_vault_secret | value_wo | value_wo_version |
azurerm | azurerm_mysql_flexible_server | administrator_password_wo | administrator_password_wo_version |
Anatomie
Section intitulée « Anatomie »| Concept | Argument classique | Argument write-only |
|---|---|---|
| Stocké dans le state | Oui | Non |
| Stocké dans le plan | Oui | Non |
| Accepte des valeurs éphémères | Non | Oui |
| Accepte des valeurs non-éphémères | Oui | Oui |
| Détection de changement | Automatique via le state | Via _wo_version |
| Envoi au provider | Uniquement si changement | À chaque opération |
Bonnes pratiques
Section intitulée « Bonnes pratiques »1. Toujours utiliser un argument write-only quand il existe
Section intitulée « 1. Toujours utiliser un argument write-only quand il existe »Si le provider expose password_wo, préférez-le à password. Même si vous protégez votre state avec du chiffrement, ne pas stocker le secret est toujours plus sûr que le chiffrer.
2. Incrémenter la version explicitement
Section intitulée « 2. Incrémenter la version explicitement »Ne changez jamais la valeur d’un argument write-only sans incrémenter la version correspondante. Sans cette discipline, le provider peut rater la mise à jour.
3. Garder la version dans une variable ou un local
Section intitulée « 3. Garder la version dans une variable ou un local »Pour les cas complexes, centralisez la version :
locals { db_password_version = 1}
resource "aws_db_instance" "example" { # ... password_wo = ephemeral.random_password.db_password.result password_wo_version = local.db_password_version}
resource "aws_secretsmanager_secret_version" "db_password" { # ... secret_string_wo = ephemeral.random_password.db_password.result secret_string_wo_version = local.db_password_version}4. Privilégier les valeurs éphémères
Section intitulée « 4. Privilégier les valeurs éphémères »Même si les arguments write-only acceptent des chaînes en dur, préférez toujours une ressource ephemeral comme source. Cela élimine aussi le risque d’un commit accidentel du secret dans le code.
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
password_wo is not a valid argument | Le provider n’expose pas cet argument (version trop ancienne) | Mettre à jour le provider AWS ≥ 5.87 |
| Le mot de passe ne change pas après un apply | password_wo_version n’a pas été incrémentée | Incrémenter la version et relancer |
password_wo et password définis en même temps | Les deux arguments sont mutuellement exclusifs | Supprimer password et utiliser uniquement password_wo |
Invalid reference to ephemeral value | Valeur éphémère utilisée dans un attribut classique | Utiliser dans un argument write-only ou un contexte autorisé |
À retenir
Section intitulée « À retenir »- Les arguments write-only (
_wo) transmettent un secret au provider sans jamais le stocker dans le state ou le plan. - Terraform envoie la valeur à chaque opération (plan et apply), puisqu’il ne la stocke pas.
- Le mécanisme de version (
_wo_version) permet de déclencher une mise à jour quand le secret change. - Le pattern recommandé est : ephemeral génère → write-only transmet → zéro secret dans le state.
- L’implémentation est spécifique au provider : consultez le Terraform Registry pour vérifier quels arguments sont write-only.