name: Security & Dependency Updates on: schedule: # Run security scans daily at 3 AM UTC - cron: "0 3 * * *" workflow_dispatch: push: paths: - "requirements*.txt" - "Dockerfile" - ".gitea/workflows/security.yml" env: PYTHON_VERSION: "3.11" # GitHub token for better rate limits and authentication GH_TOKEN: ${{ secrets.GH_TOKEN }} jobs: # Dependency vulnerability scan dependency-scan: name: Dependency Security Scan runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install dependencies run: | python -m pip install --upgrade pip --root-user-action=ignore pip install --root-user-action=ignore safety bandit semgrep - name: Run Safety check run: | safety check -r requirements.txt --json --output safety-report.json || true safety check -r requirements-dev.txt --json --output safety-dev-report.json || true - name: Run Bandit security scan run: | bandit -r src/ -f json -o bandit-report.json || true - name: Run Semgrep security scan run: | semgrep --config=auto src/ --json --output=semgrep-report.json || true - name: Upload security reports uses: actions/upload-artifact@v3 with: name: security-reports-${{ github.run_number }} path: | safety-report.json safety-dev-report.json bandit-report.json semgrep-report.json - name: Check for critical vulnerabilities run: | echo "๐Ÿ” Checking for critical vulnerabilities..." # Check Safety results if [ -f safety-report.json ]; then critical_count=$(jq '.vulnerabilities | length' safety-report.json 2>/dev/null || echo "0") if [ "$critical_count" -gt 0 ]; then echo "โš ๏ธ Found $critical_count dependency vulnerabilities" jq '.vulnerabilities[] | "- \(.package_name) \(.installed_version): \(.vulnerability_id)"' safety-report.json else echo "โœ… No dependency vulnerabilities found" fi fi # Check Bandit results if [ -f bandit-report.json ]; then high_severity=$(jq '.results[] | select(.issue_severity == "HIGH") | length' bandit-report.json 2>/dev/null | wc -l) if [ "$high_severity" -gt 0 ]; then echo "โš ๏ธ Found $high_severity high-severity security issues" else echo "โœ… No high-severity security issues found" fi fi # Docker image security scan docker-security-scan: name: Docker Security Scan runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Check GitHub token availability run: | if [ -z "${{ secrets.GH_TOKEN }}" ]; then echo "โš ๏ธ GH_TOKEN not configured. Trivy scans may fail due to rate limits." echo "๐Ÿ’ก To fix: Add GH_TOKEN secret in repository settings" else echo "โœ… GH_TOKEN is configured" fi - name: Build Docker image for scanning run: | docker build -t ping-river-monitor:scan . env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: image-ref: "ping-river-monitor:scan" format: "json" output: "trivy-report.json" github-token: ${{ secrets.GH_TOKEN }} env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} continue-on-error: true - name: Run Trivy filesystem scan uses: aquasecurity/trivy-action@master with: scan-type: "fs" scan-ref: "." format: "json" output: "trivy-fs-report.json" github-token: ${{ secrets.GH_TOKEN }} env: GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} continue-on-error: true - name: Upload Trivy reports uses: actions/upload-artifact@v3 if: always() with: name: trivy-reports-${{ github.run_number }} path: | trivy-report.json trivy-fs-report.json - name: Check Trivy results run: | echo "๐Ÿ” Analyzing Docker security scan results..." if [ -f trivy-report.json ]; then critical_vulns=$(jq '.Results[]?.Vulnerabilities[]? | select(.Severity == "CRITICAL") | length' trivy-report.json 2>/dev/null | wc -l) high_vulns=$(jq '.Results[]?.Vulnerabilities[]? | select(.Severity == "HIGH") | length' trivy-report.json 2>/dev/null | wc -l) echo "Critical vulnerabilities: $critical_vulns" echo "High vulnerabilities: $high_vulns" if [ "$critical_vulns" -gt 0 ]; then echo "โŒ Critical vulnerabilities found in Docker image!" exit 1 elif [ "$high_vulns" -gt 5 ]; then echo "โš ๏ธ Many high-severity vulnerabilities found" else echo "โœ… Docker image security scan passed" fi fi # License compliance check license-check: name: License Compliance runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install pip-licenses run: | python -m pip install --upgrade pip --root-user-action=ignore pip install --root-user-action=ignore pip-licenses pip install --root-user-action=ignore -r requirements.txt - name: Check licenses run: | echo "๐Ÿ“„ Checking dependency licenses..." pip-licenses --format=json --output-file=licenses.json pip-licenses --format=markdown --output-file=licenses.md # Check for problematic licenses problematic_licenses=("GPL" "AGPL" "LGPL") for license in "${problematic_licenses[@]}"; do if grep -i "$license" licenses.json; then echo "โš ๏ธ Found potentially problematic license: $license" fi done echo "โœ… License check completed" - name: Upload license report uses: actions/upload-artifact@v3 with: name: license-report-${{ github.run_number }} path: | licenses.json licenses.md # Dependency update check dependency-update: name: Check for Dependency Updates runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install pip-check-updates equivalent run: | python -m pip install --upgrade pip --root-user-action=ignore pip install --root-user-action=ignore pip-review - name: Check for outdated packages run: | echo "๐Ÿ“ฆ Checking for outdated packages..." pip install --root-user-action=ignore -r requirements.txt pip list --outdated --format=json > outdated-packages.json || true if [ -s outdated-packages.json ]; then echo "๐Ÿ“‹ Outdated packages found:" cat outdated-packages.json | jq -r '.[] | "- \(.name): \(.version) -> \(.latest_version)"' else echo "โœ… All packages are up to date" fi - name: Create dependency update issue if: github.event_name == 'schedule' run: | if [ -s outdated-packages.json ] && [ "$(cat outdated-packages.json)" != "[]" ]; then echo "๐Ÿ“ Creating dependency update issue..." # Create issue body cat > issue-body.md << 'EOF' ## ๐Ÿ“ฆ Dependency Updates Available The following packages have updates available: EOF cat outdated-packages.json | jq -r '.[] | "- **\(.name)**: \(.version) โ†’ \(.latest_version)"' >> issue-body.md cat >> issue-body.md << 'EOF' ## ๐Ÿ” Security Impact Please review each update for: - Security fixes - Breaking changes - Compatibility issues ## โœ… Action Items - [ ] Review changelog for each package - [ ] Test updates in development environment - [ ] Update requirements.txt - [ ] Run full test suite - [ ] Deploy to staging for validation --- *This issue was automatically created by the security workflow.* EOF echo "Issue body created. In a real implementation, you would create a Gitea issue here." cat issue-body.md fi - name: Upload dependency reports uses: actions/upload-artifact@v3 with: name: dependency-reports-${{ github.run_number }} path: | outdated-packages.json issue-body.md # Code quality metrics code-quality: name: Code Quality Metrics runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install quality tools run: | python -m pip install --upgrade pip --root-user-action=ignore pip install --root-user-action=ignore radon xenon vulture pip install --root-user-action=ignore -r requirements.txt - name: Calculate code complexity run: | echo "๐Ÿ“Š Calculating code complexity..." radon cc src/ --json > complexity-report.json radon mi src/ --json > maintainability-report.json echo "๐Ÿ” Complexity Summary:" radon cc src/ --average echo "๐Ÿ”ง Maintainability Summary:" radon mi src/ - name: Find dead code run: | echo "๐Ÿงน Checking for dead code..." vulture src/ --json > dead-code-report.json || true - name: Check for code smells run: | echo "๐Ÿ‘ƒ Checking for code smells..." xenon --max-absolute B --max-modules A --max-average A src/ || true - name: Upload quality reports uses: actions/upload-artifact@v3 with: name: code-quality-reports-${{ github.run_number }} path: | complexity-report.json maintainability-report.json dead-code-report.json # Security summary security-summary: name: Security Summary runs-on: ubuntu-latest needs: [dependency-scan, docker-security-scan, license-check, code-quality] if: always() steps: - name: Download all artifacts uses: actions/download-artifact@v3 - name: Generate security summary run: | echo "# ๐Ÿ”’ Security Scan Summary" > security-summary.md echo "" >> security-summary.md echo "**Scan Date:** $(date -u)" >> security-summary.md echo "**Repository:** ${{ github.repository }}" >> security-summary.md echo "**Commit:** ${{ github.sha }}" >> security-summary.md echo "" >> security-summary.md echo "## ๐Ÿ“Š Results" >> security-summary.md echo "" >> security-summary.md # Dependency scan results if [ -f security-reports-*/safety-report.json ]; then vuln_count=$(jq '.vulnerabilities | length' security-reports-*/safety-report.json 2>/dev/null || echo "0") if [ "$vuln_count" -eq 0 ]; then echo "- โœ… **Dependency Scan**: No vulnerabilities found" >> security-summary.md else echo "- โš ๏ธ **Dependency Scan**: $vuln_count vulnerabilities found" >> security-summary.md fi else echo "- โ“ **Dependency Scan**: Results not available" >> security-summary.md fi # Docker scan results if [ -f trivy-reports-*/trivy-report.json ]; then echo "- โœ… **Docker Scan**: Completed" >> security-summary.md else echo "- โ“ **Docker Scan**: Results not available" >> security-summary.md fi # License check results if [ -f license-report-*/licenses.json ]; then echo "- โœ… **License Check**: Completed" >> security-summary.md else echo "- โ“ **License Check**: Results not available" >> security-summary.md fi # Code quality results if [ -f code-quality-reports-*/complexity-report.json ]; then echo "- โœ… **Code Quality**: Analyzed" >> security-summary.md else echo "- โ“ **Code Quality**: Results not available" >> security-summary.md fi echo "" >> security-summary.md echo "## ๐Ÿ”— Detailed Reports" >> security-summary.md echo "" >> security-summary.md echo "Detailed reports are available in the workflow artifacts." >> security-summary.md cat security-summary.md - name: Upload security summary uses: actions/upload-artifact@v3 with: name: security-summary-${{ github.run_number }} path: security-summary.md