9/17/2025
12 min de lecture
DevSecOps

Sécurisation des Secrets GCP avec Terraform

Découvrez comment protéger vos secrets GCP lors du déploiement avec Terraform. Comparaison des solutions modernes : Write-Only Attributes, OpenTofu avec chiffrement, et intégration avec des gestionnaires de secrets externes.

TerraformGCPSécuritéSecretsOpenTofuInfrastructure as CodeDevSecOpsCloud Security

Par Edwin Istin

Sécurisation des Secrets GCP avec Terraform

Terraform est l'outil de référence pour l'Infrastructure as Code, mais il cache un problème de sécurité majeur : tous les secrets se retrouvent en clair dans le state file. Dans cet article, nous explorons les solutions modernes pour protéger vos secrets GCP lors de déploiements Terraform.

Sécurisation des Secrets GCP avec Terraform

Sécurisation des Secrets GCP avec Terraform

Le problème : Vos secrets sont exposés

Anatomie d'une fuite de secrets

Voici ce qui se passe lorsque vous créez un secret avec Terraform :

resource "google_secret_manager_secret" "api_key" {
  secret_id = "api-key"

  replication {
    auto {}
  }
}

resource "google_secret_manager_secret_version" "api_key" {
  secret = google_secret_manager_secret.api_key.id

  # Ce secret sera stocké en CLAIR dans le state !
  secret_data = "my-super-secret-api-key-12345"
}

Même avec sensitive = true, exécutez cette commande :

terraform show -json | jq '.values.root_module.resources[] |
  select(.type == "google_secret_manager_secret_version") |
  .values.secret_data'

Résultat :

"my-super-secret-api-key-12345"

Votre secret est visible en clair dans le state ! 😱

Les vecteurs de risque

Les secrets dans le state Terraform créent plusieurs points de vulnérabilité :

VecteurRisqueImpact
Stockage BackendBucket GCS avec mauvais ACLExposition massive de secrets
Backups AutomatiquesCopies du state non chiffréesSecrets historiques exposés
CI/CD LogsState parsing ou debugFuites dans les logs
Pull RequestsState inclus dans les diffsExposition publique sur GitHub
Équipe ÉlargieAccès read au state = accès aux secretsCompromission interne

Solution 1 : Write-Only Attributes (Google Provider v5.0+)

Le fonctionnement

Google Provider v5.0 introduit les write-only fields : des attributs qui ne sont jamais lus après la création.

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"  # Version minimale requise
    }
  }
}

resource "google_service_account_key" "sa_key" {
  service_account_id = google_service_account.sa.name

  # Le secret n'apparaît PAS dans le state !
  lifecycle {
    ignore_changes = [private_key]
  }
}

Avant vs Après dans le State

Avant (Provider < v5.0) :

{
  "type": "google_service_account_key",
  "values": {
    "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQE...",
    "private_key_type": "TYPE_GOOGLE_CREDENTIALS_FILE"
  }
}

Après (Provider >= v5.0) :

{
  "type": "google_service_account_key",
  "values": {
    "private_key": "[REDACTED]",
    "private_key_type": "TYPE_GOOGLE_CREDENTIALS_FILE"
  }
}

Resources supportées

Pour la liste complète des ressources et attributs supportés, consultez la documentation officielle.

Limitations importantes

⚠️ Attention : Les write-only attributes ont des contraintes :

  1. Pas de récupération : Impossible de lire le secret après création
  2. Pas de drift detection : Terraform ne peut pas détecter les modifications manuelles
  3. Recreate uniquement : Pour "changer" le secret, il faut recréer la ressource

Solution 2 : OpenTofu avec chiffrement du State

Migration vers OpenTofu

OpenTofu est un fork open-source de Terraform avec chiffrement natif du state. Il offre une compatibilité totale avec les configurations Terraform existantes tout en ajoutant des fonctionnalités de sécurité essentielles.

Configuration du chiffrement

Option 1 : Chiffrement avec passphrase (développement)

# backend.tf
terraform {
  encryption {
    key_provider "pbkdf2" "master" {
      passphrase = env("TOFU_PASSPHRASE")
      key_length = 32
      iterations = 600000
      hash_function = "sha512"
    }

    method "aes_gcm" "state_encryption" {
      keys = key_provider.pbkdf2.master
    }

    state {
      method = method.aes_gcm.state_encryption
    }
  }
}

Option 2 : Chiffrement avec GCP KMS (production)

# backend.tf
terraform {
  encryption {
    key_provider "gcp_kms" "master" {
      kms_encryption_key = "projects/${var.project_id}/locations/global/keyRings/terraform/cryptoKeys/state-key"
      key_length = 32
    }

    method "aes_gcm" "state_encryption" {
      keys = key_provider.gcp_kms.master
    }

    state {
      method = method.aes_gcm.state_encryption
      enforced = true  # Refuse d'écrire un state non chiffré
    }
  }
}

Rotation des clés de chiffrement

# Rotation avec nouvelle clé KMS
tofu state encryption rotate \
  -key-provider=gcp_kms \
  -key-id="projects/mon-projet/locations/global/keyRings/terraform/cryptoKeys/state-key-v2"

Comparaison des providers de clés

ProviderSécuritéComplexitéCoûtCas d'usage
pbkdf2BonneFaibleGratuitDev/Test
gcp_kmsExcellenteMoyenne~1$/mois/cléProduction
aws_kmsExcellenteMoyenne~1$/mois/cléMulti-cloud
ageTrès bonneFaibleGratuitOpen-source

Solution 3 : Data Sources et Secrets Externes

Architecture Zero-Secret

L'idée : ne jamais créer de secrets avec Terraform, seulement les référencer.

# Ne PAS créer le secret
# resource "google_secret_manager_secret_version" "api_key" { ... }

# Référencer uniquement
data "google_secret_manager_secret_version" "api_key" {
  secret  = "api-key"
  version = "latest"
}

resource "google_cloud_run_service" "api" {
  # ...
  template {
    spec {
      containers {
        env {
          name = "API_KEY"
          value_from {
            secret_key_ref {
              name = data.google_secret_manager_secret_version.api_key.secret
              key  = "latest"
            }
          }
        }
      }
    }
  }
}

Intégration avec HashiCorp Vault

provider "vault" {
  address = "https://vault.company.com"
}

data "vault_generic_secret" "db_creds" {
  path = "database/creds/prod"
}

resource "google_sql_user" "app" {
  instance = google_sql_database_instance.main.name
  name     = data.vault_generic_secret.db_creds.data["username"]
  password = data.vault_generic_secret.db_creds.data["password"]  # Jamais dans le state !
}

Comparaison des Solutions

Matrice de décision

CritèreWrite-OnlyOpenTofuData Sources + Externe
SécuritéTrès bonneExcellenteExcellente
Complexité d'implémentationFaibleMoyenneÉlevée
Coût d'infrastructureAucunKMS si utiliséVariable selon solution
Drift DetectionLimitéeComplèteComplète
Rotation des SecretsManuelleAutomatisableAutomatisable
Traçabilité/AuditGCP natifGCP + chiffrementComplet avec solution externe

Recommandations par contexte

Startups / Projets simples :

# Solution : Write-Only Attributes
# ✅ Simple, natif, suffisant pour la plupart des cas
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

Entreprises avec contraintes de conformité :

# Solution : OpenTofu + GCP KMS
# ✅ Chiffrement complet, audit trail, rotation automatique
terraform {
  encryption {
    key_provider "gcp_kms" "master" {
      kms_encryption_key = var.kms_key_id
    }
  }
}

Environnements multi-cloud complexes :

# Solution : Vault + External Secrets
# ✅ Centralisation, rotation automatique, multi-cloud
provider "vault" {
  # Configuration centralisée
}

Conclusion

La sécurisation des secrets dans Terraform n'est plus optionnelle. Avec les solutions modernes disponibles :

  • Write-Only Attributes : Solution simple et native pour la majorité des cas
  • OpenTofu : Pour un contrôle total avec chiffrement du state
  • External Secrets : Architecture zero-trust pour environnements complexes

L'approche recommandée : Commencez par Write-Only Attributes, évoluez vers OpenTofu si nécessaire, et considérez les solutions externes pour des besoins spécifiques.

Le plus important : agissez maintenant. Chaque jour avec des secrets en clair est un risque de compromission.


Quelle solution avez-vous adoptée pour sécuriser vos secrets Terraform ? Avez-vous rencontré des défis particuliers lors de la migration ? Partageons nos expériences pour construire des infrastructures plus sécurisées.