Aller au contenu

Confidentialite

Classification des données OpenTofu

Les workflows OpenTofu manipulent des données sensibles qui révèlent la topologie, les identifiants et la configuration de l'infrastructure. La classification est Restreint pour les éléments les plus critiques.

Pour le cadre complet de classification, consultez la rubrique Classification et zones de confiance.

Donnée Classification Risque si expose
State file Restreint Contient identifiants, cles API, topologie complète de l'infra
Variables sensibles (tfvars) Restreint Mots de passe, tokens, cles d'API en clair
Plan output (tfplan) Confidentiel Révèle les changements prevus et la structure de l'infrastructure
Code HCL (.tf) Confidentiel Révèle l'architecture, les choix techniques, les patterns déployés
Logs d'execution Confidentiel Peuvent contenir des valeurs sensibles en cas de misconfiguration
Provider credentials Restreint Accès complet aux APIs cloud (GCP, AWS, Azure)

Le state est le secret le plus critique

Le fichier terraform.tfstate contient en clair les identifiants, cles API, mots de passe de base de données, et la topologie complète de l'infrastructure. Sa compromission equivaut a la compromission de toute l'infrastructure.

Sécurité du state file

Backend remote chiffre

Ne jamais stocker le state en local. Utiliser un backend remote avec chiffrement au repos :

terraform {
  backend "gcs" {
    bucket  = "myorg-tofu-state"
    prefix  = "prod/network"
    # Chiffrement au repos par defaut (Google-managed ou CMEK)
  }
}
terraform {
  backend "s3" {
    bucket         = "myorg-tofu-state"
    key            = "prod/network/terraform.tfstate"
    region         = "eu-west-3"
    encrypt        = true                    # Chiffrement SSE-S3
    kms_key_id     = "arn:aws:kms:..."       # Ou SSE-KMS pour cle dediee
    dynamodb_table = "tofu-state-lock"       # Locking
  }
}

Contrôle d'accès au bucket de state

# GCS — IAM restreint au state bucket
resource "google_storage_bucket_iam_binding" "state_access" {
  bucket = "myorg-tofu-state"
  role   = "roles/storage.objectAdmin"
  members = [
    "serviceAccount:tofu-ci@myorg.iam.gserviceaccount.com",
  ]
}

Pas de state local

Ajoutez *.tfstate et *.tfstate.backup au .gitignore global. Un state commit par erreur dans Git expose toute l'infrastructure.

Versioning du state

Activez le versioning sur le bucket de state pour permettre la recovery en cas de corruption. Sur GCS : gcloud storage buckets update gs://myorg-tofu-state --versioning. Sur S3 : activez le versioning via put-bucket-versioning.

Secrets dans le state

Marquage des outputs sensibles

Les outputs contenant des secrets doivent etre marques sensitive pour eviter leur affichage dans les logs :

output "database_password" {
  value     = google_sql_user.app.password
  sensitive = true
}

output "api_key" {
  value     = random_password.api_key.result
  sensitive = true
}

Limite du marquage sensitive

Le flag sensitive = true masque la valeur dans tofu output et les logs, mais elle reste en clair dans le state file. Le chiffrement du backend est la seule protection reelle.

Vault provider pour les secrets dynamiques

Plutôt que de stocker des secrets statiques, utilisez HashiCorp Vault pour générer des credentials ephemeres :

# Recuperer un secret dynamique depuis Vault
data "vault_generic_secret" "db_creds" {
  path = "database/creds/app-role"
}

resource "google_sql_user" "app" {
  name     = data.vault_generic_secret.db_creds.data["username"]
  password = data.vault_generic_secret.db_creds.data["password"]
  instance = google_sql_database_instance.main.name
}

Les secrets dynamiques expirent automatiquement, limitant la fenêtre d'exposition en cas de compromission du state.

Sécurité du plan output

Le fichier tfplan génère par tofu plan -out=tfplan contient les changements prevus et peut révéler des informations sur l'infrastructure existante.

Ajoutez *.tfplan au .gitignore. En CI/CD, stockez le plan comme artefact ephemere avec une retention courte (1-4 heures) :

# GitHub Actions — artefact ephemere
- uses: actions/upload-artifact@v4
  with:
    name: tfplan
    path: infra/tfplan
    retention-days: 1

RBAC — Separation plan / apply

Tous les membres de l'équipe ne doivent pas avoir les mêmes droits. La separation entre plan et apply est une mesure de sécurité fondamentale.

Rôle plan apply state read state write Qui
Développeur Oui Non Non Non Équipe dev
Ops Oui Non Oui Non Équipe infrastructure
Lead Ops Oui Oui Oui Oui Responsables infra
CI/CD (prod) Oui Oui Oui Oui Service account pipeline
CI/CD (dev) Oui Oui Oui Oui Service account pipeline dev

Principe du moindre privilege

En production, seul le pipeline CI/CD et les leads ops peuvent exécuter tofu apply. Un développeur peut lancer tofu plan pour previsualiser ses changements, mais l'application passe par une PR approuvee et le pipeline.

Audit trail

Chaque tofu apply modifie le state. Activez le versioning sur le bucket (voir section précédente) pour conserver un historique complet des versions.

Les logs du pipeline CI/CD constituent l'audit trail principal :

  • Qui a declenche le pipeline (auteur du commit / approbateur de la PR)
  • Quoi a change (diff du code HCL dans la PR)
  • Quand le tofu apply a ete execute (timestamp du job)
  • Résultat (succès/echec, ressources créées/modifiées/detruites)

Scrub des logs

Configurez le pipeline pour masquer les variables sensibles dans les logs. OpenTofu masque les outputs sensitive, mais les providers peuvent afficher des valeurs dans les messages d'erreur.

Isolation réseau

Accès restreint au state backend

Le bucket de state ne doit etre accessible que depuis :

  • Le réseau du pipeline CI/CD
  • Les postes des ops autorises (VPN)
  • Jamais depuis l'internet public
# S3 — Bucket policy restreignant l'acces par VPC endpoint
resource "aws_s3_bucket_policy" "state" {
  bucket = aws_s3_bucket.state.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Sid       = "RestrictToVPCEndpoint"
      Effect    = "Deny"
      Principal = "*"
      Action    = "s3:*"
      Resource  = ["${aws_s3_bucket.state.arn}/*"]
      Condition = {
        StringNotEquals = {
          "aws:sourceVpce" = var.vpc_endpoint_id
        }
      }
    }]
  })
}

Sur GCS, utilisez les VPC Service Controls pour créer un perimetre autour du bucket de state.

Defense en profondeur

Combinez le chiffrement du backend, le contrôle d'accès IAM, l'isolation réseau et l'audit trail. Aucune mesure isolee n'est suffisante pour protéger le state file.