Aller au contenu
Documentation

Modules

Infrastructure as code

L'analyse des fichiers Terraform, des manifestes Kubernetes et des Dockerfile à chaque push et pull request, le commentaire et le statut de PR, la dérive entre code et cloud, et la liaison d'une ressource cloud à sa ligne Terraform.

Le module d'infrastructure as code analyse les dépôts Git connectés à chaque push et à chaque pull request, publie le résultat dans la pull request, puis rapproche ce que le code déclare de ce que le cloud exécute. La page « Infrastructure as Code » et le rapport de chaque analyse présentent le résultat.

Déclenchement

Une intégration Git (application GitHub ou groupe GitLab, voir Connecter un dépôt Git) livre des webhooks à l'instance. Un événement push ou pull_request (ouverture, nouveau commit, réouverture) sur GitHub, un « Push Hook » ou un « Merge Request Hook » sur GitLab, déclenchent une analyse si l'intégration l'autorise : « Scanner à chaque push » et « Scanner chaque pull request » se règlent dans « Paramètres », section « Intégrations Git », « Modifier l'intégration Git ». Les trois familles (« Infrastructure as Code », « Secrets », « Dépendances (SCA) ») s'activent une à une.

Ctadel clone le commit le temps de l'analyse, puis supprime le clone. Une analyse longue (un monorepo) reste en cours sans être relancée en double.

Ce qui est analysé

FichiersReconnaissanceLecture
Terraform*.tf et *.tf.jsonLes blocs resource sont parsés en HCL ; les variables sont résolues depuis terraform.tfvars, *.tfvars et *.tfvars.json. Chaque ressource est aussi inscrite dans l'inventaire du dépôt (type, adresse, fichier, ligne), qui sert à la liaison code vers cloud
Manifestes Kubernetes*.yaml et *.yml contenant kind et apiVersionLe spec du pod est extrait des Deployment, StatefulSet, DaemonSet, Job, CronJob et Pod ; les contrôles portent sur les conteneurs et leur contexte de sécurité, en tenant compte de l'héritage du pod
DockerfileFichiers nommés Dockerfile ou *.DockerfileLes instructions sont parsées étape par étape ; les contrôles portent sur l'image de base (étiquette latest ou absente), l'instruction USER, ADD à la place de COPY et les autres pratiques du CIS Docker

Les règles Terraform couvrent les fournisseurs aws, azurerm, google, scaleway, ovh et outscale. Quelques règles sont désactivées par défaut ; la raison figure dans leur description.

Un fichier de plus de 10 Mo n'est pas lu. Un lien symbolique n'est pas suivi : un .tf pointant hors du clone ne serait pas lu comme du Terraform. Un fichier Terraform qui ne parse pas, ou un YAML invalide (un gabarit Helm, une surcouche Kustomize), est compté comme non analysé.

Le fichier .ctadel.yaml

À la racine du dépôt, un fichier .ctadel.yaml déclare ce que l'équipe assume et où ranger le dépôt :

version: 1
folder: Production/Europe/France
ignores:
  - rule: IAC-AWS-TF-006
    paths:
      - "modules/bastion/**"
    resources:
      - aws_security_group.bastion
    reason: "Bastion SSH filtré par le pare-feu amont, revu le 3 mars"
    expires: "2027-03-01"
  • rule : la clé exacte, ou un préfixe suivi de *.
  • paths et resources : facultatifs ; des motifs de chemin et des adresses de ressources. Une entrée sans l'un ni l'autre couvre toute la règle.
  • reason : obligatoire, 10 caractères au moins. Une suppression silencieuse n'est pas acceptée.
  • expires : facultatif ; une entrée expirée est ignorée.
  • folder : facultatif ; le dossier de l'interface où le dépôt est rangé, créé s'il manque. Voir Projets et dossiers.

Un constat couvert par une entrée est stocké avec le statut IGNORED, la règle et la raison, et ne compte ni pour le statut de la pull request ni pour le commentaire. Les mêmes entrées couvrent les secrets du dépôt. Si le fichier ne parse pas, l'analyse continue sans suppression, et le rapport affiche « Impossible de charger le fichier .ctadel.yaml » : « Les règles de suppression ne sont pas appliquées pour cette analyse. Corrigez le fichier dans le dépôt et déclenchez une nouvelle analyse. »

Commentaire et statut de pull request

Chaque analyse d'une pull request produit :

  • un commentaire qui liste les constats par sévérité avec le fichier et la ligne, et un lien vers le rapport /gitscan/<id> ;
  • un statut de commit par famille : ctadel/iac et ctadel/secrets sur GitHub, ctadel/iac-scan sur GitLab. Votre protection de branche peut exiger ce statut.

Le statut vaut « échec » quand « Bloquer la PR en cas d'échec » est coché pour la famille et qu'un constat atteint le seuil « Bloquer si des détections ≥ » (sévérité CRITICAL, HIGH, MEDIUM ou LOW). Un seuil non reconnu bloque sur tout constat. Sans blocage, le statut est toujours « succès » et le commentaire reste informatif.

Une analyse de branche ou de pull request est jugée pour elle-même : elle ne ferme pas les constats de la branche par défaut, ne réécrit pas l'inventaire et n'alerte pas les canaux de notification. Quand une pull request est fermée sans fusion, les constats qu'elle avait introduits sont fermés avec la raison « pull request closed without merge ».

Historique des constats

Sur la branche par défaut, un constat qui n'apparaît plus dans l'analyse suivante passe à RESOLVED ; un constat déjà vu garde sa date de première détection. Chaque changement de statut est inscrit dans l'historique du constat, visible dans l'onglet « Historique » du panneau de détail. Les statuts possibles sont OPEN, IGNORED et RESOLVED.

Dérive entre code et cloud

Certaines règles Terraform ont une contrepartie dans le catalogue de configuration cloud : la même propriété, lue sur la ressource déployée. Ces paires permettent de qualifier un constat :

ConstatValeurSens
Configuration cloud« Cloud uniquement »Aucune règle de code appariée ne s'applique, ou la ressource n'est pas gérée par du code connu
Configuration cloud et IaC« Code & Cloud »La même mauvaise configuration est dans le code et dans le cloud : corriger le code suffit
Configuration cloud« DÉRIVE »La ressource est déclarée par du code connu (voir la liaison plus bas), le code est sain, mais le cloud a la mauvaise configuration : quelqu'un a modifié la ressource hors du code

La colonne « Source » de la page « Configuration cloud » (voir Configuration cloud) affiche cette valeur et un filtre « Source » la sélectionne. Le rapprochement est recalculé après chaque évaluation cloud et après chaque analyse de dépôt. Il compare les ressources par nom : l'adresse Terraform doit correspondre au nom de la ressource cloud, ou en être le dernier segment.

Les paires sont déclarées une à une et seulement quand la règle cloud teste la même propriété, dans le même sens, sur la même ressource. Certaines règles Terraform n'ont pas de contrepartie ; un constat de ces règles n'a pas de statut de dérive.

Liaison d'une ressource cloud à sa ligne Terraform

Pour qu'une ressource cloud soit reliée au code qui la déclare, Ctadel écrit une étiquette ctadel:id sur la ressource dans le code, puis la relit dans le cloud :

  1. Après la première analyse d'un dépôt GitHub, Ctadel ouvre une pull request d'étiquetage sur une branche ctadel/iac-tagging-<date>. Elle ajoute ctadel:id = "<identifiant>" dans le bloc tags (ou labels pour Google Cloud) des ressources dont le schéma Terraform accepte ce champ. Un type absent de la liste des types étiquetables est laissé intact. L'identifiant est stable : rouvrir la pull request sur un code déjà étiqueté produit un diff vide.
  2. Vous relisez et fusionnez cette pull request, puis appliquez votre Terraform.
  3. L'inventaire cloud lit l'étiquette sur chaque ressource ; Ctadel retrouve les coordonnées de l'identifiant (dépôt, adresse, fichier, ligne) et les écrit sur la ressource dans le graphe. Chaque ressource déclarée dans le code a aussi son propre nœud IacResource dans le graphe, et une relation DEPLOYED_AS le joint à la ressource cloud dès que les deux existent.
  4. Les ressources enfants qui ne portent pas d'étiquette (une règle de groupe de sécurité, une route) héritent de la liaison de leur parent.

La pull request d'étiquetage demande à l'application GitHub les droits d'écriture contents et pull_requests. Si l'installation ne les a pas, « Paramètres » affiche une bannière qui demande d'autoriser à nouveau Ctadel sur l'organisation « pour activer l'étiquetage automatique par PR », avec un bouton « Vérifier les permissions sur GitHub ». Une seule pull request d'étiquetage est ouverte à la fois par dépôt ; si vous la fermez sans fusionner, aucune autre n'est ouverte pendant 30 jours ; après une fusion, une pull request de suite est ouverte quand de nouvelles ressources apparaissent dans le code.

La carte « Couverture code vers cloud » (libellé affiché avec une flèche) en tête de la page « Infrastructure as Code » compte les ressources « Reliées (tag) », « Reliées (parent) », « Code seul » (déclarées mais pas déployées) et « Cloud non relié », et donne le pourcentage de l'ensemble attribuable à un fichier et une ligne. Les relations DEPLOYED_AS sont visibles dans l'explorateur.

Les pages

La page « Infrastructure as Code » (entrée « IaC » du menu) liste les constats de tous les dépôts avec les colonnes « Sévérité », « Statut », « Règle », « Type » (type de fichier), « Fichier » et « Dépôt ». Les filtres sont « Sévérité », « Statut », « Type de fichier », « Dépôt » et « Branche » ; le regroupement se fait sur les mêmes axes ; « Exporter CSV » exporte la sélection. Un clic ouvre le panneau de détail (onglets « Vue d'ensemble », « Remédiation », « Historique »).

La page Infrastructure as Code avec la carte de couverture code vers cloud et la liste des constats.
Figure 1. Figure 1. La page « Infrastructure as Code » sur l'instance de démonstration. Données de démonstration.

Le « Rapport d'analyse » (/gitscan/<id>, le lien du commentaire de pull request) montre une analyse : dépôt, branche, numéro de pull request, nombre de fichiers analysés, puis trois onglets « IaC », « Secrets » et « Vulnérabilités » avec les constats que cette analyse a vus. Les anciens liens /iac/scan/<id> y redirigent.

Limites

  • Quelques règles Terraform sont désactivées par défaut ; leur description dans « Politiques » dit pourquoi.
  • Les variables Terraform ne sont résolues que depuis les fichiers tfvars ; locals, les sorties de modules et les sources de données ne le sont pas. Une valeur qui dépend d'eux n'est pas évaluée.
  • Les gabarits Helm et les surcouches Kustomize ne sont pas du YAML valide et ne sont pas analysés. Seuls les manifestes rendus le sont.
  • Un fichier de plus de 10 Mo n'est pas lu.
  • Les paires code-cloud existent pour AWS, Azure et Google Cloud ; les règles Scaleway, OVHcloud et OUTSCALE n'en ont pas, donc pas de statut de dérive.
  • La pull request d'étiquetage n'existe que pour GitHub ; un dépôt GitLab reçoit le commentaire et le statut mais pas l'étiquetage automatique. Les types Terraform qui portent leurs étiquettes dans une autre forme (aws_autoscaling_group, google_container_cluster, google_sql_database_instance) ne sont pas étiquetés.
  • La page « Infrastructure as Code » n'affiche pas de colonne de source ; le statut de dérive se lit sur la page « Configuration cloud ».