# Comment Terraform 1.10 révolutionne la gestion des secrets en utilisant des valeurs éphémères dans Azure

## **Introduction à Terraform 1.10**

Terraform est un outil d'infrastructure en tant que code qui permet aux équipes DevOps de provisionner et de gérer leurs infrastructures en toute sécurité et de manière reproductible. La version 1.10 de Terraform apporte une amélioration significative dans la gestion des secrets grâce à l'introduction des valeurs éphémères (ephemeral values). Cette nouveauté est particulièrement utile lorsqu'on travaille avec des secrets sensibles tels que des clés API, des mots de passe, et des certificats.

Dans cet article, je vais explorer comment Terraform 1.10 améliore la gestion des secrets, et je vais vous démontrer dans des exemples pratiques comment l’utiliser sur le cloud Microsoft Azure.

## **Comprendre les valeurs éphémères**

Les valeurs éphémères dans Terraform sont conçues pour protéger les informations sensibles (mots de passes, clés privées, des certificats, des jetons d'API, etc.) en évitant de les stocker dans les fichiers d'état ou dans les plans de Terraform. En activant cette fonctionnalité, vous réduisez considérablement le risque de divulgation des données sensibles. Cela est particulièrement pertinent dans les environnements de cloud où les secrets jouent un rôle crucial pour l'accès aux ressources et aux services.

Jusqu’à cette version 1.10 de Terraform, ces secrets été conservés dans le fichier de plan ou d'état et comme ils été stockés **en clair** dans ces artefacts, tout accès mal géré aux fichiers les compromettrait.

## **Avantages des valeurs éphémères**

* **Sécurité améliorée** : Les secrets sont uniquement temporaires et ne sont pas persistés dans les fichiers d'état de Terraform, réduisant ainsi le risque de fuite.
    
* **Gestion simplifiée des secrets** : Permet une meilleure gestion et rotation des secrets sans risque de fuite ou d'exposition dans les fichiers d'infrastructure.
    
* **Meilleures pratiques de sécurité** : S'aligne avec les meilleures pratiques en matière de gestion des informations sensibles, telles que celles recommandées par des frameworks de sécurité comme CIS et NIST.
    

# Comment utiliser les valeurs éphémères pour vos ressources Azure ?

## **Prérequis**

* Compte Azure et abonnement actif
    
* Azure CLI installé
    
* Terraform 1.10 installé
    

Pour l’exemple, j’utilise un SPN créé sur Entra ID grâce à cette commande Azure CLI où il faudra la mettre à jour votre `scope`:

```powershell
az ad sp create-for-rbac --name ephemeral --role owner --scopes /subscriptions/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY
```

## **Exemple : Sauvegarde d’un secret dans Azure Key Vault avec Terraform et utilisation sur un service Azure Microsoft SQL Server**

Voici comment configurer et utiliser des valeurs éphémères avec Terraform 1.10 pour gérer un secret stocké dans Azure Key Vault.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Les ressources éphémères sont supportées depuis <strong>Terraform 1.10</strong> et supérieure.</div>
</div>

### **Étape 1 : Configuration du fournisseur Azure**

Commencez par configurer le fournisseur Azure dans votre fichier Terraform en mettant à jour les valeurs dans le `provider` liées à votre SPN.

```json
provider "azurerm" {
  features {}
  # TODO: Update this values with your environment context
  tenant_id       = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  subscription_id = "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY"
  client_id       = "ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ"
  client_secret   = "Azur€CloudF0rFun!!!2025"
}

terraform {
  required_version = "1.11.2"
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = ">= 4.0.0"
    }
    random = {
      source  = "hashicorp/random"
      version = ">= 3.7.1"
    }
  }
}

resource "azurerm_resource_group" "example" {
  name     = "ephemeral-example"
  location = "West US"
}
```

### **Étape 2: Génération de secrets temporaires**

Utilisez le fournisseur `random` pour générer un mot de passe éphémère tel que:

```json
ephemeral "random_password" "password" {
  length           = 16
  special          = true
  override_special = "!#$%&*()-_=+[]{}<>:?"
}
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Plus de détail dans la documentation du provider: <a target="_self" rel="noopener noreferrer nofollow" href="https://registry.terraform.io/providers/hashicorp/random/latest/docs/ephemeral-resources/password" style="pointer-events: none">Ephemeral Resource - random_password</a></div>
</div>

### **Étape 3 : Définition du secret dans Key Vault**

Définissez votre ressource Key Vault et créez un secret dans celui-ci grâce aux nouveaux arguments “`write-only`” identifiable par leur nom finissant par “`_wo`” et “`_wo_version`” :

* `value_wo`
    
* `value_wo_version`
    

```json
data "azurerm_client_config" "current" {}

resource "azurerm_key_vault" "example" {
  name                      = "ephemeral-key-vault"
  location                  = azurerm_resource_group.example.location
  resource_group_name       = azurerm_resource_group.example.name
  tenant_id                 = data.azurerm_client_config.current.tenant_id
  sku_name                  = "standard"
  enable_rbac_authorization = true
}

resource "azurerm_role_assignment" "secret_officer" {
  scope                = azurerm_key_vault.example.id
  role_definition_name = "Key Vault Secrets Officer"
  principal_id         = data.azurerm_client_config.current.object_id
}

resource "azurerm_key_vault_secret" "example" {
  name             = "vm-password"
  value_wo         = ephemeral.random_password.password.result
  value_wo_version = 1
  key_vault_id     = azurerm_key_vault.example.id
  depends_on       = [azurerm_role_assignment.secret_officer]
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1742208962401/e7dff6dc-273f-48cd-9674-7cfd34dc8af1.png align="center")

### **Étape 4 : Intégration du secret dans la configuration d’un service Azure SQL Server**

Ici nous allons de nouveau utiliser une ressource éphémère pour récupérer la valeur du secret pour l'utiliser sur notre service Azure SQL Server.

```json
ephemeral "azurerm_key_vault_secret" "password" {
  name         = azurerm_key_vault_secret.example.name
  key_vault_id = azurerm_key_vault.example.id
}

resource "azurerm_mssql_server" "example" {
  name                                    = "ephemeral-example"
  resource_group_name                     = azurerm_resource_group.example.name
  location                                = azurerm_resource_group.example.location
  version                                 = "12.0"
  administrator_login                     = "aloizeau"
  administrator_login_password_wo         = ephemeral.azurerm_key_vault_secret.password.value
  administrator_login_password_wo_version = 1
  minimum_tls_version                     = "1.2"

  azuread_administrator {
    login_username = "CurrentAzureADUser"
    object_id      = data.azurerm_client_config.current.object_id
  }
}
```

## Et mon state ?

Pour clôturer cet article et vous prouvez que ce secret n’est plus présent dans mon state voici le fichier généré lors du déploiement de mon IaC :

```json
{
  "version": 4,
  "terraform_version": "1.11.2",
  "serial": 51,
  "lineage": "2e3a9eda-4141-9317-df4d-a631412d280f",
  "outputs": {},
  "resources": [
    {
      "mode": "data",
      "type": "azurerm_client_config",
      "name": "current",
      "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "client_id": "ZZZZZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZZZZZZZZZ",
            "id": "Y2xpZW50Q29uZmlncy9jbGllbnRJZD1jNjNjN2I4ZC0xYjQ3LTQ1MTctYTczMi03YjNkNDc5MmYzOWQ7b2JqZWN0SWQ9NzRlODdjYjUtYTViYS00YThkLWE2YWQtNGY4MjkwMDE2MDE1O3N1YnNjcmlwdGlvbklkPTZhMjVhNmQzLTdlYTQtNGE5MS04MDZiLWUzZDQ2MjlmMTc4Yzt0ZW5hbnRJZD1kZjIyODIyZS1mY2EwLTRmZDMtOTI2Ni0yYzRlYjI1ZTUxOTg=",
            "object_id": "SSSSSSSS-SSSS-SSSS-SSSS-SSSSSSSSSSSS",
            "subscription_id": "YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY",
            "tenant_id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
            "timeouts": null
          },
          "sensitive_attributes": []
        }
      ]
    },
    {
      "mode": "managed",
      "type": "azurerm_key_vault",
      "name": "example",
      "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]",
      "instances": [
        {
          "schema_version": 2,
          "attributes": {
            "access_policy": [],
            "contact": [],
            "enable_rbac_authorization": true,
            "enabled_for_deployment": false,
            "enabled_for_disk_encryption": false,
            "enabled_for_template_deployment": false,
            "id": "/subscriptions/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY/resourceGroups/ephemeral-example/providers/Microsoft.KeyVault/vaults/ephemeral-key-vault",
            "location": "westus",
            "name": "ephemeral-key-vault",
            "network_acls": [
              {
                "bypass": "AzureServices",
                "default_action": "Allow",
                "ip_rules": [],
                "virtual_network_subnet_ids": []
              }
            ],
            "public_network_access_enabled": true,
            "purge_protection_enabled": false,
            "resource_group_name": "ephemeral-example",
            "sku_name": "standard",
            "soft_delete_retention_days": 90,
            "tags": {},
            "tenant_id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
            "timeouts": null,
            "vault_uri": "https://ephemeral-key-vault.vault.azure.net/"
          },
          "sensitive_attributes": [],
          "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxODAwMDAwMDAwMDAwLCJkZWxldGUiOjE4MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjoxODAwMDAwMDAwMDAwfSwic2NoZW1hX3ZlcnNpb24iOiIyIn0=",
          "dependencies": [
            "azurerm_resource_group.example",
            "data.azurerm_client_config.current"
          ]
        }
      ]
    },
    {
      "mode": "managed",
      "type": "azurerm_key_vault_secret",
      "name": "example",
      "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "content_type": "",
            "expiration_date": null,
            "id": "https://ephemeral-key-vault.vault.azure.net/secrets/password/0878134668b94d3c92c734727ccf66b6",
            "key_vault_id": "/subscriptions/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY/resourceGroups/ephemeral-example/providers/Microsoft.KeyVault/vaults/ephemeral-key-vault",
            "name": "password",
            "not_before_date": null,
            "resource_id": "/subscriptions/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY/resourceGroups/ephemeral-example/providers/Microsoft.KeyVault/vaults/ephemeral-key-vault/secrets/password/versions/0878134668b94d3c92c734727ccf66b6",
            "resource_versionless_id": "/subscriptions/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY/resourceGroups/ephemeral-example/providers/Microsoft.KeyVault/vaults/ephemeral-key-vault/secrets/password",
            "tags": {},
            "timeouts": null,
            "value": "",
            "value_wo": null,
            "value_wo_version": 1,
            "version": "0878134668b94d3c92c734727ccf66b6",
            "versionless_id": "https://ephemeral-key-vault.vault.azure.net/secrets/password"
          },
          "sensitive_attributes": [
            [
              {
                "type": "get_attr",
                "value": "value"
              }
            ]
          ],
          "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxODAwMDAwMDAwMDAwLCJkZWxldGUiOjE4MDAwMDAwMDAwMDAsInJlYWQiOjE4MDAwMDAwMDAwMDAsInVwZGF0ZSI6MTgwMDAwMDAwMDAwMH19",
          "dependencies": [
            "azurerm_key_vault.example",
            "azurerm_resource_group.example",
            "azurerm_role_assignment.secret_officer",
            "data.azurerm_client_config.current",
            "ephemeral.random_password.password"
          ]
        }
      ]
    },
    {
      "mode": "managed",
      "type": "azurerm_mssql_server",
      "name": "example",
      "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "administrator_login": "aloizeau",
            "administrator_login_password": null,
            "administrator_login_password_wo": null,
            "administrator_login_password_wo_version": 1,
            "azuread_administrator": [
              {
                "azuread_authentication_only": false,
                "login_username": "CurrentAzureADUser",
                "object_id": "SSSSSSSS-SSSS-SSSS-SSSS-SSSSSSSSSSSS",
                "tenant_id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
              }
            ],
            "connection_policy": "Default",
            "fully_qualified_domain_name": "ephemeral-example.database.windows.net",
            "id": "/subscriptions/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY/resourceGroups/ephemeral-example/providers/Microsoft.Sql/servers/ephemeral-example",
            "identity": [],
            "location": "westus",
            "minimum_tls_version": "1.2",
            "name": "ephemeral-example",
            "outbound_network_restriction_enabled": false,
            "primary_user_assigned_identity_id": "",
            "public_network_access_enabled": true,
            "resource_group_name": "ephemeral-example",
            "restorable_dropped_database_ids": [],
            "tags": {},
            "timeouts": null,
            "transparent_data_encryption_key_vault_key_id": "",
            "version": "12.0"
          },
          "sensitive_attributes": [
            [
              {
                "type": "get_attr",
                "value": "administrator_login_password"
              }
            ],
            [
              {
                "type": "get_attr",
                "value": "administrator_login_password_wo"
              }
            ]
          ],
          "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjozNjAwMDAwMDAwMDAwLCJkZWxldGUiOjM2MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjozNjAwMDAwMDAwMDAwfX0=",
          "dependencies": [
            "azurerm_key_vault.example",
            "azurerm_key_vault_secret.example",
            "azurerm_resource_group.example",
            "azurerm_role_assignment.secret_officer",
            "data.azurerm_client_config.current",
            "ephemeral.azurerm_key_vault_secret.password",
            "ephemeral.random_password.password"
          ]
        }
      ]
    },
    {
      "mode": "managed",
      "type": "azurerm_resource_group",
      "name": "example",
      "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "id": "/subscriptions/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY/resourceGroups/ephemeral-example",
            "location": "westus",
            "managed_by": "",
            "name": "ephemeral-example",
            "tags": {},
            "timeouts": null
          },
          "sensitive_attributes": [],
          "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo1NDAwMDAwMDAwMDAwLCJkZWxldGUiOjU0MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMCwidXBkYXRlIjo1NDAwMDAwMDAwMDAwfX0="
        }
      ]
    },
    {
      "mode": "managed",
      "type": "azurerm_role_assignment",
      "name": "secret_officer",
      "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "condition": "",
            "condition_version": "",
            "delegated_managed_identity_resource_id": "",
            "description": "",
            "id": "/subscriptions/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY/resourceGroups/ephemeral-example/providers/Microsoft.KeyVault/vaults/ephemeral-key-vault/providers/Microsoft.Authorization/roleAssignments/3c5661a1-e732-a747-87b2-daec9e7056e0",
            "name": "3c5661a1-e732-a747-87b2-daec9e7056e0",
            "principal_id": "SSSSSSSS-SSSS-SSSS-SSSS-SSSSSSSSSSSS",
            "principal_type": "ServicePrincipal",
            "role_definition_id": "/subscriptions/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY/providers/Microsoft.Authorization/roleDefinitions/b86a8fe4-44ce-4948-aee5-eccb2c155cd7",
            "role_definition_name": "Key Vault Secrets Officer",
            "scope": "/subscriptions/YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY/resourceGroups/ephemeral-example/providers/Microsoft.KeyVault/vaults/ephemeral-key-vault",
            "skip_service_principal_aad_check": null,
            "timeouts": null
          },
          "sensitive_attributes": [],
          "private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjoxODAwMDAwMDAwMDAwLCJkZWxldGUiOjE4MDAwMDAwMDAwMDAsInJlYWQiOjMwMDAwMDAwMDAwMH19",
          "dependencies": [
            "azurerm_key_vault.example",
            "azurerm_resource_group.example",
            "data.azurerm_client_config.current"
          ]
        }
      ]
    }
  ],
  "check_results": null
}
```

# **Conclusion**

Terraform 1.10 avec les valeurs éphémères améliore considérablement la gestion des secrets en garantissant leur sécurité et en simplifiant la rotation et l'administration des informations sensibles.

L'utilisation des secrets avec Azure Key Vault permet de renforcer la sécurité des déploiements Azure tout en suivant les meilleures pratiques en matière de gestion de l'infrastructure.

Essayez cette nouvelle fonctionnalité pour sécuriser vos infrastructures cloud dès aujourd'hui et au besoin vous savez qui contacter si vous souhaitez en savoir plus.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Le lien vers le repository GitHub contenant le code source de cet article: <a target="_self" rel="noopener noreferrer nofollow" href="https://github.com/aloizeau/tf-ephemeral/" style="pointer-events: none">https://github.com/aloizeau/tf-ephemeral/</a></div>
</div>

# Liens utiles

* [Terraform 1.10 improves handling secrets in state with ephemeral values](https://www.hashicorp.com/fr/blog/terraform-1-10-improves-handling-secrets-in-state-with-ephemeral-values)
    
* [Ephemerality in resources](https://developer.hashicorp.com/terraform/language/resources/ephemeral)
    
* [Use write-only arguments](https://developer.hashicorp.com/terraform/language/resources/ephemeral/write-only)
    
* [Provider AzureRM - azurerm\_mssql\_server](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/mssql_server)
    
* [Provider AzureRM - Ephemeral: azurerm\_key\_vault\_secret](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/ephemeral-resources/key_vault_secret)
    
* [Provider random - random\_password (Ephemeral Resource)](https://registry.terraform.io/providers/hashicorp/random/latest/docs/ephemeral-resources/password)
