Initial commit
This commit is contained in:
181
skills/devsecops/secrets-gitleaks/assets/github-action.yml
Normal file
181
skills/devsecops/secrets-gitleaks/assets/github-action.yml
Normal file
@@ -0,0 +1,181 @@
|
||||
# GitHub Actions Workflow for Gitleaks Secret Scanning
|
||||
# Save as: .github/workflows/gitleaks.yml
|
||||
|
||||
name: Secret Scanning with Gitleaks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
- 'release/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
schedule:
|
||||
# Run daily at 2 AM UTC
|
||||
- cron: '0 2 * * *'
|
||||
workflow_dispatch: # Allow manual triggers
|
||||
|
||||
# Cancel in-progress runs when new commit pushed
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
gitleaks-scan:
|
||||
name: Scan for Secrets
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
# Required for uploading SARIF results to GitHub Security tab
|
||||
security-events: write
|
||||
# Required for checking out private repos
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Fetch full history for comprehensive scanning
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run Gitleaks Scan
|
||||
id: gitleaks
|
||||
uses: gitleaks/gitleaks-action@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Optional: Use custom configuration
|
||||
# GITLEAKS_CONFIG: .gitleaks.toml
|
||||
|
||||
# Optional: Generate JSON report for further processing
|
||||
- name: Generate JSON Report
|
||||
if: always() # Run even if secrets found
|
||||
run: |
|
||||
docker run --rm -v ${{ github.workspace }}:/repo \
|
||||
zricethezav/gitleaks:latest \
|
||||
detect --source /repo \
|
||||
--report-path /repo/gitleaks-report.json \
|
||||
--report-format json \
|
||||
--exit-code 0 || true
|
||||
|
||||
# Optional: Upload JSON report as artifact
|
||||
- name: Upload Scan Report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gitleaks-report
|
||||
path: gitleaks-report.json
|
||||
retention-days: 30
|
||||
|
||||
# Optional: Generate SARIF report for GitHub Security tab
|
||||
- name: Generate SARIF Report
|
||||
if: always()
|
||||
run: |
|
||||
docker run --rm -v ${{ github.workspace }}:/repo \
|
||||
zricethezav/gitleaks:latest \
|
||||
detect --source /repo \
|
||||
--report-path /repo/gitleaks.sarif \
|
||||
--report-format sarif \
|
||||
--exit-code 0 || true
|
||||
|
||||
# Optional: Upload SARIF report to GitHub Security
|
||||
- name: Upload SARIF to GitHub Security
|
||||
if: always()
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: gitleaks.sarif
|
||||
category: gitleaks
|
||||
|
||||
# Optional: Comment on PR with findings
|
||||
- name: Comment PR with Findings
|
||||
if: failure() && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
try {
|
||||
const report = JSON.parse(fs.readFileSync('gitleaks-report.json', 'utf8'));
|
||||
const findings = report.length;
|
||||
|
||||
const comment = `## 🔒 Secret Scanning Results
|
||||
|
||||
⚠️ **${findings} potential secret(s) detected!**
|
||||
|
||||
Please review the findings and take immediate action:
|
||||
1. **Do not merge** this PR until secrets are removed
|
||||
2. Rotate any exposed credentials immediately
|
||||
3. Remove secrets from code and use environment variables
|
||||
4. Review the security tab for detailed findings
|
||||
|
||||
See [Secret Scanning Guide](https://github.com/${{ github.repository }}/blob/main/docs/secret-scanning.md) for remediation steps.`;
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('No report file or error reading it:', error.message);
|
||||
}
|
||||
|
||||
# Optional: Post to Slack on failure
|
||||
- name: Notify Slack on Failure
|
||||
if: failure()
|
||||
uses: slackapi/slack-github-action@v1
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
"text": "🚨 Secrets detected in ${{ github.repository }}",
|
||||
"blocks": [
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": "*Secret Scanning Alert*\n\nSecrets detected in repository: `${{ github.repository }}`\nBranch: `${{ github.ref_name }}`\nCommit: `${{ github.sha }}`\n\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Details>"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
|
||||
|
||||
# Optional: Baseline scanning for incremental detection
|
||||
baseline-scan:
|
||||
name: Incremental Scan Against Baseline
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push'
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download Existing Baseline
|
||||
continue-on-error: true
|
||||
run: |
|
||||
# Download baseline from artifact storage or S3
|
||||
# Example: aws s3 cp s3://bucket/.gitleaks-baseline.json .
|
||||
echo "Baseline download would go here"
|
||||
|
||||
- name: Run Incremental Scan
|
||||
run: |
|
||||
docker run --rm -v ${{ github.workspace }}:/repo \
|
||||
zricethezav/gitleaks:latest \
|
||||
detect --source /repo \
|
||||
--baseline-path /repo/.gitleaks-baseline.json \
|
||||
--report-path /repo/new-findings.json \
|
||||
--report-format json \
|
||||
--exit-code 1 || true
|
||||
|
||||
- name: Upload New Findings
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: new-findings
|
||||
path: new-findings.json
|
||||
retention-days: 90
|
||||
Reference in New Issue
Block a user