From ae7cd6bbb7866f55ec4c5030a2c94a0239d4ca68 Mon Sep 17 00:00:00 2001 From: Dan Luhring Date: Wed, 27 Jan 2021 10:07:54 -0500 Subject: [PATCH 1/4] Add test for Java cataloging with no main package Signed-off-by: Dan Luhring --- test/integration/java_no_main_package_test.go | 20 ++++++++++++++++ .../image-java-no-main-package/Dockerfile | 23 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 test/integration/java_no_main_package_test.go create mode 100644 test/integration/test-fixtures/image-java-no-main-package/Dockerfile diff --git a/test/integration/java_no_main_package_test.go b/test/integration/java_no_main_package_test.go new file mode 100644 index 000000000..e330a78fb --- /dev/null +++ b/test/integration/java_no_main_package_test.go @@ -0,0 +1,20 @@ +package integration + +import ( + "github.com/anchore/stereoscope/pkg/imagetest" + "github.com/anchore/syft/syft" + "github.com/anchore/syft/syft/source" + "testing" +) + +func TestJavaNoMainPackage(t *testing.T) { // Regression: https://github.com/anchore/syft/issues/252 + fixtureImageName := "image-java-no-main-package" + _, cleanup := imagetest.GetFixtureImage(t, "docker-archive", fixtureImageName) + tarPath := imagetest.GetFixtureImageTarPath(t, fixtureImageName) + defer cleanup() + + _, _, _, err := syft.Catalog("docker-archive:"+tarPath, source.SquashedScope) + if err != nil { + t.Fatalf("failed to catalog image: %+v", err) + } +} diff --git a/test/integration/test-fixtures/image-java-no-main-package/Dockerfile b/test/integration/test-fixtures/image-java-no-main-package/Dockerfile new file mode 100644 index 000000000..c6100ae44 --- /dev/null +++ b/test/integration/test-fixtures/image-java-no-main-package/Dockerfile @@ -0,0 +1,23 @@ +FROM jenkins:2.60.3 + +USER root + +WORKDIR /usr/share/jenkins + +RUN mkdir tmp + +WORKDIR /usr/share/jenkins/tmp + +RUN apt-get update 2>&1 > /dev/null && apt-get install -y less zip 2>&1 > /dev/null + +RUN unzip ../jenkins.war 2>&1 > /dev/null + +RUN rm -f ./META-INF/MANIFEST.MF + +WORKDIR /usr/share/jenkins + +RUN rm -rf jenkins.war + +RUN cd ./tmp && zip -r ../jenkins.war . && cd .. + +RUN rm -rf ./tmp From bb1facbf81c3c9a86f25ed7da7e81306447c219f Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 16 Dec 2020 17:23:39 -0500 Subject: [PATCH 2/4] ensure java parent pkg ref isnt nil when looking for parent matches Signed-off-by: Alex Goodman --- syft/cataloger/java/archive_parser.go | 48 +++++++++++++++------------ 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/syft/cataloger/java/archive_parser.go b/syft/cataloger/java/archive_parser.go index b25772304..770643a28 100644 --- a/syft/cataloger/java/archive_parser.go +++ b/syft/cataloger/java/archive_parser.go @@ -184,7 +184,7 @@ func (j *archiveParser) discoverPkgsFromPomProperties(parentPkg *pkg.Package) ([ // keep the artifact name within the virtual path if this package does not match the parent package vPathSuffix := "" - if !strings.HasPrefix(propsObj.ArtifactID, parentPkg.Name) { + if parentPkg != nil && !strings.HasPrefix(propsObj.ArtifactID, parentPkg.Name) { vPathSuffix += ":" + propsObj.ArtifactID } virtualPath := j.virtualPath + vPathSuffix @@ -208,30 +208,34 @@ func (j *archiveParser) discoverPkgsFromPomProperties(parentPkg *pkg.Package) ([ // the name/version pair matches... matchesParentPkg := pkgKey == parentKey - // the virtual path matches... - matchesParentPkg = matchesParentPkg || parentPkg.Metadata.(pkg.JavaMetadata).VirtualPath == virtualPath + if parentPkg != nil { + // the virtual path matches... + matchesParentPkg = matchesParentPkg || parentPkg.Metadata.(pkg.JavaMetadata).VirtualPath == virtualPath - // the pom artifactId has the parent name or vice versa - if propsObj.ArtifactID != "" { - matchesParentPkg = matchesParentPkg || strings.Contains(parentPkg.Name, propsObj.ArtifactID) || strings.Contains(propsObj.ArtifactID, parentPkg.Name) + // the pom artifactId has the parent name or vice versa + if propsObj.ArtifactID != "" { + matchesParentPkg = matchesParentPkg || strings.Contains(parentPkg.Name, propsObj.ArtifactID) || strings.Contains(propsObj.ArtifactID, parentPkg.Name) + } + + if matchesParentPkg { + // we've run across more information about our parent package, add this info to the parent package metadata + // the pom properties is typically a better source of information for name and version than the manifest + if p.Name != parentPkg.Name { + parentPkg.Name = p.Name + } + if p.Version != parentPkg.Version { + parentPkg.Version = p.Version + } + + parentMetadata, ok := parentPkg.Metadata.(pkg.JavaMetadata) + if ok { + parentMetadata.PomProperties = propsObj + parentPkg.Metadata = parentMetadata + } + } } - if matchesParentPkg { - // we've run across more information about our parent package, add this info to the parent package metadata - // the pom properties is typically a better source of information for name and version than the manifest - if p.Name != parentPkg.Name { - parentPkg.Name = p.Name - } - if p.Version != parentPkg.Version { - parentPkg.Version = p.Version - } - - parentMetadata, ok := parentPkg.Metadata.(pkg.JavaMetadata) - if ok { - parentMetadata.PomProperties = propsObj - parentPkg.Metadata = parentMetadata - } - } else if !j.discoveredPkgs.Contains(pkgKey) { + if !matchesParentPkg && !j.discoveredPkgs.Contains(pkgKey) { // only keep packages we haven't seen yet (and are not related to the parent package) pkgs = append(pkgs, p) } From 0ccfee03f1bff1c46b7d43c2f91010758ef64bf3 Mon Sep 17 00:00:00 2001 From: Dan Luhring Date: Wed, 27 Jan 2021 10:30:49 -0500 Subject: [PATCH 3/4] Fix dependency resolution issue in test image Signed-off-by: Dan Luhring --- test/integration/test-fixtures/image-large-apk-data/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/test-fixtures/image-large-apk-data/Dockerfile b/test/integration/test-fixtures/image-large-apk-data/Dockerfile index 357f0a5d9..98ccb7373 100644 --- a/test/integration/test-fixtures/image-large-apk-data/Dockerfile +++ b/test/integration/test-fixtures/image-large-apk-data/Dockerfile @@ -1,5 +1,5 @@ FROM alpine@sha256:d9a7354e3845ea8466bb00b22224d9116b183e594527fb5b6c3d30bc01a20378 RUN apk add --no-cache \ - tzdata=2020f-r0 \ + tzdata=2021a-r0 \ vim=8.2.2320-r0 \ alpine-sdk=1.0-r0 From 1416e3cb7af44dc0bc616f3e30c4730a73d561eb Mon Sep 17 00:00:00 2001 From: Dan Luhring Date: Wed, 27 Jan 2021 10:34:52 -0500 Subject: [PATCH 4/4] Invert if statement to reduce nesting in archive parser Signed-off-by: Dan Luhring --- syft/cataloger/java/archive_parser.go | 106 +++++++++++++------------- 1 file changed, 54 insertions(+), 52 deletions(-) diff --git a/syft/cataloger/java/archive_parser.go b/syft/cataloger/java/archive_parser.go index 770643a28..7b103e9b8 100644 --- a/syft/cataloger/java/archive_parser.go +++ b/syft/cataloger/java/archive_parser.go @@ -178,67 +178,69 @@ func (j *archiveParser) discoverPkgsFromPomProperties(parentPkg *pkg.Package) ([ return nil, fmt.Errorf("failed to parse pom.properties (%s): %w", j.virtualPath, err) } - if propsObj != nil { - if propsObj.Version != "" && propsObj.ArtifactID != "" { - // TODO: if there is no parentPkg (no java manifest) one of these poms could be the parent. We should discover the right parent and attach the correct info accordingly to each discovered package + if propsObj == nil { + continue + } - // keep the artifact name within the virtual path if this package does not match the parent package - vPathSuffix := "" - if parentPkg != nil && !strings.HasPrefix(propsObj.ArtifactID, parentPkg.Name) { - vPathSuffix += ":" + propsObj.ArtifactID - } - virtualPath := j.virtualPath + vPathSuffix + if propsObj.Version != "" && propsObj.ArtifactID != "" { + // TODO: if there is no parentPkg (no java manifest) one of these poms could be the parent. We should discover the right parent and attach the correct info accordingly to each discovered package - // discovered props = new package - p := pkg.Package{ - Name: propsObj.ArtifactID, - Version: propsObj.Version, - Language: pkg.Java, - Type: pkg.JavaPkg, - MetadataType: pkg.JavaMetadataType, - Metadata: pkg.JavaMetadata{ - VirtualPath: virtualPath, - PomProperties: propsObj, - Parent: parentPkg, - }, + // keep the artifact name within the virtual path if this package does not match the parent package + vPathSuffix := "" + if parentPkg != nil && !strings.HasPrefix(propsObj.ArtifactID, parentPkg.Name) { + vPathSuffix += ":" + propsObj.ArtifactID + } + virtualPath := j.virtualPath + vPathSuffix + + // discovered props = new package + p := pkg.Package{ + Name: propsObj.ArtifactID, + Version: propsObj.Version, + Language: pkg.Java, + Type: pkg.JavaPkg, + MetadataType: pkg.JavaMetadataType, + Metadata: pkg.JavaMetadata{ + VirtualPath: virtualPath, + PomProperties: propsObj, + Parent: parentPkg, + }, + } + + pkgKey := uniquePkgKey(&p) + + // the name/version pair matches... + matchesParentPkg := pkgKey == parentKey + + if parentPkg != nil { + // the virtual path matches... + matchesParentPkg = matchesParentPkg || parentPkg.Metadata.(pkg.JavaMetadata).VirtualPath == virtualPath + + // the pom artifactId has the parent name or vice versa + if propsObj.ArtifactID != "" { + matchesParentPkg = matchesParentPkg || strings.Contains(parentPkg.Name, propsObj.ArtifactID) || strings.Contains(propsObj.ArtifactID, parentPkg.Name) } - pkgKey := uniquePkgKey(&p) - - // the name/version pair matches... - matchesParentPkg := pkgKey == parentKey - - if parentPkg != nil { - // the virtual path matches... - matchesParentPkg = matchesParentPkg || parentPkg.Metadata.(pkg.JavaMetadata).VirtualPath == virtualPath - - // the pom artifactId has the parent name or vice versa - if propsObj.ArtifactID != "" { - matchesParentPkg = matchesParentPkg || strings.Contains(parentPkg.Name, propsObj.ArtifactID) || strings.Contains(propsObj.ArtifactID, parentPkg.Name) + if matchesParentPkg { + // we've run across more information about our parent package, add this info to the parent package metadata + // the pom properties is typically a better source of information for name and version than the manifest + if p.Name != parentPkg.Name { + parentPkg.Name = p.Name + } + if p.Version != parentPkg.Version { + parentPkg.Version = p.Version } - if matchesParentPkg { - // we've run across more information about our parent package, add this info to the parent package metadata - // the pom properties is typically a better source of information for name and version than the manifest - if p.Name != parentPkg.Name { - parentPkg.Name = p.Name - } - if p.Version != parentPkg.Version { - parentPkg.Version = p.Version - } - - parentMetadata, ok := parentPkg.Metadata.(pkg.JavaMetadata) - if ok { - parentMetadata.PomProperties = propsObj - parentPkg.Metadata = parentMetadata - } + parentMetadata, ok := parentPkg.Metadata.(pkg.JavaMetadata) + if ok { + parentMetadata.PomProperties = propsObj + parentPkg.Metadata = parentMetadata } } + } - if !matchesParentPkg && !j.discoveredPkgs.Contains(pkgKey) { - // only keep packages we haven't seen yet (and are not related to the parent package) - pkgs = append(pkgs, p) - } + if !matchesParentPkg && !j.discoveredPkgs.Contains(pkgKey) { + // only keep packages we haven't seen yet (and are not related to the parent package) + pkgs = append(pkgs, p) } } }