fix: Distinguish openjdk vs jdk when using file source (#3895)

* fix: Distinguish openjdk vs jdk when using file source

Signed-off-by: adammcclenaghan <adam@mcclenaghan.co.uk>

* fix: Fix goimport order

Signed-off-by: adammcclenaghan <adam@mcclenaghan.co.uk>

* add comment

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: adammcclenaghan <adam@mcclenaghan.co.uk>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Adam McClenaghan 2025-05-16 14:29:53 +01:00 committed by GitHub
parent 0480b516f6
commit 8f02bd85f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 130 additions and 1 deletions

View File

@ -27,6 +27,7 @@ import (
"github.com/anchore/syft/syft/pkg/cataloger/generic" "github.com/anchore/syft/syft/pkg/cataloger/generic"
"github.com/anchore/syft/syft/source" "github.com/anchore/syft/syft/source"
"github.com/anchore/syft/syft/source/directorysource" "github.com/anchore/syft/syft/source/directorysource"
"github.com/anchore/syft/syft/source/filesource"
"github.com/anchore/syft/syft/source/stereoscopesource" "github.com/anchore/syft/syft/source/stereoscopesource"
) )
@ -110,6 +111,18 @@ func (p *CatalogTester) FromDirectory(t *testing.T, path string) *CatalogTester
return p return p
} }
func (p *CatalogTester) FromFileSource(t *testing.T, path string) *CatalogTester {
t.Helper()
s, err := filesource.NewFromPath(path)
require.NoError(t, err)
resolver, err := s.FileResolver(source.AllLayersScope)
require.NoError(t, err)
p.resolver = resolver
return p
}
func (p *CatalogTester) FromFile(t *testing.T, path string) *CatalogTester { func (p *CatalogTester) FromFile(t *testing.T, path string) *CatalogTester {
t.Helper() t.Helper()
@ -340,6 +353,11 @@ func TestCataloger(t *testing.T, fixtureDir string, cataloger pkg.Cataloger, exp
NewCatalogTester().FromDirectory(t, fixtureDir).Expects(expectedPkgs, expectedRelationships).TestCataloger(t, cataloger) NewCatalogTester().FromDirectory(t, fixtureDir).Expects(expectedPkgs, expectedRelationships).TestCataloger(t, cataloger)
} }
func TestCatalogerFromFileSource(t *testing.T, fixturePath string, cataloger pkg.Cataloger, expectedPkgs []pkg.Package, expectedRelationships []artifact.Relationship) {
t.Helper()
NewCatalogTester().FromFileSource(t, fixturePath).Expects(expectedPkgs, expectedRelationships).TestCataloger(t, cataloger)
}
func TestFileParserWithEnv(t *testing.T, fixturePath string, parser generic.Parser, env *generic.Environment, expectedPkgs []pkg.Package, expectedRelationships []artifact.Relationship) { func TestFileParserWithEnv(t *testing.T, fixturePath string, parser generic.Parser, env *generic.Environment, expectedPkgs []pkg.Package, expectedRelationships []artifact.Relationship) {
t.Helper() t.Helper()

View File

@ -215,3 +215,111 @@ func TestJvmDistributionCataloger(t *testing.T) {
} }
} }
func TestJvmDistributionCatalogerFromFile(t *testing.T) {
cases := []struct {
name string
fixture string
expected pkg.Package
}{
{
name: "valid 1.8.0",
fixture: "test-fixtures/jvm-installs/oracle-jdk-se-8/usr/lib/jvm/jdk-1.8-oracle-x64/release",
expected: pkg.Package{
Name: "jdk",
Version: "1.8.0_411-b25",
FoundBy: "java-jvm-cataloger",
Locations: file.NewLocationSet(file.NewLocation("/release")),
Licenses: pkg.NewLicenseSet(),
Type: pkg.BinaryPkg,
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:oracle:java_se:1.8.0:update411:*:*:*:*:*:*", cpe.DeclaredSource),
cpe.Must("cpe:2.3:a:oracle:jre:1.8.0:update411:*:*:*:*:*:*", cpe.DeclaredSource),
cpe.Must("cpe:2.3:a:oracle:jdk:1.8.0:update411:*:*:*:*:*:*", cpe.DeclaredSource),
},
PURL: "pkg:generic/oracle/jdk@1.8.0_411-b25",
Metadata: pkg.JavaVMInstallation{
Release: pkg.JavaVMRelease{
JavaRuntimeVersion: "1.8.0_411-b25",
JavaVersion: "1.8.0_411",
OsArch: "amd64",
OsName: "Linux",
OsVersion: "2.6",
Source: ".:git:71ec2089cf8c+",
BuildType: "commercial",
},
Files: []string{
"/release",
},
},
},
},
{
name: "valid post-jep223",
fixture: "test-fixtures/jvm-installs/valid-post-jep223/jvm/openjdk/release",
expected: pkg.Package{
Name: "openjdk",
Version: "21.0.4+7-LTS",
FoundBy: "java-jvm-cataloger",
Locations: file.NewLocationSet(file.NewLocation("/release")),
Licenses: pkg.NewLicenseSet(),
Type: pkg.BinaryPkg,
CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:oracle:openjdk:21.0.4:*:*:*:*:*:*:*", cpe.DeclaredSource)},
PURL: "pkg:generic/oracle/openjdk@21.0.4%2B7-LTS?repository_url=https%3A%2F%2Fgithub.com%2Fadoptium%2Fjdk21u.git",
Metadata: pkg.JavaVMInstallation{
Release: pkg.JavaVMRelease{
Implementor: "Eclipse Adoptium",
ImplementorVersion: "Temurin-21.0.4+7",
JavaRuntimeVersion: "21.0.4+7-LTS",
JavaVersion: "21.0.4",
JavaVersionDate: "2024-07-16",
Libc: "gnu",
Modules: []string{
"java.base", "java.compiler", "java.datatransfer", "java.xml", "java.prefs",
"java.desktop", "java.instrument", "java.logging", "java.management",
"java.security.sasl", "java.naming", "java.rmi", "java.management.rmi",
"java.net.http", "java.scripting", "java.security.jgss",
"java.transaction.xa", "java.sql", "java.sql.rowset", "java.xml.crypto", "java.se",
"java.smartcardio", "jdk.accessibility", "jdk.internal.jvmstat", "jdk.attach",
"jdk.charsets", "jdk.internal.opt", "jdk.zipfs", "jdk.compiler", "jdk.crypto.ec",
"jdk.crypto.cryptoki", "jdk.dynalink", "jdk.internal.ed", "jdk.editpad", "jdk.hotspot.agent",
"jdk.httpserver", "jdk.incubator.vector", "jdk.internal.le", "jdk.internal.vm.ci",
"jdk.internal.vm.compiler", "jdk.internal.vm.compiler.management", "jdk.jartool",
"jdk.javadoc", "jdk.jcmd", "jdk.management", "jdk.management.agent", "jdk.jconsole",
"jdk.jdeps", "jdk.jdwp.agent", "jdk.jdi", "jdk.jfr", "jdk.jlink", "jdk.jpackage", "jdk.jshell",
"jdk.jsobject", "jdk.jstatd", "jdk.localedata", "jdk.management.jfr", "jdk.naming.dns",
"jdk.naming.rmi", "jdk.net", "jdk.nio.mapmode", "jdk.random", "jdk.sctp", "jdk.security.auth",
"jdk.security.jgss", "jdk.unsupported", "jdk.unsupported.desktop", "jdk.xml.dom",
},
OsArch: "aarch64",
OsName: "Linux",
Source: ".:git:13710926b798",
BuildSource: "git:1271f10a26c47e1489a814dd2731f936a588d621",
BuildSourceRepo: "https://github.com/adoptium/temurin-build.git",
SourceRepo: "https://github.com/adoptium/jdk21u.git",
FullVersion: "21.0.4+7-LTS",
SemanticVersion: "21.0.4+7",
BuildInfo: "OS: Linux Version: 5.4.0-150-generic",
JvmVariant: "Hotspot",
JvmVersion: "21.0.4+7-LTS",
ImageType: "JDK",
},
Files: []string{
"/release",
},
},
},
},
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
p := tt.expected
p.SetID()
pkgtest.TestCatalogerFromFileSource(t, tt.fixture, NewJvmDistributionCataloger(), []pkg.Package{p}, nil)
})
}
}

View File

@ -88,7 +88,10 @@ func parseJVMRelease(_ context.Context, resolver file.Resolver, _ *generic.Envir
installDir := path.Dir(reader.Path()) installDir := path.Dir(reader.Path())
files, hasJdk := findJvmFiles(resolver, installDir) files, hasJdk := findJvmFiles(resolver, installDir)
vendor, product := jvmPrimaryVendorProduct(ri.Implementor, reader.Path(), ri.ImageType, hasJdk) // the reason we use the reference to get the real path is in cases where the file cataloger is involved
// (thus the real path is not available except for in the original file reference). This is important
// since the path is critical for distinguishing between different JVM vendors.
vendor, product := jvmPrimaryVendorProduct(ri.Implementor, string(reader.Reference().RealPath), ri.ImageType, hasJdk)
p := pkg.Package{ p := pkg.Package{
Name: product, Name: product,