Files
syft/internal/task/unknowns_tasks_test.go

121 lines
4.9 KiB
Go

package task
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/cataloging"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/sbom"
)
func Test_unknownsLabeler_archiveReasonsSurvivePackages(t *testing.T) {
jar := file.NewCoordinates("/app.jar", "")
p := pkg.Package{Name: "app", Locations: file.NewLocationSet(file.NewLocationFromCoordinates(jar))}
p.SetID()
s := &sbom.SBOM{Artifacts: sbom.Artifacts{
Packages: pkg.NewCollection(p),
Unknowns: map[file.Coordinates][]string{jar: {
formatUnknown("archive cataloged from part of its contents: too big", ArchiveCatalogerTaskName),
formatUnknown("unable to read manifest", "java-archive-cataloger"),
}},
}}
unknownsLabelerTask{cataloging.UnknownsConfig{RemoveWhenPackagesDefined: true}}.finalize(file.NewMockResolverForPaths(), s)
assert.Equal(t, []string{formatUnknown("archive cataloged from part of its contents: too big", ArchiveCatalogerTaskName)}, s.Artifacts.Unknowns[jar],
"a package describing the archive explains a parse failure, not contents left out")
}
func Test_unknownsLabeler_archiveContentsAreReportedByFullPath(t *testing.T) {
// a package describing an archive does not account for the files within it
war := file.NewCoordinates("/app.war", "layer")
in := func(fullPath string) file.Coordinates {
return file.Coordinates{RealPath: "/app.war", FileSystemID: "layer", FullPath: fullPath}
}
nativeLib := in("/app.war!/WEB-INF/lib/jna.jar!/linux-x86-64/libjnidispatch.so")
unidentifiedJar := in("/app.war!/WEB-INF/lib/javax.inject-1.jar")
p := pkg.Package{Name: "app", Locations: file.NewLocationSet(file.NewLocationFromCoordinates(war))}
p.SetID()
noPackage := formatUnknown("no package identified in archive", "java-archive-cataloger")
s := &sbom.SBOM{
Artifacts: sbom.Artifacts{
Packages: pkg.NewCollection(p),
Executables: map[file.Coordinates]file.Executable{nativeLib: {}},
Unknowns: map[file.Coordinates][]string{unidentifiedJar: {noPackage}},
},
Relationships: []artifact.Relationship{{From: war, To: unidentifiedJar, Type: artifact.ContainsRelationship}},
}
unknownsLabelerTask{cataloging.UnknownsConfig{RemoveWhenPackagesDefined: true, IncludeExecutablesWithoutPackages: true}}.finalize(file.NewMockResolverForPaths(), s)
assert.Equal(t, map[file.Coordinates][]string{
nativeLib: {formatUnknown("no package identified in executable file", unknownsLabelerTaskName)},
unidentifiedJar: {noPackage},
}, s.Artifacts.Unknowns)
}
func Test_unknownsLabeler_relativeOwnedPathsNameNothingInAnArchive(t *testing.T) {
// a python RECORD lists paths relative to site-packages, which resolve nowhere at the scan root either
whl := func(fullPath string) file.Coordinates {
return file.Coordinates{RealPath: "/pip.whl", FullPath: fullPath}
}
tool := whl("/pip.whl!/pip/tool")
p := pkg.Package{
Name: "pip",
Locations: file.NewLocationSet(file.NewLocationFromCoordinates(whl("/pip.whl!/pip.dist-info/METADATA"))),
Metadata: pkg.PythonPackage{Files: []pkg.PythonFileRecord{{Path: "pip/tool"}}},
}
p.SetID()
s := &sbom.SBOM{Artifacts: sbom.Artifacts{
Packages: pkg.NewCollection(p),
Executables: map[file.Coordinates]file.Executable{tool: {}},
}}
unknownsLabelerTask{cataloging.UnknownsConfig{IncludeExecutablesWithoutPackages: true}}.finalize(file.NewMockResolverForPaths(), s)
assert.NotEmpty(t, s.Artifacts.Unknowns[tool])
}
func Test_unknownsLabeler_ownedFilesAreWithinTheOwnersContainer(t *testing.T) {
atRoot := file.NewCoordinates("/usr/bin/foo", "")
inArchive := file.Coordinates{RealPath: "/rootfs.tar", FullPath: "/rootfs.tar!/usr/bin/foo"}
owner := func(at file.Coordinates) pkg.Package {
p := pkg.Package{
Name: "owner",
Type: pkg.RpmPkg,
Locations: file.NewLocationSet(file.NewLocationFromCoordinates(at)),
Metadata: pkg.RpmDBEntry{Files: []pkg.RpmFileRecord{{Path: "/usr/bin/foo"}}},
}
p.SetID()
return p
}
tests := []struct {
name string
owner file.Coordinates
referenced file.Coordinates
}{
{name: "an owner at the scan root", owner: file.NewCoordinates("/var/lib/rpm/Packages", ""), referenced: atRoot},
{name: "an owner inside an archive", owner: file.Coordinates{RealPath: "/rootfs.tar", FullPath: "/rootfs.tar!/var/lib/rpm/Packages"}, referenced: inArchive},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s := &sbom.SBOM{Artifacts: sbom.Artifacts{
Packages: pkg.NewCollection(owner(tt.owner)),
Executables: map[file.Coordinates]file.Executable{atRoot: {}, inArchive: {}},
}}
unknownsLabelerTask{cataloging.UnknownsConfig{IncludeExecutablesWithoutPackages: true}}.finalize(file.NewMockResolverForPaths("/usr/bin/foo"), s)
for _, exe := range []file.Coordinates{atRoot, inArchive} {
assert.Equal(t, exe != tt.referenced, len(s.Artifacts.Unknowns[exe]) > 0, exe.FullNestedPath())
}
})
}
}