Aller au contenu
Infrastructure as Code medium

sensitive en Terraform : masquer, propager, et ses pièges

20 min de lecture

logo terraform

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 sensitive masque, 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(), et ephemeral comme vraie exclusion

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 :

Fenêtre de terminal
terraform output -json # secret en clair
terraform output -raw db_dsn # secret en clair

Vé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.

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 ./enfant
output "child_out" {
value = "secret"
sensitive = true
}
# module racine
output "root_out" {
value = module.m.child_out # herite du sensible
}
Error: Output refers to sensitive values

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 :

Fenêtre de terminal
terraform plan -out=tf.plan
terraform show -json tf.plan | jq '.variables.db_password.value' # en clair

Un 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.

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 argument

Le 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.

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 empreinte sha256 d'un secret, par exemple) sans désarmer le secret lui-même.
output "empreinte" {
value = nonsensitive(sha256(var.db_password))
}

Pour savoir ce que la propagation a réellement marqué, terraform show -json expose un objet sensitive_values par ressource :

Fenêtre de terminal
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.

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
}

Ces symptômes viennent tous de la propagation ou de la limite d'affichage.

SymptômeCauseSolution
Output refers to sensitive valuesUn 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_eachNe pas utiliser de secret comme clé ; réorganiser la configuration
Un secret apparaît en clair en CIoutput -json, -raw ou un plan -out archivéChiffrer le state, ne pas publier le plan, ou ephemeral
Marquer une variable sensitive casse le planEffet de bord (for_each, contexte d'affichage)Isoler le secret des clés et des index
  1. sensitive masque l'affichage, pas le state ni le plan ; -json et -raw rendent la valeur en clair.
  2. La sensibilité se propage, y compris des modules enfants vers le parent.
  3. La valeur est en clair dans le state ET les fichiers de plan -out.
  4. Une valeur sensible ne peut pas servir de clé for_each : Invalid for_each argument.
  5. nonsensitive() publie une valeur dérivée sûre ; sensitive() reste un pis-aller.
  6. Pour exclure réellement du state, c'est ephemeral (variable/output en 1.10), pas sensitive.

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.

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn