From 7838840acde4cb508139d13b9d439470acdddfa9 Mon Sep 17 00:00:00 2001 From: Kurt Boberg Date: Tue, 30 May 2023 15:50:14 -0700 Subject: [PATCH] add tests for missing metadata fields Signed-off-by: Kurt Boberg --- .../exampledata/cyclonedx-bom-example.json | 95 +++++++++++++++++++ internal/testing/testdata/testdata.go | 27 ++++++ .../parser/cyclonedx/parser_cyclonedx.go | 8 +- .../parser/cyclonedx/parser_cyclonedx_test.go | 10 ++ 4 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 internal/testing/testdata/exampledata/cyclonedx-bom-example.json diff --git a/internal/testing/testdata/exampledata/cyclonedx-bom-example.json b/internal/testing/testdata/exampledata/cyclonedx-bom-example.json new file mode 100644 index 0000000000..af2c92f05e --- /dev/null +++ b/internal/testing/testdata/exampledata/cyclonedx-bom-example.json @@ -0,0 +1,95 @@ +{ + "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.4", + "serialNumber": "urn:uuid:588bb01b-577e-4e1b-a055-b51b8f5f2ed1", + "version": 1, + "metadata": { + "timestamp": "2023-04-18T21:47:45.707189+00:00", + "tools": [ + { + "vendor": "CycloneDX", + "name": "cyclonedx-bom", + "version": "3.11.0" + }, + { + "vendor": "CycloneDX", + "name": "cyclonedx-python-lib", + "version": "3.1.5", + "externalReferences": [ + { + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/actions", + "type": "build-system" + }, + { + "url": "https://pypi.org/project/cyclonedx-python-lib/", + "type": "distribution" + }, + { + "url": "https://cyclonedx.github.io/cyclonedx-python-lib/", + "type": "documentation" + }, + { + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/issues", + "type": "issue-tracker" + }, + { + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE", + "type": "license" + }, + { + "url": "https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md", + "type": "release-notes" + }, + { + "url": "https://github.com/CycloneDX/cyclonedx-python-lib", + "type": "vcs" + }, + { + "url": "https://cyclonedx.org", + "type": "website" + } + ] + } + ] + }, + "components": [ + { + "type": "library", + "bom-ref": "13ca86b0-38a2-47aa-9a39-b2b042da8bc4", + "name": "ruamel.yaml", + "version": "0.17.21", + "purl": "pkg:pypi/ruamel.yaml@0.17.21", + "externalReferences": [ + { + "url": "https://pypi.org/project/ruamel.yaml/0.17.21", + "comment": "Distribution available from pypi.org", + "type": "distribution", + "hashes": [ + { + "alg": "SHA-256", + "content": "742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7" + } + ] + }, + { + "url": "https://pypi.org/project/ruamel.yaml/0.17.21", + "comment": "Distribution available from pypi.org", + "type": "distribution", + "hashes": [ + { + "alg": "SHA-256", + "content": "8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af" + } + ] + } + ] + } + ], + "dependencies": [ + { + "ref": "13ca86b0-38a2-47aa-9a39-b2b042da8bc4", + "dependsOn": [] + } + ] +} \ No newline at end of file diff --git a/internal/testing/testdata/testdata.go b/internal/testing/testdata/testdata.go index 25f0a154d0..b12298cde4 100644 --- a/internal/testing/testdata/testdata.go +++ b/internal/testing/testdata/testdata.go @@ -91,6 +91,9 @@ var ( //go:embed exampledata/no-dependent-components-cyclonedx.json CycloneDXExampleNoDependentComponents []byte + //go:embed exampledata/cyclonedx-bom-example.json + CycloneDXExampleCycloneDXpyNoBOMRef []byte + //go:embed exampledata/crev-review.json ITE6CREVExample []byte @@ -798,6 +801,30 @@ var ( HasSBOM: CdxNpmHasSBOM, } + cdxPyRuamelPackage, _ = asmhelpers.PurlToPkg("pkg:pypi/ruamel.yaml@0.17.21") + + CdxPipenvDeps = []assembler.IsDependencyIngest{ + { + Pkg: cdxPyRuamelPackage, + }, + } + + CdxPipenvHasSBOM = []assembler.HasSBOMIngest{ + { + Pkg: cdxPyRuamelPackage, + HasSBOM: &model.HasSBOMInputSpec{ + Uri: "TestSource", + Algorithm: "sha256", + Digest: "35363f03c80f26a88db6f2400771bdcc6624bb7b61b96da8503be0f757605fde", + DownloadLocation: "TestSource", + }, + }, + } + + CdxPipenvIngestionPredicates = assembler.IngestPredicates{ + //without a root node, the parser will return empty predicates. Not sure what the "correct" behavior here should be + } + quarkusParentPackage, _ = asmhelpers.PurlToPkg("pkg:maven/io.quarkus/quarkus-parent@999-SNAPSHOT?type=pom") quarkusParentPackageHasSBOM = []assembler.HasSBOMIngest{ diff --git a/pkg/ingestor/parser/cyclonedx/parser_cyclonedx.go b/pkg/ingestor/parser/cyclonedx/parser_cyclonedx.go index aaa58f75c8..8ca4a27a59 100644 --- a/pkg/ingestor/parser/cyclonedx/parser_cyclonedx.go +++ b/pkg/ingestor/parser/cyclonedx/parser_cyclonedx.go @@ -202,7 +202,13 @@ func (c *cyclonedxParser) GetPredicates(ctx context.Context) *assembler.IngestPr preds := &assembler.IngestPredicates{} - toplevel := c.getPackageElement(string(c.cdxBom.Metadata.Component.BOMRef)) + var toplevel []*model.PkgInputSpec = nil + + if c.cdxBom.Metadata.Component != nil && c.cdxBom.Metadata.Component.BOMRef != "" { + // BOMRef is not a required element + toplevel = c.getPackageElement(string(c.cdxBom.Metadata.Component.BOMRef)) + } + // adding top level package edge manually for all depends on package // TODO: This is not based on the relationship so that can be inaccurate (can capture both direct and in-direct)...Remove this and be done below by the *c.cdxBom.Dependencies? // see https://github.com/CycloneDX/specification/issues/33 diff --git a/pkg/ingestor/parser/cyclonedx/parser_cyclonedx_test.go b/pkg/ingestor/parser/cyclonedx/parser_cyclonedx_test.go index fd7f67fadd..294aa03242 100644 --- a/pkg/ingestor/parser/cyclonedx/parser_cyclonedx_test.go +++ b/pkg/ingestor/parser/cyclonedx/parser_cyclonedx_test.go @@ -89,6 +89,16 @@ func Test_cyclonedxParser(t *testing.T) { }, wantPredicates: &testdata.CdxEmptyIngestionPredicates, wantErr: false, + }, { + name: "valid CycloneDX document generated by cyclonedx-bom Python utility with a single dependency", + doc: &processor.Document{ + Blob: testdata.CycloneDXExampleCycloneDXpyNoBOMRef, + Format: processor.FormatJSON, + Type: processor.DocumentCycloneDX, + SourceInformation: processor.SourceInformation{}, + }, + wantPredicates: &testdata.CdxPipenvIngestionPredicates, + wantErr: false, }, } for _, tt := range tests {