Chuyển đến nội dung chính

Lesson 29: Automated Reporting and Remediation Tracking

CI/CD reporting integration, Jira/GitHub Issues automation, remediation SLA tracking, vulnerability lifecycle management.

🔒 DevSecOps — Lesson 29 Lesson 29: Automated Reporting and Remediation__HTMLTAG_53___ Tracking

Performance Testing & Pentest: Enterprise Standard Process 2026

Part 6: Report & Professional Process

xdev.asia

1. Automated Reporting Pipeline

Automated Security Reporting Pipeline:

  Security Tools ──▶ Normalize ──▶ Aggregate ──▶ Report
  ├── Nuclei        ├── SARIF     ├── DefectDojo  ├── PDF/DOCX
  ├── ZAP           ├── JSON      ├── Jira        ├── Dashboard
  ├── Trivy         ├── CSV       ├── GitHub       ├── Slack/Email
  ├── SonarQube     └── XML       └── ServiceNow   └── Metrics
  └── k6 (perf)

Integration Points:
  ├── CI/CD: Generate reports on each pipeline run
  ├── Ticketing: Auto-create issues for findings
  ├── Dashboard: Real-time vulnerability metrics
  └── Notifications: Alert on critical findings

2. DefectDojo — Vulnerability Management

# DefectDojo — Open-source vulnerability management

# Install with Docker
git clone https://github.com/DefectDojo/django-DefectDojo.git
cd django-DefectDojo

docker compose up -d

# Access: http://localhost:8080
# Default credentials in docker compose logs

# --- Import scan results via API ---

# Create product
curl -X POST "http://localhost:8080/api/v2/products/" \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Example App",
    "description": "Main web application",
    "prod_type": 1
  }'

# Import Nuclei scan
curl -X POST "http://localhost:8080/api/v2/import-scan/" \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -F "file=@nuclei_results.json" \
  -F "scan_type=Nuclei Scan" \
  -F "product_name=Example App" \
  -F "engagement_name=Q2 2026 Pentest" \
  -F "auto_create_context=true" \
  -F "deduplication_on_engagement=true"

# Import ZAP scan
curl -X POST "http://localhost:8080/api/v2/import-scan/" \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -F "file=@zap_report.xml" \
  -F "scan_type=ZAP Scan" \
  -F "product_name=Example App" \
  -F "engagement_name=Q2 2026 Pentest"

# Import Trivy scan
curl -X POST "http://localhost:8080/api/v2/import-scan/" \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -F "file=@trivy_results.json" \
  -F "scan_type=Trivy Scan" \
  -F "product_name=Example App"

# Get findings summary
curl "http://localhost:8080/api/v2/findings/?product=1&active=true" \
  -H "Authorization: Token YOUR_API_TOKEN" | jq '.count'

3. CI/CD Reporting Integration

# .github/workflows/security-report.yml

name: Security Scan & Report

on:
  push:
    branches: [main]
  schedule:
    - cron: '0 6 * * 1'  # Every Monday 6AM

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # SAST — SonarQube
      - name: SonarQube Scan
        uses: sonarsource/sonarqube-scan-action@v3
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

      # Container scanning — Trivy
      - name: Build and scan image
        run: |
          docker build -t myapp:${{ github.sha }} .
          trivy image --format json --output trivy.json \
            --severity HIGH,CRITICAL myapp:${{ github.sha }}

      # DAST — ZAP baseline
      - name: Start app
        run: docker compose up -d && sleep 30

      - name: ZAP Scan
        uses: zaproxy/[email protected]
        with:
          target: 'http://localhost:3000'

      # Dependency audit
      - name: npm audit
        run: npm audit --json > npm-audit.json || true

      # Upload all results to DefectDojo
      - name: Upload to DefectDojo
        run: |
          # Trivy results
          curl -X POST "${{ secrets.DEFECTDOJO_URL }}/api/v2/reimport-scan/" \
            -H "Authorization: Token ${{ secrets.DEFECTDOJO_TOKEN }}" \
            -F "[email protected]" \
            -F "scan_type=Trivy Scan" \
            -F "product_name=Example App" \
            -F "engagement_name=CI/CD Scans" \
            -F "auto_create_context=true" \
            -F "deduplication_on_engagement=true"

          # ZAP results
          curl -X POST "${{ secrets.DEFECTDOJO_URL }}/api/v2/reimport-scan/" \
            -H "Authorization: Token ${{ secrets.DEFECTDOJO_TOKEN }}" \
            -F "file=@report_html.html" \
            -F "scan_type=ZAP Scan" \
            -F "product_name=Example App"

      # Performance test
      - name: k6 Load Test
        run: |
          k6 run --out json=k6-results.json tests/load-test.js

      # Generate combined report
      - name: Generate Report
        run: python scripts/generate-report.py

      # Notify on critical findings
      - name: Slack notification
        if: failure()
        uses: 8398a7/action-slack@v3
        with:
          status: failure
          text: '🚨 Critical security findings detected!'
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

4. Jira/GitHub Issues Automation

# auto_create_issues.py — Auto-create Jira tickets from findings

import requests
import json

class SecurityIssueCreator:
    def __init__(self, jira_url: str, jira_token: str, project_key: str):
        self.jira_url = jira_url
        self.headers = {
            "Authorization": f"Basic {jira_token}",
            "Content-Type": "application/json"
        }
        self.project_key = project_key

    def create_issue_from_finding(self, finding: dict) -> str:
        """Create Jira ticket from security finding"""
        severity_map = {
            "Critical": "Highest",
            "High": "High",
            "Medium": "Medium",
            "Low": "Low"
        }

        sla_map = {
            "Critical": "48 hours",
            "High": "1 week",
            "Medium": "2 weeks",
            "Low": "1 month"
        }

        issue_data = {
            "fields": {
                "project": {"key": self.project_key},
                "summary": f"[Security] {finding['title']}",
                "description": self._format_description(finding),
                "issuetype": {"name": "Bug"},
                "priority": {"name": severity_map.get(finding["severity"], "Medium")},
                "labels": ["security", "pentest", f"cvss-{finding['cvss']}"],
                "customfield_10100": sla_map.get(finding["severity"]),  # SLA field
            }
        }

        response = requests.post(
            f"{self.jira_url}/rest/api/3/issue",
            headers=self.headers,
            json=issue_data
        )
        response.raise_for_status()
        issue_key = response.json()["key"]
        return issue_key

    def _format_description(self, finding: dict) -> str:
        return f"""
h2. Security Finding: {finding['title']}

||Attribute||Value||
|Severity|{finding['severity']}|
|CVSS v4.0|{finding['cvss']}|
|CWE|{finding.get('cwe', 'N/A')}|
|OWASP|{finding.get('owasp', 'N/A')}|
|Affected|{finding['affected']}|

h3. Description
{finding['description']}

h3. Steps to Reproduce
{finding['steps']}

h3. Business Impact
{finding['impact']}

h3. Remediation
{finding['remediation']}

h3. References
{finding.get('references', 'N/A')}
"""

# Usage
creator = SecurityIssueCreator(
    jira_url="https://company.atlassian.net",
    jira_token="base64_encoded_email:token",
    project_key="SEC"
)

# From DefectDojo findings
findings = requests.get(
    "http://defectdojo:8080/api/v2/findings/?active=true&severity=Critical",
    headers={"Authorization": "Token dojo_token"}
).json()["results"]

for finding in findings:
    issue_key = creator.create_issue_from_finding({
        "title": finding["title"],
        "severity": finding["severity"],
        "cvss": finding["cvssv3_score"],
        "description": finding["description"],
        "affected": finding["file_path"],
        "steps": finding["steps_to_reproduce"],
        "impact": finding["impact"],
        "remediation": finding["mitigation"],
        "cwe": finding["cwe"],
    })
    print(f"Created {issue_key}: {finding['title']}")

5. Remediation SLA Tracking

Vulnerability SLA Framework:

Severity   │ Detection → Triage │ Triage → Fix  │ Fix → Verify
───────────┼────────────────────┼───────────────┼─────────────
Critical   │ 4 hours            │ 48 hours      │ 24 hours
High       │ 8 hours            │ 7 days        │ 3 days
Medium     │ 24 hours           │ 30 days       │ 7 days
Low        │ 48 hours           │ 90 days       │ 14 days

SLA Compliance Dashboard:

  On-time │ ████████████████████████ 78%
  At-risk │ █████████ 15%
  Overdue │ ████ 7%

  Overdue Breakdown:
  ├── Critical: 0 (target: always 0)
  ├── High: 2 findings (avg 3 days overdue)
  ├── Medium: 5 findings (avg 10 days overdue)
  └── Low: 8 findings (avg 20 days overdue)

Escalation Process:
  Day 0: Finding created → assigned to team
  SLA - 2d: Warning notification to team lead
  SLA: Escalation to engineering manager
  SLA + 2d: Escalation to VP Engineering
  SLA + 7d: Escalation to CISO
# Grafana dashboard for vulnerability metrics
# datasource: DefectDojo PostgreSQL

# Panel 1: Findings by Severity (Pie chart)
# SELECT severity, COUNT(*) FROM dojo_finding 
# WHERE active = true GROUP BY severity

# Panel 2: SLA Compliance (Stat)
# SELECT 
#   COUNT(CASE WHEN resolved_at <= sla_deadline THEN 1 END) * 100.0 / COUNT(*)
# FROM dojo_finding WHERE resolved_at IS NOT NULL

# Panel 3: Mean Time to Remediate (Time series)
# SELECT date_trunc('week', resolved_at), 
#   AVG(resolved_at - created_at)
# FROM dojo_finding 
# WHERE resolved_at IS NOT NULL
# GROUP BY 1 ORDER BY 1

# Panel 4: Open Findings Trend (Time series)
# Uses DefectDojo API: /api/v2/finding_count_by_date/

6. Vulnerability Lifecycle Management

Vulnerability Lifecycle:

  Discovery → Triage → Assign → Fix → Verify → Close
      │          │        │       │       │        │
      ▼          ▼        ▼       ▼       ▼        ▼
  Scanner/   Confirm/  Dev     Deploy  Retest   Update
  Pentest    Dedup     team    fix     by       report
                                      pentester

States:
  ├── New: Just discovered, not yet reviewed
  ├── Confirmed: Validated as true positive
  ├── Assigned: Assigned to dev team
  ├── In Progress: Fix being developed
  ├── Fixed: Code fix deployed
  ├── Verified: Retested and confirmed fixed
  ├── Closed: Finding resolved
  ├── Risk Accepted: Business accepts the risk
  ├── False Positive: Confirmed false positive
  └── Duplicate: Same as existing finding

Metrics to Track:
  ├── MTTD (Mean Time to Detect)
  ├── MTTR (Mean Time to Remediate)
  ├── SLA Compliance %
  ├── Reopen Rate (fixed but came back)
  ├── False Positive Rate
  ├── Risk Acceptance Rate
  └── Finding Trend (new vs closed per week)

7. Summary

  • Automated Pipeline: Scanner → Normalize → DefectDojo → Ticketing
  • DefectDojo: Central vulnerability management — import, dedup, track
  • CI/CD Integration: Auto-scan on every push, report to DefectDojo
  • Ticketing: Auto-create Jira/GitHub issues from critical findings
  • SLA Tracking: Define and enforce remediation timelines per severity
  • Metrics: MTTD, MTTR, SLA compliance, trend dashboards

The next (final!) post will be Capstone Project — End-to-end.