DevSecOps — Sécurité dans les pipelines CI/CD
Intégration de la sécurité dans les pipelines CI/CD : SAST, DAST, SCA, secret scanning, container scanning avec GitHub Actions et GitLab CI
Principe Shift-Left
Traditionnel Dveloppement Test Staging Production Audit scuShift-Left Scu Scu Scu Scu ProductionIDE Commit CI/CD Release
Outils par phase
| Phase | Outil | Type | |-------|-------|------| | IDE | SonarLint, Snyk IDE | SAST temps réel | | Pre-commit | detect-secrets, gitleaks | Secret scanning | | CI — Build | SonarQube, Bandit, Semgrep | SAST | | CI — Dépendances | OWASP Dependency-Check, Snyk | SCA | | CI — Container | Trivy, Grype, Syft | Container scan | | CD — Deploy | OWASP ZAP, Nuclei | DAST | | Runtime | Falco, Wazuh | RASP / monitoring |
GitHub Actions — Pipeline complet
# .github/workflows/devsecops.ymlname: DevSecOps Pipelineon:push:branches: [main, develop]pull_request:jobs:# ─── 1. Secret scanning ───────────────────────────────secret-scan:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4with:fetch-depth: 0 # Historique complet pour Gitleaks- name: Gitleaks — scan secretsuses: gitleaks/gitleaks-action@v2env:GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}# ─── 2. SAST — Analyse statique ───────────────────────sast:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- name: Semgrep SASTuses: semgrep/semgrep-action@v1with:config: >-p/security-auditp/owasp-top-tenp/pythonenv:SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}- name: Bandit (Python)run: |pip install banditbandit -r . -f json -o bandit-report.json || true- name: Upload SAST resultsuses: actions/upload-artifact@v4with:name: sast-reportspath: "*.json"# ─── 3. SCA — Dépendances vulnérables ─────────────────dependency-check:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- name: OWASP Dependency-Checkuses: dependency-check/Dependency-Check_Action@mainwith:project: 'MonApp'path: '.'format: 'HTML'out: 'reports'- name: Snyk — Scan dépendancesuses: snyk/actions/python@masterenv:SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}with:args: --severity-threshold=high# ─── 4. Container scanning ────────────────────────────container-scan:runs-on: ubuntu-latestneeds: [sast]steps:- uses: actions/checkout@v4- name: Build imagerun: docker build -t app:${{ github.sha }} .- name: Trivy — scan imageuses: aquasecurity/trivy-action@masterwith:image-ref: 'app:${{ github.sha }}'format: 'sarif'output: 'trivy-results.sarif'severity: 'CRITICAL,HIGH'exit-code: '1'- name: Upload Trivy resultsuses: github/codeql-action/upload-sarif@v2with:sarif_file: trivy-results.sarif# ─── 5. DAST — Test dynamique (staging) ───────────────dast:runs-on: ubuntu-latestneeds: [container-scan]if: github.ref == 'refs/heads/main'steps:- name: Start apprun: docker run -d -p 8080:8080 app:${{ github.sha }}- name: OWASP ZAP Baseline Scanuses: zaproxy/action-baseline@v0.9.0with:target: 'http://localhost:8080'fail_action: falseartifact_name: 'zap-report'
GitLab CI — Pipeline équivalent
# .gitlab-ci.ymlstages:- secret-scan- sast- dependency-check- build- container-scan- dastvariables:DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHAsecret-scan:stage: secret-scanimage: zricethezav/gitleaks:latestscript:- gitleaks detect --source . --exit-code 1semgrep:stage: sastimage: returntocorp/semgrep:latestscript:- semgrep --config=p/owasp-top-ten --json > semgrep-report.jsonartifacts:reports:sast: semgrep-report.jsondependency-check:stage: dependency-checkimage: owasp/dependency-check:latestscript:- /usr/share/dependency-check/bin/dependency-check.sh--project "MonApp" --scan . --format HTML --out reports/artifacts:paths: [reports/]trivy-scan:stage: container-scanimage: aquasec/trivy:latestscript:- trivy image --exit-code 1 --severity CRITICAL,HIGH $DOCKER_IMAGEowasp-zap:stage: dastimage: ghcr.io/zaproxy/zaproxy:stablescript:- zap-baseline.py -t http://staging.target.com -r zap-report.htmlartifacts:paths: [zap-report.html]only:- main
Secret Scanning — Configuration
# Gitleaks — config .gitleaks.tomlallowlistdescription "Allowed secrets"regexes'''EXAMPLE_API_KEY_[A-Z0-9]{20}''' # Clés de testpaths'''tests/fixtures/'''# Pre-commit hook localpip install detect-secretsdetect-secrets scan > secretsbaselinedetect-secrets audit secretsbaseline# Hook Gitcat > git/hooks/pre-commit << 'EOF'detect-secrets-hook --baseline secretsbaselineEOFchmod x git/hooks/pre-commit
SonarQube — Quality Gate DevSecOps
# docker-compose.yml SonarQubeservices:sonarqube:image: sonarqube:communityports:- "9000:9000"environment:- SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=truevolumes:- sonar_data:/opt/sonarqube/data- sonar_logs:/opt/sonarqube/logs# sonar-project.propertiessonar.projectKey=mon-projetsonar.sources=srcsonar.tests=testssonar.python.coverage.reportPaths=coverage.xml# Quality Gate — seuils recommandés# Security Rating : A (0 vulnérabilités)# Reliability Rating : A (0 bugs bloquants)# Maintainability Rating : A# Coverage : > 80%# Duplicated Lines : < 3%
Infrastructure as Code — Sécurité
# Checkov — scan Terraform/Kubernetes/Dockerfilepip install checkovcheckov -d --framework terraformcheckov -d --framework kubernetescheckov -f Dockerfile# tfsec — Terraform security scannertfsec# kube-bench — CIS Benchmark Kubernetesdocker run --pid=host -v /etc/etcro -v /var/varroaquasec/kube-benchlatest# hadolint — Dockerfile linterhadolint Dockerfile
Métriques DevSecOps
| Métrique | Cible | Mesure | |----------|-------|--------| | MTTF (Mean Time To Fix) | < 5 jours (High) | Ticket JIRA → merge | | Vulnérabilités critiques en prod | 0 | Trivy + Dependabot | | Couverture SAST | > 90% du code | SonarQube | | Secrets en clair commités | 0 | Gitleaks alertes | | Score sécurité image Docker | A | Trivy |