generated from actions/typescript-action
-
Notifications
You must be signed in to change notification settings - Fork 3
/
sbom.ts
99 lines (83 loc) · 2.39 KB
/
sbom.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import fs from 'fs'
import * as path from 'path'
import type { Predicate } from '@actions/attest'
export type SBOM = {
type: 'spdx' | 'cyclonedx'
object: object
}
export async function parseSBOMFromPath(filePath: string): Promise<SBOM> {
// Read the file content
const fileContent = await fs.promises.readFile(filePath, 'utf8')
const sbom = JSON.parse(fileContent) as object
if (checkIsSPDX(sbom)) {
return { type: 'spdx', object: sbom }
} else if (checkIsCycloneDX(sbom)) {
return { type: 'cyclonedx', object: sbom }
}
throw new Error('Unsupported SBOM format')
}
function checkIsSPDX(sbomObject: {
spdxVersion?: string
SPDXID?: string
}): boolean {
if (sbomObject?.spdxVersion && sbomObject?.SPDXID) {
return true
} else {
return false
}
}
function checkIsCycloneDX(sbomObject: {
bomFormat?: string
serialNumber?: string
specVersion?: string
}): boolean {
if (
sbomObject?.bomFormat &&
sbomObject?.serialNumber &&
sbomObject?.specVersion
) {
return true
} else {
return false
}
}
export const storePredicate = (predicate: Predicate): string => {
// random tempfile
const basePath = process.env['RUNNER_TEMP']
if (!basePath) {
throw new Error('Missing RUNNER_TEMP environment variable')
}
const tmpDir = fs.mkdtempSync(path.join(basePath, path.sep))
const tempFile = path.join(tmpDir, 'predicate.json')
// write predicate to file
fs.writeFileSync(tempFile, JSON.stringify(predicate.params))
return tempFile
}
export const generateSBOMPredicate = (sbom: SBOM): Predicate => {
if (sbom.type === 'spdx') {
return generateSPDXIntoto(sbom.object)
}
if (sbom.type === 'cyclonedx') {
return generateCycloneDXIntoto(sbom.object)
}
throw new Error('Unsupported SBOM format')
}
// ref: https://github.com/in-toto/attestation/blob/main/spec/predicates/spdx.md
const generateSPDXIntoto = (sbom: object): Predicate => {
const spdxVersion = (sbom as { spdxVersion?: string })?.['spdxVersion']
if (!spdxVersion) {
throw new Error('Cannot find spdxVersion in the SBOM')
}
const version = spdxVersion.split('-')[1]
return {
type: `https://spdx.dev/Document/v${version}`,
params: sbom
}
}
// ref: https://github.com/in-toto/attestation/blob/main/spec/predicates/cyclonedx.md
const generateCycloneDXIntoto = (sbom: object): Predicate => {
return {
type: 'https://cyclonedx.org/bom',
params: sbom
}
}