Security Scan #76
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Security Scan | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| schedule: | |
| # Run security scans daily at 3 AM UTC | |
| - cron: '0 3 * * *' | |
| workflow_dispatch: | |
| env: | |
| PYTHON_VERSION: '3.11' | |
| NODE_VERSION: '18' | |
| jobs: | |
| # Job 1: Dependency vulnerability scanning | |
| dependency-scan: | |
| name: Dependency Vulnerability Scan | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| component: [backend, frontend] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python (backend) | |
| if: matrix.component == 'backend' | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Set up Node.js (frontend) | |
| if: matrix.component == 'frontend' | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Install Python dependencies and scan (backend) | |
| if: matrix.component == 'backend' | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install safety bandit semgrep | |
| # Install project dependencies | |
| find services/ -name requirements.txt -exec pip install -r {} \; | |
| if [ -f tests/test-requirements.txt ]; then pip install -r tests/test-requirements.txt; fi | |
| # Run Safety scan | |
| echo "🔍 Running Safety vulnerability scan..." | |
| safety check --json --output safety-report.json || true | |
| safety check --short-report | |
| # Run Bandit security scan | |
| echo "🔍 Running Bandit security scan..." | |
| bandit -r services/ -f json -o bandit-report.json || true | |
| bandit -r services/ --severity-level medium --confidence-level medium | |
| - name: Install Node.js dependencies and scan (frontend) | |
| if: matrix.component == 'frontend' | |
| working-directory: frontend | |
| run: | | |
| npm ci | |
| # Run npm audit | |
| echo "🔍 Running npm audit..." | |
| npm audit --audit-level=moderate --json > npm-audit-report.json || true | |
| npm audit --audit-level=moderate | |
| # Run ESLint security rules | |
| echo "🔍 Running ESLint security scan..." | |
| npx eslint src/ --format json --output-file eslint-security-report.json \ | |
| --config .eslintrc-security.js || true | |
| - name: Upload security reports | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: security-reports-${{ matrix.component }} | |
| path: | | |
| safety-report.json | |
| bandit-report.json | |
| frontend/npm-audit-report.json | |
| frontend/eslint-security-report.json | |
| # Job 2: Container security scanning | |
| container-scan: | |
| name: Container Security Scan | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| service: [auth-service, data-processing, analytics, api-gateway] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: ./services/${{ matrix.service }} | |
| file: ./services/${{ matrix.service }}/Dockerfile | |
| tags: energy-tracking/${{ matrix.service }}:security-test | |
| load: true | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: 'energy-tracking/${{ matrix.service }}:security-test' | |
| format: 'sarif' | |
| output: 'trivy-results-${{ matrix.service }}.sarif' | |
| severity: 'CRITICAL,HIGH,MEDIUM' | |
| - name: Upload Trivy scan results | |
| uses: github/codeql-action/upload-sarif@v2 | |
| if: always() | |
| with: | |
| sarif_file: 'trivy-results-${{ matrix.service }}.sarif' | |
| - name: Run Hadolint (Dockerfile linting) | |
| uses: hadolint/[email protected] | |
| with: | |
| dockerfile: ./services/${{ matrix.service }}/Dockerfile | |
| format: sarif | |
| output-file: hadolint-results-${{ matrix.service }}.sarif | |
| - name: Upload Hadolint results | |
| uses: github/codeql-action/upload-sarif@v2 | |
| if: always() | |
| with: | |
| sarif_file: hadolint-results-${{ matrix.service }}.sarif | |
| # Job 3: SAST (Static Application Security Testing) | |
| sast-scan: | |
| name: Static Application Security Testing | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@v2 | |
| with: | |
| languages: 'python,javascript' | |
| config-file: ./.github/codeql/codeql-config.yml | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install Python dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| find services/ -name requirements.txt -exec pip install -r {} \; | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Install Node.js dependencies | |
| working-directory: frontend | |
| run: npm ci | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@v2 | |
| with: | |
| category: "/language:python,javascript" | |
| - name: Run Semgrep | |
| uses: returntocorp/semgrep-action@v1 | |
| with: | |
| config: >- | |
| p/security-audit | |
| p/secrets | |
| p/python | |
| p/javascript | |
| p/react | |
| generateSarif: "1" | |
| - name: Upload Semgrep results | |
| uses: github/codeql-action/upload-sarif@v2 | |
| if: always() | |
| with: | |
| sarif_file: semgrep.sarif | |
| # Job 4: Secret scanning | |
| secret-scan: | |
| name: Secret Scanning | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Run TruffleHog | |
| uses: trufflesecurity/trufflehog@main | |
| with: | |
| path: ./ | |
| base: main | |
| head: HEAD | |
| extra_args: --debug --only-verified | |
| - name: Run GitLeaks | |
| uses: gitleaks/gitleaks-action@v2 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} | |
| # Job 5: Infrastructure security scan | |
| infrastructure-scan: | |
| name: Infrastructure Security Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run Checkov | |
| uses: bridgecrewio/checkov-action@master | |
| with: | |
| directory: . | |
| framework: dockerfile,docker_compose,kubernetes,terraform | |
| output_format: sarif | |
| output_file_path: checkov-results.sarif | |
| - name: Upload Checkov results | |
| uses: github/codeql-action/upload-sarif@v2 | |
| if: always() | |
| with: | |
| sarif_file: checkov-results.sarif | |
| - name: Run Terrascan | |
| uses: tenable/terrascan-action@main | |
| with: | |
| iac_type: 'docker' | |
| iac_version: 'v1' | |
| policy_type: 'docker' | |
| only_warn: true | |
| sarif_upload: true | |
| # Job 6: License compliance scan | |
| license-scan: | |
| name: License Compliance Scan | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| component: [backend, frontend] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python (backend) | |
| if: matrix.component == 'backend' | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Set up Node.js (frontend) | |
| if: matrix.component == 'frontend' | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Scan Python licenses (backend) | |
| if: matrix.component == 'backend' | |
| run: | | |
| pip install pip-licenses | |
| # Generate license report | |
| echo "🔍 Scanning Python package licenses..." | |
| pip-licenses --format=json --output-file=python-licenses.json | |
| pip-licenses --format=html --output-file=python-licenses.html | |
| # Check for problematic licenses | |
| pip-licenses --fail-on="GPL v3,AGPL v3,GPL v2" || { | |
| echo "⚠️ Found problematic licenses in Python dependencies" | |
| exit 1 | |
| } | |
| - name: Scan Node.js licenses (frontend) | |
| if: matrix.component == 'frontend' | |
| working-directory: frontend | |
| run: | | |
| npm install -g license-checker | |
| # Generate license report | |
| echo "🔍 Scanning Node.js package licenses..." | |
| license-checker --json --out ../nodejs-licenses.json | |
| license-checker --csv --out ../nodejs-licenses.csv | |
| # Check for problematic licenses | |
| license-checker --failOn "GPL-3.0;AGPL-3.0;GPL-2.0" || { | |
| echo "⚠️ Found problematic licenses in Node.js dependencies" | |
| exit 1 | |
| } | |
| - name: Upload license reports | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: license-reports-${{ matrix.component }} | |
| path: | | |
| python-licenses.json | |
| python-licenses.html | |
| nodejs-licenses.json | |
| nodejs-licenses.csv | |
| # Job 7: Security summary and reporting | |
| security-summary: | |
| name: Security Summary | |
| runs-on: ubuntu-latest | |
| needs: [dependency-scan, container-scan, sast-scan, secret-scan, infrastructure-scan, license-scan] | |
| if: always() | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Download all security artifacts | |
| uses: actions/download-artifact@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Generate security report | |
| run: | | |
| python .github/scripts/generate_security_report.py \ | |
| --input-dir . \ | |
| --output security-dashboard.html | |
| - name: Upload security dashboard | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: security-dashboard | |
| path: security-dashboard.html | |
| - name: Check security status | |
| id: security_check | |
| run: | | |
| python .github/scripts/check_security_status.py \ | |
| --input-dir . \ | |
| --output-var GITHUB_OUTPUT | |
| - name: Create security issue | |
| if: steps.security_check.outputs.critical_issues > 0 | |
| uses: actions/github-script@v6 | |
| with: | |
| script: | | |
| const issue = await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: `🚨 Security Vulnerabilities Detected - ${new Date().toISOString().split('T')[0]}`, | |
| body: `## Security Scan Results | |
| **Date:** ${new Date().toISOString()} | |
| **Workflow:** [${context.runId}](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}) | |
| ### Critical Issues Found: ${{ steps.security_check.outputs.critical_issues }} | |
| ### High Issues Found: ${{ steps.security_check.outputs.high_issues }} | |
| ### Medium Issues Found: ${{ steps.security_check.outputs.medium_issues }} | |
| ### Categories: | |
| - Dependency Vulnerabilities: ${{ steps.security_check.outputs.dependency_issues }} | |
| - Container Vulnerabilities: ${{ steps.security_check.outputs.container_issues }} | |
| - Code Vulnerabilities: ${{ steps.security_check.outputs.code_issues }} | |
| - Secret Exposures: ${{ steps.security_check.outputs.secret_issues }} | |
| ### Next Steps: | |
| 1. Review the security dashboard for detailed findings | |
| 2. Address critical and high severity issues immediately | |
| 3. Update vulnerable dependencies | |
| 4. Fix identified code security issues | |
| 5. Rotate any exposed secrets | |
| ### Resources: | |
| - [Security Dashboard](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}) | |
| - [NIST CVE Database](https://nvd.nist.gov/) | |
| - [Security Best Practices](./docs/SECURITY.md) | |
| **Auto-generated by Security Scanning Workflow** | |
| `, | |
| labels: ['security', 'vulnerability', 'urgent', 'automated'] | |
| }); | |
| console.log(`Created security issue #${issue.data.number}`); | |
| - name: Post to Slack (critical issues) | |
| if: steps.security_check.outputs.critical_issues > 0 | |
| uses: 8398a7/action-slack@v3 | |
| with: | |
| status: failure | |
| text: | | |
| 🚨 Critical Security Vulnerabilities Detected! | |
| Critical Issues: ${{ steps.security_check.outputs.critical_issues }} | |
| High Issues: ${{ steps.security_check.outputs.high_issues }} | |
| View Details: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| env: | |
| SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} |