Centralized Secret Scanning Report #2
This file contains 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: Secret Scanning Report Generator | |
on: | |
workflow_dispatch: | |
inputs: | |
include_inactive: | |
description: 'Include inactive alerts in report' | |
required: false | |
type: boolean | |
default: false | |
max_workers: | |
description: 'Maximum number of concurrent workers' | |
required: false | |
type: number | |
default: 10 | |
log_level: | |
description: 'Logging level' | |
required: false | |
type: choice | |
options: | |
- INFO | |
- DEBUG | |
- WARNING | |
- ERROR | |
default: 'INFO' | |
schedule: | |
- cron: '0 0 * * 1' # Weekly on Monday at midnight | |
permissions: | |
security-events: read # Required for secret scanning API | |
contents: read # Required for checking out code | |
actions: write # Required for artifact upload | |
issues: write # Required for creating issues on failure | |
jobs: | |
generate-report: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 1 | |
- name: Set up Python | |
uses: actions/setup-python@v4 | |
with: | |
python-version: '3.11' # Updated to latest stable Python | |
cache: 'pip' | |
cache-dependency-path: requirements.txt | |
- name: Install dependencies | |
run: | | |
python -m pip install --upgrade pip | |
pip install -r requirements.txt | |
- name: Generate timestamp | |
id: timestamp | |
run: echo "timestamp=$(date +%Y%m%d_%H%M%S)" >> $GITHUB_OUTPUT | |
- name: Generate Secret Report | |
id: generate-report | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
ORGANIZATION: ${{ github.repository_owner }} | |
REPORT_FILE: "secret_report_${{ steps.timestamp.outputs.timestamp }}.csv" | |
run: | | |
# Create output directory | |
mkdir -p reports | |
# Run the scanner with configured parameters | |
python ./scripts/github_secret_scanner.py \ | |
--org "$ORGANIZATION" \ | |
--token "$GITHUB_TOKEN" \ | |
--output "reports/${REPORT_FILE}" \ | |
--log-level ${{ inputs.log_level || 'INFO' }} \ | |
--max-workers ${{ inputs.max_workers || 10 }} \ | |
--max-retries 3 \ | |
${{ inputs.include_inactive && '--include-inactive' || '' }} | |
# Save report path for later steps | |
echo "report_path=reports/${REPORT_FILE}" >> $GITHUB_OUTPUT | |
- name: Upload report | |
uses: actions/upload-artifact@v4 | |
if: success() | |
with: | |
name: secret-scanning-report-${{ steps.timestamp.outputs.timestamp }} | |
path: ${{ steps.generate-report.outputs.report_path }} | |
retention-days: 30 | |
if-no-files-found: error | |
- name: Process report statistics | |
if: success() | |
id: stats | |
run: | | |
total_alerts=$(python scripts/process_report.py --input ${{ steps.generate-report.outputs.report_path }} --count) | |
active_alerts=$(python scripts/process_report.py --input ${{ steps.generate-report.outputs.report_path }} --active) | |
echo "Total alerts found: $total_alerts" | |
echo "Active alerts: $active_alerts" | |
# Save stats for issue creation | |
echo "total_alerts=$total_alerts" >> $GITHUB_OUTPUT | |
echo "active_alerts=$active_alerts" >> $GITHUB_OUTPUT | |
- name: Create summary issue | |
if: success() && ${{ steps.stats.outputs.active_alerts > 10 }} | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const stats = { | |
total: '${{ steps.stats.outputs.total_alerts }}', | |
active: '${{ steps.stats.outputs.active_alerts }}' | |
}; | |
const body = ` | |
# Secret Scanning Report Summary | |
Report generated on: ${new Date().toISOString()} | |
## Statistics | |
- Total alerts analyzed: ${stats.total} | |
- Active alerts found: ${stats.active} | |
## Details | |
- Report artifact: [Download report](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}) | |
- Workflow run: [View details](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}) | |
## Configuration | |
- Include inactive alerts: ${{ inputs.include_inactive || 'false' }} | |
- Max workers: ${{ inputs.max_workers || '10' }} | |
- Log level: ${{ inputs.log_level || 'INFO' }} | |
`; | |
await github.rest.issues.create({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
title: `📊 Secret Scanning Report - ${new Date().toISOString().split('T')[0]}`, | |
body: body, | |
labels: ['secret-scanning', 'report'] | |
}); | |
- name: Notify on failure | |
if: failure() | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const body = ` | |
# 🚨 Secret Scanning Report Generation Failed | |
Workflow run failed at ${new Date().toISOString()} | |
## Details | |
- Run ID: \`${context.runId}\` | |
- Trigger: ${context.eventName} | |
- Actor: @${context.actor} | |
## Links | |
- [View run details](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}) | |
- [View workflow file](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/blob/main/.github/workflows/secret-scanning-report.yml) | |
Please check the workflow logs for detailed error information. | |
`; | |
await github.rest.issues.create({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
title: '🚨 Secret Scanning Report Generation Failed', | |
body: body, | |
labels: ['secret-scanning', 'failed'] | |
}); | |
- name: Clean up | |
if: always() | |
run: | | |
# Securely remove any sensitive files | |
if [ -d "reports" ]; then | |
find reports -type f -exec shred -u {} \; | |
rm -rf reports | |
fi | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true |