
L'argument sensitive = true masque une valeur dans l'affichage de
Terraform. C'est utile contre les fuites dans les logs, mais dangereux si on le
prend pour une protection : la valeur reste en clair dans le state et le
plan. Et le marquage a des effets de bord qu'on ne soupçonne pas : il se
propage (y compris des modules enfants vers le parent), et il interdit
certaines constructions comme for_each.
Ce guide traite ce que sensitive masque et ce qu'il ne masque pas, sa
propagation dans les deux sens, la fuite dans le state et le plan, ses effets de
bord, les fonctions sensitive() / nonsensitive(), et ephemeral comme vraie
exclusion. Tous les comportements ont été vérifiés sur Terraform v1.15.4.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Ce que
sensitivemasque, et ce qu'il ne masque pas - La propagation, y compris remontante à travers les modules
- La valeur en clair dans le state ET le plan
- L'effet de bord qui casse
for_each sensitive()/nonsensitive(), etephemeralcomme vraie exclusion
Prérequis
Section intitulée « Prérequis »- Variables et outputs (variables Terraform)
- Terraform 1.15.x, la série stable courante
Ce que sensitive masque, et ce qu'il ne masque pas
Section intitulée « Ce que sensitive masque, et ce qu'il ne masque pas »sensitive = true masque la valeur dans la sortie humaine de plan, apply
et terraform output :
variable "db_password" { type = string sensitive = true}Mais la valeur reste en clair là où on ne la regarde pas. Deux commandes lèvent la redaction, et il faut le savoir :
terraform output -json # secret en clairterraform output -raw db_dsn # secret en clairVérifié en 1.15.4 : terraform output -raw rend admin:S3cr3t@db:5432 sans
aucun masquage. sensitive est un filtre d'affichage, pas un chiffrement.
La propagation, dans les deux sens
Section intitulée « La propagation, dans les deux sens »Terraform traite comme sensible toute expression qui utilise une valeur sensible. La contagion descend dans les locals, les attributs de ressources et les outputs. Mais elle remonte aussi : c'est le point le plus mal compris.
Un output marqué sensitive dans un module enfant contamine le module
appelant. Un output racine qui l'expose sans être marqué fait échouer le
plan :
# module ./enfantoutput "child_out" { value = "secret" sensitive = true}
# module racineoutput "root_out" { value = module.m.child_out # herite du sensible}Error: Output refers to sensitive valuesLa fuite : state ET plan
Section intitulée « La fuite : state ET plan »sensitive n'enlève rien du fichier d'état. La documentation nomme deux
fichiers : « Terraform stores values with the sensitive argument in both
state and plan files ». Un terraform.tfstate contient la valeur en clair, et
un plan enregistré par -out aussi :
terraform plan -out=tf.planterraform show -json tf.plan | jq '.variables.db_password.value' # en clairUn plan archivé comme artefact de CI est donc une fuite au même titre que le state. Chiffrez le state (backend distant), restreignez son accès, et ne publiez jamais un fichier de plan.
L'effet de bord qui casse for_each
Section intitulée « L'effet de bord qui casse for_each »Voici le piège Professional le plus net, et il casse une configuration qui
marchait. Une valeur sensible ne peut pas servir d'argument à for_each :
variable "noms" { type = set(string) sensitive = true}
resource "local_file" "f" { for_each = var.noms # interdit}Error: Invalid for_each argumentLe message précise « var.noms has a sensitive value ». La raison est logique :
Terraform utilise la valeur de for_each comme identifiant d'instance et
l'affiche toujours dans l'UI, ce qui divulguerait le secret. Marquer une variable
sensitive peut donc casser un for_each existant : le marquage n'est pas
sans effet de bord.
sensitive() et nonsensitive()
Section intitulée « sensitive() et nonsensitive() »Deux fonctions dédiées, disponibles depuis la v0.15 :
sensitive(v)marque une valeur comme sensible dans une expression. La doc la présente comme un pis-aller : « we recommend marking variables and outputs as sensitive directly, which is more reliable ».nonsensitive(v)retire la marque, pour publier une valeur dérivée sûre (une empreintesha256d'un secret, par exemple) sans désarmer le secret lui-même.
output "empreinte" { value = nonsensitive(sha256(var.db_password))}Auditer ce qui a été contaminé
Section intitulée « Auditer ce qui a été contaminé »Pour savoir ce que la propagation a réellement marqué, terraform show -json
expose un objet sensitive_values par ressource :
terraform show -json | jq '.values.root_module.resources[] | {address, sensitive_values}'Un attribut de ressource alimenté par une valeur sensible y apparaît, et le plan
l'affiche content = (sensitive value). C'est la trace exploitable pour auditer
la contamination.
La vraie exclusion : ephemeral
Section intitulée « La vraie exclusion : ephemeral »Si le besoin est qu'une valeur ne touche jamais le state ni le plan,
sensitive ne suffit pas : c'est ephemeral. L'argument ephemeral = true
sur un bloc variable ou output (Terraform 1.10) omet la valeur du state
et du plan. Les ressources éphémères datent aussi de 1.10 ; seuls les
arguments write-only sont arrivés en 1.11.
variable "jeton" { type = string ephemeral = true}Dépannage
Section intitulée « Dépannage »Ces symptômes viennent tous de la propagation ou de la limite d'affichage.
| Symptôme | Cause | Solution |
|---|---|---|
Output refers to sensitive values | Un output (racine ou héritant d'un module) expose du sensible non marqué | Ajouter sensitive = true, ou nonsensitive() si la valeur ne divulgue rien |
Invalid for_each argument (has a sensitive value) | Une valeur sensible sert de clé for_each | Ne pas utiliser de secret comme clé ; réorganiser la configuration |
| Un secret apparaît en clair en CI | output -json, -raw ou un plan -out archivé | Chiffrer le state, ne pas publier le plan, ou ephemeral |
Marquer une variable sensitive casse le plan | Effet de bord (for_each, contexte d'affichage) | Isoler le secret des clés et des index |
À retenir
Section intitulée « À retenir »sensitivemasque l'affichage, pas le state ni le plan ;-jsonet-rawrendent la valeur en clair.- La sensibilité se propage, y compris des modules enfants vers le parent.
- La valeur est en clair dans le state ET les fichiers de plan
-out. - Une valeur sensible ne peut pas servir de clé
for_each:Invalid for_each argument. nonsensitive()publie une valeur dérivée sûre ;sensitive()reste un pis-aller.- Pour exclure réellement du state, c'est
ephemeral(variable/output en 1.10), passensitive.
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »Les questions ci-dessous reprennent les confusions les plus fréquentes sur
sensitive : la propagation, la fuite dans le state, et l'effet de bord sur
for_each.
Un filtre d'affichage
sensitive = true masque la valeur dans la sortie humaine de plan, apply et terraform output. C'est tout.Où elle reste en clair
« Terraform stores values with thesensitive argument in both state and plan files. » Vérifié en 1.15.4 : terraform output -raw et -json rendent aussi la valeur en clair.La vraie protection
Chiffrer le state, ne pas archiver un plan-out, ou utiliser ephemeral pour exclure la valeur du state et du plan.La propagation remonte
Vérifié en 1.15.4 : unoutput sensible d'un module enfant contamine le parent.output "root_out" {
value = module.m.child_out # child_out est sensitive
}
Error: Output refers to sensitive values
L'idée fausse
Un guide répandu affirme que le sensible « ne remonte pas vers les blocs parents ». C'est faux : l'output racine doit être marquésensitive, ou le plan échoue.Un effet de bord qui casse
variable "noms" {
type = set(string)
sensitive = true
}
resource "local_file" "f" {
for_each = var.noms # interdit
}
Error: Invalid for_each argument
Pourquoi
Terraform utilise la valeur defor_each comme identifiant d'instance et l'affiche toujours dans l'UI, ce qui divulguerait le secret. Marquer une variable sensitive peut donc casser un for_each qui marchait : ce n'est pas sans effet de bord.Deux fonctions opposées
sensitive(v)marque une valeur sensible dans une expression. La doc : « we recommend marking variables and outputs as sensitive directly, which is more reliable. »nonsensitive(v)retire la marque, pour publier une valeur dérivée sûre :
output "empreinte" {
value = nonsensitive(sha256(var.db_password))
}
L'avertissement
« It's your responsibility to ensure that the expression passed as its argument will remove all sensitive content. » Unsha256 convient, un substr du secret non. À noter : nonsensitive("plain") sur une valeur déjà non sensible ne lève pas d'erreur en 1.15.4.State ET plan
« Terraform stores values with thesensitive argument in both state and plan files. »terraform plan -out=tf.plan
terraform show -json tf.plan | jq '.variables.db_password.value' # en clair
La conséquence en CI
Un plan-out archivé comme artefact de pipeline expose les secrets au même titre que le state. Ne publiez jamais un fichier de plan, et chiffrez le state.Le champ sensitive_values
terraform show -json | jq '.values.root_module.resources[] | {address, sensitive_values}'
Un attribut de ressource alimenté par une valeur sensible apparaît dans sensitive_values, et le plan l'affiche content = (sensitive value).À quoi ça sert
C'est la trace machine pour auditer ce que la propagation a marqué, au-delà de ce que vous avez explicitement déclarésensitive.Deux portées
sensitive: masque l'affichage, la valeur reste dans le state et le plan.ephemeral: exclut la valeur du state et du plan.
variable "jeton" {
type = string
ephemeral = true
}
Les versions
L'argumentephemeral sur variable/output et les ressources éphémères datent de Terraform 1.10 ; les arguments write-only sont arrivés en 1.11. Pour un secret qui ne doit jamais toucher le disque, c'est ephemeral, pas sensitive.Pour aller plus loin
Section intitulée « Pour aller plus loin »- Les arguments write-only : L'argument qui n'est jamais enregistré, là où sensitive se contente de masquer.
- Quiz Écrire du code Terraform : Un contrôle des acquis sur les variables, les outputs et le traitement des secrets.
- Comprendre le state Terraform : L'endroit exact où les valeurs marquées sensitive restent écrites en clair.