IT-Admin.tech

Sécuriser les runners CI/CD : isolation des identifiants, nettoyage sécurisé de l'espace de travail et protection de la chaîne de build

Architekturdiagramm einer CI/CD-Pipeline mit Ephemeral-VM-Runnern, OIDC-Tokenflow, HSM-basiertem Signierdienst und...
Diagramm zeigt Trennung: Ephemeral Runner, internes Mirror, Artefakt-Repository und HSM/Signierdienst — so minimieren Sie Blast Radius bei kompromittierten Builds.

Sécuriser les runners CI/CD n’est pas un bricolage de sécurité ponctuel, mais une tâche opérationnelle durable : les runners extraient le code source, construisent des artefacts et ont souvent accès aux credentials, aux caches et au réseau interne. Pour les administrateurs et opérateurs, il est crucial de réduire de manière mesurable la surface d’attaque et d’avoir des chemins clairs de contrôle et de repli. Ce guide fournit des mesures concrètes, des étapes de vérification et du dépannage pour l’isolation des identifiants, un nettoyage robuste des espaces de travail et la protection de la chaîne de build.

Pourquoi les runners sont un vecteur d’attaque critique

Les runners sont des environnements d’exécution pour les jobs CI/CD (builds, tests, packaging). Un runner compromis peut :

  • exfiltrer des secrets (tokens, clés SSH, credentials cloud).
  • modifier des artefacts ou les signer de manière manipulée.
  • effectuer du cache-poisoning et ainsi influencer les builds suivants.
  • permettre du pivoting vers le réseau interne.

Distinction importante : trusted-Builds (p. ex. branches protégées ou Releases) versus untrusted-Builds (forks, PR externes, contributions publiques). Pour les builds non fiables, l’hypothèse opérationnelle doit être : le job est potentiellement malveillant.

Principes de base : droits minimaux, isolation, traçabilité

Renforcez l’exploitation selon trois objectifs mesurables :

  • Objectif d’isolation : aucun job ne doit voir l’état d’un autre job.
  • Objectif Credential : les jobs reçoivent uniquement les credentials strictement nécessaires, de préférence éphémères.
  • Objectif d’intégrité : l’origine et l’inaltérabilité des dépendances et des artefacts doivent être traçables.

Ces objectifs peuvent être opérationnalisés, testés et audités.

Isolation des identifiants : mise en œuvre, raisons et pièges typiques

L’isolation des identifiants signifie : pas de tokens statiques polyvalents. Séparez les identités selon la phase de la pipeline (build, package, release, deploy) et le contexte. Utilisez des tokens éphémères (TTL en minutes/heures) via OIDC, STS (Security Token Service) ou les leases de HashiCorp Vault. Les credentials éphémères limitent le blast radius en cas de compromission et simplifient la révocation.

Options techniques et usages

OIDC (OpenID Connect) est un protocole pour l’émission de tokens éphémères ; il connecte les systèmes CI aux Cloud-IAM ou à Vault sans secrets persistants. KMS/HSM (Key Management Service / Hardware Security Module) stocke les clés privées hors des runners. Vault propose des secrets dynamiques (p. ex. des credentials de base de données sur la base de leases). Chaque option comporte des exigences opérationnelles : OIDC nécessite des claims de token fiables, Vault exige une haute disponibilité et des politiques d’accès.

Beispiel: Vault-Policy für Package-Push

Hcl
# Vault policy (HCL) - erlaubt Token zum Schreiben in ein internes Artefakt-Repo
path "secret/data/ci/artifacts/*" {
  capabilities = ["create", "update", "read"]
}

Pourquoi cela fonctionne : Vault délivre des tokens limités dans le temps, et la policy restreint les chemins. Quand cela échoue : si les runners persistent le token Vault (p. ex. dans un cache) ou si les policies sont définies trop largement.

Signature limitée par policy via un service de signature

Les clés privées de signature ne doivent pas résider sur des runners standards. Un service de signature (service interne qui signe via KMS/HSM) reçoit les hash des artefacts, vérifie les policies (p. ex. que le build provient d’une branche protégée) puis signe. L’opération de signature nécessite des logs d’audit séparés et une authentification stricte.

Sécuriser les runners CI/CD : isolation au niveau de l’infrastructure

Choisissez l’isolation selon le risque et la rentabilité :

  • Host-Runner : Rapide, mais uniquement pour des jobs entièrement dignes de confiance.
  • Container-Runner : Bonne performance, mais uniquement avec rootless et des politiques de montage strictes.
  • Ephemeral VM/Instance-Runner : Isolation maximale ; par job une VM ou un snapshot frais. Coûts plus élevés, sécurité maximale.

Les Ephemeral-Runner sont particulièrement recommandés pour les builds non fiables : après achèvement, l’instance est détruite, empêchant toute persistance.

Exemple : Kubernetes-Runner en tant que job éphémère

Yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: runner-job-{{ .RunID }}
spec:
  template:
    spec:
      securityContext:
        runAsUser: 1000
        runAsGroup: 1000
        fsGroup: 1000
      containers:
      - name: builder
        image: registry.internal/runner-image:stable
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
      RESTartPolicy: Never
  backoffLimit: 0

Pourquoi cela aide : Kubernetes permet d’utiliser Namespaces, NetworkPolicies et les contextes Pod-Security pour RESTreindre. Attention : des configurations RBAC ou de volumes incorrectes peuvent compromettre l’isolation.

Nettoyage sécurisé des workspaces : robuste et résistant aux manipulations

Un nettoyage défectueux permet la persistance. Les problèmes proviennent de handles ouverts, de systèmes de fichiers montés, d’astuces de symlinks et d’ACLs RESTrictives. Un nettoyage robuste met en œuvre plusieurs couches de protection : workspaces dédiés, normalisation des propriétaires, –one-file-system lors de la suppression et des tests avec journalisation d’audit.

Linux : Nettoyage étendu incluant la vérification des handles

Shell
#!/usr/bin/env bash
set -euo pipefail
JOB_DIR="$1"
RUNNER_UID=1001
RUNNER_GID=1001

# 1) Prozesse beenden, die in JOB_DIR arbeiten
fuser -k -TERM -m "$JOB_DIR" || true
sleep 1
fuser -k -KILL -m "$JOB_DIR" || true

# 2) Ownership und Rechte normalisieren
chown -R "${RUNNER_UID}:${RUNNER_GID}" "$JOB_DIR" 2>/dev/null || true
chmod -R u+rwX,go-rwx "$JOB_DIR" 2>/dev/null || true

# 3) Prüfen auf Mountpoints im Jobdir
mountpoints=$(findmnt -n -o TARGET --target "$JOB_DIR" || true)
if [ -n "$mountpoints" ]; then
  echo "Found mounts: $mountpoints" >&2
  # Option: detach mounts safely or warn and abort
fi

# 4) Löschen sicher durchführen
rm -rf --one-file-system "$JOB_DIR"

Pourquoi fuser est nécessaire : des handles de fichiers ouverts empêchent la suppression ; les processus doivent être correctement terminés. Le script peut échouer si un job a lancé des processus système que le script ne peut pas terminer — d’où l’importance du logging et des niveaux d’avertissement.

Windows : Handles, plan de redémarrage et interaction avec l’antivirus

Sur Windows, les verrous causés par des services et des AV sont courants. Complétez le nettoyage par des vérifications des handles (Sysinternals Handle/Process Explorer), des tentatives répétées et une procédure de redémarrage planifiée si la suppression est impossible. De simples tentatives répétées ne suffisent pas toujours face à des verrous persistants — documentez une procédure de rollback.

Sécurité de la chaîne de build : sources de paquets, caches et signature

Protégez la chaîne de build par l’isolation des sources de paquets, des proxys avec allow-lists, des caches contrôlés et des politiques d’artefacts immuables.

Miroirs internes et RESTriction de l’egress

Outre des allow‑lists pour les endpoints de paquets, les runners ne devraient avoir qu’un egress défini : VCS, miroir, dépôt d’artefacts, KMS/service de signature. Les Egress-ACLs réduisent les possibilités d’exfiltration / d’établissement d’une infrastructure de Command-and-Control. Testez d’abord les modifications en Monitor-Mode (seulement logging) avant de bloquer.

Renforcement du dépôt d’artefacts

Appliquez des write-policies (non-overwrite), des retention-policies et les flags require-signed-artifact si votre repo le supporte. Les logs d’audit doivent indiquer qui a publié quel artefact et quand. Règle d’exemple : „Les releases ne peuvent être publiées qu’après signature par le service de signature“.

Stratégies de cache contre l’empoisonnement

Séparez les caches par zones de confiance et par projet. Évitez les shared writable caches pour les jobs non fiables. Utilisez l’invalidation par TTL et des hash de cache consignés pour détecter l’empoisonnement.

Renforcement du réseau et de l’hôte : mesures concrètes

Traitez les Runner comme des composants d’infrastructure critiques :

  • segments réseau dédiés ou VLANs
  • ACLs egress définies
  • pare-feu hôte et processus de gestion des correctifs
  • monitoring et logs centralisés

Exemple : règle iptables simple pour l’egress (VM-Runner)

Shell
# Erlaube nur DNS, HTTP(S) zu mirror.example und signing.example
iptables -A OUTPUT -m owner --uid-owner runner -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -p tcp -d mirror.example --dport 443 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -p tcp -d signing.example --dport 443 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -j DROP

Warum das hilft: Selbst wenn ein Job versucht, bösartige Kommunikation aufzubauen, bleibt Egress begrenzt. Achtung: DNS-over-HTTPS und andere Umgehungswege können dies unterlaufen—testen und monitoren.

Tests, audit und validation

Validez les mesures par des tests et des audits automatisés :

  • Jobs d’audit réguliers qui tentent d’exécuter depuis un Runner des actions non autorisées (uniquement dans un réseau de test isolé !).
  • Audits post-job : vérifier la présence de répertoires de workspace, les descripteurs ouverts, les processus actifs.
  • Analyse des logs : détection d’exfiltration de tokens ou de connexions egress inhabituelles.

Exemple de script de test : validation après nettoyage

Shell
#!/usr/bin/env bash
# Prüft, ob ein Job-Verzeichnis nach Cleanup noch existiert
JOB_DIR="$1"
if [ -e "$JOB_DIR" ]; then
  echo "CLEANUP FAILED: $JOB_DIR still exists" >&2
  ls -la "$JOB_DIR" >&2
  exit 2
fi
# Prüfe auf aktive Prozesse des Runner-User
if pgrep -u runner >/dev/null; then
  echo "ACTIVE PROCESSES FOUND" >&2
  ps -u runner -o pid,cmd
  exit 3
fi
exit 0

Pièges typiques et dépannage

1) Secrets accidentellement dans le build-log

Cause : prints de debug ou masquage manquant. Mesures : activer le masquage des logs CI, ne pas afficher les variables sensibles en clair. Vérifiez automatiquement les logs à la recherche de motifs (API-Keys, Bearer-Tokens) avec un job scanner.

2) Conteneurs privilégiés abusés

Cause : conteneurs privilégiés ou passage du socket Docker. Mesure : builds rootless, pas de montages du socket hôte, utilisation de Buildkit/remote daemon. Test : le job tente de lancer de nouveaux conteneurs sur l’hôte (uniquement en environnement de test !).

3) Clés de signature sur les Runner

Cause : praticité plutôt que sécurité — les équipes stockent les clés localement. Mesure : centraliser les services de signature, stocker les clés uniquement dans un HSM/KMS. En cas de compromission : rotation immédiate et invalidation de toutes les clés potentiellement compromises.

Stratégie de rollback et d’urgence

Implémentez les changements par étapes :

  1. Mode monitoring : uniquement journalisation, pas de blocage.
  2. Fermeture progressive des zones egress/politiques.
  3. Exploitation parallèle des anciens et nouveaux pools de Runner ; bascule via feature-flag/route.
  4. Break-glass tokens pour les urgences, à durée courte et traçables en audit.

Important : documentez les étapes de retour arrière et testez‑les régulièrement dans un essai isolé.

Checklist pratique : mise en œuvre en 90–180 minutes

  • Inventorier les tokens actifs et vérifier les droits pour chaque phase du pipeline.
  • Migrer les jobs non fiables vers des pools de runners séparés ou des Ephemeral-VMs.
  • Étendre les scripts de nettoyage : process-kill, chown, chmod, –one-file-system, post‑validation.
  • Auditer le processus de signature et planifier la gestion des clés dans un HSM/KMS.
  • Créer des Egress-ACLs en mode monitor et observer le trafic.
  • Job d’audit : tenter d’exécuter depuis le runner des actions non autorisées (isolé).

Conclusion

Sécuriser les runners CI/CD implique de concilier praticité et sécurité mesurable. Priorisez la séparation des identifiants selon la phase du pipeline (avec des tokens éphémères), un nettoyage garanti des workspaces (ou des Ephemeral-Runners) et la signature via un service de signature ou un HSM/KMS. Complétez par des RESTrictions d’egress, du monitoring et des tests d’audit réguliers. Avec une introduction progressive, des phases en mode monitor et des procédures de repli testées, la sécurité RESTe gérable et opérationnellement fiable.

FAQ

Quelle est la plus grande erreur lors de la sécurisation des runners CI/CD ?

L’erreur la plus fréquente est l’utilisation d’un token permanent et largement permissif pour toutes les phases du pipeline. Un job compromis obtient ainsi trop de pouvoir. Il est préférable de séparer par phase (Build, Package, Release, Deploy) et d’utiliser des tokens éphémères, liés au contexte.

Un conteneur suffit‑il comme isolation pour des builds non fiables ?

Un conteneur seul suffit uniquement si les privilèges, les mounts et le réseau sont strictement RESTreints. Sont particulièrement dangereux les conteneurs en privileged ou le passage du socket Docker. Pour les builds non fiables, des Ephemeral VMs ou des jobs Kubernetes fortement isolés sont plus robustes.

Comment m’assurer que le nettoyage du workspace fonctionne réellement ?

Utilisez des workspaces dédiés par job, normalisez la propriété/les permissions avant suppression et supprimez avec –one-file-system. Pour Windows arrêtez les handles de processus de l’utilisateur du job et prévoyez des retries. Des audits post‑job automatisés vérifient qu’aucun résidu ne subsiste.

Pourquoi la clé privée de signature ne doit‑elle pas résider sur le runner ?

Si la clé est présente sur des runners standards, un job compromis peut signer des artefacts manipulés. Il est préférable de signer via un HSM/KMS ou via un service de signature distinct qui signe uniquement dans des contextes concrets, soumis à des politiques.

Comment gérer la dégradation des performances due à une isolation renforcée ?

Séparez les caches par zones de confiance et par projet, utilisez des mirrors internes et des images de runners warm‑started (snapshots). Cela permet de conserver des performances sans exposer au risque de cache‑poisoning.

Quelles vérifications un job d’audit pour runners devrait‑il inclure ?

Les jobs d’audit doivent tenter d’établir des connexions d’egress non autorisées, d’obtenir des accès en écriture à d’autres workspaces, de tester l’accès aux APIs de signature sans claims valides et de vérifier que le post‑cleanup ne laisse ni fichiers ni processus. Ne lancez ces tests que dans des environnements isolés.

Sécuriser les runners CI/CD : exploitation, monitoring et intégration

Les mesures techniques ne valent que par leur exploitation. Prévoyez le monitoring, les métriques et les intégrations dès l’introduction des durcissements des runners, afin que la sécurité reste reproductible et mesurable.

Métriques importantes et alertes :

  • Taux d’échec de nettoyage : proportion de jobs pour lesquels la validation post‑job a échoué. Définissez un seuil et déclenchez une alerte avant que des déficiences d“nettoyage ne deviennent persistantes.
  • Vault‑Lease‑Errors et OIDC‑Token‑Failures : signalent des problèmes liés aux identifiants temporaires ou à des claims erronés.
  • Connexions egress inhabituelles par pool de runners : des augmentations soudaines peuvent indiquer une exfiltration ou des tentatives de contournement.
  • Demandes de signature par heure et erreurs de signature : des écarts peuvent révéler des pipelines compromis ou des erreurs de politique.

Conseils d’intégration :

  • IAM/IdP : Connectez le CI en tant que client OAuth/OIDC au fournisseur d’identité existant (p. ex. AD, Okta). Ainsi l’audit et le cycle de vie des utilisateurs restent gérés de façon centralisée.
  • Secrets‑Backends : Utilisez Vault/KMS de manière dynamique ; automatisez le renouvellement des leases et la rotation. Documentez les rotations d’urgence et testez le chemin de révocation des clés.
  • Dépôt d’artefacts : Complétez les politiques de signature par des attestations (métadonnées de build, SBOM). Cela rend la provenance vérifiable et facilite les analyses d’incident.

Runbook et procédures de repli :

  • Rédigez un runbook succinct : étapes pour isoler un pool de runners, rotation des clés, interrupteur de désactivation pour le service de signature et retour en arrière vers des runners en warm‑standby.
  • Effectuez régulièrement des tests chaos dans une zone de test (échec de cleanup, blocage des sorties egress) et évaluez les processus opérationnels au regard de SLA concrets.

Conclusion : L’exploitation et l’intégration ne sont pas des après‑pensées. De bonnes métriques, la rotation automatisée ainsi que des runbooks coordonnés rendent la sécurité CI/CD robuste et maniable au quotidien.

Pour ce sujet, la sécurité de la chaîne d’approvisionnement et la protection de la chaîne de build sont également importantes. L’article situe ces aspects de manière claire et montre ce qui compte au quotidien.