dc4ad3cc6c
* consolidate attestation actions Signed-off-by: Brian DeHamer <bdehamer@github.com> * better errors Signed-off-by: Brian DeHamer <bdehamer@github.com> * Update src/sbom.ts Co-authored-by: Austin Beattie <ajbeattie@github.com> * clarify dedupe comment Signed-off-by: Brian DeHamer <bdehamer@github.com> --------- Signed-off-by: Brian DeHamer <bdehamer@github.com> Co-authored-by: Austin Beattie <ajbeattie@github.com>
162 lines
4.3 KiB
TypeScript
162 lines
4.3 KiB
TypeScript
import fs from 'fs/promises'
|
|
import os from 'os'
|
|
import path from 'path'
|
|
import { parseSBOMFromPath, generateSBOMPredicate, SBOM } from '../src/sbom'
|
|
|
|
describe('parseSBOMFromPath', () => {
|
|
let tmpDir: string
|
|
|
|
beforeEach(async () => {
|
|
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'sbom-test-'))
|
|
})
|
|
|
|
afterEach(async () => {
|
|
await fs.rm(tmpDir, { recursive: true })
|
|
})
|
|
|
|
describe('when file does not exist', () => {
|
|
it('throws an error', async () => {
|
|
await expect(parseSBOMFromPath('/nonexistent/file.json')).rejects.toThrow(
|
|
/SBOM file not found/
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('when file contains valid SPDX SBOM', () => {
|
|
const spdxSBOM = {
|
|
spdxVersion: 'SPDX-2.3',
|
|
SPDXID: 'SPDXRef-DOCUMENT',
|
|
name: 'test-package',
|
|
packages: []
|
|
}
|
|
|
|
it('returns SBOM with type spdx', async () => {
|
|
const filePath = path.join(tmpDir, 'sbom.spdx.json')
|
|
await fs.writeFile(filePath, JSON.stringify(spdxSBOM))
|
|
|
|
const result = await parseSBOMFromPath(filePath)
|
|
|
|
expect(result.type).toBe('spdx')
|
|
expect(result.object).toEqual(spdxSBOM)
|
|
})
|
|
})
|
|
|
|
describe('when file contains valid CycloneDX SBOM', () => {
|
|
const cyclonedxSBOM = {
|
|
bomFormat: 'CycloneDX',
|
|
specVersion: '1.4',
|
|
serialNumber: 'urn:uuid:12345',
|
|
components: []
|
|
}
|
|
|
|
it('returns SBOM with type cyclonedx', async () => {
|
|
const filePath = path.join(tmpDir, 'sbom.cdx.json')
|
|
await fs.writeFile(filePath, JSON.stringify(cyclonedxSBOM))
|
|
|
|
const result = await parseSBOMFromPath(filePath)
|
|
|
|
expect(result.type).toBe('cyclonedx')
|
|
expect(result.object).toEqual(cyclonedxSBOM)
|
|
})
|
|
})
|
|
|
|
describe('when file contains invalid SBOM format', () => {
|
|
it('throws an error', async () => {
|
|
const filePath = path.join(tmpDir, 'invalid.json')
|
|
await fs.writeFile(filePath, JSON.stringify({ random: 'data' }))
|
|
|
|
await expect(parseSBOMFromPath(filePath)).rejects.toThrow(
|
|
/Unsupported SBOM format/
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('when file contains invalid JSON', () => {
|
|
it('throws an error', async () => {
|
|
const filePath = path.join(tmpDir, 'invalid.json')
|
|
await fs.writeFile(filePath, 'not valid json')
|
|
|
|
await expect(parseSBOMFromPath(filePath)).rejects.toThrow()
|
|
})
|
|
})
|
|
|
|
describe('when file exceeds maximum size', () => {
|
|
it('throws an error', async () => {
|
|
const filePath = path.join(tmpDir, 'large.json')
|
|
// Create a file larger than 16MB
|
|
const largeContent = 'x'.repeat(17 * 1024 * 1024)
|
|
await fs.writeFile(filePath, largeContent)
|
|
|
|
await expect(parseSBOMFromPath(filePath)).rejects.toThrow(
|
|
/SBOM file exceeds maximum allowed size/
|
|
)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('generateSBOMPredicate', () => {
|
|
describe('for SPDX SBOM', () => {
|
|
const spdxSBOM: SBOM = {
|
|
type: 'spdx',
|
|
object: {
|
|
spdxVersion: 'SPDX-2.3',
|
|
SPDXID: 'SPDXRef-DOCUMENT',
|
|
name: 'test-package'
|
|
}
|
|
}
|
|
|
|
it('returns predicate with correct SPDX type', () => {
|
|
const predicate = generateSBOMPredicate(spdxSBOM)
|
|
|
|
expect(predicate.type).toBe('https://spdx.dev/Document/v2.3')
|
|
expect(predicate.params).toEqual(spdxSBOM.object)
|
|
})
|
|
})
|
|
|
|
describe('for CycloneDX SBOM', () => {
|
|
const cyclonedxSBOM: SBOM = {
|
|
type: 'cyclonedx',
|
|
object: {
|
|
bomFormat: 'CycloneDX',
|
|
specVersion: '1.4',
|
|
serialNumber: 'urn:uuid:12345'
|
|
}
|
|
}
|
|
|
|
it('returns predicate with correct CycloneDX type', () => {
|
|
const predicate = generateSBOMPredicate(cyclonedxSBOM)
|
|
|
|
expect(predicate.type).toBe('https://cyclonedx.org/bom')
|
|
expect(predicate.params).toEqual(cyclonedxSBOM.object)
|
|
})
|
|
})
|
|
|
|
describe('for SPDX without version', () => {
|
|
const invalidSBOM: SBOM = {
|
|
type: 'spdx',
|
|
object: {
|
|
SPDXID: 'SPDXRef-DOCUMENT'
|
|
}
|
|
}
|
|
|
|
it('throws an error', () => {
|
|
expect(() => generateSBOMPredicate(invalidSBOM)).toThrow(
|
|
/Cannot find spdxVersion/
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('for unsupported SBOM type', () => {
|
|
const unsupportedSBOM = {
|
|
type: 'unknown' as SBOM['type'],
|
|
object: { foo: 'bar' }
|
|
}
|
|
|
|
it('throws an error', () => {
|
|
expect(() => generateSBOMPredicate(unsupportedSBOM)).toThrow(
|
|
/Unsupported SBOM format/
|
|
)
|
|
})
|
|
})
|
|
})
|