Skip to content

Commit 557ae90

Browse files
authored
feat: add enhanced workflows (#16)
Add enhanced workflows to generate & sign SBOMs, run OSV Scanner
1 parent c52c5a7 commit 557ae90

6 files changed

Lines changed: 455 additions & 65 deletions

File tree

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
name: SBOM Generation, Signing, & Vulnerability Scanning
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches: [ main ]
7+
tags:
8+
- 'v*'
9+
10+
jobs:
11+
generate_sbom:
12+
name: 🔏 Generate & Sign SBOM
13+
runs-on: ubuntu-latest
14+
outputs:
15+
sanitized_ref: ${{ steps.vars.outputs.sanitized_ref }}
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Set up Go
21+
uses: actions/setup-go@v5
22+
with:
23+
go-version-file: 'go.mod'
24+
cache: true
25+
26+
- name: Sanitize branch name
27+
id: vars
28+
run: echo "sanitized_ref=${GITHUB_REF_NAME//\//-}" >> $GITHUB_OUTPUT
29+
30+
- name: Generate SBOM (CycloneDX)
31+
uses: CycloneDX/gh-gomod-generate-sbom@v2
32+
with:
33+
version: v1
34+
args: mod -licenses -json -output-version 1.6 -output sbom-validator.${{ steps.vars.outputs.sanitized_ref }}.cdx.json
35+
env:
36+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37+
38+
- name: Sign SBOM
39+
uses: shiftleftcyber/secure-sbom-action@v1.3.1
40+
with:
41+
sbom_file: sbom-validator.${{ steps.vars.outputs.sanitized_ref }}.cdx.json
42+
secure_sbom_action: sign
43+
api_key: ${{ secrets.SECURE_SBOM_API_KEY }}
44+
key_id: ${{ secrets.SECURE_SBOM_KEYID }}
45+
46+
- name: Verify SBOM
47+
uses: shiftleftcyber/secure-sbom-action@v1.3.1
48+
with:
49+
sbom_file: sbom-validator.${{ steps.vars.outputs.sanitized_ref }}.cdx.signed.json
50+
secure_sbom_action: verify
51+
api_key: ${{ secrets.SECURE_SBOM_API_KEY }}
52+
key_id: ${{ secrets.SECURE_SBOM_KEYID }}
53+
54+
- name: Upload SBOM Artifacts
55+
uses: actions/upload-artifact@v4
56+
with:
57+
name: sbom-artifacts
58+
path: |
59+
sbom-validator.${{ steps.vars.outputs.sanitized_ref }}.cdx.json
60+
sbom-validator.${{ steps.vars.outputs.sanitized_ref }}.cdx.signed.json
61+
62+
- name: Add Job Summary
63+
run: |
64+
echo "### 🔏 SBOM Lifecycle Completed" >> $GITHUB_STEP_SUMMARY
65+
echo "- ✅ SBOM generated, signed, and verified successfully" >> $GITHUB_STEP_SUMMARY
66+
echo "- 📄 Artifacts uploaded for transparency" >> $GITHUB_STEP_SUMMARY
67+
68+
osv-scan:
69+
name: 🔎 OSV Scan
70+
needs: generate_sbom
71+
runs-on: ubuntu-latest
72+
permissions:
73+
security-events: write
74+
contents: read
75+
actions: read
76+
77+
steps:
78+
- name: Checkout Repo
79+
uses: actions/checkout@v4
80+
81+
- name: Download Signed SBOM
82+
uses: actions/download-artifact@v4
83+
with:
84+
name: sbom-artifacts
85+
path: .
86+
87+
- name: Run OSV Scanner
88+
run: |
89+
SAFE_REF="${{ needs.generate_sbom.outputs.sanitized_ref || github.ref_name }}"
90+
SAFE_REF="${SAFE_REF//\//-}"
91+
docker run --rm -v ${{ github.workspace }}:/opt --workdir /opt ghcr.io/google/osv-scanner:latest \
92+
scan --lockfile sbom-validator.${SAFE_REF}.cdx.json \
93+
--format json --output osv-scan-report.json || true
94+
95+
- name: Upload OSV Report
96+
uses: actions/upload-artifact@v4
97+
with:
98+
name: osv-scan-report
99+
path: osv-scan-report.json
100+
101+
- name: Enforce Security Gate
102+
id: enforce-gate
103+
run: |
104+
echo "🔍 Evaluating OSV scan results..."
105+
COUNT=$(jq '[.results[] | select(.severity == "HIGH" or .severity == "CRITICAL")] | length' osv-scan-report.json)
106+
if [ "$COUNT" -gt 0 ]; then
107+
echo "❌ Blocking release - $COUNT high/critical vulnerabilities detected!"
108+
jq '.results[] | select(.severity == "HIGH" or .severity == "CRITICAL") | {package: .package.name, severity: .severity, summary: .summary}' osv-scan-report.json
109+
echo "blocked=true" >> $GITHUB_OUTPUT
110+
exit 1
111+
else
112+
echo "✅ No blocking vulnerabilities found."
113+
echo "blocked=false" >> $GITHUB_OUTPUT
114+
fi
115+
116+
- name: Add Job Summary
117+
if: always()
118+
run: |
119+
echo "### 🔒 OSV Vulnerability Scan Summary" >> $GITHUB_STEP_SUMMARY
120+
echo "- **Scan file:** \`osv-scan-report.json\`" >> $GITHUB_STEP_SUMMARY
121+
if [[ '${{ steps.enforce-gate.outputs.blocked }}' == 'true' ]]; then
122+
echo "- ❌ **High/Critical vulnerabilities found — release blocked**" >> $GITHUB_STEP_SUMMARY
123+
else
124+
echo "- ✅ **No blocking vulnerabilities detected — safe to proceed**" >> $GITHUB_STEP_SUMMARY
125+
fi
126+
echo "" >> $GITHUB_STEP_SUMMARY
127+
echo "For full report, download the [osv-scan-report artifact](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: OSV-Scanner Scan
2+
3+
on:
4+
schedule:
5+
- cron: "30 12 * * 1"
6+
7+
permissions:
8+
actions: read
9+
security-events: write
10+
contents: read
11+
12+
jobs:
13+
scan-scheduled:
14+
uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@v2.2.3"

.github/workflows/release.yml

Lines changed: 140 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ on:
66
- 'v*'
77

88
permissions:
9+
actions: read
10+
security-events: write
911
contents: write
1012

1113
jobs:
@@ -33,14 +35,147 @@ jobs:
3335
env:
3436
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3537

38+
- name: Add Job Summary
39+
run: |
40+
echo "### 🚀 Release Completed" >> $GITHUB_STEP_SUMMARY
41+
echo "- ✅ GoReleaser successfully published binaries and SBOM" >> $GITHUB_STEP_SUMMARY
42+
43+
generate_sbom:
44+
name: 🔏 Generate SBOM
45+
runs-on: ubuntu-latest
46+
needs: goreleaser
47+
48+
steps:
49+
- name: Checkout Repository
50+
uses: actions/checkout@v4
51+
52+
- name: Setup Go
53+
uses: actions/setup-go@v5
54+
with:
55+
go-version: "1.21"
56+
check-latest: true
57+
58+
- name: Generate SBOM (CycloneDX)
59+
uses: CycloneDX/gh-gomod-generate-sbom@v2
60+
with:
61+
version: v1
62+
args: mod -licenses -json -output-version 1.6 -output sbom-validator.${{ github.ref_name }}.cdx.json
63+
env:
64+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
65+
66+
- name: Sign SBOM
67+
uses: shiftleftcyber/secure-sbom-action@v1.3.1
68+
with:
69+
sbom_file: sbom-validator.${{ github.ref_name }}.cdx.json
70+
secure_sbom_action: sign
71+
api_key: ${{ secrets.SECURE_SBOM_API_KEY }}
72+
key_id: ${{ secrets.SECURE_SBOM_KEYID }}
73+
74+
- name: Upload SBOM Artifacts
75+
uses: actions/upload-artifact@v4
76+
with:
77+
name: unsigned-sbom
78+
path: sbom-validator.${{ github.ref_name }}.cdx.json
79+
retention-days: 7
80+
81+
- name: Add Job Summary
82+
run: |
83+
echo "### 🔏 SBOM Generated & Signed" >> $GITHUB_STEP_SUMMARY
84+
echo "- ✅ CycloneDX SBOM created" >> $GITHUB_STEP_SUMMARY
85+
echo "- 🔐 Signed with SecureSBOM API" >> $GITHUB_STEP_SUMMARY
86+
echo "- 📦 Uploaded as release asset" >> $GITHUB_STEP_SUMMARY
87+
88+
sign-sbom:
89+
name: Sign SBOM via SecureSBOM
90+
needs: generate_sbom
91+
runs-on: ubuntu-latest
92+
93+
steps:
94+
- name: Checkout Repo
95+
uses: actions/checkout@v4
96+
97+
- name: Download Signed SBOM
98+
uses: actions/download-artifact@v4
99+
with:
100+
name: unsigned-sbom
101+
path: .
102+
103+
- name: Sign SBOM via SecureSBOM
104+
uses: shiftleftcyber/secure-sbom-action@v1.3.1
105+
with:
106+
sbom_file: sbom-validator.${{ github.ref_name }}.cdx.json
107+
secure_sbom_action: sign
108+
api_key: ${{ secrets.SECURE_SBOM_API_KEY }}
109+
key_id: ${{ secrets.SECURE_SBOM_KEYID }}
110+
111+
- name: Upload Signed SBOM
112+
uses: actions/upload-artifact@v4
113+
with:
114+
name: signed-sbom
115+
path: sbom-validator.${{ github.ref_name }}.cdx.signed.json
116+
retention-days: 7
117+
36118
- name: Upload Signed SBOM to Release
37119
uses: softprops/action-gh-release@v2
38120
with:
39-
files: |
40-
sbom-validator.${{ github.ref_name }}.cdx.signed.json
121+
files: sbom-validator.${{ github.ref_name }}.cdx.signed.json
41122

123+
osv-scan:
124+
name: 🔎 OSV Scan
125+
needs: generate_sbom
126+
runs-on: ubuntu-latest
127+
permissions:
128+
security-events: write
129+
contents: read
130+
actions: read
131+
132+
steps:
133+
- name: Checkout Repo
134+
uses: actions/checkout@v4
135+
136+
- name: Download Signed SBOM
137+
uses: actions/download-artifact@v4
138+
with:
139+
name: unsigned-sbom
140+
path: .
141+
142+
- name: Run OSV Scanner
143+
run: |
144+
docker run --rm -v ${{ github.workspace }}:/opt --workdir /opt ghcr.io/google/osv-scanner:latest \
145+
scan --lockfile sbom-validator.${{ github.ref_name }}.cdx.json \
146+
--format json --output osv-scan-report.json || true
147+
148+
- name: Upload OSV Report
149+
uses: actions/upload-artifact@v4
150+
with:
151+
name: osv-scan-report
152+
path: osv-scan-report.json
153+
154+
- name: Enforce Security Gate
155+
id: enforce-gate
156+
run: |
157+
echo "🔍 Evaluating OSV scan results..."
158+
COUNT=$(jq '[.results[] | select(.severity == "HIGH" or .severity == "CRITICAL")] | length' osv-scan-report.json)
159+
if [ "$COUNT" -gt 0 ]; then
160+
echo "❌ Blocking release - $COUNT high/critical vulnerabilities detected!"
161+
jq '.results[] | select(.severity == "HIGH" or .severity == "CRITICAL") | {package: .package.name, severity: .severity, summary: .summary}' osv-scan-report.json
162+
echo "blocked=true" >> $GITHUB_OUTPUT
163+
exit 1
164+
else
165+
echo "✅ No blocking vulnerabilities found."
166+
echo "blocked=false" >> $GITHUB_OUTPUT
167+
fi
168+
42169
- name: Add Job Summary
170+
if: always()
43171
run: |
44-
echo "### 🚀 Release Completed" >> $GITHUB_STEP_SUMMARY
45-
echo "- ✅ GoReleaser successfully published binaries and SBOM" >> $GITHUB_STEP_SUMMARY
46-
echo "- 🔏 Signed SBOM attached to GitHub release" >> $GITHUB_STEP_SUMMARY
172+
echo "### 🔒 OSV Vulnerability Scan Summary" >> $GITHUB_STEP_SUMMARY
173+
echo "- **Scan file:** \`osv-scan-report.json\`" >> $GITHUB_STEP_SUMMARY
174+
if [[ '${{ steps.enforce-gate.outputs.blocked }}' == 'true' ]]; then
175+
echo "- ❌ **High/Critical vulnerabilities found — release blocked**" >> $GITHUB_STEP_SUMMARY
176+
else
177+
echo "- ✅ **No blocking vulnerabilities detected — safe to proceed**" >> $GITHUB_STEP_SUMMARY
178+
fi
179+
echo "" >> $GITHUB_STEP_SUMMARY
180+
echo "For full report, download the [osv-scan-report artifact](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY
181+

.github/workflows/sbom-sign-verify.yml

Lines changed: 0 additions & 60 deletions
This file was deleted.

0 commit comments

Comments
 (0)