Skip to content

Commit 0892804

Browse files
Merge pull request #49 from NHSDigital/feature/APM-6390
Added new SBOM config
2 parents ff169b2 + 7ae8f91 commit 0892804

4 files changed

Lines changed: 181 additions & 5 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import json
2+
import csv
3+
import sys
4+
5+
input_file = sys.argv[1] if len(sys.argv) > 1 else "grype-report.json"
6+
output_file = sys.argv[2] if len(sys.argv) > 2 else "grype-report.csv"
7+
8+
with open(input_file, "r", encoding="utf-8") as f:
9+
data = json.load(f)
10+
11+
columns = ["NAME", "INSTALLED", "FIXED-IN", "TYPE", "VULNERABILITY", "SEVERITY"]
12+
13+
with open(output_file, "w", newline="", encoding="utf-8") as csvfile:
14+
writer = csv.DictWriter(csvfile, fieldnames=columns)
15+
writer.writeheader()
16+
for match in data.get("matches", []):
17+
pkg = match.get("artifact", {})
18+
vuln = match.get("vulnerability", {})
19+
row = {
20+
"NAME": pkg.get("name", ""),
21+
"INSTALLED": pkg.get("version", ""),
22+
"FIXED-IN": vuln.get("fix", {}).get("versions", [""])[0] if vuln.get("fix", {}).get("versions") else "",
23+
"TYPE": pkg.get("type", ""),
24+
"VULNERABILITY": vuln.get("id", ""),
25+
"SEVERITY": vuln.get("severity", ""),
26+
}
27+
writer.writerow(row)
28+
print(f"CSV export complete: {output_file}")
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import json
2+
import csv
3+
import sys
4+
# from pathlib import Path
5+
from tabulate import tabulate
6+
7+
input_file = sys.argv[1] if len(sys.argv) > 1 else "sbom.json"
8+
output_file = sys.argv[2] if len(sys.argv) > 2 else "sbom.csv"
9+
10+
with open(input_file, "r", encoding="utf-8") as f:
11+
sbom = json.load(f)
12+
13+
packages = sbom.get("packages", [])
14+
15+
columns = [
16+
"name",
17+
"versionInfo",
18+
"type",
19+
"supplier",
20+
"downloadLocation",
21+
"licenseConcluded",
22+
"licenseDeclared",
23+
"externalRefs"
24+
]
25+
26+
27+
def get_type(pkg):
28+
spdxid = pkg.get("SPDXID", "")
29+
if "-" in spdxid:
30+
parts = spdxid.split("-")
31+
if len(parts) > 2:
32+
return parts[2]
33+
refs = pkg.get("externalRefs", [])
34+
for ref in refs:
35+
if ref.get("referenceType") == "purl":
36+
return ref.get("referenceLocator", "").split("/")[0]
37+
return ""
38+
39+
40+
def get_external_refs(pkg):
41+
refs = pkg.get("externalRefs", [])
42+
return ";".join([ref.get("referenceLocator", "") for ref in refs])
43+
44+
45+
with open(output_file, "w", newline="", encoding="utf-8") as csvfile:
46+
writer = csv.DictWriter(csvfile, fieldnames=columns)
47+
writer.writeheader()
48+
for pkg in packages:
49+
row = {
50+
"name": pkg.get("name", ""),
51+
"versionInfo": pkg.get("versionInfo", ""),
52+
"type": get_type(pkg),
53+
"supplier": pkg.get("supplier", ""),
54+
"downloadLocation": pkg.get("downloadLocation", ""),
55+
"licenseConcluded": pkg.get("licenseConcluded", ""),
56+
"licenseDeclared": pkg.get("licenseDeclared", ""),
57+
"externalRefs": get_external_refs(pkg)
58+
}
59+
writer.writerow(row)
60+
61+
print(f"CSV export complete: {output_file}")
62+
63+
64+
with open("sbom_table.txt", "w", encoding="utf-8") as f:
65+
table = []
66+
for pkg in packages:
67+
row = [
68+
pkg.get("name", ""),
69+
pkg.get("versionInfo", ""),
70+
get_type(pkg),
71+
pkg.get("supplier", ""),
72+
pkg.get("downloadLocation", ""),
73+
pkg.get("licenseConcluded", ""),
74+
pkg.get("licenseDeclared", ""),
75+
get_external_refs(pkg)
76+
]
77+
table.append(row)
78+
f.write(tabulate(table, columns, tablefmt="grid"))
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import json
2+
import csv
3+
import sys
4+
import os
5+
6+
input_file = sys.argv[1] if len(sys.argv) > 1 else "sbom.json"
7+
repo_name = sys.argv[2] if len(sys.argv) > 2 else os.getenv("GITHUB_REPOSITORY", "unknown-repo").split("/")[-1]
8+
output_file = f"sbom-packages-{repo_name}.csv"
9+
10+
with open(input_file, "r", encoding="utf-8") as f:
11+
sbom = json.load(f)
12+
13+
packages = sbom.get("packages", [])
14+
15+
columns = ["name", "type", "version"]
16+
17+
with open(output_file, "w", newline="", encoding="utf-8") as csvfile:
18+
writer = csv.DictWriter(csvfile, fieldnames=columns)
19+
writer.writeheader()
20+
for pkg in packages:
21+
row = {
22+
"name": pkg.get("name", ""),
23+
"type": pkg.get("type", ""),
24+
"version": pkg.get("versionInfo", "")
25+
}
26+
writer.writerow(row)
27+
28+
print(f"Package list CSV generated: {output_file}")

.github/workflows/sbom.yml

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: SBOM Check
1+
name: SBOM Vulnerability Scanning
22

33
on:
44
workflow_dispatch:
@@ -56,13 +56,55 @@ jobs:
5656
chmod +x syft
5757
5858
# Add to PATH for subsequent steps
59-
echo "$(pwd)" >> $GITHUB_PATH
59+
echo "$(pwd)" >> $GITHUB_PATH
6060
6161
- name: Create SBOM
6262
run: bash scripts/create-sbom.sh terraform python tflint
6363

64-
- name: Upload SBOM as artifact
64+
- name: Convert SBOM JSON to CSV
65+
run: |
66+
pip install --upgrade pip
67+
pip install tabulate
68+
REPO_NAME=$(basename $GITHUB_REPOSITORY)
69+
python .github/scripts/sbom_json_to_csv.py sbom.json SBOM_${REPO_NAME}.csv
70+
71+
- name: Upload SBOM CSV as artifact
72+
uses: actions/upload-artifact@v4
73+
with:
74+
name: sbom-csv
75+
path: SBOM_${{ github.event.repository.name }}.csv
76+
77+
- name: Install Grype
78+
run: |
79+
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
80+
81+
- name: Scan SBOM for Vulnerabilities (JSON)
82+
run: |
83+
grype sbom:sbom.json -o json > grype-report.json
84+
85+
86+
87+
- name: Convert Grype JSON to CSV
88+
run: |
89+
pip install --upgrade pip
90+
REPO_NAME=$(basename $GITHUB_REPOSITORY)
91+
python .github/scripts/grype_json_to_csv.py grype-report.json grype-report-${REPO_NAME}.csv
92+
93+
94+
- name: Upload Vulnerability Report
95+
uses: actions/upload-artifact@v4
96+
with:
97+
name: grype-report
98+
path: grype-report-${{ github.event.repository.name }}.csv
99+
100+
- name: Generate Package Inventory CSV
101+
run: |
102+
pip install --upgrade pip
103+
REPO_NAME=$(basename $GITHUB_REPOSITORY)
104+
python .github/scripts/sbom_packages_to_csv.py sbom.json $REPO_NAME
105+
106+
- name: Upload Package Inventory CSV
65107
uses: actions/upload-artifact@v4
66108
with:
67-
name: sbom
68-
path: sbom.json
109+
name: sbom-packages
110+
path: sbom-packages-${{ github.event.repository.name }}.csv

0 commit comments

Comments
 (0)