mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-13 00:00:19 -08:00
feat(docker): add support for scanning Bitnami components (#5062)
* feat(bitnami): add support for scanning Bitnami components Signed-off-by: juan131 <jariza@vmware.com> * chore(deps): bump packageurl-go TypeBitnami is not included in v0.1.1 * feat(spdx): handle orphan packages * fix: update Elastic SPDX Signed-off-by: juan131 <jariza@vmware.com> * Update pkg/fanal/analyzer/sbom/sbom.go Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> * fix: remove useless else Signed-off-by: juan131 <jariza@vmware.com> * call AnalysisResult.Sort() Signed-off-by: knqyf263 <knqyf263@gmail.com> * delete app packages Signed-off-by: knqyf263 <knqyf263@gmail.com> * fix: set the component path to packages Signed-off-by: knqyf263 <knqyf263@gmail.com> * docs: add a comment about continue Signed-off-by: knqyf263 <knqyf263@gmail.com> * chore: bump trivy-db Signed-off-by: knqyf263 <knqyf263@gmail.com> * docs: add Bitnami Signed-off-by: knqyf263 <knqyf263@gmail.com> --------- Signed-off-by: juan131 <jariza@vmware.com> Signed-off-by: knqyf263 <knqyf263@gmail.com> Co-authored-by: knqyf263 <knqyf263@gmail.com> Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
9628b1cbf3
commit
7acc5e8312
1
.github/workflows/semantic-pr.yaml
vendored
1
.github/workflows/semantic-pr.yaml
vendored
@@ -74,6 +74,7 @@ jobs:
|
||||
elixir
|
||||
dart
|
||||
swift
|
||||
bitnami
|
||||
|
||||
os
|
||||
lang
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Google Distroless
|
||||
# Google Distroless Images
|
||||
Trivy supports the following scanners for OS packages.
|
||||
|
||||
| Scanner | Supported |
|
||||
|
||||
@@ -26,7 +26,13 @@ Trivy supports operating systems for
|
||||
| [Photon OS](photon.md) | 1.0, 2.0, 3.0, 4.0 | tndf/yum/rpm |
|
||||
| [Debian GNU/Linux](debian.md) | 7, 8, 9, 10, 11, 12 | apt/dpkg |
|
||||
| [Ubuntu](ubuntu.md) | All versions supported by Canonical | apt/dpkg |
|
||||
|
||||
## Supported container images
|
||||
|
||||
| Container image | Supported Versions | Package Managers |
|
||||
|-----------------------------------------------|-------------------------------------|------------------|
|
||||
| [Google Distroless](google-distroless.md)[^2] | Any | apt/dpkg |
|
||||
| [Bitnami](bitnami.md) | Any | - |
|
||||
|
||||
Each page gives more details.
|
||||
|
||||
|
||||
4
go.mod
4
go.mod
@@ -23,7 +23,7 @@ require (
|
||||
github.com/aquasecurity/table v1.8.0
|
||||
github.com/aquasecurity/testdocker v0.0.0-20230111101738-e741bda259da
|
||||
github.com/aquasecurity/tml v0.6.1
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230828105148-2c9c4da5a321
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230831170347-f732860d4917
|
||||
github.com/aquasecurity/trivy-java-db v0.0.0-20230209231723-7cddb1406728
|
||||
github.com/aquasecurity/trivy-kubernetes v0.5.7-0.20230830063136-fe986af3f10f
|
||||
github.com/aws/aws-sdk-go v1.44.273
|
||||
@@ -74,7 +74,7 @@ require (
|
||||
github.com/opencontainers/image-spec v1.1.0-rc4
|
||||
github.com/openvex/go-vex v0.2.5
|
||||
github.com/owenrumney/go-sarif/v2 v2.2.0
|
||||
github.com/package-url/packageurl-go v0.1.1
|
||||
github.com/package-url/packageurl-go v0.1.2-0.20230812223828-f8bb31c1f10b
|
||||
github.com/samber/lo v1.38.1
|
||||
github.com/saracen/walker v0.1.3
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.7.0
|
||||
|
||||
8
go.sum
8
go.sum
@@ -344,8 +344,8 @@ github.com/aquasecurity/testdocker v0.0.0-20230111101738-e741bda259da h1:pj/adfN
|
||||
github.com/aquasecurity/testdocker v0.0.0-20230111101738-e741bda259da/go.mod h1:852lbQLpK2nCwlR4ZLYIccxYCfoQao6q9Nl6tjz54v8=
|
||||
github.com/aquasecurity/tml v0.6.1 h1:y2ZlGSfrhnn7t4ZJ/0rotuH+v5Jgv6BDDO5jB6A9gwo=
|
||||
github.com/aquasecurity/tml v0.6.1/go.mod h1:OnYMWY5lvI9ejU7yH9LCberWaaTBW7hBFsITiIMY2yY=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230828105148-2c9c4da5a321 h1:oAXkM8x6jMal+6p2XB78+ntPs5LGjxZhtWHdOy4crlg=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230828105148-2c9c4da5a321/go.mod h1:WJ5Qnk5ZNGWvks07GOZe2IOsuXrPfSC5c8hYGOGfrsU=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230831170347-f732860d4917 h1:MQd7h7yUyA8UlUzhjNMzpUX0NpD7jfxmRfSKwp/Ji3E=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20230831170347-f732860d4917/go.mod h1:WJ5Qnk5ZNGWvks07GOZe2IOsuXrPfSC5c8hYGOGfrsU=
|
||||
github.com/aquasecurity/trivy-java-db v0.0.0-20230209231723-7cddb1406728 h1:0eS+V7SXHgqoT99tV1mtMW6HL4HdoB9qGLMCb1fZp8A=
|
||||
github.com/aquasecurity/trivy-java-db v0.0.0-20230209231723-7cddb1406728/go.mod h1:Ldya37FLi0e/5Cjq2T5Bty7cFkzUDwTcPeQua+2M8i8=
|
||||
github.com/aquasecurity/trivy-kubernetes v0.5.7-0.20230830063136-fe986af3f10f h1:KOB3oGBjP+usI88PzDehhJ0AUWoKUCs7wBspcxBAF00=
|
||||
@@ -1459,8 +1459,8 @@ github.com/owenrumney/go-sarif/v2 v2.2.0 h1:1DmZaijK0HBZCR1fgcDSGa7VzYkU9NDmbZ7q
|
||||
github.com/owenrumney/go-sarif/v2 v2.2.0/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w=
|
||||
github.com/owenrumney/squealer v1.1.1 h1:e+fg29IxdNARSc4s7CbYnqVSepm9eOqErLNNNR5XbAs=
|
||||
github.com/owenrumney/squealer v1.1.1/go.mod h1:Q5ekVoyFSG2FlnCVIBGsyk/FSMA/ATv8PtwKIVX7t/o=
|
||||
github.com/package-url/packageurl-go v0.1.1 h1:KTRE0bK3sKbFKAk3yy63DpeskU7Cvs/x/Da5l+RtzyU=
|
||||
github.com/package-url/packageurl-go v0.1.1/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c=
|
||||
github.com/package-url/packageurl-go v0.1.2-0.20230812223828-f8bb31c1f10b h1:mUXbYcE4/ZAh9uto21SUH+FL/RGmD0OGYci9JX66jDc=
|
||||
github.com/package-url/packageurl-go v0.1.2-0.20230812223828-f8bb31c1f10b/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -76,7 +76,6 @@ nav:
|
||||
- CentOS: docs/coverage/os/centos.md
|
||||
- Chainguard: docs/coverage/os/chainguard.md
|
||||
- Debian: docs/coverage/os/debian.md
|
||||
- Google Distroless: docs/coverage/os/google-distroless.md
|
||||
- Oracle Linux: docs/coverage/os/oracle.md
|
||||
- Photon OS: docs/coverage/os/photon.md
|
||||
- Red Hat: docs/coverage/os/rhel.md
|
||||
@@ -84,6 +83,8 @@ nav:
|
||||
- SUSE: docs/coverage/os/suse.md
|
||||
- Ubuntu: docs/coverage/os/ubuntu.md
|
||||
- Wolfi: docs/coverage/os/wolfi.md
|
||||
- Google Distroless (Images): docs/coverage/os/google-distroless.md
|
||||
- Bitnami (Images): docs/coverage/os/bitnami.md
|
||||
- Language:
|
||||
- Overview: docs/coverage/language/index.md
|
||||
- C/C++: docs/coverage/language/c.md
|
||||
|
||||
@@ -65,6 +65,9 @@ func NewDriver(libType string) (Driver, bool) {
|
||||
// https://www.swift.org/package-manager/#importing-dependencies
|
||||
ecosystem = vulnerability.Swift
|
||||
comparer = compare.GenericComparer{}
|
||||
case ftypes.Bitnami:
|
||||
ecosystem = vulnerability.Bitnami
|
||||
comparer = compare.GenericComparer{}
|
||||
case ftypes.Cocoapods:
|
||||
// CocoaPods uses RubyGems version specifiers
|
||||
// https://guides.cocoapods.org/making/making-a-cocoapod.html#cocoapods-versioning-specifics
|
||||
|
||||
@@ -194,7 +194,10 @@ func (r *AnalysisResult) Sort() {
|
||||
|
||||
// Language-specific packages
|
||||
sort.Slice(r.Applications, func(i, j int) bool {
|
||||
return r.Applications[i].FilePath < r.Applications[j].FilePath
|
||||
if r.Applications[i].FilePath != r.Applications[j].FilePath {
|
||||
return r.Applications[i].FilePath < r.Applications[j].FilePath
|
||||
}
|
||||
return r.Applications[i].Type < r.Applications[j].Type
|
||||
})
|
||||
|
||||
for _, app := range r.Applications {
|
||||
|
||||
@@ -9,7 +9,9 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/aquasecurity/trivy/pkg/sbom"
|
||||
"github.com/aquasecurity/trivy/pkg/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -39,26 +41,12 @@ func (a sbomAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (
|
||||
return nil, xerrors.Errorf("SBOM decode error: %w", err)
|
||||
}
|
||||
|
||||
// For Bitnami images
|
||||
// Bitnami images
|
||||
// SPDX files are located under the /opt/bitnami/<component> directory
|
||||
// and named with the pattern .spdx-<component>.spdx
|
||||
// ref: https://github.com/bitnami/vulndb#how-to-consume-this-cve-feed
|
||||
if strings.HasPrefix(input.FilePath, "opt/bitnami/") {
|
||||
dir, file := path.Split(input.FilePath)
|
||||
bin := strings.TrimPrefix(file, ".spdx-")
|
||||
bin = strings.TrimSuffix(bin, ".spdx")
|
||||
binPath := path.Join(input.FilePath, "../bin", bin)
|
||||
for i, app := range bom.Applications {
|
||||
// Replace the SBOM path with the binary path
|
||||
bom.Applications[i].FilePath = binPath
|
||||
|
||||
for j, pkg := range app.Libraries {
|
||||
if pkg.FilePath == "" {
|
||||
continue
|
||||
}
|
||||
// Set the absolute path since SBOM in Bitnami images contain a relative path
|
||||
// e.g. modules/apm/elastic-apm-agent-1.36.0.jar
|
||||
// => opt/bitnami/elasticsearch/modules/apm/elastic-apm-agent-1.36.0.jar
|
||||
bom.Applications[i].Libraries[j].FilePath = path.Join(dir, pkg.FilePath)
|
||||
}
|
||||
}
|
||||
handleBitnamiImages(path.Dir(input.FilePath), bom)
|
||||
}
|
||||
|
||||
return &analyzer.AnalysisResult{
|
||||
@@ -83,3 +71,22 @@ func (a sbomAnalyzer) Type() analyzer.Type {
|
||||
func (a sbomAnalyzer) Version() int {
|
||||
return version
|
||||
}
|
||||
|
||||
func handleBitnamiImages(componentPath string, bom types.SBOM) {
|
||||
for i, app := range bom.Applications {
|
||||
if app.Type == ftypes.Bitnami {
|
||||
// Set the component dir path to the application
|
||||
bom.Applications[i].FilePath = componentPath
|
||||
// Either Application.FilePath or Application.Libraries[].FilePath should be set
|
||||
continue
|
||||
}
|
||||
|
||||
for j, pkg := range app.Libraries {
|
||||
// Set the absolute path since SBOM in Bitnami images contain a relative path
|
||||
// e.g. modules/apm/elastic-apm-agent-1.36.0.jar
|
||||
// => opt/bitnami/elasticsearch/modules/apm/elastic-apm-agent-1.36.0.jar
|
||||
// If the file path is empty, the file path will be set to the component dir path.
|
||||
bom.Applications[i].Libraries[j].FilePath = path.Join(componentPath, pkg.FilePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,38 +2,92 @@ package sbom
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_sbomAnalyzer_Analyze(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
file string
|
||||
want *analyzer.AnalysisResult
|
||||
wantErr require.ErrorAssertionFunc
|
||||
name string
|
||||
file string
|
||||
filePath string
|
||||
want *analyzer.AnalysisResult
|
||||
wantErr require.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "valid spdx file",
|
||||
file: "testdata/spdx.json",
|
||||
name: "valid elasticsearch spdx file",
|
||||
file: "testdata/elasticsearch.spdx.json",
|
||||
filePath: "opt/bitnami/elasticsearch/.spdx-elasticsearch.spdx",
|
||||
want: &analyzer.AnalysisResult{
|
||||
Applications: []types.Application{
|
||||
{
|
||||
Type: types.Jar,
|
||||
FilePath: "opt/bitnami/bin/elasticsearch",
|
||||
Type: types.Jar,
|
||||
Libraries: types.Packages{
|
||||
{
|
||||
FilePath: "opt/bitnami/modules/apm/elastic-apm-agent-1.36.0.jar",
|
||||
Name: "co.elastic.apm:apm-agent",
|
||||
Version: "1.36.0",
|
||||
Ref: "pkg:maven/co.elastic.apm/apm-agent@1.36.0",
|
||||
FilePath: "opt/bitnami/elasticsearch",
|
||||
},
|
||||
{
|
||||
Name: "co.elastic.apm:apm-agent-cached-lookup-key",
|
||||
Version: "1.36.0",
|
||||
Ref: "pkg:maven/co.elastic.apm/apm-agent-cached-lookup-key@1.36.0",
|
||||
FilePath: "opt/bitnami/elasticsearch",
|
||||
},
|
||||
{
|
||||
Name: "co.elastic.apm:apm-agent-common",
|
||||
Version: "1.36.0",
|
||||
Ref: "pkg:maven/co.elastic.apm/apm-agent-common@1.36.0",
|
||||
FilePath: "opt/bitnami/elasticsearch",
|
||||
},
|
||||
{
|
||||
Name: "co.elastic.apm:apm-agent-core",
|
||||
Version: "1.36.0",
|
||||
Ref: "pkg:maven/co.elastic.apm/apm-agent-core@1.36.0",
|
||||
FilePath: "opt/bitnami/elasticsearch",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: types.Bitnami,
|
||||
FilePath: "opt/bitnami/elasticsearch",
|
||||
Libraries: types.Packages{
|
||||
{
|
||||
Name: "elasticsearch",
|
||||
Version: "8.9.1",
|
||||
Ref: "pkg:bitnami/elasticsearch@8.9.1?arch=arm64",
|
||||
Arch: "arm64",
|
||||
Licenses: []string{"Elastic-2.0"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: require.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid elasticsearch cdx file",
|
||||
file: "testdata/cdx.json",
|
||||
filePath: "opt/bitnami/elasticsearch/.spdx-elasticsearch.cdx",
|
||||
want: &analyzer.AnalysisResult{
|
||||
Applications: []types.Application{
|
||||
{
|
||||
Type: types.Jar,
|
||||
Libraries: types.Packages{
|
||||
{
|
||||
FilePath: "opt/bitnami/elasticsearch/modules/apm/elastic-apm-agent-1.36.0.jar",
|
||||
Name: "co.elastic.apm:apm-agent",
|
||||
Version: "1.36.0",
|
||||
Ref: "pkg:maven/co.elastic.apm/apm-agent@1.36.0",
|
||||
},
|
||||
{
|
||||
FilePath: "opt/bitnami/modules/apm/elastic-apm-agent-1.36.0.jar",
|
||||
FilePath: "opt/bitnami/elasticsearch/modules/apm/elastic-apm-agent-1.36.0.jar",
|
||||
Name: "co.elastic.apm:apm-agent-cached-lookup-key",
|
||||
Version: "1.36.0",
|
||||
Ref: "pkg:maven/co.elastic.apm/apm-agent-cached-lookup-key@1.36.0",
|
||||
@@ -45,25 +99,38 @@ func Test_sbomAnalyzer_Analyze(t *testing.T) {
|
||||
wantErr: require.NoError,
|
||||
},
|
||||
{
|
||||
name: "valid cdx file",
|
||||
file: "testdata/cdx.json",
|
||||
name: "valid postgresql spdx file",
|
||||
file: "testdata/postgresql.spdx.json",
|
||||
filePath: "opt/bitnami/postgresql/.spdx-postgresql.spdx",
|
||||
want: &analyzer.AnalysisResult{
|
||||
Applications: []types.Application{
|
||||
{
|
||||
Type: types.Jar,
|
||||
FilePath: "opt/bitnami/bin/elasticsearch",
|
||||
Type: types.Bitnami,
|
||||
FilePath: "opt/bitnami/postgresql",
|
||||
Libraries: types.Packages{
|
||||
{
|
||||
FilePath: "opt/bitnami/modules/apm/elastic-apm-agent-1.36.0.jar",
|
||||
Name: "co.elastic.apm:apm-agent",
|
||||
Version: "1.36.0",
|
||||
Ref: "pkg:maven/co.elastic.apm/apm-agent@1.36.0",
|
||||
Name: "gdal",
|
||||
Version: "3.7.1",
|
||||
Ref: "pkg:bitnami/gdal@3.7.1",
|
||||
Licenses: []string{"MIT"},
|
||||
},
|
||||
{
|
||||
FilePath: "opt/bitnami/modules/apm/elastic-apm-agent-1.36.0.jar",
|
||||
Name: "co.elastic.apm:apm-agent-cached-lookup-key",
|
||||
Version: "1.36.0",
|
||||
Ref: "pkg:maven/co.elastic.apm/apm-agent-cached-lookup-key@1.36.0",
|
||||
Name: "geos",
|
||||
Version: "3.8.3",
|
||||
Ref: "pkg:bitnami/geos@3.8.3",
|
||||
Licenses: []string{"LGPL-2.1-only"},
|
||||
},
|
||||
{
|
||||
Name: "postgresql",
|
||||
Version: "15.3.0",
|
||||
Ref: "pkg:bitnami/postgresql@15.3.0",
|
||||
Licenses: []string{"PostgreSQL"},
|
||||
},
|
||||
{
|
||||
Name: "proj",
|
||||
Version: "6.3.2",
|
||||
Ref: "pkg:bitnami/proj@6.3.2",
|
||||
Licenses: []string{"MIT"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -72,10 +139,11 @@ func Test_sbomAnalyzer_Analyze(t *testing.T) {
|
||||
wantErr: require.NoError,
|
||||
},
|
||||
{
|
||||
name: "invalid spdx file",
|
||||
file: "testdata/invalid_spdx.json",
|
||||
want: nil,
|
||||
wantErr: require.Error,
|
||||
name: "invalid spdx file",
|
||||
file: "testdata/invalid_spdx.json",
|
||||
filePath: "opt/bitnami/elasticsearch/.spdx-elasticsearch.spdx",
|
||||
want: nil,
|
||||
wantErr: require.Error,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@@ -86,10 +154,14 @@ func Test_sbomAnalyzer_Analyze(t *testing.T) {
|
||||
|
||||
a := sbomAnalyzer{}
|
||||
got, err := a.Analyze(context.Background(), analyzer.AnalysisInput{
|
||||
FilePath: "opt/bitnami/.spdx-elasticsearch.spdx",
|
||||
FilePath: tt.filePath,
|
||||
Content: f,
|
||||
})
|
||||
tt.wantErr(t, err)
|
||||
|
||||
if got != nil {
|
||||
got.Sort()
|
||||
}
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
|
||||
150
pkg/fanal/analyzer/sbom/testdata/elasticsearch.spdx.json
vendored
Normal file
150
pkg/fanal/analyzer/sbom/testdata/elasticsearch.spdx.json
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
{
|
||||
"SPDXID": "SPDXRef-elasticsearch",
|
||||
"spdxVersion": "SPDX-2.3",
|
||||
"creationInfo": {
|
||||
"created": "2023-08-18T20:09:40.708Z",
|
||||
"creators": [
|
||||
"Organization: VMware, Inc."
|
||||
]
|
||||
},
|
||||
"name": "SPDX document for Elasticsearch 8.9.1",
|
||||
"dataLicense": "CC0-1.0",
|
||||
"documentDescribes": [
|
||||
"SPDXRef-elasticsearch"
|
||||
],
|
||||
"documentNamespace": "elasticsearch-8.9.1",
|
||||
"packages": [
|
||||
{
|
||||
"SPDXID": "SPDXRef-elasticsearch",
|
||||
"name": "Elasticsearch",
|
||||
"versionInfo": "8.9.1",
|
||||
"downloadLocation": "https://github.com/elastic/elasticsearch/archive/v8.9.1.tar.gz",
|
||||
"licenseConcluded": "Elastic-2.0",
|
||||
"licenseDeclared": "Elastic-2.0",
|
||||
"filesAnalyzed": false,
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "SECURITY",
|
||||
"referenceType": "cpe23Type",
|
||||
"referenceLocator": "cpe:2.3:*:elastic:elasticsearch:8.9.1:*:*:*:*:*:*:*"
|
||||
},
|
||||
{
|
||||
"referenceCategory": "PACKAGE_MANAGER",
|
||||
"referenceType": "purl",
|
||||
"referenceLocator": "pkg:bitnami/elasticsearch@8.9.1?arch=arm64"
|
||||
}
|
||||
],
|
||||
"copyrightText": "NOASSERTION"
|
||||
},
|
||||
{
|
||||
"name": "jar",
|
||||
"SPDXID": "SPDXRef-Application-150e605f5f17224d",
|
||||
"downloadLocation": "NONE",
|
||||
"sourceInfo": "Java",
|
||||
"copyrightText": "NOASSERTION",
|
||||
"licenseConcluded": "NOASSERTION",
|
||||
"licenseDeclared": "NOASSERTION",
|
||||
"filesAnalyzed": false
|
||||
},
|
||||
{
|
||||
"name": "co.elastic.apm:apm-agent",
|
||||
"SPDXID": "SPDXRef-Package-f0db45781e6813a1",
|
||||
"versionInfo": "1.36.0",
|
||||
"supplier": "NOASSERTION",
|
||||
"downloadLocation": "NONE",
|
||||
"licenseConcluded": "NONE",
|
||||
"licenseDeclared": "NONE",
|
||||
"copyrightText": "NOASSERTION",
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "PACKAGE_MANAGER",
|
||||
"referenceType": "purl",
|
||||
"referenceLocator": "pkg:maven/co.elastic.apm/apm-agent@1.36.0"
|
||||
}
|
||||
],
|
||||
"filesAnalyzed": false
|
||||
},
|
||||
{
|
||||
"name": "co.elastic.apm:apm-agent-cached-lookup-key",
|
||||
"SPDXID": "SPDXRef-Package-efe22bf5916f985f",
|
||||
"versionInfo": "1.36.0",
|
||||
"supplier": "NOASSERTION",
|
||||
"downloadLocation": "NONE",
|
||||
"licenseConcluded": "NONE",
|
||||
"licenseDeclared": "NONE",
|
||||
"copyrightText": "NOASSERTION",
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "PACKAGE_MANAGER",
|
||||
"referenceType": "purl",
|
||||
"referenceLocator": "pkg:maven/co.elastic.apm/apm-agent-cached-lookup-key@1.36.0"
|
||||
}
|
||||
],
|
||||
"filesAnalyzed": false
|
||||
},
|
||||
{
|
||||
"name": "co.elastic.apm:apm-agent-common",
|
||||
"SPDXID": "SPDXRef-Package-33d86d2d11abe114",
|
||||
"versionInfo": "1.36.0",
|
||||
"supplier": "NOASSERTION",
|
||||
"downloadLocation": "NONE",
|
||||
"licenseConcluded": "NONE",
|
||||
"licenseDeclared": "NONE",
|
||||
"copyrightText": "NOASSERTION",
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "PACKAGE_MANAGER",
|
||||
"referenceType": "purl",
|
||||
"referenceLocator": "pkg:maven/co.elastic.apm/apm-agent-common@1.36.0"
|
||||
}
|
||||
],
|
||||
"filesAnalyzed": false
|
||||
},
|
||||
{
|
||||
"name": "co.elastic.apm:apm-agent-core",
|
||||
"SPDXID": "SPDXRef-Package-b905fcf69ca61281",
|
||||
"versionInfo": "1.36.0",
|
||||
"supplier": "NOASSERTION",
|
||||
"downloadLocation": "NONE",
|
||||
"licenseConcluded": "NONE",
|
||||
"licenseDeclared": "NONE",
|
||||
"copyrightText": "NOASSERTION",
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "PACKAGE_MANAGER",
|
||||
"referenceType": "purl",
|
||||
"referenceLocator": "pkg:maven/co.elastic.apm/apm-agent-core@1.36.0"
|
||||
}
|
||||
],
|
||||
"filesAnalyzed": false
|
||||
}
|
||||
],
|
||||
"files": [],
|
||||
"relationships": [
|
||||
{
|
||||
"spdxElementId": "SPDXRef-elasticsearch",
|
||||
"relationshipType": "CONTAINS",
|
||||
"relatedSpdxElement": "SPDXRef-Application-150e605f5f17224d"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Application-150e605f5f17224d",
|
||||
"relatedSpdxElement": "SPDXRef-Package-f0db45781e6813a1",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Application-150e605f5f17224d",
|
||||
"relatedSpdxElement": "SPDXRef-Package-efe22bf5916f985f",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Application-150e605f5f17224d",
|
||||
"relatedSpdxElement": "SPDXRef-Package-33d86d2d11abe114",
|
||||
"relationshipType": "CONTAINS"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-Application-150e605f5f17224d",
|
||||
"relatedSpdxElement": "SPDXRef-Package-b905fcf69ca61281",
|
||||
"relationshipType": "CONTAINS"
|
||||
}
|
||||
]
|
||||
}
|
||||
120
pkg/fanal/analyzer/sbom/testdata/postgresql.spdx.json
vendored
Normal file
120
pkg/fanal/analyzer/sbom/testdata/postgresql.spdx.json
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
{
|
||||
"SPDXID": "SPDXRef-postgresql",
|
||||
"spdxVersion": "SPDX-2.3",
|
||||
"creationInfo": {
|
||||
"created": "2023-07-13T19:24:23.609Z",
|
||||
"creators": [
|
||||
"Organization: VMware, Inc."
|
||||
]
|
||||
},
|
||||
"name": "SPDX document for PostgreSQL 15.3.0",
|
||||
"dataLicense": "CC0-1.0",
|
||||
"documentDescribes": [
|
||||
"SPDXRef-postgresql"
|
||||
],
|
||||
"documentNamespace": "postgresql-15.3.0",
|
||||
"packages": [
|
||||
{
|
||||
"SPDXID": "SPDXRef-postgresql",
|
||||
"name": "PostgreSQL",
|
||||
"versionInfo": "15.3.0",
|
||||
"downloadLocation": "https://ftp.postgresql.org/pub/source/v15.3/postgresql-15.3.tar.gz",
|
||||
"licenseConcluded": "PostgreSQL",
|
||||
"licenseDeclared": "PostgreSQL",
|
||||
"filesAnalyzed": false,
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "SECURITY",
|
||||
"referenceType": "cpe23Type",
|
||||
"referenceLocator": "cpe:2.3:*:postgresql:postgresql:15.3.0:*:*:*:*:*:*:*"
|
||||
},
|
||||
{
|
||||
"referenceCategory": "PACKAGE-MANAGER",
|
||||
"referenceType": "purl",
|
||||
"referenceLocator": "pkg:bitnami/postgresql@15.3.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"SPDXID": "SPDXRef-geos",
|
||||
"name": "GEOS",
|
||||
"versionInfo": "3.8.3",
|
||||
"downloadLocation": "https://github.com/libgeos/geos/archive/3.8.3.tar.gz",
|
||||
"licenseConcluded": "LGPL-2.1-only",
|
||||
"licenseDeclared": "LGPL-2.1-only",
|
||||
"filesAnalyzed": false,
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "SECURITY",
|
||||
"referenceType": "cpe23Type",
|
||||
"referenceLocator": "cpe:2.3:*:libgeos:geos:3.8.3:*:*:*:*:*:*:*"
|
||||
},
|
||||
{
|
||||
"referenceCategory": "PACKAGE-MANAGER",
|
||||
"referenceType": "purl",
|
||||
"referenceLocator": "pkg:bitnami/geos@3.8.3"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"SPDXID": "SPDXRef-proj",
|
||||
"name": "Proj",
|
||||
"versionInfo": "6.3.2",
|
||||
"downloadLocation": "https://github.com/OSGeo/PROJ/archive/6.3.2.tar.gz",
|
||||
"licenseConcluded": "MIT",
|
||||
"licenseDeclared": "MIT",
|
||||
"filesAnalyzed": false,
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "SECURITY",
|
||||
"referenceType": "cpe23Type",
|
||||
"referenceLocator": "cpe:2.3:*:proj:proj:6.3.2:*:*:*:*:*:*:*"
|
||||
},
|
||||
{
|
||||
"referenceCategory": "PACKAGE-MANAGER",
|
||||
"referenceType": "purl",
|
||||
"referenceLocator": "pkg:bitnami/proj@6.3.2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"SPDXID": "SPDXRef-gdal",
|
||||
"name": "GDAL",
|
||||
"versionInfo": "3.7.1",
|
||||
"downloadLocation": "https://github.com/OSGeo/gdal/releases/download/v3.7.1/gdal-3.7.1.tar.gz",
|
||||
"licenseConcluded": "MIT",
|
||||
"licenseDeclared": "MIT",
|
||||
"filesAnalyzed": false,
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "SECURITY",
|
||||
"referenceType": "cpe23Type",
|
||||
"referenceLocator": "cpe:2.3:*:osgeo:gdal:3.7.1:*:*:*:*:*:*:*"
|
||||
},
|
||||
{
|
||||
"referenceCategory": "PACKAGE-MANAGER",
|
||||
"referenceType": "purl",
|
||||
"referenceLocator": "pkg:bitnami/gdal@3.7.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"files": [],
|
||||
"relationships": [
|
||||
{
|
||||
"spdxElementId": "SPDXRef-postgresql",
|
||||
"relationshipType": "CONTAINS",
|
||||
"relatedSpdxElement": "SPDXRef-geos"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-postgresql",
|
||||
"relationshipType": "CONTAINS",
|
||||
"relatedSpdxElement": "SPDXRef-proj"
|
||||
},
|
||||
{
|
||||
"spdxElementId": "SPDXRef-postgresql",
|
||||
"relationshipType": "CONTAINS",
|
||||
"relatedSpdxElement": "SPDXRef-gdal"
|
||||
}
|
||||
]
|
||||
}
|
||||
97
pkg/fanal/analyzer/sbom/testdata/spdx.json
vendored
97
pkg/fanal/analyzer/sbom/testdata/spdx.json
vendored
@@ -1,97 +0,0 @@
|
||||
{
|
||||
"SPDXID": "SPDXRef-elasticsearch",
|
||||
"spdxVersion": "SPDX-2.3",
|
||||
"creationInfo": {
|
||||
"created": "2023-05-17T15:59:30.511Z",
|
||||
"creators": [
|
||||
"Organization: VMware, Inc."
|
||||
]
|
||||
},
|
||||
"name": "SPDX document for Elasticsearch 8.7.1",
|
||||
"dataLicense": "CC0-1.0",
|
||||
"documentDescribes": [
|
||||
"SPDXRef-elasticsearch"
|
||||
],
|
||||
"documentNamespace": "elasticsearch-8.7.1",
|
||||
"packages": [
|
||||
{
|
||||
"SPDXID": "SPDXRef-elasticsearch",
|
||||
"name": "Elasticsearch",
|
||||
"versionInfo": "8.7.1",
|
||||
"downloadLocation": "https://github.com/elastic/elasticsearch/archive/v8.7.1.tar.gz",
|
||||
"licenseConcluded": "Elastic-2.0",
|
||||
"licenseDeclared": "Elastic-2.0",
|
||||
"filesAnalyzed": false,
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "SECURITY",
|
||||
"referenceType": "cpe23Type",
|
||||
"referenceLocator": "cpe:2.3:*:elasticsearch:elasticsearch:8.7.1:*:*:*:*:*:*:*"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "co.elastic.apm:apm-agent",
|
||||
"SPDXID": "SPDXRef-Package-d6465ccdd5385c16",
|
||||
"versionInfo": "1.36.0",
|
||||
"supplier": "NOASSERTION",
|
||||
"downloadLocation": "NONE",
|
||||
"licenseConcluded": "NONE",
|
||||
"licenseDeclared": "NONE",
|
||||
"copyrightText": "",
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "PACKAGE-MANAGER",
|
||||
"referenceType": "purl",
|
||||
"referenceLocator": "pkg:maven/co.elastic.apm/apm-agent@1.36.0"
|
||||
}
|
||||
],
|
||||
"primaryPackagePurpose": "LIBRARY",
|
||||
"files": [
|
||||
{
|
||||
"fileName":"modules/apm/elastic-apm-agent-1.36.0.jar",
|
||||
"SPDXID": "SPDXRef-File-4d457bf4ff3526ea",
|
||||
"checksums": [
|
||||
{
|
||||
"algorithm": "SHA1",
|
||||
"checksumValue": "d2a9ad9b159eb650d25add9395c4f4198f200066"
|
||||
}
|
||||
],
|
||||
"copyrightText": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "co.elastic.apm:apm-agent-cached-lookup-key",
|
||||
"SPDXID": "SPDXRef-Package-8e3a2cf58d7bd790",
|
||||
"versionInfo": "1.36.0",
|
||||
"supplier": "NOASSERTION",
|
||||
"downloadLocation": "NONE",
|
||||
"licenseConcluded": "NONE",
|
||||
"licenseDeclared": "NONE",
|
||||
"copyrightText": "",
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "PACKAGE-MANAGER",
|
||||
"referenceType": "purl",
|
||||
"referenceLocator": "pkg:maven/co.elastic.apm/apm-agent-cached-lookup-key@1.36.0"
|
||||
}
|
||||
],
|
||||
"primaryPackagePurpose": "LIBRARY",
|
||||
"files": [
|
||||
{
|
||||
"fileName": "modules/apm/elastic-apm-agent-1.36.0.jar",
|
||||
"SPDXID": "SPDXRef-File-4d457bf4ff3526ea",
|
||||
"checksums": [
|
||||
{
|
||||
"algorithm": "SHA1",
|
||||
"checksumValue": "d2a9ad9b159eb650d25add9395c4f4198f200066"
|
||||
}
|
||||
],
|
||||
"copyrightText": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"files": []
|
||||
}
|
||||
@@ -34,6 +34,7 @@ const (
|
||||
Swift = "swift"
|
||||
Pub = "pub"
|
||||
Hex = "hex"
|
||||
Bitnami = "bitnami"
|
||||
|
||||
// Config files
|
||||
YAML = "yaml"
|
||||
|
||||
@@ -129,6 +129,8 @@ func (p *PackageURL) PackageType() string {
|
||||
return ftypes.Conan
|
||||
case TypeDart: // TODO: replace with packageurl.TypeDart once they add it.
|
||||
return ftypes.Pub
|
||||
case packageurl.TypeBitnami:
|
||||
return ftypes.Bitnami
|
||||
}
|
||||
return p.Type
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ func TestMarshaler_CoreComponent(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
BOMRef: "pkg:oci/kube-apiserver@sha256:18e61c783b41758dd391ab901366ec3546b26fae00eef7e223d1f94da808e02f?repository_url=k8s.gcr.io%2Fkube-apiserver&arch=",
|
||||
BOMRef: "pkg:oci/kube-apiserver@sha256%3A18e61c783b41758dd391ab901366ec3546b26fae00eef7e223d1f94da808e02f?arch=&repository_url=k8s.gcr.io%2Fkube-apiserver",
|
||||
Hashes: &[]cdx.Hash{
|
||||
{
|
||||
Algorithm: "SHA-256",
|
||||
@@ -303,7 +303,7 @@ func TestMarshaler_CoreComponent(t *testing.T) {
|
||||
Type: "container",
|
||||
Name: "k8s.gcr.io/kube-apiserver",
|
||||
Version: "sha256:18e61c783b41758dd391ab901366ec3546b26fae00eef7e223d1f94da808e02f",
|
||||
PackageURL: "pkg:oci/kube-apiserver@sha256:18e61c783b41758dd391ab901366ec3546b26fae00eef7e223d1f94da808e02f?repository_url=k8s.gcr.io%2Fkube-apiserver&arch=",
|
||||
PackageURL: "pkg:oci/kube-apiserver@sha256%3A18e61c783b41758dd391ab901366ec3546b26fae00eef7e223d1f94da808e02f?arch=&repository_url=k8s.gcr.io%2Fkube-apiserver",
|
||||
Properties: &[]cdx.Property{
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgID",
|
||||
@@ -326,7 +326,7 @@ func TestMarshaler_CoreComponent(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Ref: "3ff14136-e09f-4df9-80ea-000000000003",
|
||||
Dependencies: &[]string{"pkg:oci/kube-apiserver@sha256:18e61c783b41758dd391ab901366ec3546b26fae00eef7e223d1f94da808e02f?repository_url=k8s.gcr.io%2Fkube-apiserver&arch="},
|
||||
Dependencies: &[]string{"pkg:oci/kube-apiserver@sha256%3A18e61c783b41758dd391ab901366ec3546b26fae00eef7e223d1f94da808e02f?arch=&repository_url=k8s.gcr.io%2Fkube-apiserver"},
|
||||
},
|
||||
{
|
||||
Ref: "3ff14136-e09f-4df9-80ea-000000000004",
|
||||
@@ -355,7 +355,7 @@ func TestMarshaler_CoreComponent(t *testing.T) {
|
||||
Dependencies: &noDepRefs,
|
||||
},
|
||||
{
|
||||
Ref: "pkg:oci/kube-apiserver@sha256:18e61c783b41758dd391ab901366ec3546b26fae00eef7e223d1f94da808e02f?repository_url=k8s.gcr.io%2Fkube-apiserver&arch=",
|
||||
Ref: "pkg:oci/kube-apiserver@sha256%3A18e61c783b41758dd391ab901366ec3546b26fae00eef7e223d1f94da808e02f?arch=&repository_url=k8s.gcr.io%2Fkube-apiserver",
|
||||
Dependencies: &noDepRefs,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -191,8 +191,8 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
},
|
||||
Component: &cdx.Component{
|
||||
Type: cdx.ComponentTypeContainer,
|
||||
BOMRef: "pkg:oci/rails@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177?repository_url=index.docker.io%2Flibrary%2Frails&arch=arm64",
|
||||
PackageURL: "pkg:oci/rails@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177?repository_url=index.docker.io%2Flibrary%2Frails&arch=arm64",
|
||||
BOMRef: "pkg:oci/rails@sha256%3Aa27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177?arch=arm64&repository_url=index.docker.io%2Flibrary%2Frails",
|
||||
PackageURL: "pkg:oci/rails@sha256%3Aa27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177?arch=arm64&repository_url=index.docker.io%2Flibrary%2Frails",
|
||||
Name: "rails:latest",
|
||||
Properties: &[]cdx.Property{
|
||||
{
|
||||
@@ -464,7 +464,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Dependencies: lo.ToPtr([]string{}),
|
||||
},
|
||||
{
|
||||
Ref: "pkg:oci/rails@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177?repository_url=index.docker.io%2Flibrary%2Frails&arch=arm64",
|
||||
Ref: "pkg:oci/rails@sha256%3Aa27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177?arch=arm64&repository_url=index.docker.io%2Flibrary%2Frails",
|
||||
Dependencies: &[]string{
|
||||
"3ff14136-e09f-4df9-80ea-000000000002",
|
||||
"3ff14136-e09f-4df9-80ea-000000000003",
|
||||
@@ -823,7 +823,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
BOMRef: "pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&epoch=1&distro=centos-8.3.2011",
|
||||
BOMRef: "pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&distro=centos-8.3.2011&epoch=1",
|
||||
Type: cdx.ComponentTypeLibrary,
|
||||
Name: "acl",
|
||||
Version: "2.2.53-1.el8",
|
||||
@@ -834,7 +834,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
PackageURL: "pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&epoch=1&distro=centos-8.3.2011",
|
||||
PackageURL: "pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&distro=centos-8.3.2011&epoch=1",
|
||||
Properties: &[]cdx.Property{
|
||||
{
|
||||
Name: "aquasecurity:trivy:PkgID",
|
||||
@@ -923,7 +923,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
{
|
||||
Ref: "3ff14136-e09f-4df9-80ea-000000000003",
|
||||
Dependencies: &[]string{
|
||||
"pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&epoch=1&distro=centos-8.3.2011",
|
||||
"pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&distro=centos-8.3.2011&epoch=1",
|
||||
// Trivy is unable to identify the direct OS packages as of today.
|
||||
"pkg:rpm/centos/glibc@2.28-151.el8?arch=aarch64&distro=centos-8.3.2011",
|
||||
},
|
||||
@@ -937,7 +937,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
Dependencies: lo.ToPtr([]string{}),
|
||||
},
|
||||
{
|
||||
Ref: "pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&epoch=1&distro=centos-8.3.2011",
|
||||
Ref: "pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&distro=centos-8.3.2011&epoch=1",
|
||||
Dependencies: &[]string{
|
||||
"pkg:rpm/centos/glibc@2.28-151.el8?arch=aarch64&distro=centos-8.3.2011",
|
||||
},
|
||||
|
||||
@@ -209,7 +209,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
{
|
||||
Category: tspdx.CategoryPackageManager,
|
||||
RefType: tspdx.RefTypePurl,
|
||||
Locator: "pkg:oci/rails@sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177?repository_url=index.docker.io%2Flibrary%2Frails&arch=arm64",
|
||||
Locator: "pkg:oci/rails@sha256%3Aa27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177?arch=arm64&repository_url=index.docker.io%2Flibrary%2Frails",
|
||||
},
|
||||
},
|
||||
PackageAttributionTexts: []string{
|
||||
@@ -370,7 +370,7 @@ func TestMarshaler_Marshal(t *testing.T) {
|
||||
{
|
||||
Category: tspdx.CategoryPackageManager,
|
||||
RefType: tspdx.RefTypePurl,
|
||||
Locator: "pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&epoch=1&distro=centos-8.3.2011",
|
||||
Locator: "pkg:rpm/centos/acl@2.2.53-1.el8?arch=aarch64&distro=centos-8.3.2011&epoch=1",
|
||||
},
|
||||
},
|
||||
PackageSourceInfo: "built package from: acl 1:2.2.53-1.el8",
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
version "github.com/knqyf263/go-rpm-version"
|
||||
@@ -73,6 +74,9 @@ func (s *SPDX) unmarshal(spdxDocument *spdx.Document) error {
|
||||
packageSPDXIdentifierMap := createPackageSPDXIdentifierMap(spdxDocument.Packages)
|
||||
packageFilePaths := getPackageFilePaths(spdxDocument)
|
||||
|
||||
// Hold packages that are not processed by relationships
|
||||
orphanPkgs := createPackageSPDXIdentifierMap(spdxDocument.Packages)
|
||||
|
||||
relationships := lo.Filter(spdxDocument.Relationships, func(rel *spdx.Relationship, _ int) bool {
|
||||
// Skip the DESCRIBES relationship.
|
||||
return rel.Relationship != common.TypeRelationshipDescribe && rel.Relationship != "DESCRIBE"
|
||||
@@ -90,8 +94,8 @@ func (s *SPDX) unmarshal(spdxDocument *spdx.Document) error {
|
||||
// - Python package A
|
||||
// - Python package B
|
||||
for _, rel := range relationships {
|
||||
pkgA := packageSPDXIdentifierMap[string(rel.RefA.ElementRefID)]
|
||||
pkgB := packageSPDXIdentifierMap[string(rel.RefB.ElementRefID)]
|
||||
pkgA := packageSPDXIdentifierMap[rel.RefA.ElementRefID]
|
||||
pkgB := packageSPDXIdentifierMap[rel.RefB.ElementRefID]
|
||||
|
||||
if pkgA == nil || pkgB == nil {
|
||||
// Skip the missing pkg relationship.
|
||||
@@ -102,6 +106,7 @@ func (s *SPDX) unmarshal(spdxDocument *spdx.Document) error {
|
||||
// Relationship: root package => OS
|
||||
case isOperatingSystem(pkgB.PackageSPDXIdentifier):
|
||||
s.SBOM.OS = parseOS(*pkgB)
|
||||
delete(orphanPkgs, pkgB.PackageSPDXIdentifier)
|
||||
// Relationship: OS => OS package
|
||||
case isOperatingSystem(pkgA.PackageSPDXIdentifier):
|
||||
pkg, _, err := parsePkg(*pkgB, packageFilePaths)
|
||||
@@ -111,6 +116,7 @@ func (s *SPDX) unmarshal(spdxDocument *spdx.Document) error {
|
||||
return xerrors.Errorf("failed to parse os package: %w", err)
|
||||
}
|
||||
osPkgs = append(osPkgs, *pkg)
|
||||
delete(orphanPkgs, pkgB.PackageSPDXIdentifier)
|
||||
// Relationship: root package => application
|
||||
case isApplication(pkgB.PackageSPDXIdentifier):
|
||||
// pass
|
||||
@@ -129,6 +135,10 @@ func (s *SPDX) unmarshal(spdxDocument *spdx.Document) error {
|
||||
return xerrors.Errorf("failed to parse language-specific package: %w", err)
|
||||
}
|
||||
app.Libraries = append(app.Libraries, *lib)
|
||||
|
||||
// They are no longer orphan packages
|
||||
delete(orphanPkgs, pkgA.PackageSPDXIdentifier)
|
||||
delete(orphanPkgs, pkgB.PackageSPDXIdentifier)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,10 +153,8 @@ func (s *SPDX) unmarshal(spdxDocument *spdx.Document) error {
|
||||
}
|
||||
|
||||
// Fallback for when there are no effective relationships.
|
||||
if len(relationships) == 0 {
|
||||
if err := s.parsePackages(spdxDocument); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.parsePackages(orphanPkgs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Keep the original document
|
||||
@@ -156,13 +164,13 @@ func (s *SPDX) unmarshal(spdxDocument *spdx.Document) error {
|
||||
|
||||
// parsePackages processes the packages and categorizes them into OS packages and application packages.
|
||||
// Note that all language-specific packages are treated as a single application.
|
||||
func (s *SPDX) parsePackages(spdxDocument *spdx.Document) error {
|
||||
func (s *SPDX) parsePackages(pkgs map[common.ElementID]*spdx.Package) error {
|
||||
var (
|
||||
osPkgs []ftypes.Package
|
||||
app ftypes.Application
|
||||
apps = map[string]ftypes.Application{}
|
||||
)
|
||||
|
||||
for _, p := range spdxDocument.Packages {
|
||||
for _, p := range pkgs {
|
||||
pkg, pkgType, err := parsePkg(*p, nil)
|
||||
if errors.Is(err, errUnknownPackageFormat) {
|
||||
continue
|
||||
@@ -174,27 +182,28 @@ func (s *SPDX) parsePackages(spdxDocument *spdx.Document) error {
|
||||
osPkgs = append(osPkgs, *pkg)
|
||||
default:
|
||||
// Language-specific packages
|
||||
if app.Type == "" {
|
||||
app, ok := apps[pkgType]
|
||||
if !ok {
|
||||
app.Type = pkgType
|
||||
}
|
||||
app.Libraries = append(app.Libraries, *pkg)
|
||||
apps[pkgType] = app
|
||||
}
|
||||
}
|
||||
if len(osPkgs) > 0 {
|
||||
s.Packages = []ftypes.PackageInfo{{Packages: osPkgs}}
|
||||
}
|
||||
if len(app.Libraries) > 0 {
|
||||
for _, app := range apps {
|
||||
sort.Sort(app.Libraries)
|
||||
s.SBOM.Applications = append(s.SBOM.Applications, app)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createPackageSPDXIdentifierMap(packages []*spdx.Package) map[string]*spdx.Package {
|
||||
ret := make(map[string]*spdx.Package)
|
||||
for _, info := range packages {
|
||||
ret[string(info.PackageSPDXIdentifier)] = info
|
||||
}
|
||||
return ret
|
||||
func createPackageSPDXIdentifierMap(packages []*spdx.Package) map[common.ElementID]*spdx.Package {
|
||||
return lo.SliceToMap(packages, func(pkg *spdx.Package) (common.ElementID, *spdx.Package) {
|
||||
return pkg.PackageSPDXIdentifier, pkg
|
||||
})
|
||||
}
|
||||
|
||||
func createFileSPDXIdentifierMap(files []*spdx.File) map[string]*spdx.File {
|
||||
@@ -218,14 +227,14 @@ func isFile(elementID spdx.ElementID) bool {
|
||||
}
|
||||
|
||||
func initApplication(pkg spdx.Package) *ftypes.Application {
|
||||
app := &ftypes.Application{
|
||||
Type: pkg.PackageName,
|
||||
FilePath: pkg.PackageSourceInfo,
|
||||
}
|
||||
if pkg.PackageName == ftypes.NodePkg || pkg.PackageName == ftypes.PythonPkg ||
|
||||
pkg.PackageName == ftypes.GemSpec || pkg.PackageName == ftypes.Jar || pkg.PackageName == ftypes.CondaPkg {
|
||||
app := &ftypes.Application{Type: pkg.PackageName}
|
||||
switch pkg.PackageName {
|
||||
case ftypes.NodePkg, ftypes.PythonPkg, ftypes.GemSpec, ftypes.Jar, ftypes.CondaPkg:
|
||||
app.FilePath = ""
|
||||
default:
|
||||
app.FilePath = pkg.PackageSourceInfo
|
||||
}
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user