Distribuée
Cloud & AI Security
← Tous les insights

Écosystème

Wiz + Terramate : checker les configs cloud avant le apply, pas après l'incident

Analyse DevSecOps : orchestrer les stacks Terramate changées, scanner le plan Terraform avec wizcli, bloquer les misconfigs critiques en CI, puis corréler au runtime Wiz.

· 8 min · #wiz#terramate#terraform#iac#cspm#github-actions#cloud-config#ecosysteme

Wiz scanne très bien ce qui tourne déjà dans le cloud. Terramate orchestre très bien des dizaines de stacks Terraform / OpenTofu. Le trou classique : la misconfig arrive au apply, et le CSPM la découvre heures ou jours plus tard. Security group 0.0.0.0/0, bucket sans block public access, rôle IAM Action: "*" — le review de PR ne les voit pas toujours, surtout quand le plan touche trois modules et deux workspaces.

Il n’existe pas d’intégration native « bouton Wiz » dans Terramate Cloud. C’est une bonne nouvelle : le pattern robuste est client-side. Terramate sélectionne les stacks changées ; terraform plan produit un plan résolu ; wizcli scanne ce plan (ou le HCL) avec la même policy engine que le reste de Wiz ; la CI bloque avant l’apply. Ensuite le connecteur cloud Wiz reprend pour le runtime et le code-to-cloud via le state.

Cet article décrit le pipeline que je mets en place quand une équipe a déjà Terramate et Wiz (ou envisage les deux) : menace → contrôle CI → artefact GitHub Actions → preuve.

Pipeline Terramate → plan → scan Wiz → apply → runtime

La menace : config cloud validée trop tard

Trois échecs de process, pas de CVE exotique.

Le plan « trop grand pour être relu ». Terramate aide précisément parce qu’une monorepo Terraform grossit vite. Sans terramate list --changed, la CI planifie tout, ou rien. Les reviewers regardent le diff HCL, pas l’effet réel des variables et modules. Un count ou un for_each conditionnel crée une ressource publique que personne n’a lue dans le HCL brut.

Le scan HCL sans plan. Un scanner qui ne lit que les .tf rate ce qui n’apparaît qu’après résolution : modules distants, valeurs de variables d’environnement, data sources. Wiz CLI peut scanner un répertoire Terraform et un plan JSON (terraform show -json) — c’est le second qui se rapproche de ce qui sera appliqué.

Le CSPM runtime comme seul filet. Utile, indispensable même (on en parle dans le comparatif Wiz vs natif). Mais une fois le SG ouvert, la fenêtre d’exposition existe. Le shift-left n’élimine pas le CSPM : il réduit le flux de findings « on vient de se tirer une balle dans le pied ».

Rôles : qui fait quoi

CoucheOutilJob
Orchestration monorepoTerramatestacks, run --changed, order, tags, code generation
ProvisioningTerraform / OpenTofuplan / apply par stack
Policy IaC (avant apply)Wiz CLI (wizcli)misconfigs, secrets dans le code/plan, seuils de blocage
Posture runtimeWiz CSPM / Security Graphfindings live, chemins d’attaque, code-to-cloud via state

Terramate ne remplace pas Wiz ; Wiz ne sélectionne pas vos stacks changées. Le glue code est un workflow CI — et c’est ce glue code qui manque dans 80 % des démos « on a Wiz ».

Prérequis côté Wiz

  1. Compte service Wiz dédié CI (pas le compte d’un humain) : WIZ_CLIENT_ID / WIZ_CLIENT_SECRET en secrets GitHub (OIDC vers un secrets manager si vous le pouvez).
  2. Une IaC policy dans Wiz avec enforcement CLI en BLOCK sur Critical (et idéalement High pour les contrôles CIS que vous avez déjà remédiés).
  3. Connecteur cloud (AWS/Azure/GCP) déjà branché — sinon vous n’aurez que le scan préventif, pas la boucle code-to-cloud.
  4. Optionnel mais utile : connecteur VCS pour mapper fichiers / auteurs ; le state Terraform reste le pont le plus fiable entre ressource live et déclaration.

Artefact : GitHub Actions — stacks changées → plan JSON → wizcli

Workflow minimal, OIDC-ready pour AWS, calqué sur le preview Terramate avec une étape Wiz après le plan. Ajustez versions et rôle IAM.

name: terramate-wiz-preview

on:
  pull_request:
    paths:
      - "stacks/**"
      - "**.tf"
      - "**.tm.hcl"

permissions:
  id-token: write
  contents: read
  pull-requests: write
  security-events: write

jobs:
  preview-and-scan:
    runs-on: ubuntu-latest
    env:
      WIZ_IAC_POLICY: "Default IaC policy"
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Install Terramate
        uses: terramate-io/terramate-action@v3
        with:
          version: "0.14.0"

      - name: Install Terraform
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: "1.12.2"
          terraform_wrapper: false

      - name: List changed stacks
        id: list
        run: |
          CHANGED=$(terramate list --changed)
          echo "changed<<EOF" >> "$GITHUB_OUTPUT"
          echo "$CHANGED" >> "$GITHUB_OUTPUT"
          echo "EOF" >> "$GITHUB_OUTPUT"
          if [ -z "$CHANGED" ]; then
            echo "No changed stacks — skip."
          else
            echo "Changed stacks:"
            echo "$CHANGED"
          fi

      - name: Configure AWS credentials (OIDC)
        if: steps.list.outputs.changed != ''
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN_PLAN }}
          aws-region: eu-west-3

      - name: Terraform init (changed stacks)
        if: steps.list.outputs.changed != ''
        run: |
          terramate run --changed --parallel 1 -- \
            terraform init -lock-timeout=5m

      - name: Terraform plan (changed stacks)
        if: steps.list.outputs.changed != ''
        run: |
          terramate run --changed --parallel 5 -- \
            terraform plan -out out.tfplan -lock=false

      - name: Export plan JSON per stack
        if: steps.list.outputs.changed != ''
        run: |
          terramate run --changed -- \
            bash -c 'terraform show -json out.tfplan > out.tfplan.json'

      - name: Install wizcli
        if: steps.list.outputs.changed != ''
        run: |
          curl -fsSL -o wizcli \
            https://downloads.wiz.io/wizcli/latest/wizcli-linux-amd64
          chmod +x wizcli
          sudo mv wizcli /usr/local/bin/wizcli
          wizcli version

      - name: Authenticate wizcli
        if: steps.list.outputs.changed != ''
        env:
          WIZ_CLIENT_ID: ${{ secrets.WIZ_CLIENT_ID }}
          WIZ_CLIENT_SECRET: ${{ secrets.WIZ_CLIENT_SECRET }}
        run: wizcli auth --id "$WIZ_CLIENT_ID" --secret "$WIZ_CLIENT_SECRET"

      - name: Wiz IaC scan on plan JSON (fail on policy)
        if: steps.list.outputs.changed != ''
        run: |
          set -euo pipefail
          FAIL=0
          while IFS= read -r stack; do
            [ -z "$stack" ] && continue
            echo "::group::Wiz scan $stack"
            if ! wizcli iac scan \
              --path "${stack}/out.tfplan.json" \
              --name "pr-${{ github.event.pull_request.number }}-${stack}" \
              --policy "$WIZ_IAC_POLICY" \
              --format sarif \
              --output "${stack}/wiz-iac.sarif"; then
              FAIL=1
            fi
            echo "::endgroup::"
          done <<< "${{ steps.list.outputs.changed }}"
          exit $FAIL

      - name: Upload SARIF (first stack with report)
        if: always() && steps.list.outputs.changed != ''
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: stacks
          # Si upload-sarif exige un fichier unique, fusionnez les SARIF
          # ou uploadez le premier : $(terramate list --changed | head -1)/wiz-iac.sarif

Notes de terrain :

  • --changed est non négociable : scanner toute la monorepo à chaque PR brûle le quota Wiz et noie le signal.
  • Scannez le plan JSON, pas seulement le dossier .tf, dès que vous avez des modules externes ou des variables injectées en CI.
  • La commande exacte (wizcli iac scan vs variantes selon version) évolue : validez avec wizcli iac scan --help sur l’image CI épinglée ; épingler le binaire par hash est préférable à latest en prod.
  • Le job d’apply (branche protégée / environment GitHub) ne démarre que si ce workflow est vert — pas de continue-on-error sur le scan.

Script Terramate pour standardiser le scan

Pour éviter de dupliquer la logique dans cinq workflows, un script Terramate dans le dépôt :

# stacks/networking/prod/stack.tm.hcl  (extrait)
stack {
  name        = "networking-prod"
  description = "VPC, SG, endpoints — prod"
  tags        = ["aws", "prod", "networking"]
}
# terramate.tm.hcl à la racine
scripts {
  wiz-scan-plan {
    description = "plan → JSON → wizcli iac scan"
    jobs = [
      {
        name   = "plan"
        commands = [
          ["terraform", "plan", "-out", "out.tfplan", "-lock=false"],
          ["terraform", "show", "-json", "out.tfplan", ">", "out.tfplan.json"],
        ]
      },
      {
        name = "wiz"
        commands = [
          [
            "wizcli", "iac", "scan",
            "--path", "out.tfplan.json",
            "--policy", "${env.WIZ_IAC_POLICY}",
            "--name", "${terramate.stack.path.absolute}",
          ],
        ]
      },
    ]
  }
}

Puis en CI : terramate script run --changed wiz-scan-plan (syntaxe selon votre version Terramate Scripts — vérifiez la doc de la version épinglée). L’idée compte plus que le DSL : une commande repo = plan + scan, réutilisable en local par les devs avec le même service account de préprod.

Ce que Wiz doit bloquer en priorité

Ne partez pas d’une policy à 400 contrôles. Activez d’abord le blocage sur :

  1. Exposition publique involontaire (SG/NACL 0.0.0.0/0 sur ports sensibles, buckets/objets publics, load balancers sans restriction).
  2. Identités dangereuses (Action / Resource *, trust policies trop larges, absence de condition oidc sur les rôles CI).
  3. Secrets en clair dans le plan (variables non marked sensitive qui fuient dans le plan JSON — attention : le plan JSON peut contenir des secrets ; traitez les artefacts CI comme sensibles, rétention courte).
  4. Stockage non chiffré / sans CMK là où votre politique l’exige.

Le reste (conformité CIS complète) peut rester en WARN jusqu’à ce que le backlog de remédiation suive.

Boucle runtime : fermer le code-to-cloud

Après apply, Wiz côté cloud rattache souvent le finding live au fichier Terraform via le state. Conditions :

  • Le state est accessible au connecteur / à l’intégration prévue (S3 backend + droits lecture dédiés, ou sync via plateforme type HCP/Scalr si vous y êtes).
  • Les ressources sont taguées de façon stable (Owner, Stack, ManagedBy=terramate) pour le triage humain quand le mapping automatique échoue.
  • Un finding Critical runtime sans ticket lié au stack Terramate = dette de process, pas seulement de scanner.

Sans cette boucle, vous avez un joli gate CI et un CSPM qui ne se parlent pas — deux silos.

Preuve pour l’audit / le client

# Stacks touchées par la PR
terramate list --changed

# Dernier rapport local (exemple)
jq '.runs[0].results | length' out/wiz-summary.json

# Dans GitHub : check "Wiz IaC scan" required sur main
# Dans Wiz : filtre reports name=pr-* + policy enforcement CLI=BLOCK

Livrables typiques d’une mission : workflow ci-dessus, policy Wiz documentée (quels contrôles bloquent), matrice tags Terramate ↔ comptes cloud, et 5 findings historiques montrant « aurait été bloqué en CI ».

Quand ne pas forcer Wiz dans Terramate

  • Vous n’avez pas encore Wiz : commencez par Checkov / Trivy / OPA sur le plan — moins cher, déjà utile. Wiz vient quand le graphe runtime et le code-to-cloud justifient le ticket (grille de décision).
  • Votre monorepo a moins de 5 stacks : Terramate est optionnel ; un terraform plan + wizcli sur le dossier suffit.
  • Personne ne regarde les SARIF : un gate qui échoue sans propriétaire de remédiation devient du bruit. Nommez un owner par tag Terramate.

Conclusion

Wiz et Terramate se complètent dès qu’on accepte qu’il n’y a pas de connecteur magique : Terramate choisit quoi planifier, wizcli décide si le plan a le droit d’être appliqué, Wiz CSPM vérifie ce qui tourne. Si vous voulez cadrer ce pipeline (OIDC, policy de blocage, découpage des stacks, lien avec Security Hub natif), un Audit Sécurité Cloud ou une mission supply chain selon que le goulot est l’IaC ou le runtime.

Sources : Terramate — GitHub Actions preview workflow, Terramate — security & data access, Wiz × HashiCorp / Terraform run tasks, Wiz + HCP Terraform (code-to-cloud).

Cet article vous a été utile ? Partagez-le.

Aller plus loin

Un sujet, une mission, une question ?

Distribuée accompagne des PME exigeantes sur la sécurité cloud, la supply chain CI/CD et la sécurité IA.

Réserver 15 min