From 4a4a4c7cd8138288b08924749cc70e44287bd9da Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Wed, 6 Nov 2024 17:21:15 +0600 Subject: [PATCH 1/5] feat(parser): add UUID for pom Packages --- pkg/dependency/parser/java/pom/artifact.go | 2 ++ pkg/dependency/parser/java/pom/parse.go | 23 ++++++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/pkg/dependency/parser/java/pom/artifact.go b/pkg/dependency/parser/java/pom/artifact.go index 8fc20b236b51..484615d6d6ab 100644 --- a/pkg/dependency/parser/java/pom/artifact.go +++ b/pkg/dependency/parser/java/pom/artifact.go @@ -8,6 +8,7 @@ import ( "strings" "sync" + "github.com/aquasecurity/trivy/pkg/uuid" "github.com/samber/lo" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" @@ -25,6 +26,7 @@ var ( ) type artifact struct { + ID uuid.UUID // UUID is required to build correctly dep tree when multiple modules contain dependencies with same GAV GroupID string ArtifactID string Version version diff --git a/pkg/dependency/parser/java/pom/parse.go b/pkg/dependency/parser/java/pom/parse.go index 60a83ba9d81b..4a7048971fbb 100644 --- a/pkg/dependency/parser/java/pom/parse.go +++ b/pkg/dependency/parser/java/pom/parse.go @@ -13,6 +13,7 @@ import ( "sort" "strings" + "github.com/aquasecurity/trivy/pkg/uuid" "github.com/hashicorp/go-multierror" "github.com/samber/lo" "golang.org/x/net/html/charset" @@ -132,7 +133,7 @@ func (p *Parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]ft deps ftypes.Dependencies rootDepManagement []pomDependency uniqArtifacts = make(map[string]artifact) - uniqDeps = make(map[string][]string) + uniqDeps = make(map[uuid.UUID][]string) ) // Iterate direct and transitive dependencies @@ -209,26 +210,28 @@ func (p *Parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]ft // Offline mode may be missing some fields. if !art.IsEmpty() { // Override the version - uniqArtifacts[art.Name()] = artifact{ + newArt := artifact{ + ID: uuid.New(), Version: art.Version, Licenses: result.artifact.Licenses, Relationship: art.Relationship, Locations: art.Locations, } + uniqArtifacts[art.Name()] = newArt // save only dependency names // version will be determined later dependsOn := lo.Map(result.dependencies, func(a artifact, _ int) string { return a.Name() }) - uniqDeps[packageID(art.Name(), art.Version.String())] = dependsOn + uniqDeps[newArt.ID] = dependsOn } } // Convert to []ftypes.Package and []ftypes.Dependency for name, art := range uniqArtifacts { pkg := ftypes.Package{ - ID: packageID(name, art.Version.String()), + ID: art.ID.String(), Name: name, Version: art.Version.String(), Licenses: art.Licenses, @@ -238,9 +241,9 @@ func (p *Parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]ft pkgs = append(pkgs, pkg) // Convert dependency names into dependency IDs - dependsOn := lo.FilterMap(uniqDeps[pkg.ID], func(dependOnName string, _ int) (string, bool) { - ver := depVersion(dependOnName, uniqArtifacts) - return packageID(dependOnName, ver), ver != "" + dependsOn := lo.FilterMap(uniqDeps[art.ID], func(dependOnName string, _ int) (string, bool) { + id := depID(dependOnName, uniqArtifacts) + return id, id != "" }) sort.Strings(dependsOn) @@ -258,10 +261,10 @@ func (p *Parser) parseRoot(root artifact, uniqModules map[string]struct{}) ([]ft return pkgs, deps, nil } -// depVersion finds dependency in uniqArtifacts and return its version -func depVersion(depName string, uniqArtifacts map[string]artifact) string { +// depID finds dependency in uniqArtifacts and return its ID +func depID(depName string, uniqArtifacts map[string]artifact) string { if art, ok := uniqArtifacts[depName]; ok { - return art.Version.String() + return art.ID.String() } return "" } From c5ae33b74289060893d93888564a43b399a7d281 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Wed, 6 Nov 2024 17:21:33 +0600 Subject: [PATCH 2/5] test: update tests --- .../testdata/pom-cyclonedx.json.golden | 16 +- integration/testdata/pom.json.golden | 8 +- pkg/dependency/parser/java/pom/parse_test.go | 760 ++++++++++-------- .../analyzer/language/java/pom/pom_test.go | 28 +- 4 files changed, 459 insertions(+), 353 deletions(-) diff --git a/integration/testdata/pom-cyclonedx.json.golden b/integration/testdata/pom-cyclonedx.json.golden index 42650c62b54e..adad8c3dea13 100644 --- a/integration/testdata/pom-cyclonedx.json.golden +++ b/integration/testdata/pom-cyclonedx.json.golden @@ -2,7 +2,7 @@ "$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.6", - "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000005", + "serialNumber": "urn:uuid:3ff14136-e09f-4df9-80ea-000000000007", "version": 1, "metadata": { "timestamp": "2021-08-25T12:20:30+00:00", @@ -17,7 +17,7 @@ ] }, "component": { - "bom-ref": "3ff14136-e09f-4df9-80ea-000000000001", + "bom-ref": "3ff14136-e09f-4df9-80ea-000000000003", "type": "application", "name": "testdata/fixtures/repo/pom", "properties": [ @@ -30,7 +30,7 @@ }, "components": [ { - "bom-ref": "3ff14136-e09f-4df9-80ea-000000000002", + "bom-ref": "3ff14136-e09f-4df9-80ea-000000000004", "type": "application", "name": "pom.xml", "properties": [ @@ -54,7 +54,7 @@ "properties": [ { "name": "aquasecurity:trivy:PkgID", - "value": "com.example:log4shell:1.0-SNAPSHOT" + "value": "3ff14136-e09f-4df9-80ea-000000000001" }, { "name": "aquasecurity:trivy:PkgType", @@ -72,7 +72,7 @@ "properties": [ { "name": "aquasecurity:trivy:PkgID", - "value": "com.fasterxml.jackson.core:jackson-databind:2.9.1" + "value": "3ff14136-e09f-4df9-80ea-000000000002" }, { "name": "aquasecurity:trivy:PkgType", @@ -83,13 +83,13 @@ ], "dependencies": [ { - "ref": "3ff14136-e09f-4df9-80ea-000000000001", + "ref": "3ff14136-e09f-4df9-80ea-000000000003", "dependsOn": [ - "3ff14136-e09f-4df9-80ea-000000000002" + "3ff14136-e09f-4df9-80ea-000000000004" ] }, { - "ref": "3ff14136-e09f-4df9-80ea-000000000002", + "ref": "3ff14136-e09f-4df9-80ea-000000000004", "dependsOn": [ "pkg:maven/com.example/log4shell@1.0-SNAPSHOT" ] diff --git a/integration/testdata/pom.json.golden b/integration/testdata/pom.json.golden index a583f02ce8e9..56e5dfe57494 100644 --- a/integration/testdata/pom.json.golden +++ b/integration/testdata/pom.json.golden @@ -23,11 +23,11 @@ "Vulnerabilities": [ { "VulnerabilityID": "CVE-2020-9548", - "PkgID": "com.fasterxml.jackson.core:jackson-databind:2.9.1", + "PkgID": "3ff14136-e09f-4df9-80ea-000000000002", "PkgName": "com.fasterxml.jackson.core:jackson-databind", "PkgIdentifier": { "PURL": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.9.1", - "UID": "a704d87fd1c0b0e1" + "UID": "d0a262c16975e41d" }, "InstalledVersion": "2.9.1", "FixedVersion": "2.9.10.4", @@ -89,11 +89,11 @@ }, { "VulnerabilityID": "CVE-2021-20190", - "PkgID": "com.fasterxml.jackson.core:jackson-databind:2.9.1", + "PkgID": "3ff14136-e09f-4df9-80ea-000000000002", "PkgName": "com.fasterxml.jackson.core:jackson-databind", "PkgIdentifier": { "PURL": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.9.1", - "UID": "a704d87fd1c0b0e1" + "UID": "d0a262c16975e41d" }, "InstalledVersion": "2.9.1", "FixedVersion": "2.9.10.7", diff --git a/pkg/dependency/parser/java/pom/parse_test.go b/pkg/dependency/parser/java/pom/parse_test.go index 8d0bf002d6dc..1f97d851000e 100644 --- a/pkg/dependency/parser/java/pom/parse_test.go +++ b/pkg/dependency/parser/java/pom/parse_test.go @@ -7,6 +7,7 @@ import ( "path/filepath" "testing" + "github.com/aquasecurity/trivy/pkg/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -15,7 +16,7 @@ import ( ) var ( - exampleNestedScopeCompile = func(start, end int) ftypes.Package { + exampleNestedScopeCompile = func(id string, start, end int) ftypes.Package { var location ftypes.Locations if start != 0 && end != 0 { location = append(location, ftypes.Location{ @@ -24,7 +25,7 @@ var ( }) } return ftypes.Package{ - ID: "org.example:example-nested-scope-compile:1.0.0", + ID: id, Name: "org.example:example-nested-scope-compile", Version: "1.0.0", Relationship: ftypes.RelationshipDirect, @@ -32,7 +33,7 @@ var ( } } - exampleNestedScopeEmpty = func(start, end int) ftypes.Package { + exampleNestedScopeEmpty = func(id string, start, end int) ftypes.Package { var location ftypes.Locations if start != 0 && end != 0 { location = append(location, ftypes.Location{ @@ -41,7 +42,7 @@ var ( }) } return ftypes.Package{ - ID: "org.example:example-nested-scope-empty:1.0.0", + ID: id, Name: "org.example:example-nested-scope-empty", Version: "1.0.0", Relationship: ftypes.RelationshipDirect, @@ -49,7 +50,7 @@ var ( } } - exampleNestedScopeRuntime = func(start, end int) ftypes.Package { + exampleNestedScopeRuntime = func(id string, start, end int) ftypes.Package { var location ftypes.Locations if start != 0 && end != 0 { location = append(location, ftypes.Location{ @@ -58,7 +59,7 @@ var ( }) } return ftypes.Package{ - ID: "org.example:example-nested-scope-runtime:1.0.0", + ID: id, Name: "org.example:example-nested-scope-runtime", Version: "1.0.0", Relationship: ftypes.RelationshipDirect, @@ -66,45 +67,57 @@ var ( } } - exampleScopeCompile = ftypes.Package{ - ID: "org.example:example-scope-compile:2.0.0", - Name: "org.example:example-scope-compile", - Version: "2.0.0", - Relationship: ftypes.RelationshipIndirect, + exampleScopeCompile = func(id string) ftypes.Package { + return ftypes.Package{ + ID: id, + Name: "org.example:example-scope-compile", + Version: "2.0.0", + Relationship: ftypes.RelationshipIndirect, + } } - exampleScopeEmpty = ftypes.Package{ - ID: "org.example:example-scope-empty:2.0.0", - Name: "org.example:example-scope-empty", - Version: "2.0.0", - Relationship: ftypes.RelationshipIndirect, + exampleScopeEmpty = func(id string) ftypes.Package { + return ftypes.Package{ + ID: id, + Name: "org.example:example-scope-empty", + Version: "2.0.0", + Relationship: ftypes.RelationshipIndirect, + } } - exampleScopeRuntime = ftypes.Package{ - ID: "org.example:example-scope-runtime:2.0.0", - Name: "org.example:example-scope-runtime", - Version: "2.0.0", - Relationship: ftypes.RelationshipIndirect, + exampleScopeRuntime = func(id string) ftypes.Package { + return ftypes.Package{ + ID: id, + Name: "org.example:example-scope-runtime", + Version: "2.0.0", + Relationship: ftypes.RelationshipIndirect, + } } - exampleApiCompile = ftypes.Package{ - ID: "org.example:example-api-compile:3.0.0", - Name: "org.example:example-api-compile", - Version: "3.0.0", - Relationship: ftypes.RelationshipIndirect, + exampleApiCompile = func(id string) ftypes.Package { + return ftypes.Package{ + ID: id, + Name: "org.example:example-api-compile", + Version: "3.0.0", + Relationship: ftypes.RelationshipIndirect, + } } - exampleApiEmpty = ftypes.Package{ - ID: "org.example:example-api-empty:3.0.0", - Name: "org.example:example-api-empty", - Version: "3.0.0", - Relationship: ftypes.RelationshipIndirect, + exampleApiEmpty = func(id string) ftypes.Package { + return ftypes.Package{ + ID: id, + Name: "org.example:example-api-empty", + Version: "3.0.0", + Relationship: ftypes.RelationshipIndirect, + } } - exampleApiRuntime = ftypes.Package{ - ID: "org.example:example-api-runtime:3.0.0", - Name: "org.example:example-api-runtime", - Version: "3.0.0", - Relationship: ftypes.RelationshipIndirect, + exampleApiRuntime = func(id string) ftypes.Package { + return ftypes.Package{ + ID: id, + Name: "org.example:example-api-runtime", + Version: "3.0.0", + Relationship: ftypes.RelationshipIndirect, + } } ) @@ -124,14 +137,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:happy:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:happy", Version: "1.0.0", Licenses: []string{"BSD-3-Clause"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -144,7 +157,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-runtime:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-runtime", Version: "1.0.0", Relationship: ftypes.RelationshipDirect, @@ -158,10 +171,10 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:happy:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:1.7.30", - "org.example:example-runtime:1.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, }, @@ -172,14 +185,14 @@ func TestPom_Parse(t *testing.T) { local: false, want: []ftypes.Package{ { - ID: "com.example:happy:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:happy", Version: "1.0.0", Licenses: []string{"BSD-3-Clause"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -192,7 +205,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-runtime:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-runtime", Version: "1.0.0", Relationship: ftypes.RelationshipDirect, @@ -206,10 +219,10 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:happy:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:1.7.30", - "org.example:example-runtime:1.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, }, @@ -220,13 +233,13 @@ func TestPom_Parse(t *testing.T) { local: false, want: []ftypes.Package{ { - ID: "com.example:happy:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:happy", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-dependency:1.2.3-SNAPSHOT", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-dependency", Version: "1.2.3-SNAPSHOT", Relationship: ftypes.RelationshipDirect, @@ -238,7 +251,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-api", Version: "2.0.0", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -247,15 +260,15 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:happy:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-dependency:1.2.3-SNAPSHOT", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "org.example:example-dependency:1.2.3-SNAPSHOT", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, }, @@ -266,13 +279,13 @@ func TestPom_Parse(t *testing.T) { local: false, want: []ftypes.Package{ { - ID: "com.example:happy:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:happy", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-dependency:2.17.0-SNAPSHOT", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-dependency", Version: "2.17.0-SNAPSHOT", Relationship: ftypes.RelationshipDirect, @@ -284,7 +297,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-api", Version: "2.0.0", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -293,15 +306,15 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:happy:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-dependency:2.17.0-SNAPSHOT", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "org.example:example-dependency:2.17.0-SNAPSHOT", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, }, @@ -313,7 +326,7 @@ func TestPom_Parse(t *testing.T) { offline: true, want: []ftypes.Package{ { - ID: "org.example:example-offline:2.3.4", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "org.example:example-offline", Version: "2.3.4", Relationship: ftypes.RelationshipDirect, @@ -332,14 +345,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:child:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:child", Version: "1.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -354,9 +367,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:child:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:1.7.30", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -367,13 +380,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:child:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:child", Version: "2.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "2.0.0", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -388,9 +401,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:child:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -401,13 +414,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:test:0.0.1-SNAPSHOT", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:test", Version: "0.0.1-SNAPSHOT", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "2.0.0", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -422,9 +435,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:test:0.0.1-SNAPSHOT", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -435,13 +448,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:child:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:child", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-dependency", Version: "1.2.3", Relationship: ftypes.RelationshipDirect, @@ -453,7 +466,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-api:4.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-api", Version: "4.0.0", Relationship: ftypes.RelationshipIndirect, @@ -461,15 +474,15 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:child:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-dependency:1.2.3", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:4.0.0", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, }, @@ -480,14 +493,14 @@ func TestPom_Parse(t *testing.T) { local: false, want: []ftypes.Package{ { - ID: "com.example:child:1.0.0-SNAPSHOT", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:child", Version: "1.0.0-SNAPSHOT", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -496,9 +509,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:child:1.0.0-SNAPSHOT", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:1.7.30", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -509,14 +522,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:child:3.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:child", Version: "3.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -531,9 +544,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:child:3.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:1.7.30", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -544,14 +557,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:base:4.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:base", Version: "4.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-child:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-child", Version: "2.0.0", Licenses: []string{"Apache 2.0"}, @@ -564,7 +577,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -573,15 +586,15 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:base:4.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-child:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "org.example:example-child:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:1.7.30", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, }, @@ -592,14 +605,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:child:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:child", Version: "1.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -614,9 +627,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:child:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:1.7.30", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -627,13 +640,13 @@ func TestPom_Parse(t *testing.T) { local: false, want: []ftypes.Package{ { - ID: "com.example:child:1.0.0-SNAPSHOT", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:child", Version: "1.0.0-SNAPSHOT", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.1.1", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "1.1.1", Relationship: ftypes.RelationshipDirect, @@ -647,9 +660,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:child:1.0.0-SNAPSHOT", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:1.1.1", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -660,14 +673,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "org.example:child:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "org.example:child", Version: "1.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -682,9 +695,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "org.example:child:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:1.7.30", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -700,14 +713,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:soft:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:soft", Version: "1.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -720,7 +733,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-dependency", Version: "1.2.3", Relationship: ftypes.RelationshipDirect, @@ -734,16 +747,16 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:soft:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:1.7.30", - "org.example:example-dependency:1.2.3", + "3ff14136-e09f-4df9-80ea-000000000002", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000003", DependsOn: []string{ - "org.example:example-api:1.7.30", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -760,13 +773,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:soft-transitive:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:soft-transitive", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-dependency", Version: "1.2.3", Relationship: ftypes.RelationshipDirect, @@ -778,7 +791,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-dependency2:2.3.4", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-dependency2", Version: "2.3.4", Relationship: ftypes.RelationshipDirect, @@ -790,7 +803,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000004", Name: "org.example:example-api", Version: "2.0.0", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -799,22 +812,22 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:soft-transitive:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-dependency2:2.3.4", - "org.example:example-dependency:1.2.3", + "3ff14136-e09f-4df9-80ea-000000000002", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, { - ID: "org.example:example-dependency2:2.3.4", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000003", DependsOn: []string{ - "org.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, }, @@ -831,14 +844,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:hard:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:hard", Version: "1.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000004", Name: "org.example:example-dependency", Version: "1.2.3", Relationship: ftypes.RelationshipDirect, @@ -850,7 +863,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-nested:3.3.4", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-nested", Version: "3.3.4", Relationship: ftypes.RelationshipDirect, @@ -862,7 +875,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000005", Name: "org.example:example-api", Version: "2.0.0", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -871,22 +884,22 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:hard:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-dependency:1.2.3", - "org.example:example-nested:3.3.4", + "3ff14136-e09f-4df9-80ea-000000000002", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, { - ID: "org.example:example-nested:3.3.4", + ID: "3ff14136-e09f-4df9-80ea-000000000004", DependsOn: []string{ - "org.example:example-dependency:1.2.3", + "3ff14136-e09f-4df9-80ea-000000000005", }, }, }, @@ -897,14 +910,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:hard:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:hard", Version: "1.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Relationship: ftypes.RelationshipDirect, Locations: []ftypes.Location{ @@ -915,6 +928,14 @@ func TestPom_Parse(t *testing.T) { }, }, }, + wantDeps: []ftypes.Dependency{ + { + ID: "3ff14136-e09f-4df9-80ea-000000000001", + DependsOn: []string{ + "3ff14136-e09f-4df9-80ea-000000000002", + }, + }, + }, }, { name: "import dependencyManagement", @@ -922,14 +943,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:import:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:import", Version: "2.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -944,9 +965,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:import:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:1.7.30", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -957,14 +978,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:import:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:import", Version: "2.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -979,9 +1000,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:import:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:1.7.30", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -992,13 +1013,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:exclusions:3.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:exclusions", Version: "3.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-nested:3.3.3", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-nested", Version: "3.3.3", Relationship: ftypes.RelationshipDirect, @@ -1010,7 +1031,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-dependency", Version: "1.2.3", Relationship: ftypes.RelationshipIndirect, @@ -1018,15 +1039,15 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:exclusions:3.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-nested:3.3.3", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "org.example:example-nested:3.3.3", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-dependency:1.2.3", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, }, @@ -1037,13 +1058,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:example:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:example", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-exclusions:4.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-exclusions", Version: "4.0.0", Relationship: ftypes.RelationshipDirect, @@ -1055,14 +1076,14 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000004", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, Relationship: ftypes.RelationshipIndirect, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-dependency", Version: "1.2.3", Relationship: ftypes.RelationshipIndirect, @@ -1070,16 +1091,16 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:example:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-exclusions:4.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "org.example:example-exclusions:4.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:1.7.30", - "org.example:example-dependency:1.2.3", + "3ff14136-e09f-4df9-80ea-000000000003", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, }, @@ -1098,14 +1119,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:child:3.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:child", Version: "3.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-exclusions:3.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-exclusions", Version: "3.0.0", Relationship: ftypes.RelationshipDirect, @@ -1117,7 +1138,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-nested:3.3.3", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-nested", Version: "3.3.3", Relationship: ftypes.RelationshipIndirect, @@ -1125,15 +1146,15 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:child:3.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-exclusions:3.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "org.example:example-exclusions:3.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-nested:3.3.3", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, }, @@ -1144,13 +1165,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:wildcard-exclusions:4.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:wildcard-exclusions", Version: "4.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-dependency", Version: "1.2.3", Relationship: ftypes.RelationshipDirect, @@ -1162,7 +1183,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-dependency2:2.3.4", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-dependency2", Version: "2.3.4", Relationship: ftypes.RelationshipDirect, @@ -1174,7 +1195,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-nested:3.3.3", + ID: "3ff14136-e09f-4df9-80ea-000000000004", Name: "org.example:example-nested", Version: "3.3.3", Relationship: ftypes.RelationshipDirect, @@ -1188,11 +1209,11 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:wildcard-exclusions:4.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-dependency2:2.3.4", - "org.example:example-dependency:1.2.3", - "org.example:example-nested:3.3.3", + "3ff14136-e09f-4df9-80ea-000000000002", + "3ff14136-e09f-4df9-80ea-000000000003", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, }, @@ -1203,27 +1224,27 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:aggregation:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:aggregation", Version: "1.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "com.example:module:1.1.1", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "com.example:module", Version: "1.1.1", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, // TODO: Several root modules break SBOM relationships }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-dependency", Version: "1.2.3", Relationship: ftypes.RelationshipDirect, }, { - ID: "org.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000004", Name: "org.example:example-api", Version: "2.0.0", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -1249,15 +1270,84 @@ func TestPom_Parse(t *testing.T) { // [INFO] com.example:aggregation:pom:1.0.0 wantDeps: []ftypes.Dependency{ { - ID: "com.example:module:1.1.1", + ID: "3ff14136-e09f-4df9-80ea-000000000002", + DependsOn: []string{ + "3ff14136-e09f-4df9-80ea-000000000003", + }, + }, + { + ID: "3ff14136-e09f-4df9-80ea-000000000003", + DependsOn: []string{ + "3ff14136-e09f-4df9-80ea-000000000004", + }, + }, + }, + }, + { + name: "multi module with deps with same GAV", + inputFile: filepath.Join("testdata", "multiple-modules-with-deps-with-same-gav", "pom.xml"), + local: true, + want: []ftypes.Package{ + { + ID: "3ff14136-e09f-4df9-80ea-000000000002", + Name: "com.example:module1", + Version: "1.0.0", + Relationship: ftypes.RelationshipRoot, + }, + { + ID: "3ff14136-e09f-4df9-80ea-000000000004", + Name: "com.example:module2", + Version: "2.0.0", + Relationship: ftypes.RelationshipRoot, + }, + { + ID: "3ff14136-e09f-4df9-80ea-000000000001", + Name: "com.example:root", + Version: "1.0.0", + Relationship: ftypes.RelationshipRoot, + }, + { + ID: "3ff14136-e09f-4df9-80ea-000000000003", + Name: "org.example:example-api", + Version: "1.7.30", + Licenses: []string{"The Apache Software License, Version 2.0"}, + Relationship: ftypes.RelationshipDirect, + }, + { + ID: "3ff14136-e09f-4df9-80ea-000000000005", + Name: "org.example:example-api", + Version: "1.7.30", + Licenses: []string{"The Apache Software License, Version 2.0"}, + Relationship: ftypes.RelationshipDirect, + }, + }, + //[INFO] --------------------------------[ pom ]--------------------------------- + //[INFO] + //[INFO] --- dependency:3.7.0:tree (default-cli) @ module1 --- + //[INFO] com.example:module1:pom:1.0.0 + //[INFO] \- org.example:example-api:jar:1.7.30:compile + //[INFO] --------------------------------[ pom ]--------------------------------- + //[INFO] + //[INFO] --- dependency:3.7.0:tree (default-cli) @ module2 --- + //[INFO] com.example:module2:pom:2.0.0 + //[INFO] \- org.example:example-api:jar:1.7.30:compile + //[INFO] + //[INFO] --------------------------------[ pom ]--------------------------------- + //[INFO] + //[INFO] --- dependency:3.7.0:tree (default-cli) @ root --- + //[INFO] com.example:root:pom:1.0.0 + //[INFO] ------------------------------------------------------------------------ + wantDeps: []ftypes.Dependency{ + { + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-dependency:1.2.3", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000004", DependsOn: []string{ - "org.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000005", }, }, }, @@ -1269,26 +1359,26 @@ func TestPom_Parse(t *testing.T) { want: []ftypes.Package{ // as module { - ID: "org.example:module-1:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:module-1", Version: "2.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:module-2:3.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:module-2", Version: "3.0.0", Relationship: ftypes.RelationshipRoot, // TODO: Several root modules break SBOM relationships }, { - ID: "org.example:root:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "org.example:root", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, // TODO: Several root modules break SBOM relationships }, // as dependency { - ID: "org.example:module-1:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000004", Name: "org.example:module-1", Version: "2.0.0", Relationship: ftypes.RelationshipDirect, @@ -1296,9 +1386,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "org.example:module-2:3.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000003", DependsOn: []string{ - "org.example:module-1:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, }, @@ -1309,32 +1399,32 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:aggregation:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:aggregation", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "com.example:module1:1.1.1", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "com.example:module1", Version: "1.1.1", Relationship: ftypes.RelationshipRoot, }, { - ID: "com.example:module2:1.1.1", + ID: "3ff14136-e09f-4df9-80ea-000000000004", Name: "com.example:module2", Version: "1.1.1", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, Relationship: ftypes.RelationshipDirect, }, { - ID: "org.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000005", Name: "org.example:example-api", Version: "2.0.0", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -1343,15 +1433,15 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:module1:1.1.1", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:1.7.30", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, { - ID: "com.example:module2:1.1.1", + ID: "3ff14136-e09f-4df9-80ea-000000000004", DependsOn: []string{ - "org.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000005", }, }, }, @@ -1362,13 +1452,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:root-pom-dep-management:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:root-pom-dep-management", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-nested:3.3.3", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-nested", Version: "3.3.3", Relationship: ftypes.RelationshipDirect, @@ -1380,7 +1470,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000004", Name: "org.example:example-api", Version: "2.0.0", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -1389,7 +1479,7 @@ func TestPom_Parse(t *testing.T) { // dependency version is taken from `com.example:root-pom-dep-management` from dependencyManagement // not from `com.example:example-nested` from `com.example:example-nested` { - ID: "org.example:example-dependency:1.2.4", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-dependency", Version: "1.2.4", Relationship: ftypes.RelationshipIndirect, @@ -1397,21 +1487,21 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:root-pom-dep-management:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-nested:3.3.3", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "org.example:example-dependency:1.2.4", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, { - ID: "org.example:example-nested:3.3.3", + ID: "3ff14136-e09f-4df9-80ea-000000000003", DependsOn: []string{ - "org.example:example-dependency:1.2.4", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, }, @@ -1422,13 +1512,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "org.example:transitive-dependency-management:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "org.example:transitive-dependency-management", Version: "2.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-dependency-management3:1.1.1", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-dependency-management3", Version: "1.1.1", Relationship: ftypes.RelationshipDirect, @@ -1442,14 +1532,14 @@ func TestPom_Parse(t *testing.T) { // Managed dependencies (org.example:example-api:1.7.30) in org.example:example-dependency-management3 // should not affect dependencies of example-dependency (org.example:example-api:2.0.0) { - ID: "org.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000004", Name: "org.example:example-api", Version: "2.0.0", Licenses: []string{"The Apache Software License, Version 2.0"}, Relationship: ftypes.RelationshipIndirect, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-dependency", Version: "1.2.3", Relationship: ftypes.RelationshipIndirect, @@ -1457,21 +1547,21 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "org.example:example-dependency-management3:1.1.1", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-dependency:1.2.3", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "org.example:example-dependency:1.2.3", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, { - ID: "org.example:transitive-dependency-management:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000003", DependsOn: []string{ - "org.example:example-dependency-management3:1.1.1", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, }, @@ -1482,14 +1572,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:no-parent:1.0-SNAPSHOT", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:no-parent", Version: "1.0-SNAPSHOT", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.7.30", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Version: "1.7.30", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -1504,9 +1594,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:no-parent:1.0-SNAPSHOT", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api:1.7.30", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -1517,14 +1607,14 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:not-found-dependency:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:not-found-dependency", Version: "1.0.0", Licenses: []string{"Apache 2.0"}, Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-not-found:999", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-not-found", Version: "999", Relationship: ftypes.RelationshipDirect, @@ -1538,9 +1628,9 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:not-found-dependency:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-not-found:999", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, }, @@ -1551,7 +1641,7 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:aggregation:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:aggregation", Version: "1.0.0", Licenses: []string{"Apache 2.0"}, @@ -1565,7 +1655,7 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:multiply-licenses:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:multiply-licenses", Version: "1.0.0", Licenses: []string{ @@ -1582,7 +1672,7 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example.app:submodule:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example.app:submodule", Version: "1.0.0", Licenses: []string{"Apache-2.0"}, @@ -1596,7 +1686,7 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:child:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:child", Version: "1.0.0", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -1610,13 +1700,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:dep-without-version:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:dep-without-version", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Relationship: ftypes.RelationshipDirect, Locations: ftypes.Locations{ @@ -1627,6 +1717,14 @@ func TestPom_Parse(t *testing.T) { }, }, }, + wantDeps: []ftypes.Dependency{ + { + ID: "3ff14136-e09f-4df9-80ea-000000000001", + DependsOn: []string{ + "3ff14136-e09f-4df9-80ea-000000000002", + }, + }, + }, }, // [INFO] com.example:root-depManagement-in-parent:jar:1.0.0 // [INFO] \- org.example:example-dependency:jar:2.0.0:compile @@ -1637,13 +1735,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:root-depManagement-in-parent:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:root-depManagement-in-parent", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-dependency:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-dependency", Version: "2.0.0", Relationship: ftypes.RelationshipDirect, @@ -1655,7 +1753,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-api:1.0.1", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-api", Version: "1.0.1", Relationship: ftypes.RelationshipIndirect, @@ -1663,15 +1761,15 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:root-depManagement-in-parent:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-dependency:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "org.example:example-dependency:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:1.0.1", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, }, @@ -1685,13 +1783,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:root-depManagement-in-parent:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:root-depManagement-in-parent", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-dependency:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-dependency", Version: "2.0.0", Relationship: ftypes.RelationshipDirect, @@ -1703,7 +1801,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-api:2.0.1", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-api", Version: "2.0.1", Relationship: ftypes.RelationshipIndirect, @@ -1711,15 +1809,15 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:root-depManagement-in-parent:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-dependency:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "org.example:example-dependency:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:2.0.1", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, }, @@ -1734,25 +1832,25 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:child-depManagement-in-parent:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:child-depManagement-in-parent", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-api:1.0.1", + ID: "3ff14136-e09f-4df9-80ea-000000000004", Name: "org.example:example-api", Version: "1.0.1", Relationship: ftypes.RelationshipDirect, }, { - ID: "org.example:example-api2:1.0.2", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api2", Version: "1.0.2", Relationship: ftypes.RelationshipDirect, }, { - ID: "org.example:example-api3:4.0.3", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-api3", Version: "4.0.3", Relationship: ftypes.RelationshipDirect, @@ -1760,11 +1858,11 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:child-depManagement-in-parent:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-api2:1.0.2", - "org.example:example-api3:4.0.3", - "org.example:example-api:1.0.1", + "3ff14136-e09f-4df9-80ea-000000000002", + "3ff14136-e09f-4df9-80ea-000000000003", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, }, @@ -1787,64 +1885,64 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:inherit-scopes-from-child-deps-and-their-parents:0.0.1", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:inherit-scopes-from-child-deps-and-their-parents", Version: "0.0.1", Relationship: ftypes.RelationshipRoot, }, - exampleNestedScopeCompile(16, 21), - exampleNestedScopeEmpty(22, 26), - exampleNestedScopeRuntime(10, 15), - exampleApiCompile, - exampleApiEmpty, - exampleApiRuntime, - exampleScopeCompile, - exampleScopeEmpty, - exampleScopeRuntime, + exampleNestedScopeCompile("3ff14136-e09f-4df9-80ea-000000000003", 16, 21), + exampleNestedScopeEmpty("3ff14136-e09f-4df9-80ea-000000000004", 22, 26), + exampleNestedScopeRuntime("3ff14136-e09f-4df9-80ea-000000000002", 10, 15), + exampleApiCompile("3ff14136-e09f-4df9-80ea-000000000009"), + exampleApiEmpty("3ff14136-e09f-4df9-80ea-000000000010"), + exampleApiRuntime("3ff14136-e09f-4df9-80ea-000000000008"), + exampleScopeCompile("3ff14136-e09f-4df9-80ea-000000000006"), + exampleScopeEmpty("3ff14136-e09f-4df9-80ea-000000000007"), + exampleScopeRuntime("3ff14136-e09f-4df9-80ea-000000000005"), }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:inherit-scopes-from-child-deps-and-their-parents:0.0.1", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-nested-scope-compile:1.0.0", - "org.example:example-nested-scope-empty:1.0.0", - "org.example:example-nested-scope-runtime:1.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", + "3ff14136-e09f-4df9-80ea-000000000003", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, { - ID: "org.example:example-nested-scope-compile:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-scope-compile:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000005", }, }, { - ID: "org.example:example-nested-scope-empty:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000003", DependsOn: []string{ - "org.example:example-scope-empty:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000006", }, }, { - ID: "org.example:example-nested-scope-runtime:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000004", DependsOn: []string{ - "org.example:example-scope-runtime:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000007", }, }, { - ID: "org.example:example-scope-compile:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000005", DependsOn: []string{ - "org.example:example-api-compile:3.0.0", + "3ff14136-e09f-4df9-80ea-000000000008", }, }, { - ID: "org.example:example-scope-empty:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000006", DependsOn: []string{ - "org.example:example-api-empty:3.0.0", + "3ff14136-e09f-4df9-80ea-000000000009", }, }, { - ID: "org.example:example-scope-runtime:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000007", DependsOn: []string{ - "org.example:example-api-runtime:3.0.0", + "3ff14136-e09f-4df9-80ea-000000000010", }, }, }, @@ -1868,50 +1966,50 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:inherit-scopes-in-children-from-root:0.0.1", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:inherit-scopes-in-children-from-root", Version: "0.0.1", Relationship: ftypes.RelationshipRoot, }, - exampleNestedScopeCompile(51, 56), - exampleNestedScopeEmpty(57, 61), - exampleNestedScopeRuntime(45, 50), - exampleApiRuntime, - exampleScopeCompile, - exampleScopeEmpty, - exampleScopeRuntime, + exampleNestedScopeCompile("3ff14136-e09f-4df9-80ea-000000000003", 51, 56), + exampleNestedScopeEmpty("3ff14136-e09f-4df9-80ea-000000000004", 57, 61), + exampleNestedScopeRuntime("3ff14136-e09f-4df9-80ea-000000000002", 45, 50), + exampleApiRuntime("3ff14136-e09f-4df9-80ea-000000000008"), + exampleScopeCompile("3ff14136-e09f-4df9-80ea-000000000006"), + exampleScopeEmpty("3ff14136-e09f-4df9-80ea-000000000007"), + exampleScopeRuntime("3ff14136-e09f-4df9-80ea-000000000005"), }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:inherit-scopes-in-children-from-root:0.0.1", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-nested-scope-compile:1.0.0", - "org.example:example-nested-scope-empty:1.0.0", - "org.example:example-nested-scope-runtime:1.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", + "3ff14136-e09f-4df9-80ea-000000000003", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, { - ID: "org.example:example-nested-scope-compile:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-scope-compile:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000005", }, }, { - ID: "org.example:example-nested-scope-empty:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000003", DependsOn: []string{ - "org.example:example-scope-empty:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000006", }, }, { - ID: "org.example:example-nested-scope-runtime:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000004", DependsOn: []string{ - "org.example:example-scope-runtime:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000007", }, }, { - ID: "org.example:example-scope-runtime:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000005", DependsOn: []string{ - "org.example:example-api-runtime:3.0.0", + "3ff14136-e09f-4df9-80ea-000000000008", }, }, }, @@ -1935,41 +2033,41 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:inherit-scopes-in-parents-from-root:0.1.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:inherit-scopes-in-parents-from-root", Version: "0.1.0", Relationship: ftypes.RelationshipRoot, }, - exampleNestedScopeCompile(0, 0), - exampleNestedScopeRuntime(0, 0), - exampleApiRuntime, - exampleScopeCompile, - exampleScopeRuntime, + exampleNestedScopeCompile("3ff14136-e09f-4df9-80ea-000000000003", 0, 0), + exampleNestedScopeRuntime("3ff14136-e09f-4df9-80ea-000000000002", 0, 0), + exampleApiRuntime("3ff14136-e09f-4df9-80ea-000000000006"), + exampleScopeCompile("3ff14136-e09f-4df9-80ea-000000000005"), + exampleScopeRuntime("3ff14136-e09f-4df9-80ea-000000000004"), }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:inherit-scopes-in-parents-from-root:0.1.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-nested-scope-compile:1.0.0", - "org.example:example-nested-scope-runtime:1.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, { - ID: "org.example:example-nested-scope-compile:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-scope-compile:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, { - ID: "org.example:example-nested-scope-runtime:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000003", DependsOn: []string{ - "org.example:example-scope-runtime:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000005", }, }, { - ID: "org.example:example-scope-runtime:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000004", DependsOn: []string{ - "org.example:example-api-runtime:3.0.0", + "3ff14136-e09f-4df9-80ea-000000000006", }, }, }, @@ -1984,13 +2082,13 @@ func TestPom_Parse(t *testing.T) { local: true, want: []ftypes.Package{ { - ID: "com.example:root-pom-with-spaces:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:root-pom-with-spaces", Version: "1.0.0", Relationship: ftypes.RelationshipRoot, }, { - ID: "org.example:example-nested:3.3.3", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-nested", Version: "3.3.3", Relationship: ftypes.RelationshipDirect, @@ -2002,7 +2100,7 @@ func TestPom_Parse(t *testing.T) { }, }, { - ID: "org.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000004", Name: "org.example:example-api", Version: "2.0.0", Licenses: []string{"The Apache Software License, Version 2.0"}, @@ -2011,7 +2109,7 @@ func TestPom_Parse(t *testing.T) { // dependency version is taken from `com.example:root-pom-with-spaces` from dependencyManagement // not from `com.example:example-nested` from `com.example:example-nested` { - ID: "org.example:example-dependency:1.2.4", + ID: "3ff14136-e09f-4df9-80ea-000000000003", Name: "org.example:example-dependency", Version: "1.2.4", Relationship: ftypes.RelationshipIndirect, @@ -2019,21 +2117,21 @@ func TestPom_Parse(t *testing.T) { }, wantDeps: []ftypes.Dependency{ { - ID: "com.example:root-pom-with-spaces:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", DependsOn: []string{ - "org.example:example-nested:3.3.3", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "org.example:example-dependency:1.2.4", + ID: "3ff14136-e09f-4df9-80ea-000000000002", DependsOn: []string{ - "org.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000003", }, }, { - ID: "org.example:example-nested:3.3.3", + ID: "3ff14136-e09f-4df9-80ea-000000000003", DependsOn: []string{ - "org.example:example-dependency:1.2.4", + "3ff14136-e09f-4df9-80ea-000000000004", }, }, }, @@ -2041,6 +2139,8 @@ func TestPom_Parse(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d") + f, err := os.Open(tt.inputFile) require.NoError(t, err) defer f.Close() diff --git a/pkg/fanal/analyzer/language/java/pom/pom_test.go b/pkg/fanal/analyzer/language/java/pom/pom_test.go index ea147a4d1141..243fa130de7c 100644 --- a/pkg/fanal/analyzer/language/java/pom/pom_test.go +++ b/pkg/fanal/analyzer/language/java/pom/pom_test.go @@ -5,6 +5,7 @@ import ( "path/filepath" "testing" + "github.com/aquasecurity/trivy/pkg/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -30,17 +31,17 @@ func Test_pomAnalyzer_Analyze(t *testing.T) { FilePath: "testdata/happy/pom.xml", Packages: types.Packages{ { - ID: "com.example:example:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:example", Version: "1.0.0", Licenses: []string{"Apache-2.0"}, Relationship: types.RelationshipRoot, DependsOn: []string{ - "com.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "com.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "com.example:example-api", Version: "2.0.0", Relationship: types.RelationshipDirect, @@ -67,17 +68,17 @@ func Test_pomAnalyzer_Analyze(t *testing.T) { FilePath: "pom.xml", Packages: types.Packages{ { - ID: "com.example:example:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:example", Version: "1.0.0", Relationship: types.RelationshipRoot, Licenses: []string{"Apache-2.0"}, DependsOn: []string{ - "com.example:example-api:2.0.0", + "3ff14136-e09f-4df9-80ea-000000000002", }, }, { - ID: "com.example:example-api:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "com.example:example-api", Version: "2.0.0", Relationship: types.RelationshipDirect, @@ -103,18 +104,18 @@ func Test_pomAnalyzer_Analyze(t *testing.T) { FilePath: "testdata/mark-as-dev/src/it/example/pom.xml", Packages: types.Packages{ { - ID: "com.example:example:1.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:example", Version: "1.0.0", Licenses: []string{"Apache-2.0"}, Relationship: types.RelationshipRoot, DependsOn: []string{ - "com.example:example-api:@example.version@", + "3ff14136-e09f-4df9-80ea-000000000002", }, Dev: true, }, { - ID: "com.example:example-api:@example.version@", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "com.example:example-api", Version: "@example.version@", Relationship: types.RelationshipDirect, @@ -141,14 +142,17 @@ func Test_pomAnalyzer_Analyze(t *testing.T) { FilePath: "testdata/requirements/pom.xml", Packages: types.Packages{ { - ID: "com.example:example:2.0.0", + ID: "3ff14136-e09f-4df9-80ea-000000000001", Name: "com.example:example", Version: "2.0.0", Licenses: []string{"Apache-2.0"}, Relationship: types.RelationshipRoot, + DependsOn: []string{ + "3ff14136-e09f-4df9-80ea-000000000002", + }, }, { - ID: "org.example:example-api", + ID: "3ff14136-e09f-4df9-80ea-000000000002", Name: "org.example:example-api", Relationship: types.RelationshipDirect, Locations: []types.Location{ @@ -177,6 +181,8 @@ func Test_pomAnalyzer_Analyze(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + uuid.SetFakeUUID(t, "3ff14136-e09f-4df9-80ea-%012d") + f, err := os.Open(filepath.Join(tt.inputDir, tt.inputFile)) require.NoError(t, err) defer f.Close() From 68aa1f062ef5a1376c250d1b1b1275860e60c767 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Wed, 6 Nov 2024 17:21:50 +0600 Subject: [PATCH 3/5] fix: use pkgID to filter vulns --- pkg/result/filter.go | 2 +- pkg/result/filter_test.go | 96 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/pkg/result/filter.go b/pkg/result/filter.go index 83e0c0a7170e..b8fe8ef5caec 100644 --- a/pkg/result/filter.go +++ b/pkg/result/filter.go @@ -103,7 +103,7 @@ func filterVulnerabilities(result *types.Result, severities []string, ignoreStat } // Check if there is a duplicate vulnerability - key := fmt.Sprintf("%s/%s/%s/%s", vuln.VulnerabilityID, vuln.PkgName, vuln.InstalledVersion, vuln.PkgPath) + key := fmt.Sprintf("%s/%s/%s/%s/%s", vuln.VulnerabilityID, vuln.PkgID, vuln.PkgName, vuln.InstalledVersion, vuln.PkgPath) if old, ok := uniqVulns[key]; ok && !shouldOverwrite(old, vuln) { continue } diff --git a/pkg/result/filter_test.go b/pkg/result/filter_test.go index 08b523dd2dde..5d948695d70a 100644 --- a/pkg/result/filter_test.go +++ b/pkg/result/filter_test.go @@ -998,6 +998,102 @@ func TestFilter(t *testing.T) { }, }, }, + { + name: "happy path with duplicates and different package IDs", + args: args{ + report: types.Report{ + Results: types.Results{ + { + Vulnerabilities: []types.DetectedVulnerability{ + { + VulnerabilityID: "CVE-2019-0001", + PkgID: "3ff14136-e09f-4df9-80ea-000000000001", + PkgName: "foo", + InstalledVersion: "1.2.3", + FixedVersion: "1.2.4", + Vulnerability: dbTypes.Vulnerability{ + Severity: dbTypes.SeverityCritical.String(), + }, + }, + { + VulnerabilityID: "CVE-2019-0001", + PkgID: "3ff14136-e09f-4df9-80ea-000000000002", + PkgName: "foo", + InstalledVersion: "1.2.3", + FixedVersion: "1.2.4", + Vulnerability: dbTypes.Vulnerability{ + Severity: dbTypes.SeverityCritical.String(), + }, + }, + { + VulnerabilityID: "CVE-2019-0002", + PkgID: "bar@1.2.3", + PkgName: "bar", + InstalledVersion: "1.2.3", + FixedVersion: "1.2.4", + Vulnerability: dbTypes.Vulnerability{ + Severity: dbTypes.SeverityCritical.String(), + }, + }, + { + VulnerabilityID: "CVE-2019-0002", + PkgID: "bar@1.2.3", + PkgName: "bar", + InstalledVersion: "1.2.3", + FixedVersion: "1.2.4", + Vulnerability: dbTypes.Vulnerability{ + Severity: dbTypes.SeverityCritical.String(), + }, + }, + }, + }, + }, + }, + severities: []dbTypes.Severity{ + dbTypes.SeverityCritical, + dbTypes.SeverityHigh, + dbTypes.SeverityUnknown, + }, + }, + want: types.Report{ + Results: types.Results{ + { + Vulnerabilities: []types.DetectedVulnerability{ + { + VulnerabilityID: "CVE-2019-0002", + PkgID: "bar@1.2.3", + PkgName: "bar", + InstalledVersion: "1.2.3", + FixedVersion: "1.2.4", + Vulnerability: dbTypes.Vulnerability{ + Severity: dbTypes.SeverityCritical.String(), + }, + }, + { + VulnerabilityID: "CVE-2019-0001", + PkgID: "3ff14136-e09f-4df9-80ea-000000000001", + PkgName: "foo", + InstalledVersion: "1.2.3", + FixedVersion: "1.2.4", + Vulnerability: dbTypes.Vulnerability{ + Severity: dbTypes.SeverityCritical.String(), + }, + }, + { + VulnerabilityID: "CVE-2019-0001", + PkgID: "3ff14136-e09f-4df9-80ea-000000000002", + PkgName: "foo", + InstalledVersion: "1.2.3", + FixedVersion: "1.2.4", + Vulnerability: dbTypes.Vulnerability{ + Severity: dbTypes.SeverityCritical.String(), + }, + }, + }, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From 29fc583756e0568356ea9c7f8f7668f02df3ad26 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Wed, 6 Nov 2024 17:22:21 +0600 Subject: [PATCH 4/5] fix: use `pkgName:pkgVersion` for dep tree of pom packages --- pkg/report/table/vulnerability.go | 23 +++- pkg/report/table/vulnerability_test.go | 152 +++++++++++++++++++++++++ 2 files changed, 170 insertions(+), 5 deletions(-) diff --git a/pkg/report/table/vulnerability.go b/pkg/report/table/vulnerability.go index 450349ed5fcb..aaf30a2a900b 100644 --- a/pkg/report/table/vulnerability.go +++ b/pkg/report/table/vulnerability.go @@ -10,6 +10,7 @@ import ( "strings" "sync" + "github.com/aquasecurity/trivy/pkg/dependency" "github.com/fatih/color" "github.com/samber/lo" "github.com/xlab/treeprint" @@ -276,10 +277,10 @@ Dependency Origin Tree (Reversed) // Render tree for _, vulnPkg := range vulnPkgs { _, summaries := summarize(r.severities, pkgSeverityCount[vulnPkg.ID]) - topLvlID := tml.Sprintf("%s, (%s)", vulnPkg.ID, strings.Join(summaries, ", ")) + topLvlID := tml.Sprintf("%s, (%s)", r.pkgID(vulnPkg), strings.Join(summaries, ", ")) branch := root.AddBranch(topLvlID) - addParents(branch, vulnPkg, parents, ancestors, map[string]struct{}{vulnPkg.ID: {}}, 1) + r.addParents(branch, vulnPkg, parents, ancestors, map[string]struct{}{vulnPkg.ID: {}}, 1) } r.printf(root.String()) @@ -290,7 +291,7 @@ func (r *vulnerabilityRenderer) printf(format string, args ...any) { _ = tml.Fprintf(r.w, format, args...) } -func addParents(topItem treeprint.Tree, pkg ftypes.Package, parentMap map[string]ftypes.Packages, ancestors map[string][]string, +func (r *vulnerabilityRenderer) addParents(topItem treeprint.Tree, pkg ftypes.Package, parentMap map[string]ftypes.Packages, ancestors map[string][]string, seen map[string]struct{}, depth int) { if pkg.Relationship == ftypes.RelationshipDirect { return @@ -304,7 +305,7 @@ func addParents(topItem treeprint.Tree, pkg ftypes.Package, parentMap map[string seen[parent.ID] = struct{}{} // to avoid infinite loops if depth == 1 && parent.Relationship == ftypes.RelationshipDirect { - topItem.AddBranch(parent.ID) + topItem.AddBranch(r.pkgID(parent)) } else { // We omit intermediate dependencies and show only direct dependencies // as this could make the dependency tree huge. @@ -323,11 +324,23 @@ func addParents(topItem treeprint.Tree, pkg ftypes.Package, parentMap map[string if len(rootIDs) > 0 { branch := topItem.AddBranch("...(omitted)...") for _, rootID := range rootIDs { - branch.AddBranch(rootID) + rootIDPkg, _ := lo.Find(r.result.Packages, func(pkg ftypes.Package) bool { + return pkg.ID == rootID + }) + branch.AddBranch(r.pkgID(rootIDPkg)) } } } +// pkgID overwrites ID for pom packages. +// This is required to overwrite UUIDs to maven (:) format. +func (r *vulnerabilityRenderer) pkgID(pkg ftypes.Package) string { + if r.result.Type != ftypes.Pom { + return pkg.ID + } + return dependency.ID(r.result.Type, pkg.Name, pkg.Version) +} + func traverseAncestors(pkgs []ftypes.Package, parentMap map[string]ftypes.Packages) map[string][]string { ancestors := make(map[string][]string) for _, pkg := range pkgs { diff --git a/pkg/report/table/vulnerability_test.go b/pkg/report/table/vulnerability_test.go index 9a773c90eafe..c24d429267ed 100644 --- a/pkg/report/table/vulnerability_test.go +++ b/pkg/report/table/vulnerability_test.go @@ -259,6 +259,158 @@ package-lock.json │ └── ...(omitted)... │ └── styled-components@3.1.3 └── sanitize-html@1.20.0, (MEDIUM: 1, HIGH: 0) +`, + }, + { + name: "happy path with vulnerability origin graph for pom.xml file with modules", + result: types.Result{ + Target: "pom.xml", + Class: types.ClassLangPkg, + Type: "pom", + Packages: []ftypes.Package{ + { + ID: "3ff14136-e09f-4df9-80ea-000000000001", + Name: "com.example:root", + Version: "0.0.1", + Relationship: ftypes.RelationshipRoot, + DependsOn: []string{ + "3ff14136-e09f-4df9-80ea-000000000003", + }, + }, + // module1 + { + ID: "3ff14136-e09f-4df9-80ea-000000000002", + Name: "com.example:module1", + Version: "1.0.0", + Relationship: ftypes.RelationshipRoot, + DependsOn: []string{ + "3ff14136-e09f-4df9-80ea-000000000003", + }, + }, + { + ID: "3ff14136-e09f-4df9-80ea-000000000003", + Name: "org.apache.logging.log4j:log4j-core", + Version: "2.6.1", + Relationship: ftypes.RelationshipDirect, + }, + // module2 + { + ID: "3ff14136-e09f-4df9-80ea-000000000004", + Name: "com.example:module2", + Version: "2.0.0", + Relationship: ftypes.RelationshipRoot, + DependsOn: []string{ + "3ff14136-e09f-4df9-80ea-000000000005", + }, + }, + { + ID: "3ff14136-e09f-4df9-80ea-000000000005", + Name: "com.example:example-dependency", + Version: "2.0.0", + Relationship: ftypes.RelationshipDirect, + DependsOn: []string{ + "3ff14136-e09f-4df9-80ea-000000000006", + }, + }, + { + ID: "3ff14136-e09f-4df9-80ea-000000000006", + Name: "org.apache.logging.log4j:log4j-core", + Version: "2.6.1", + Relationship: ftypes.RelationshipIndirect, + }, + // Root pkg + { + ID: "3ff14136-e09f-4df9-80ea-000000000007", + Name: "com.example:example-nested-dependency", + Version: "2.0.0", + Relationship: ftypes.RelationshipDirect, + DependsOn: []string{ + "3ff14136-e09f-4df9-80ea-000000000008", + }, + }, + { + ID: "3ff14136-e09f-4df9-80ea-000000000008", + Name: "com.example:example-dependency", + Version: "2.0.0", + Relationship: ftypes.RelationshipIndirect, + DependsOn: []string{ + "3ff14136-e09f-4df9-80ea-000000000009", + }, + }, + + { + ID: "3ff14136-e09f-4df9-80ea-000000000009", + Name: "org.apache.logging.log4j:log4j-core", + Version: "2.6.1", + Relationship: ftypes.RelationshipIndirect, + }, + }, + Vulnerabilities: []types.DetectedVulnerability{ + { + VulnerabilityID: "CVE-2017-5645", + PkgID: "3ff14136-e09f-4df9-80ea-000000000003", + PkgName: "org.apache.logging.log4j:log4j-core", + Vulnerability: dbTypes.Vulnerability{ + Title: "foobar", + Description: "baz", + Severity: "HIGH", + }, + InstalledVersion: "2.6.1", + FixedVersion: "2.8.2", + Status: dbTypes.StatusFixed, + }, + { + VulnerabilityID: "CVE-2017-5645", + PkgID: "3ff14136-e09f-4df9-80ea-000000000006", + PkgName: "org.apache.logging.log4j:log4j-core", + Vulnerability: dbTypes.Vulnerability{ + Title: "foobar", + Description: "baz", + Severity: "HIGH", + }, + InstalledVersion: "2.6.1", + FixedVersion: "2.8.2", + Status: dbTypes.StatusFixed, + }, + { + VulnerabilityID: "CVE-2017-5645", + PkgID: "3ff14136-e09f-4df9-80ea-000000000009", + PkgName: "org.apache.logging.log4j:log4j-core", + Vulnerability: dbTypes.Vulnerability{ + Title: "foobar", + Description: "baz", + Severity: "HIGH", + }, + InstalledVersion: "2.6.1", + FixedVersion: "2.8.2", + Status: dbTypes.StatusFixed, + }, + }, + }, + want: ` +pom.xml (pom) +============= +Total: 3 (MEDIUM: 0, HIGH: 3) + +┌─────────────────────────────────────┬───────────────┬──────────┬────────┬───────────────────┬───────────────┬────────┐ +│ Library │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │ Title │ +├─────────────────────────────────────┼───────────────┼──────────┼────────┼───────────────────┼───────────────┼────────┤ +│ org.apache.logging.log4j:log4j-core │ CVE-2017-5645 │ HIGH │ fixed │ 2.6.1 │ 2.8.2 │ foobar │ +│ │ │ │ │ │ │ │ +│ │ │ │ │ │ │ │ +│ │ │ │ │ │ │ │ +│ │ │ │ │ │ │ │ +└─────────────────────────────────────┴───────────────┴──────────┴────────┴───────────────────┴───────────────┴────────┘ + +Dependency Origin Tree (Reversed) +================================= +pom.xml +├── org.apache.logging.log4j:log4j-core:2.6.1, (MEDIUM: 0, HIGH: 1) +├── org.apache.logging.log4j:log4j-core:2.6.1, (MEDIUM: 0, HIGH: 1) +│ └── com.example:example-dependency:2.0.0 +└── org.apache.logging.log4j:log4j-core:2.6.1, (MEDIUM: 0, HIGH: 1) + └── ...(omitted)... + └── com.example:example-nested-dependency:2.0.0 `, }, { From c72a080e8312f9921d9ab7de71e75398de887b95 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Wed, 6 Nov 2024 17:22:43 +0600 Subject: [PATCH 5/5] test(bom): add test with same GAV from different modules --- pkg/sbom/io/encode_test.go | 295 +++++++++++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) diff --git a/pkg/sbom/io/encode_test.go b/pkg/sbom/io/encode_test.go index 5a5b821590b8..f5b7f99016b9 100644 --- a/pkg/sbom/io/encode_test.go +++ b/pkg/sbom/io/encode_test.go @@ -764,6 +764,301 @@ func TestEncoder_Encode(t *testing.T) { }, wantVulns: make(map[uuid.UUID][]core.Vulnerability), }, + { + name: "multimodule maven project with deps with same GAV", + report: types.Report{ + SchemaVersion: 2, + ArtifactName: "pom.xml", + ArtifactType: artifact.TypeFilesystem, + Results: []types.Result{ + { + Target: "pom.xml", + Type: ftypes.Pom, + Class: types.ClassLangPkg, + Packages: []ftypes.Package{ + { + ID: "2ff14136-e09f-4df9-80ea-000000000002", + Name: "com.example:module1", + Version: "1.0.0", + Identifier: ftypes.PkgIdentifier{ + UID: "dd331628c74fdbed", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeMaven, + Namespace: "com.example", + Name: "module1", + Version: "1.0.0", + }, + }, + Relationship: ftypes.RelationshipRoot, + DependsOn: []string{ + "2ff14136-e09f-4df9-80ea-000000000003", + }, + }, + { + ID: "2ff14136-e09f-4df9-80ea-000000000004", + Name: "com.example:module2", + Version: "2.0.0", + Identifier: ftypes.PkgIdentifier{ + UID: "d9f69cbb644299b2", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeMaven, + Namespace: "com.example", + Name: "module2", + Version: "2.0.0", + }, + }, + Relationship: ftypes.RelationshipRoot, + DependsOn: []string{ + "2ff14136-e09f-4df9-80ea-000000000005", + }, + }, + { + ID: "2ff14136-e09f-4df9-80ea-000000000001", + Name: "com.example:root", + Version: "1.0.0", + Identifier: ftypes.PkgIdentifier{ + UID: "b4bdd7e3e8cc94d", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeMaven, + Namespace: "com.example", + Name: "root", + Version: "1.0.0", + }, + }, + Relationship: ftypes.RelationshipRoot, + }, + { + ID: "2ff14136-e09f-4df9-80ea-000000000003", + Name: "org.apache.logging.log4j:log4j-core", + Version: "2.6.1", + Identifier: ftypes.PkgIdentifier{ + UID: "d249736f7ddaaf4f", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeMaven, + Namespace: "org.apache.logging.log4j", + Name: "log4j-core", + Version: "2.6.1", + }, + }, + Relationship: ftypes.RelationshipDirect, + }, + { + ID: "2ff14136-e09f-4df9-80ea-000000000005", + Name: "org.apache.logging.log4j:log4j-core", + Version: "2.6.1", + Identifier: ftypes.PkgIdentifier{ + UID: "2955bd45b32b9058", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeMaven, + Namespace: "org.apache.logging.log4j", + Name: "log4j-core", + Version: "2.6.1", + }, + }, + Relationship: ftypes.RelationshipDirect, + }, + }, + }, + }, + }, + wantComponents: map[uuid.UUID]*core.Component{ + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000001"): { + Type: core.TypeFilesystem, + Name: "pom.xml", + Root: true, + Properties: []core.Property{ + { + Name: core.PropertySchemaVersion, + Value: "2", + }, + }, + PkgIdentifier: ftypes.PkgIdentifier{ + BOMRef: "3ff14136-e09f-4df9-80ea-000000000001", + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000002"): { + Type: core.TypeApplication, + Name: "pom.xml", + Properties: []core.Property{ + { + Name: core.PropertyClass, + Value: "lang-pkgs", + }, + { + Name: core.PropertyType, + Value: "pom", + }, + }, + PkgIdentifier: ftypes.PkgIdentifier{ + BOMRef: "3ff14136-e09f-4df9-80ea-000000000002", + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000003"): { + Type: core.TypeLibrary, + Group: "com.example", + Name: "module1", + Version: "1.0.0", + SrcFile: "pom.xml", + Properties: []core.Property{ + { + Name: core.PropertyPkgID, + Value: "2ff14136-e09f-4df9-80ea-000000000002", + }, + { + Name: core.PropertyPkgType, + Value: "pom", + }, + }, + PkgIdentifier: ftypes.PkgIdentifier{ + UID: "dd331628c74fdbed", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeMaven, + Namespace: "com.example", + Name: "module1", + Version: "1.0.0", + }, + BOMRef: "pkg:maven/com.example/module1@1.0.0", + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000004"): { + Type: core.TypeLibrary, + Group: "com.example", + Name: "module2", + Version: "2.0.0", + SrcFile: "pom.xml", + Properties: []core.Property{ + { + Name: core.PropertyPkgID, + Value: "2ff14136-e09f-4df9-80ea-000000000004", + }, + { + Name: core.PropertyPkgType, + Value: "pom", + }, + }, + PkgIdentifier: ftypes.PkgIdentifier{ + UID: "d9f69cbb644299b2", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeMaven, + Namespace: "com.example", + Name: "module2", + Version: "2.0.0", + }, + BOMRef: "pkg:maven/com.example/module2@2.0.0", + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000005"): { + Type: core.TypeLibrary, + Group: "com.example", + Name: "root", + Version: "1.0.0", + SrcFile: "pom.xml", + Properties: []core.Property{ + { + Name: core.PropertyPkgID, + Value: "2ff14136-e09f-4df9-80ea-000000000001", + }, + { + Name: core.PropertyPkgType, + Value: "pom", + }, + }, + PkgIdentifier: ftypes.PkgIdentifier{ + UID: "b4bdd7e3e8cc94d", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeMaven, + Namespace: "com.example", + Name: "root", + Version: "1.0.0", + }, + BOMRef: "pkg:maven/com.example/root@1.0.0", + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000006"): { + Type: core.TypeLibrary, + Group: "org.apache.logging.log4j", + Name: "log4j-core", + Version: "2.6.1", + SrcFile: "pom.xml", + Properties: []core.Property{ + { + Name: core.PropertyPkgID, + Value: "2ff14136-e09f-4df9-80ea-000000000003", + }, + { + Name: core.PropertyPkgType, + Value: "pom", + }, + }, + PkgIdentifier: ftypes.PkgIdentifier{ + UID: "d249736f7ddaaf4f", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeMaven, + Namespace: "org.apache.logging.log4j", + Name: "log4j-core", + Version: "2.6.1", + }, + BOMRef: "3ff14136-e09f-4df9-80ea-000000000006", + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000007"): { + Type: core.TypeLibrary, + Group: "org.apache.logging.log4j", + Name: "log4j-core", + Version: "2.6.1", + SrcFile: "pom.xml", + Properties: []core.Property{ + { + Name: core.PropertyPkgID, + Value: "2ff14136-e09f-4df9-80ea-000000000005", + }, + { + Name: core.PropertyPkgType, + Value: "pom", + }, + }, + PkgIdentifier: ftypes.PkgIdentifier{ + UID: "2955bd45b32b9058", + PURL: &packageurl.PackageURL{ + Type: packageurl.TypeMaven, + Namespace: "org.apache.logging.log4j", + Name: "log4j-core", + Version: "2.6.1", + }, + BOMRef: "3ff14136-e09f-4df9-80ea-000000000007", + }, + }, + }, + wantRels: map[uuid.UUID][]core.Relationship{ + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000001"): { + { + Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000002"), + Type: core.RelationshipContains, + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000002"): { + { + Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000003"), + Type: core.RelationshipContains, + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000003"): { + { + Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000006"), + Type: core.RelationshipContains, + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000004"): { + { + Dependency: uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000007"), + Type: core.RelationshipContains, + }, + }, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000006"): nil, + uuid.MustParse("3ff14136-e09f-4df9-80ea-000000000007"): nil, + }, + wantVulns: make(map[uuid.UUID][]core.Vulnerability), + }, { name: "json file created from SBOM file (BOM is empty)", report: types.Report{