From e0e33b8be5f0aabfe7dd6f9c590acbb35a1a3e60 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Wed, 16 Aug 2023 15:32:11 -0400 Subject: [PATCH 1/3] feat: use java package names to determine known groupids Signed-off-by: Keith Zantow --- syft/pkg/cataloger/common/cpe/java.go | 45 ++++++++++++++++++++-- syft/pkg/cataloger/common/cpe/java_test.go | 36 +++++++++++++++++ syft/pkg/cataloger/java/package_url.go | 2 +- 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/syft/pkg/cataloger/common/cpe/java.go b/syft/pkg/cataloger/common/cpe/java.go index 6de454c06af..94865c9c787 100644 --- a/syft/pkg/cataloger/common/cpe/java.go +++ b/syft/pkg/cataloger/common/cpe/java.go @@ -41,6 +41,39 @@ var ( } ) +var defaultArtifactIDToGroupID = map[string]string{ + "spring": "org.springframework", + "spring-amqp": "org.springframework.amqp", + "spring-batch-core": "org.springframework.batch", + "spring-beans": "org.springframework", + "spring-boot": "org.springframework.boot", + "spring-boot-starter-web": "org.springframework.boot", + "spring-boot-starter-webflux": "org.springframework.boot", + "spring-cloud-function-context": "org.springframework.cloud", + "spring-cloud-function-parent": "org.springframework.cloud", + "spring-cloud-gateway": "org.springframework.cloud", + "spring-cloud-openfeign-core": "org.springframework.cloud", + "spring-cloud-task-dependencies": "org.springframework.cloud", + "spring-core": "org.springframework", + "spring-data-jpa": "org.springframework.data", + "spring-data-mongodb": "org.springframework.data", + "spring-data-rest-core": "org.springframework.data", + "spring-expression": "org.springframework", + "spring-integration-zip": "org.springframework.integration", + "spring-oxm": "org.springframework", + "spring-security-core": "org.springframework.security", + "spring-security-config": "org.springframework.security", + "spring-security-oauth": "org.springframework.security.oauth", + "spring-security-oauth-parent": "org.springframework.security.oauth", + "spring-security-oauth2-client": "org.springframework.security", + "spring-session-core": "org.springframework.session", + "spring-vault-core": "org.springframework.vault", + "spring-web": "org.springframework", + "spring-webflow": "org.springframework.webflow", + "spring-webflux": "org.springframework", + "spring-webmvc": "org.springframework", +} + func candidateProductsForJava(p pkg.Package) []string { return productsFromArtifactAndGroupIDs(artifactIDFromJavaPackage(p), GroupIDsFromJavaPackage(p)) } @@ -181,13 +214,13 @@ func GroupIDsFromJavaPackage(p pkg.Package) (groupIDs []string) { return nil } - return GroupIDsFromJavaMetadata(metadata) + return GroupIDsFromJavaMetadata(p.Name, metadata) } -func GroupIDsFromJavaMetadata(metadata pkg.JavaMetadata) (groupIDs []string) { +func GroupIDsFromJavaMetadata(pkgName string, metadata pkg.JavaMetadata) (groupIDs []string) { groupIDs = append(groupIDs, groupIDsFromPomProperties(metadata.PomProperties)...) groupIDs = append(groupIDs, groupIDsFromPomProject(metadata.PomProject)...) - groupIDs = append(groupIDs, groupIDsFromJavaManifest(metadata.Manifest)...) + groupIDs = append(groupIDs, groupIDsFromJavaManifest(pkgName, metadata.Manifest)...) return groupIDs } @@ -241,11 +274,15 @@ func addGroupIDsFromGroupIDsAndArtifactID(groupID, artifactID string) (groupIDs return groupIDs } -func groupIDsFromJavaManifest(manifest *pkg.JavaManifest) []string { +func groupIDsFromJavaManifest(pkgName string, manifest *pkg.JavaManifest) []string { if manifest == nil { return nil } + if groupID, ok := defaultArtifactIDToGroupID[pkgName]; ok { + return []string{groupID} + } + // try the common manifest fields first for a set of candidates groupIDs := getManifestFieldGroupIDs(manifest, primaryJavaManifestGroupIDFields) diff --git a/syft/pkg/cataloger/common/cpe/java_test.go b/syft/pkg/cataloger/common/cpe/java_test.go index c27e2ac5b57..9d75014ac48 100644 --- a/syft/pkg/cataloger/common/cpe/java_test.go +++ b/syft/pkg/cataloger/common/cpe/java_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/anchore/syft/syft/pkg" ) @@ -427,3 +428,38 @@ func Test_vendorsFromJavaManifestNames(t *testing.T) { }) } } + +func Test_groupIDsFromJavaManifest(t *testing.T) { + tests := []struct { + name string + manifest pkg.JavaManifest + expected []string + }{ + { + name: "spring-security-core", + manifest: pkg.JavaManifest{}, + expected: []string{"org.springframework.security"}, + }, + { + name: "spring-web", + manifest: pkg.JavaManifest{}, + expected: []string{"org.springframework"}, + }, + { + name: "spring-foo", + manifest: pkg.JavaManifest{ + Main: map[string]string{ + "Implementation-Vendor": "org.foo", + }, + }, + expected: []string{"org.foo"}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := groupIDsFromJavaManifest(test.name, &test.manifest) + require.Equal(t, test.expected, got) + }) + } +} diff --git a/syft/pkg/cataloger/java/package_url.go b/syft/pkg/cataloger/java/package_url.go index b091ac383cf..adf05ff74e8 100644 --- a/syft/pkg/cataloger/java/package_url.go +++ b/syft/pkg/cataloger/java/package_url.go @@ -9,7 +9,7 @@ import ( // PackageURL returns the PURL for the specific java package (see https://github.com/package-url/purl-spec) func packageURL(name, version string, metadata pkg.JavaMetadata) string { var groupID = name - groupIDs := cpe.GroupIDsFromJavaMetadata(metadata) + groupIDs := cpe.GroupIDsFromJavaMetadata(name, metadata) if len(groupIDs) > 0 { groupID = groupIDs[0] } From 441127387b393146f8d48ed80eaefbf1d8b06bd6 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Thu, 17 Aug 2023 11:45:08 -0400 Subject: [PATCH 2/3] chore: PR feedback Signed-off-by: Keith Zantow --- syft/pkg/cataloger/common/cpe/java.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/syft/pkg/cataloger/common/cpe/java.go b/syft/pkg/cataloger/common/cpe/java.go index 94865c9c787..5b1f295283a 100644 --- a/syft/pkg/cataloger/common/cpe/java.go +++ b/syft/pkg/cataloger/common/cpe/java.go @@ -275,14 +275,14 @@ func addGroupIDsFromGroupIDsAndArtifactID(groupID, artifactID string) (groupIDs } func groupIDsFromJavaManifest(pkgName string, manifest *pkg.JavaManifest) []string { - if manifest == nil { - return nil - } - if groupID, ok := defaultArtifactIDToGroupID[pkgName]; ok { return []string{groupID} } + if manifest == nil { + return nil + } + // try the common manifest fields first for a set of candidates groupIDs := getManifestFieldGroupIDs(manifest, primaryJavaManifestGroupIDFields) From 86c096e6b4e602ad18a322d00eb52cadd41c3a00 Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Thu, 17 Aug 2023 12:18:14 -0400 Subject: [PATCH 3/3] chore: add apache ant groupIDs Signed-off-by: Keith Zantow --- syft/pkg/cataloger/common/cpe/java.go | 33 --------- .../cataloger/common/cpe/java_groupid_map.go | 69 +++++++++++++++++++ 2 files changed, 69 insertions(+), 33 deletions(-) create mode 100644 syft/pkg/cataloger/common/cpe/java_groupid_map.go diff --git a/syft/pkg/cataloger/common/cpe/java.go b/syft/pkg/cataloger/common/cpe/java.go index 5b1f295283a..2e838de3010 100644 --- a/syft/pkg/cataloger/common/cpe/java.go +++ b/syft/pkg/cataloger/common/cpe/java.go @@ -41,39 +41,6 @@ var ( } ) -var defaultArtifactIDToGroupID = map[string]string{ - "spring": "org.springframework", - "spring-amqp": "org.springframework.amqp", - "spring-batch-core": "org.springframework.batch", - "spring-beans": "org.springframework", - "spring-boot": "org.springframework.boot", - "spring-boot-starter-web": "org.springframework.boot", - "spring-boot-starter-webflux": "org.springframework.boot", - "spring-cloud-function-context": "org.springframework.cloud", - "spring-cloud-function-parent": "org.springframework.cloud", - "spring-cloud-gateway": "org.springframework.cloud", - "spring-cloud-openfeign-core": "org.springframework.cloud", - "spring-cloud-task-dependencies": "org.springframework.cloud", - "spring-core": "org.springframework", - "spring-data-jpa": "org.springframework.data", - "spring-data-mongodb": "org.springframework.data", - "spring-data-rest-core": "org.springframework.data", - "spring-expression": "org.springframework", - "spring-integration-zip": "org.springframework.integration", - "spring-oxm": "org.springframework", - "spring-security-core": "org.springframework.security", - "spring-security-config": "org.springframework.security", - "spring-security-oauth": "org.springframework.security.oauth", - "spring-security-oauth-parent": "org.springframework.security.oauth", - "spring-security-oauth2-client": "org.springframework.security", - "spring-session-core": "org.springframework.session", - "spring-vault-core": "org.springframework.vault", - "spring-web": "org.springframework", - "spring-webflow": "org.springframework.webflow", - "spring-webflux": "org.springframework", - "spring-webmvc": "org.springframework", -} - func candidateProductsForJava(p pkg.Package) []string { return productsFromArtifactAndGroupIDs(artifactIDFromJavaPackage(p), GroupIDsFromJavaPackage(p)) } diff --git a/syft/pkg/cataloger/common/cpe/java_groupid_map.go b/syft/pkg/cataloger/common/cpe/java_groupid_map.go new file mode 100644 index 00000000000..9e36db185f3 --- /dev/null +++ b/syft/pkg/cataloger/common/cpe/java_groupid_map.go @@ -0,0 +1,69 @@ +package cpe + +var defaultArtifactIDToGroupID = map[string]string{ + "ant": "org.apache.ant", + "ant-antlr": "org.apache.ant", + "ant-antunit": "org.apache.ant", + "ant-apache-bcel": "org.apache.ant", + "ant-apache-bsf": "org.apache.ant", + "ant-apache-log4j": "org.apache.ant", + "ant-apache-oro": "org.apache.ant", + "ant-apache-regexp": "org.apache.ant", + "ant-apache-resolver": "org.apache.ant", + "ant-apache-xalan2": "org.apache.ant", + "ant-commons-logging": "org.apache.ant", + "ant-commons-net": "org.apache.ant", + "ant-compress": "org.apache.ant", + "ant-dotnet": "org.apache.ant", + "ant-imageio": "org.apache.ant", + "ant-jai": "org.apache.ant", + "ant-jakartamail": "org.apache.ant", + "ant-javamail": "org.apache.ant", + "ant-jdepend": "org.apache.ant", + "ant-jmf": "org.apache.ant", + "ant-jsch": "org.apache.ant", + "ant-junit": "org.apache.ant", + "ant-junit4": "org.apache.ant", + "ant-junitlauncher": "org.apache.ant", + "ant-launcher": "org.apache.ant", + "ant-netrexx": "org.apache.ant", + "ant-nodeps": "org.apache.ant", + "ant-parent": "org.apache.ant", + "ant-starteam": "org.apache.ant", + "ant-stylebook": "org.apache.ant", + "ant-swing": "org.apache.ant", + "ant-testutil": "org.apache.ant", + "ant-trax": "org.apache.ant", + "ant-weblogic": "org.apache.ant", + "ant-xz": "org.apache.ant", + "spring": "org.springframework", + "spring-amqp": "org.springframework.amqp", + "spring-batch-core": "org.springframework.batch", + "spring-beans": "org.springframework", + "spring-boot": "org.springframework.boot", + "spring-boot-starter-web": "org.springframework.boot", + "spring-boot-starter-webflux": "org.springframework.boot", + "spring-cloud-function-context": "org.springframework.cloud", + "spring-cloud-function-parent": "org.springframework.cloud", + "spring-cloud-gateway": "org.springframework.cloud", + "spring-cloud-openfeign-core": "org.springframework.cloud", + "spring-cloud-task-dependencies": "org.springframework.cloud", + "spring-core": "org.springframework", + "spring-data-jpa": "org.springframework.data", + "spring-data-mongodb": "org.springframework.data", + "spring-data-rest-core": "org.springframework.data", + "spring-expression": "org.springframework", + "spring-integration-zip": "org.springframework.integration", + "spring-oxm": "org.springframework", + "spring-security-core": "org.springframework.security", + "spring-security-config": "org.springframework.security", + "spring-security-oauth": "org.springframework.security.oauth", + "spring-security-oauth-parent": "org.springframework.security.oauth", + "spring-security-oauth2-client": "org.springframework.security", + "spring-session-core": "org.springframework.session", + "spring-vault-core": "org.springframework.vault", + "spring-web": "org.springframework", + "spring-webflow": "org.springframework.webflow", + "spring-webflux": "org.springframework", + "spring-webmvc": "org.springframework", +}