الامتثال والحوكمة ونضج DevSecOps
لوحات الأمان وإدارة الثغرات
4 دقيقة للقراءة
الرؤية هي أساس الأمان. بدون لوحات مركزية وإدارة منهجية للثغرات، تغرق فرق الأمان في التنبيهات بينما تفلت المشاكل الحرجة. هذا الدرس يغطي بناء رؤية أمنية فعالة عبر خط أنابيب DevSecOps.
هندسة الرؤية الأمنية
┌─────────────────────────────────────────────────────────┐
│ طبقة الرؤية الأمنية │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ SAST │ │ SCA │ │ DAST │ │ فحص │ │
│ │ النتائج │ │ النتائج │ │ النتائج │ │الحاويات │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │ │
│ └───────────┴───────────┴───────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────┐ │
│ │ طبقة التجميع │ │
│ │ (DefectDojo, ASPM) │ │
│ └───────────┬───────────┘ │
│ │ │
│ ┌───────────┴───────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ اللوحة │ │ التنبيهات │ │
│ │ (Grafana) │ │ (PagerDuty) │ │
│ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
DefectDojo: منصة إدارة الثغرات
التثبيت
# نشر Docker Compose
git clone https://github.com/DefectDojo/django-DefectDojo.git
cd django-DefectDojo
# بدء DefectDojo
docker-compose up -d
استيراد نتائج الفحص
# الاستيراد عبر API
curl -X POST "https://defectdojo.example.com/api/v2/import-scan/" \
-H "Authorization: Token $DEFECTDOJO_TOKEN" \
-H "Content-Type: multipart/form-data" \
-F "scan_type=Trivy Scan" \
-F "file=@trivy-results.json" \
-F "product_name=MyApp" \
-F "engagement_name=CI/CD Pipeline"
تكامل GitHub Actions
# .github/workflows/security-scan.yml
name: Security Scan & Report
on:
push:
branches: [main]
jobs:
scan-and-report:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Trivy Scan
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
format: 'json'
output: 'trivy-results.json'
- name: Run Semgrep
uses: returntocorp/semgrep-action@v1
with:
config: auto
output: semgrep-results.json
- name: Upload to DefectDojo
run: |
# رفع نتائج Trivy
curl -X POST "${{ secrets.DEFECTDOJO_URL }}/api/v2/import-scan/" \
-H "Authorization: Token ${{ secrets.DEFECTDOJO_TOKEN }}" \
-F "scan_type=Trivy Scan" \
-F "file=@trivy-results.json" \
-F "product_name=${{ github.repository }}" \
-F "engagement_name=Pipeline-${{ github.run_id }}" \
-F "close_old_findings=true"
# رفع نتائج Semgrep
curl -X POST "${{ secrets.DEFECTDOJO_URL }}/api/v2/import-scan/" \
-H "Authorization: Token ${{ secrets.DEFECTDOJO_TOKEN }}" \
-F "scan_type=Semgrep JSON Report" \
-F "file=@semgrep-results.json" \
-F "product_name=${{ github.repository }}" \
-F "engagement_name=Pipeline-${{ github.run_id }}"
بناء لوحات الأمان بـ Grafana
جمع المقاييس مع Prometheus
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'security-metrics'
static_configs:
- targets: ['security-exporter:9090']
مصدّر مقاييس الأمان
# security_exporter.py
from prometheus_client import start_http_server, Gauge
import requests
import time
# تعريف المقاييس
VULNERABILITIES_TOTAL = Gauge(
'security_vulnerabilities_total',
'إجمالي الثغرات حسب الخطورة',
['severity', 'product']
)
SLA_COMPLIANCE = Gauge(
'security_sla_compliance_percentage',
'نسبة الثغرات ضمن SLA',
['product']
)
MTTR = Gauge(
'security_mttr_days',
'متوسط وقت الإصلاح بالأيام',
['severity', 'product']
)
def collect_metrics():
# جلب من DefectDojo API
response = requests.get(
f"{DEFECTDOJO_URL}/api/v2/findings/",
headers={"Authorization": f"Token {DEFECTDOJO_TOKEN}"},
params={"active": "true"}
)
findings = response.json()['results']
# العد حسب الخطورة
severity_counts = {}
for finding in findings:
severity = finding['severity']
product = finding['product_name']
key = (severity, product)
severity_counts[key] = severity_counts.get(key, 0) + 1
for (severity, product), count in severity_counts.items():
VULNERABILITIES_TOTAL.labels(
severity=severity,
product=product
).set(count)
if __name__ == '__main__':
start_http_server(9090)
while True:
collect_metrics()
time.sleep(60)
JSON لوحة Grafana
{
"dashboard": {
"title": "نظرة عامة على الأمان",
"panels": [
{
"title": "الثغرات الحرجة",
"type": "stat",
"targets": [{
"expr": "sum(security_vulnerabilities_total{severity='Critical'})"
}],
"fieldConfig": {
"defaults": {
"thresholds": {
"steps": [
{"color": "green", "value": 0},
{"color": "yellow", "value": 1},
{"color": "red", "value": 5}
]
}
}
}
},
{
"title": "اتجاه الثغرات",
"type": "timeseries",
"targets": [{
"expr": "sum(security_vulnerabilities_total) by (severity)",
"legendFormat": "{{severity}}"
}]
},
{
"title": "MTTR حسب الخطورة",
"type": "bargauge",
"targets": [{
"expr": "security_mttr_days",
"legendFormat": "{{severity}}"
}]
}
]
}
}
إدارة SLA للثغرات
تعريف SLAs
| الخطورة | من الاكتشاف إلى الفرز | من الفرز إلى الإصلاح |
|---|---|---|
| حرج | 4 ساعات | 24 ساعة |
| عالي | 24 ساعة | 7 أيام |
| متوسط | 3 أيام | 30 يوم |
| منخفض | 7 أيام | 90 يوم |
سير عمل تتبع SLA
# .github/workflows/sla-check.yml
name: SLA Compliance Check
on:
schedule:
- cron: '0 9 * * *' # يومياً الساعة 9 صباحاً
jobs:
check-sla:
runs-on: ubuntu-latest
steps:
- name: Check SLA Breaches
uses: actions/github-script@v7
with:
script: |
const response = await fetch(
`${process.env.DEFECTDOJO_URL}/api/v2/findings/?active=true`,
{
headers: {
'Authorization': `Token ${process.env.DEFECTDOJO_TOKEN}`
}
}
);
const data = await response.json();
const now = new Date();
const slaLimits = {
'Critical': 1, // يوم واحد
'High': 7, // 7 أيام
'Medium': 30, // 30 يوم
'Low': 90 // 90 يوم
};
const breaches = data.results.filter(finding => {
const created = new Date(finding.created);
const daysOpen = (now - created) / (1000 * 60 * 60 * 24);
return daysOpen > slaLimits[finding.severity];
});
if (breaches.length > 0) {
console.log(`SLA Breaches: ${breaches.length}`);
breaches.forEach(b => {
console.log(`- ${b.title} (${b.severity})`);
});
// إنشاء issue أو إرسال تنبيه
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Security SLA Breach Alert: ${breaches.length} findings`,
body: breaches.map(b => `- ${b.title} (${b.severity})`).join('\n'),
labels: ['security', 'sla-breach']
});
}
env:
DEFECTDOJO_URL: ${{ secrets.DEFECTDOJO_URL }}
DEFECTDOJO_TOKEN: ${{ secrets.DEFECTDOJO_TOKEN }}
تكوين التنبيهات
تكامل PagerDuty
# alertmanager.yml
route:
receiver: 'security-team'
routes:
- match:
severity: critical
receiver: 'security-critical'
continue: true
receivers:
- name: 'security-team'
slack_configs:
- api_url: 'https://hooks.slack.com/services/xxx'
channel: '#security-alerts'
title: '{{ .CommonAnnotations.summary }}'
- name: 'security-critical'
pagerduty_configs:
- routing_key: 'your-pagerduty-key'
severity: critical
تنسيق تنبيه Slack
# قالب التنبيه
- name: Security Vulnerability Alert
run: |
curl -X POST ${{ secrets.SLACK_WEBHOOK }} \
-H 'Content-type: application/json' \
-d '{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "🚨 تم اكتشاف ثغرة حرجة"
}
},
{
"type": "section",
"fields": [
{"type": "mrkdwn", "text": "*الخطورة:*\nحرجة"},
{"type": "mrkdwn", "text": "*المستودع:*\n${{ github.repository }}"},
{"type": "mrkdwn", "text": "*CVE:*\nCVE-2024-XXXXX"},
{"type": "mrkdwn", "text": "*SLA:*\n24 ساعة"}
]
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {"type": "plain_text", "text": "عرض التفاصيل"},
"url": "https://defectdojo.example.com/finding/123"
}
]
}
]
}'
مقاييس الأمان الرئيسية
| المقياس | الوصف | الهدف |
|---|---|---|
| MTTR | متوسط وقت الإصلاح | حرج < 24 ساعة |
| MTTD | متوسط وقت الاكتشاف | < يوم واحد |
| كثافة الثغرات | الثغرات لكل 1000 سطر كود | < 1.0 |
| امتثال SLA | النسبة ضمن SLA | > 95% |
| معدل الإيجابيات الخاطئة | النتائج غير الصالحة | < 10% |
| التغطية | نسبة المستودعات المفحوصة | 100% |
بعد ذلك، سنستكشف نموذج نضج DevSecOps وبناء ثقافة الأمان أولاً. :::