From fb468c839fb6d583a5b73e318c99c4643b06e815 Mon Sep 17 00:00:00 2001 From: Patrik Beno Date: Sun, 5 Jun 2022 16:31:19 +0200 Subject: [PATCH] SBOM cataloger Signed-off-by: Patrik Beno --- syft/pkg/cataloger/cataloger.go | 4 ++ syft/pkg/cataloger/sbom/cataloger.go | 70 ++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 syft/pkg/cataloger/sbom/cataloger.go diff --git a/syft/pkg/cataloger/cataloger.go b/syft/pkg/cataloger/cataloger.go index 1aded4adf63..d7755bd9551 100644 --- a/syft/pkg/cataloger/cataloger.go +++ b/syft/pkg/cataloger/cataloger.go @@ -24,6 +24,7 @@ import ( "github.com/anchore/syft/syft/pkg/cataloger/rpmdb" "github.com/anchore/syft/syft/pkg/cataloger/ruby" "github.com/anchore/syft/syft/pkg/cataloger/rust" + "github.com/anchore/syft/syft/pkg/cataloger/sbom" "github.com/anchore/syft/syft/source" ) @@ -51,6 +52,7 @@ func ImageCatalogers(cfg Config) []Cataloger { apkdb.NewApkdbCataloger(), golang.NewGoModuleBinaryCataloger(), dotnet.NewDotnetDepsCataloger(), + sbom.NewSBOMCataloger(), }, cfg.Catalogers) } @@ -72,6 +74,7 @@ func DirectoryCatalogers(cfg Config) []Cataloger { rust.NewCargoLockCataloger(), dart.NewPubspecLockCataloger(), dotnet.NewDotnetDepsCataloger(), + sbom.NewSBOMCataloger(), }, cfg.Catalogers) } @@ -94,6 +97,7 @@ func AllCatalogers(cfg Config) []Cataloger { rust.NewCargoLockCataloger(), dart.NewPubspecLockCataloger(), dotnet.NewDotnetDepsCataloger(), + sbom.NewSBOMCataloger(), }, cfg.Catalogers) } diff --git a/syft/pkg/cataloger/sbom/cataloger.go b/syft/pkg/cataloger/sbom/cataloger.go new file mode 100644 index 00000000000..e55341e4da9 --- /dev/null +++ b/syft/pkg/cataloger/sbom/cataloger.go @@ -0,0 +1,70 @@ +package sbom + +import ( + "bytes" + "fmt" + "github.com/anchore/syft/internal/formats/cyclonedxjson" + "github.com/anchore/syft/internal/formats/cyclonedxxml" + "github.com/anchore/syft/internal/formats/spdx22json" + "github.com/anchore/syft/internal/formats/spdx22tagvalue" + "github.com/anchore/syft/internal/formats/syftjson" + "github.com/anchore/syft/syft/artifact" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/pkg/cataloger/common" + "github.com/anchore/syft/syft/sbom" + "io" +) + +// NewSBOMCataloger returns a new SBOM cataloger object loaded from saved SBOM JSON. +func NewSBOMCataloger() *common.GenericCataloger { + globParsers := map[string]common.ParserFn{ + "**/*.syft.json": parseSyftJson, + "**/bom.json": parseCyclonedxJson, + "**/bom.xml": parseCyclonedxXml, + "**/*.cdx.json": parseCyclonedxJson, + "**/*.cdx.xml": parseCyclonedxXml, + "**/*.spdx.json": parseSpdxJson, + "**/*.spdx": parseSpdx, + } + return common.NewGenericCataloger(nil, globParsers, "sbom-cataloger") +} + +func parseSyftJson(path string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) { + return parseSBOM(path, reader, syftjson.Format()) +} + +func parseCyclonedxJson(path string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) { + return parseSBOM(path, reader, cyclonedxjson.Format()) +} + +func parseCyclonedxXml(path string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) { + return parseSBOM(path, reader, cyclonedxxml.Format()) +} + +func parseSpdxJson(path string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) { + return parseSBOM(path, reader, spdx22json.Format()) +} + +func parseSpdx(path string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) { + return parseSBOM(path, reader, spdx22tagvalue.Format()) +} + +func parseSBOM(_ string, reader io.Reader, format sbom.Format) ([]*pkg.Package, []artifact.Relationship, error) { + by, err := io.ReadAll(reader) + if err != nil { + return nil, nil, fmt.Errorf("unable to read sbom: %w", err) + } + + s, err := format.Decode(bytes.NewReader(by)) + if err != nil { + return nil, nil, fmt.Errorf("unable to decode sbom: %w", err) + } + + var packages []*pkg.Package + for _, p := range s.Artifacts.PackageCatalog.Sorted() { + x := p //copy + packages = append(packages, &x) + } + + return packages, nil, nil +}