Configurer l'audit de sécurité quotidien¶
Vous êtes mainteneur·se de Kirexo et vous voulez activer la vérification quotidienne des vulnérabilités Composer : un cron GitLab lance composer audit chaque matin sur main, et tente d'ouvrir une MR de patch (composer update --with-all-dependencies) ; à défaut, il ouvre une issue d'alerte.
La schedule n'existe pas par défaut sur un nouveau projet GitLab — il faut la créer manuellement une fois.
Une seule schedule, plusieurs jobs de maintenance
La schedule créée ici déclenche en réalité tous les jobs de maintenance du stage maintenance, filtrés sur $CI_PIPELINE_SOURCE == "schedule" :
security:composer-audit— l'audit Composer décrit sur cette page (MR-first, fallback issue) ;dependencies:renovate— montées de version automatiques (cf. Configurer Renovate, réutilise le mêmeGITLAB_TOKEN) ;tools:version-check— contrôle des outils épinglés dans leDockerfile(cf. référence) ;container_scanning— scan des CVE de l'image de production publiée (kirexo-prod:latest) : vulnérabilités des paquets OS et des bibliothèques système embarqués dans l'image ;container_scanning:builders— même scan, mais sur les images CI (kirexo-base:php8.5,kirexo-dev:php8.5) —parallel:matrixà deux entrées ;security:container-issue(+security:container-issue:builders) — ouvre une issue GitLab par image vulnérable uniquement si au moins une CVE Critical ou High est remontée. Le récap par sévérité (Critical / High / Medium / Low / Other / Total) reste dans le corps de l'issue pour traçabilité. Non bloquant : c'est une alerte, pas un gate. Authentification viaGITLAB_TOKEN(cf. Pré-requis).
Inutile de créer une schedule par job : une seule suffit.
Container scanning en tier Free : on parse le rapport nous-mêmes
L'onglet Security et le widget de sécurité dans la MR sont réservés à GitLab Ultimate. En tier gratuit, les jobs container_scanning et container_scanning:builders produisent bien leur rapport JSON, mais ce sont security:container-issue et security:container-issue:builders qui le parsent pour décider d'ouvrir une issue — l'alerting est donc fait par nos soins, sans surface GitLab native.
Prérequis¶
- Vous avez les droits Maintainer ou Owner sur le projet GitLab.
- La variable CI/CD
GITLAB_TOKENest configurée avec les scopesapi+write_repository(cf. Variables CI/CD GitLab). C'est un Personal Access Token (les project access tokens sont réservés à GitLab Premium/Ultimate) — le même que celui utilisé partag:createet Renovate. Le scopewrite_repositoryest requis parsecurity:composer-auditpour pousser sa branche de patch ;apicouvre la création de MR et d'issue parsecurity:composer-audit,tools:version-check, Renovate et parsecurity:container-issue(+:builders) — ces deux derniers utilisent eux aussiGITLAB_TOKENcarCI_JOB_TOKENn'est pas accepté surPOST /projects/:id/issuesen tier Free (HTTP 401 testé empiriquement). - Le fichier
.gitlab/ci/security.ymlest présent dans le repo (introduit au Lot 4 de l'étape 4) et le jobsecurity:composer-audity est défini.
Créer la schedule¶
- Dans le projet GitLab, aller dans Build → Pipeline schedules.
- Cliquer sur New schedule (bouton en haut à droite).
-
Renseigner les champs suivants :
Champ Valeur Description Audit sécurité quotidienInterval pattern 0 5 * * *(5 h UTC chaque jour — soit 6 h ou 7 h en France selon la saison)Cron timezone UTC(laisser par défaut)Target branch mainVariables (laisser vide — la pipeline filtre sur $CI_PIPELINE_SOURCE == "schedule", pas sur une variable)Activated Coché -
Cliquer sur Save pipeline schedule.
À partir de la prochaine exécution planifiée, GitLab démarrera une pipeline avec $CI_PIPELINE_SOURCE == "schedule". Les jobs qui s'exécutent dans ce cas sont security:composer-audit, dependencies:renovate, tools:version-check, container_scanning, container_scanning:builders, security:container-issue et security:container-issue:builders — tous les autres jobs sont filtrés par leurs rules:.
Tester immédiatement sans attendre 5 h UTC
Depuis Build → Pipeline schedules, cliquer sur l'icône ▶ à droite de la schedule pour la déclencher manuellement. La pipeline se lance avec $CI_PIPELINE_SOURCE == "schedule" exactement comme à l'heure planifiée — pratique pour valider la configuration une fois pour toutes.
Ce que fait security:composer-audit¶
Le job tourne en MR-first : il essaie d'abord d'ouvrir une merge request de patch (composer update --with-all-dependencies) ciblée sur les packages vulnérables, et ne retombe sur une simple issue d'alerte que si l'update ne suffit pas à corriger toutes les vulnérabilités.
Enchaînement :
composer audit --no-interaction --format=json > audit-composer.json.- Si aucune vulnérabilité : le job passe, exit
0. - Si une MR
security/composer-*est déjà ouverte (filtrée par labelssecurity,dependencieset préfixe desource_branch) : le job log « on ne duplique pas » et sort en0— le cron quotidien ne recrée pas la même MR tant qu'elle n'est pas mergée. - Sinon,
composer update --no-interaction --with-all-dependencies <packages vulnérables>puis un ré-audit :- Update OK + ré-audit clean → branche
security/composer-YYYYMMDD-HHMMSSpoussée (push -o ci.skip, identitéci-bot@kirexo.app) et MR ouverte viaPOST /projects/:id/merge_requests(labelssecurity,dependencies,remove_source_branch: true,squash: true). Titre :Patch sécurité Composer du YYYY-MM-DD. Le job termine en0. - Update KO ou ré-audit toujours rouge (versions patchées hors des contraintes
composer.json, conflit de resolver) → fallback issue :POST /projects/:id/issueslistant packages, versions affectées, titres et CVE. Labelssecurity,dependencies. Le job termine enexit 1pour rester rouge.
- Update OK + ré-audit clean → branche
- Si l'audit initial est cassé (réseau, packagist HS,
composer.lockcorrompu, JSON malformé) → ni MR ni issue, le job échoue avec le code de sortie decomposer audit.
| Cas | Effet |
|---|---|
| Aucune vulnérabilité | Job vert, aucun appel API. |
| MR déjà ouverte | Job vert, dédup. |
| Update suffit | MR de patch ouverte (branche security/composer-*). Job vert. |
| Update insuffisant ou en conflit | Issue d'alerte (fallback). Job rouge. |
| Audit cassé | Job rouge, ni MR ni issue. |
L'artifact audit-composer.json est conservé 1 mois quel que soit le résultat (when: always). Il est consultable depuis la page du job → Browse.
Diagramme de flux complet et caractéristiques détaillées : Référence — Job security:composer-audit.
Vérifier que la schedule fonctionne¶
- Aller dans Build → Pipeline schedules — la colonne Last pipeline doit afficher la date du dernier passage.
- Cliquer sur le statut de la dernière pipeline pour voir le job
security:composer-audit. - Si une issue a été créée, elle apparaît dans Plan → Issues avec les labels
securityetdependencieset un titreFailles Composer détectées le YYYY-MM-DD.
Cas d'erreur¶
Le job échoue avec 401 Unauthorized lors de la création de l'issue ou de la MR¶
Le GITLAB_TOKEN est absent, expiré, ou n'a pas le scope api. Régénérer le token (Settings → Access Tokens), mettre à jour la variable CI/CD (Settings → CI/CD → Variables).
Le job échoue avec 403 Forbidden au moment du git push¶
Le GITLAB_TOKEN n'a pas le scope write_repository (présent depuis l'étape 4 du projet). C'est ce scope qui autorise la création de la branche security/composer-*. Régénérer le PAT en cochant api et write_repository, puis mettre à jour la variable CI/CD.
Le job échoue mais aucune issue n'est créée¶
C'est le comportement attendu quand composer audit n'a pas pu produire de rapport JSON exploitable (réseau, registry packagist HS, composer.lock cassé). Consulter le log du job — la ligne Composer audit a échoué sans produire de rapport JSON exploitable est affichée explicitement avec le code de sortie. Aucune action n'est requise tant que la cause est transitoire ; si elle persiste, vérifier l'accès réseau du runner et l'intégrité de composer.lock.
La schedule ne se déclenche jamais¶
Vérifier que :
- La case Activated est cochée dans la schedule.
- Le runner CI est disponible (pas de quota épuisé sur les runners partagés).
- L'utilisateur·rice qui a créé la schedule a toujours accès au projet — GitLab désactive la schedule si son auteur·rice perd l'accès.
Voir aussi¶
- Bootstrapper la pipeline CI — séquence globale de configuration (DNS, PAT, variable CI/CD, custom domain Pages, schedule, premier build d'images) sur une nouvelle instance.
- Pipeline GitLab CI — Stage
maintenance— détail des jobssemgrep-sast,security:composer-audit,dependencies:renovate,tools:version-check,container_scanning(+:builders) etsecurity:container-issue(+:builders). - Configurer les montées de version automatiques (Renovate) — comportement du bot, déclenché par la même schedule et réutilisant le même
GITLAB_TOKEN. - Variables CI/CD GitLab — détail de
GITLAB_TOKEN.