10 KiB
CI/CD sécurisée — Gitea 1.22.6
La version du serveur https://gitea.ops.xpeditis.com a été vérifiée via
/api/v1/version : 1.22.6. Les pipelines ciblent Gitea Actions / act_runner,
avec des jobs exécutés dans des conteneurs Linux AMD64 ou ARM64.
Workflows et contrôles
Les quatre workflows actifs se trouvent dans .gitea/workflows/. Les anciennes
copies .github/workflows/ sont déplacées pour éviter une double exécution.
L'action composite .gitea/actions/security est appelée directement par chaque
pipeline ; aucun workflow réutilisable GitHub ni client gh n'est nécessaire.
| Pipeline | Déclenchement | Contrôles |
|---|---|---|
| Dev CI | Push/PR vers dev |
Lint, types, tests unitaires, sécurité |
| PR Checks | PR vers preprod ou main |
Idem + tests d'intégration PostgreSQL/Redis |
| CD Preprod | Push vers preprod |
Idem + build, scan AMD64/ARM64, déploiement, contrôles HTTP |
| CD Production | Push vers main |
Qualité/tests/sécurité, provenance préprod, build frontend, scan AMD64, déploiement SSH, tests de fumée |
Le job Security gate exécute :
npm audit --package-lock-only --audit-level=highsur la racine, le backend, le frontend et le log-exporter, sans installer de dépendances ni exécuter leurs scripts. Les dépendances de développement sont incluses.- Trivy sur les fichiers suivis du commit : détection de secrets et de mauvaises configurations Docker/Kubernetes/Terraform, seuil HIGH/CRITICAL.
- La validation statique des workflows et les tests des scripts de promotion/santé.
Les images sont analysées par digest, avec HIGH/CRITICAL bloquants, y compris
lorsqu'aucun correctif n'est disponible. Les erreurs de scanner ou de registre
échouent aussi : aucune exclusion générale ni échec masqué n'est ajouté.
Les installations applicatives utilisent npm ci, le runtime est Node 22 et les
actions sont épinglées par SHA. Trivy, Actionlint et Hetzner CLI sont téléchargés
avec détection native AMD64/ARM64 et vérification SHA256. Le lint backend ne réécrit plus les fichiers.
Les rapports sont joints aux exécutions Gitea Actions avec
actions/upload-artifact v3, compatible avec le protocole de cette version
Gitea. security-reports est conservé 7 jours, image-security-* 14 jours selon
la politique de rétention du serveur. Les valeurs et extraits de code des secrets
sont retirés du rapport téléchargeable. Les URLs GitHub servent uniquement à
récupérer les actions publiques épinglées, pas à exécuter les pipelines.
Ces scans ne remplacent pas un audit du code métier ni un test d'intrusion ; la recherche de secrets porte sur le commit courant, pas tout l'historique.
Promotion sans API GitHub
Gitea 1.22.6 n'expose pas d'API de consultation des runs Actions dans son Swagger.
La provenance utilise donc le registre Scaleway existant : après scans, webhooks
et contrôles HTTP backend/frontend réussis, le job préprod publie des marqueurs
validated-preprod-<SHA complet> pour le backend et le log-exporter, à partir des
digests construits et scannés. Le log-exporter est construit/scanné par cette
chaîne ; son déploiement n'a pas de webhook ni de contrôle HTTP dédié existant.
La production accepte seulement un commit de main ou un de ses parents dont
l'arbre Git est identique, avec les deux marqueurs présents. Elle récupère leurs
digests, les rescane et les promeut sans reconstruire le backend/log-exporter.
Le frontend est reconstruit avec les URLs prod puis scanné par digest. Les tags
prod-SHA et latest ne sont publiés que dans le job de déploiement, après scans.
Utiliser un merge classique ou fast-forward de préprod vers main ; un squash ou rebase qui supprime cette provenance sera refusé. Il faut une première préprod réussie avec ces nouveaux workflows avant de promouvoir en production. La preuve repose sur les droits du registre : réserver l'écriture des marqueurs au compte CI et ne pas les créer manuellement. Ce n'est pas une attestation cryptographique.
Les images candidates peuvent rester dans le registre après un échec de scan, sans être publiées sous les alias d'environnement par le pipeline.
Configuration nécessaire sur ton instance
Gitea 1.22 ignore notamment concurrency, permissions, environment, les délais
YAML de jobs et workflow_dispatch. Ces paramètres ne sont donc pas présentés
comme des protections effectives dans les workflows adaptés.
- Activer Actions dans le dépôt et disposer d'un runner Docker Linux AMD64 ou ARM64 avec
le label
ubuntu-latest, Git, Bash, Python 3, curl, tar, timeout et les outils Docker. Les builds multiarchitecture ont besoin du support QEMU/binfmt. Les services d'intégration sont joints viapostgresetredis, sans ports hôte fixes ; un runner en mode host n'est pas la cible de ces workflows. - Enregistrer un seul runner avec le label
xpeditis-deploy, une capacité 1, et une limite d'exécution adaptée (par exemple 1 h). Les deux jobs de déploiement utilisent ce label : publication des alias, déploiement, santé et fermeture du firewall restent dans le même job. Ne pas donner ce label à plusieurs runners. Le runner doit être isolé des jobs de PR et disposer de Docker, Git, curl, SSH et rsync. Sans ce runner, les déploiements restent en attente. - Protéger
dev,preprod,maindans les réglages de branches Gitea : interdire les push directs/force-push et exiger Security gate, les deux contrôles qualité et les deux tests unitaires ; ajouter l'intégration pour preprod/main. Choisir les noms exacts proposés après la première exécution. Les approbations humaines doivent être imposées sur les PR, pas viaenvironment. - Renseigner les secrets/variables dans Settings → Actions du dépôt Gitea : registre, webhooks Portainer, URLs préprod, URLs de build et identifiants SSH/Hetzner déjà référencés. Les secrets ne sont pas des secrets d'environnement GitHub. Les clés SSH temporaires sont écrites dans le répertoire du job.
- Les fonctions manuelles
workflow_dispatchne sont pas disponibles sur 1.22. L'ancien workflow de rollback est conservé hors du dossier actif dans.gitea/manual/rollback.reference.ymlcomme référence, sans prétendre qu'il est exécutable sur cette version. Le rollback SSH automatique de production reste actif en cas d'échec du déploiement ou des tests de fumée. Pour une intervention manuelle, utiliser la procédure serveur existante ; ne pas ajouter un faux bouton de lancement Gitea.
Ces réglages serveur/runners n'ont pas été modifiés depuis cette session. Aucun pipeline distant ni déploiement n'a été lancé.
Mises à jour de dépendances
Dependabot a été remplacé par renovate.json. La configuration propose des PR
vers dev pour npm, Docker et les actions, sans fusion automatique. Elle n'installe
ni ne démarre un bot. Un service Renovate doit être configuré séparément avec
RENOVATE_PLATFORM=gitea, RENOVATE_ENDPOINT=https://gitea.ops.xpeditis.com/api/v1,
un compte bot et son token, et le dépôt David/xpeditis2.0. Conserver le token hors
du dépôt. Les hashes des outils téléchargés dans les scripts doivent être mis à
jour en même temps que leurs versions.
Alertes déjà constatées
Audits npm des lockfiles au 22 septembre 2026 :
| Projet | HIGH | CRITICAL |
|---|---|---|
| Racine | 0 | 0 |
| Backend | 50 | 0 |
| Frontend | 13 | 1 |
| Log-exporter | 0 | 0 |
Ce sont des entrées de dépendances signalées, pas nécessairement autant de CVE
distinctes. L'entrée critique frontend concerne next ; npm propose une migration
majeure. Aucune mise à jour applicative forcée n'a été faite pour masquer ces résultats.
Le scan local des configurations a relevé 11 alertes Kubernetes HIGH : systèmes de fichiers inscriptibles, droits de monitoring et accès hôte. Elles restent à examiner et bloquantes. Certains accès peuvent être nécessaires au monitoring.
Les secrets Stripe en dur de la stack préprod ont été remplacés par les variables
Portainer obligatoires STRIPE_SECRET_KEY et STRIPE_WEBHOOK_SECRET. Renseigner
ces variables avant redéploiement. Si les anciennes valeurs sont actives, les
révoquer/renouveler dans Stripe : elles restent dans l'historique Git. Le scan de
ces configurations ne signale plus ce secret après modification.
Validation
Les 25 tests offline de promotion et santé passent : arbre différent, marqueurs manquants, panne du registre, digest invalide, mauvaise branche, saisie hostile et échec HTTP sont refusés. Les tests vérifient aussi que les échecs et délais des audits restent bloquants et que le rapport masque les valeurs de secrets. Actionlint valide la syntaxe après normalisation des URLs d'actions Gitea ; ce contrôle ne remplace pas une exécution avec act_runner.
ACTIONLINT_BIN=/chemin/vers/actionlint bash scripts/ci/validate-workflows.sh
La correction du 23 septembre 2026 a aussi été exécutée dans un conteneur Linux
ARM64 : Trivy 0.74.0, Actionlint 1.7.12 et Hetzner CLI 1.49.0 démarrent avec leurs
archives officielles vérifiées. activate-node.sh place le Node 22 natif du cache
en tête du PATH et vérifie son exécution ; un Node 18 préinstallé ne peut plus
être sélectionné silencieusement. Node 22.23.2 a été vérifié dans l'étape suivante.
Le téléchargement/affichage de version dans setup-node ne suffit pas à confirmer
le runtime utilisé par les étapes shell ; la nouvelle étape affiche le chemin
absolu et la version réellement activés.
L'installateur commun est scripts/ci/install-tool.sh. Chaque architecture a sa
propre archive et son empreinte. QEMU couvre AMD64 et ARM64 dans les builds préprod
et frontend prod, dont la cible reste AMD64 même si le runner est ARM64.
Les installations ont été vérifiées avec npm ci --dry-run --offline --ignore-scripts --legacy-peer-deps. Les builds Docker, les tests applicatifs sous
Node 22, le transport réel des artefacts et les déploiements sont encore à valider
sur les runners de l'instance.
Références : différences Gitea 1.22, Renovate sur Gitea.