در بیشتر سازمانها تست امنیت هنوز یعنی یک «تست نفوذ» در هفتهی آخر قبل از انتشار. نتیجه هم همیشه همان است: دهها آسیبپذیری، فرصت کم و انتخاب بین «انتشار با ریسک» و «تأخیر». DevSecOps یعنی همین بررسیها را به داخل Pipeline بیاوریم تا هر مشکل در همان Merge Request که ایجادش کرده پیدا شود.
با پیادهسازی همین لایهها در Pipelineهای یکی از تیمها، تعداد آسیبپذیریهایی که به Production میرسید حدود ۶۰٪ کاهش پیدا کرد.
لایههای امنیت در Pipeline
| لایه | چه چیزی را پیدا میکند | ابزار | زمان اجرا |
|---|---|---|---|
| Secret Detection | رمز، Token و کلید API در کد | Gitleaks | ثانیه |
| SAST | باگهای امنیتی در سورس (Injection، XSS و…) | SonarQube | ۱ تا ۵ دقیقه |
| SCA | کتابخانههای آسیبپذیر | Trivy fs | کمتر از ۱ دقیقه |
| Image Scan | CVE در سیستمعامل و پکیجهای Image | Trivy image | کمتر از ۱ دقیقه |
| DAST | آسیبپذیری در برنامهی در حال اجرا | OWASP ZAP | ۵ تا ۱۵ دقیقه |
| Mobile | مشکلات امنیتی APK و IPA | MobSF | چند دقیقه |
۱. Gitleaks: قبل از هر چیز
secrets:
stage: .pre
image: { name: zricethezav/gitleaks:v8.18.4, entrypoint: [""] }
script:
- gitleaks detect --source . --redact --report-format json --report-path gitleaks.json
artifacts:
when: always
paths: [gitleaks.json]
۲. SonarQube: کیفیت و امنیت کد
sonarqube:
stage: test
image: { name: sonarsource/sonar-scanner-cli:latest, entrypoint: [""] }
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
GIT_DEPTH: "0" # full history for accurate new-code detection
cache:
key: sonar
paths: [.sonar/cache]
script:
- sonar-scanner
-Dsonar.projectKey=$CI_PROJECT_PATH_SLUG
-Dsonar.host.url=$SONAR_HOST_URL
-Dsonar.token=$SONAR_TOKEN
-Dsonar.qualitygate.wait=true
allow_failure: false
sonar.qualitygate.wait=true باعث میشود Job منتظر نتیجهی Quality Gate بماند و اگر رد شد، Pipeline هم شکست بخورد.
۳. Trivy: وابستگیها و Image
dependency-scan:
stage: test
image: { name: aquasec/trivy:0.56.2, entrypoint: [""] }
script:
- trivy fs --scanners vuln --severity HIGH,CRITICAL --exit-code 0
--format json --output trivy-fs.json .
artifacts:
paths: [trivy-fs.json]
image-scan:
stage: scan
image: { name: aquasec/trivy:0.56.2, entrypoint: [""] }
needs: [docker-image]
variables:
TRIVY_USERNAME: $CI_REGISTRY_USER
TRIVY_PASSWORD: $CI_REGISTRY_PASSWORD
TRIVY_CACHE_DIR: .trivycache/
cache:
paths: [.trivycache/]
script:
- trivy image --format json --output trivy-image.json "$IMAGE"
- trivy image --exit-code 1 --severity CRITICAL --ignore-unfixed "$IMAGE"
artifacts:
when: always
paths: [trivy-image.json]
۴. OWASP ZAP: تست برنامهی در حال اجرا
DAST بعد از استقرار روی Develop اجرا میشود و برنامه را مثل یک مهاجم از بیرون بررسی میکند:
dast:
stage: verify
image: ghcr.io/zaproxy/zaproxy:stable
needs: [deploy-dev]
script:
- mkdir -p /zap/wrk
- zap-baseline.py -t https://dev.example.ir -J zap.json -r zap.html -I || true
- cp /zap/wrk/zap.* .
artifacts:
when: always
paths: [zap.json, zap.html]
Baseline Scan حملهی فعال انجام نمیدهد و برای اجرا در هر Pipeline امن است. Full Scan را به یک Job شبانه بسپارید. هیچوقت DAST فعال را روی Production اجرا نکنید.
۵. DefectDojo: یک داشبورد برای همه
وقتی پنج ابزار گزارش میدهند، تیم امنیت نمیتواند پنج داشبورد را دنبال کند. DefectDojo همهی گزارشها را دریافت، موارد تکراری را حذف و وضعیت هر مشکل را از «جدید» تا «رفعشده» دنبال میکند:
upload-defectdojo:
stage: .post
image: curlimages/curl:8.10.1
when: always
script:
- |
upload() {
curl -sf -X POST "$DOJO_URL/api/v2/import-scan/" \
-H "Authorization: Token $DOJO_TOKEN" \
-F "scan_type=$1" -F "file=@$2" \
-F "engagement=$DOJO_ENGAGEMENT_ID" \
-F "close_old_findings=true" -F "active=true" -F "verified=false"
}
upload "Gitleaks Scan" gitleaks.json
upload "Trivy Scan" trivy-image.json
upload "ZAP Scan" zap.json || true
close_old_findings=true یعنی مشکلاتی که دیگر در اسکن جدید دیده نمیشوند، خودکار بسته میشوند و داشبورد همیشه وضعیت واقعی را نشان میدهد.
سیاست مسدودسازی: چه چیزی Pipeline را متوقف کند؟
| یافته | اقدام |
|---|---|
| هر Secret در کد | مسدود |
| Quality Gate سونار روی کد جدید رد شد | مسدود |
| CVE با شدت CRITICAL که Patch دارد | مسدود |
| CVE با شدت HIGH | هشدار و ثبت در DefectDojo، رفع در Sprint بعد |
| یافتههای ZAP Baseline | بازبینی تیم امنیت، بدون مسدودسازی |
جمعبندی
DevSecOps یعنی امنیت بخش عادی هر Merge Request باشد، نه یک مرحلهی جدا در انتهای پروژه. از Gitleaks و Trivy شروع کنید که سریعاند و بیشترین ارزش را دارند، بعد SonarQube و ZAP را اضافه کنید و در آخر همه را در DefectDojo جمع کنید.