Skip to content

Commit

Permalink
⭐️ include npm packages in sbom export
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-rock committed Feb 16, 2024
1 parent 0bb01bd commit f797eee
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 14 deletions.
12 changes: 12 additions & 0 deletions sbom/cnquery_bom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,20 @@ func TestSimpleBom(t *testing.T) {
require.NoError(t, err)

data := output.String()

// ensure os package is included
assert.Contains(t, data, "alpine-baselayout")
assert.Contains(t, data, "cpe:2.3:a:alpine-baselayout:alpine-baselayout:1695795276:aarch64:*:*:*:*:*:*")
// check that package files are included
assert.Contains(t, data, "etc/profile.d/color_prompt.sh.disabled")

// ensure python package is included
assert.Contains(t, data, "pip")
assert.Contains(t, data, "cpe:2.3:a:pip_project:pip:21.2.4:*:*:*:*:*:*:*")
assert.Contains(t, data, "pkg:pypi/[email protected]")

// ensure npm package is included
assert.Contains(t, data, "npm")
assert.Contains(t, data, "cpe:2.3:a:npm:npm:10.2.4:*:*:*:*:*:*:*")
assert.Contains(t, data, "pkg:npm/[email protected]")
}
12 changes: 12 additions & 0 deletions sbom/cyclonedx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,20 @@ func TestCycloneDX(t *testing.T) {
data := output.String()
// os.WriteFile("./testdata/bom_cyclone.json", output.Bytes(), 0700)
assert.Contains(t, data, "cyclonedx")

// ensure os package is included
assert.Contains(t, data, "alpine-baselayout")
assert.Contains(t, data, "cpe:2.3:a:alpine-baselayout:alpine-baselayout:1695795276:aarch64:*:*:*:*:*:*")
// check that package files are included
assert.Contains(t, data, "etc/profile.d/color_prompt.sh.disabled")

// ensure python package is included
assert.Contains(t, data, "pip")
assert.Contains(t, data, "cpe:2.3:a:pip_project:pip:21.2.4:*:*:*:*:*:*:*")
assert.Contains(t, data, "pkg:pypi/[email protected]")

// ensure npm package is included
assert.Contains(t, data, "npm")
assert.Contains(t, data, "cpe:2.3:a:npm:npm:10.2.4:*:*:*:*:*:*:*")
assert.Contains(t, data, "pkg:npm/[email protected]")
}
1 change: 1 addition & 0 deletions sbom/report_collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type BomReport struct {
Asset *BomAsset `json:"asset,omitempty"`
Packages []BomPackage `json:"packages.list,omitempty"`
PythonPackages []BomPackage `json:"python.packages,omitempty"`
NpmPackages []BomPackage `json:"npm.packages.list,omitempty"`
}

func (b *BomReport) ToJSON() ([]byte, error) {
Expand Down
20 changes: 20 additions & 0 deletions sbom/sbom.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,26 @@ func GenerateBom(r *ReportCollectionJson) ([]Sbom, error) {
})
}

bom.Packages = append(bom.Packages, bomPkg)
}
}
if rb.NpmPackages != nil {
for _, pkg := range rb.NpmPackages {
bomPkg := &Package{
Name: pkg.Name,
Version: pkg.Version,
Purl: pkg.Purl,
Cpes: pkg.CPEs,
Type: "npm",
}

for _, filepath := range pkg.FilePaths {
bomPkg.EvidenceList = append(bomPkg.EvidenceList, &Evidence{
Type: EvidenceType_EVIDENCE_TYPE_FILE,
Value: filepath,
})
}

bom.Packages = append(bom.Packages, bomPkg)
}
}
Expand Down
5 changes: 4 additions & 1 deletion sbom/sbom.mql.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ packs:
mql: packages { name version purl cpes.map(uri) format files.map(path) }
- uid: mondoo-sbom-python-packages
title: Retrieve list of installed Python packages
mql: python.packages { name version purl cpes.map(uri) file.path }
mql: python.packages { name version purl cpes.map(uri) file.path }
- uid: mondoo-sbom-npm-packages
title: Retrieve list of installed npm packages
mql: npm.packages { name version purl cpes.map(uri) files.map(path) }
34 changes: 26 additions & 8 deletions sbom/sbom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,38 @@ func TestSbomParsing(t *testing.T) {
assert.Equal(t, "3.19.0", selectedBom.Asset.Platform.Version)
assert.Equal(t, []string{"//platformid.api.mondoo.app/runtime/docker/images/1dc785547989b0db1c3cd9949c57574393e69bea98bfe044b0588e24721aa402"}, selectedBom.Asset.PlatformIds)

var pkg *Package
for i := range selectedBom.Packages {
if selectedBom.Packages[i].Name == "alpine-baselayout" {
pkg = selectedBom.Packages[i]
break
}
}
require.NotNil(t, pkg)
// search os package
pkg := findProtoPkg(selectedBom.Packages, "alpine-baselayout")
assert.Equal(t, "alpine-baselayout", pkg.Name)
assert.Contains(t, pkg.EvidenceList, &Evidence{
Type: EvidenceType_EVIDENCE_TYPE_FILE,
Value: "etc/profile.d/color_prompt.sh.disabled",
})

// search python package
pkg = findProtoPkg(selectedBom.Packages, "pip")
assert.Equal(t, "pip", pkg.Name)
assert.Contains(t, pkg.EvidenceList, &Evidence{
Type: EvidenceType_EVIDENCE_TYPE_FILE,
Value: "/opt/lib/python3.9/site-packages/pip-21.2.4.dist-info/METADATA",
})

// search npm package
pkg = findProtoPkg(selectedBom.Packages, "npm")
assert.Equal(t, "npm", pkg.Name)
assert.Contains(t, pkg.EvidenceList, &Evidence{
Type: EvidenceType_EVIDENCE_TYPE_FILE,
Value: "/opt/lib/node_modules/npm/package.json",
})
}

func findProtoPkg(pkgs []*Package, name string) *Package {
for i := range pkgs {
if pkgs[i].Name == name {
return pkgs[i]
}
}
panic("package not found: " + name)
}

func TestArnGeneration(t *testing.T) {
Expand Down
20 changes: 16 additions & 4 deletions sbom/spdx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,20 @@ func TestSpdx(t *testing.T) {
err = exporter.Render(&output, &selectedBom)
require.NoError(t, err)

res := output.String()
assert.Contains(t, res, "SPDX-2.3")
assert.Contains(t, res, "\"name\": \"alpine-baselayout\",")
assert.Contains(t, res, "\"cpe:2.3:a:alpine-baselayout:alpine-baselayout:1695795276:aarch64:*:*:*:*:*:*\"")
data := output.String()
assert.Contains(t, data, "SPDX-2.3")

// ensure os package is included
assert.Contains(t, data, "alpine-baselayout")
assert.Contains(t, data, "cpe:2.3:a:alpine-baselayout:alpine-baselayout:1695795276:aarch64:*:*:*:*:*:*")

// ensure python package is included
assert.Contains(t, data, "pip")
assert.Contains(t, data, "cpe:2.3:a:pip_project:pip:21.2.4:*:*:*:*:*:*:*")
assert.Contains(t, data, "pkg:pypi/[email protected]")

// ensure npm package is included
assert.Contains(t, data, "npm")
assert.Contains(t, data, "cpe:2.3:a:npm:npm:10.2.4:*:*:*:*:*:*:*")
assert.Contains(t, data, "pkg:npm/[email protected]")
}
27 changes: 26 additions & 1 deletion sbom/testdata/alpine.json
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,32 @@
]
},
"//local.cnquery.io/run/local-execution/queries/mondoo-sbom-python-packages": {
"python.packages": []
"python.packages": [
{
"name": "pip",
"version": "21.2.4",
"cpes.map": [
"cpe:2.3:a:pip_project:pip:21.2.4:*:*:*:*:*:*:*"
],
"purl": "pkg:pypi/[email protected]",
"file.path": "/opt/lib/python3.9/site-packages/pip-21.2.4.dist-info/METADATA"
}
]
},
"//local.cnquery.io/run/local-execution/queries/mondoo-sbom-npm-packages": {
"npm.packages.list": [
{
"name": "npm",
"files.map": [
"/opt/lib/node_modules/npm/package.json"
],
"cpes.map": [
"cpe:2.3:a:npm:npm:10.2.4:*:*:*:*:*:*:*"
],
"purl": "pkg:npm/[email protected]",
"version": "10.2.4"
}
]
}
}
},
Expand Down

0 comments on commit f797eee

Please sign in to comment.