fix: discover deb file relationships in distroless images (#1901)

Signed-off-by: Weston Steimel <weston.steimel@anchore.com>
This commit is contained in:
Weston Steimel 2023-06-28 13:28:20 +01:00 committed by GitHub
parent 026be3c0f1
commit 8219f8d55b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 198 additions and 65 deletions

View File

@ -9,16 +9,21 @@ import (
)
func TestDpkgCataloger(t *testing.T) {
licenseLocation := file.NewVirtualLocation("/usr/share/doc/libpam-runtime/copyright", "/usr/share/doc/libpam-runtime/copyright")
expected := []pkg.Package{
tests := []struct {
name string
expected []pkg.Package
}{
{
name: "image-dpkg",
expected: []pkg.Package{
{
Name: "libpam-runtime",
Version: "1.1.8-3.6",
FoundBy: "dpkgdb-cataloger",
Licenses: pkg.NewLicenseSet(
pkg.NewLicenseFromLocations("GPL-1", licenseLocation),
pkg.NewLicenseFromLocations("GPL-2", licenseLocation),
pkg.NewLicenseFromLocations("LGPL-2.1", licenseLocation),
pkg.NewLicenseFromLocations("GPL-1", file.NewVirtualLocation("/usr/share/doc/libpam-runtime/copyright", "/usr/share/doc/libpam-runtime/copyright")),
pkg.NewLicenseFromLocations("GPL-2", file.NewVirtualLocation("/usr/share/doc/libpam-runtime/copyright", "/usr/share/doc/libpam-runtime/copyright")),
pkg.NewLicenseFromLocations("LGPL-2.1", file.NewVirtualLocation("/usr/share/doc/libpam-runtime/copyright", "/usr/share/doc/libpam-runtime/copyright")),
),
Locations: file.NewLocationSet(
file.NewVirtualLocation("/var/lib/dpkg/status", "/var/lib/dpkg/status"),
@ -75,15 +80,80 @@ func TestDpkgCataloger(t *testing.T) {
},
},
},
},
},
{
name: "image-distroless-deb",
expected: []pkg.Package{
{
Name: "libsqlite3-0",
Version: "3.34.1-3",
FoundBy: "dpkgdb-cataloger",
Licenses: pkg.NewLicenseSet(
pkg.NewLicenseFromLocations("public-domain", file.NewVirtualLocation("/usr/share/doc/libsqlite3-0/copyright", "/usr/share/doc/libsqlite3-0/copyright")),
pkg.NewLicenseFromLocations("GPL-2+", file.NewVirtualLocation("/usr/share/doc/libsqlite3-0/copyright", "/usr/share/doc/libsqlite3-0/copyright")),
pkg.NewLicenseFromLocations("GPL-2", file.NewVirtualLocation("/usr/share/doc/libsqlite3-0/copyright", "/usr/share/doc/libsqlite3-0/copyright")),
),
Locations: file.NewLocationSet(
file.NewVirtualLocation("/var/lib/dpkg/status.d/libsqlite3-0", "/var/lib/dpkg/status.d/libsqlite3-0"),
file.NewVirtualLocation("/var/lib/dpkg/status.d/libsqlite3-0.md5sums", "/var/lib/dpkg/status.d/libsqlite3-0.md5sums"),
file.NewVirtualLocation("/usr/share/doc/libsqlite3-0/copyright", "/usr/share/doc/libsqlite3-0/copyright"),
),
Type: pkg.DebPkg,
MetadataType: pkg.DpkgMetadataType,
Metadata: pkg.DpkgMetadata{
Package: "libsqlite3-0",
Source: "sqlite3",
Version: "3.34.1-3",
Architecture: "arm64",
Maintainer: "Laszlo Boszormenyi (GCS) <gcs@debian.org>",
InstalledSize: 1490,
Description: `SQLite 3 shared library
SQLite is a C library that implements an SQL database engine.
Programs that link with the SQLite library can have SQL database
access without running a separate RDBMS process.`,
Files: []pkg.DpkgFileRecord{
{Path: "/usr/lib/aarch64-linux-gnu/libsqlite3.so.0.8.6", Digest: &file.Digest{
Algorithm: "md5",
Value: "e11d70c96979a1328ae4e7e50542782b",
}},
{Path: "/usr/share/doc/libsqlite3-0/README.Debian", Digest: &file.Digest{
Algorithm: "md5",
Value: "9d8facc2fa9d2df52f1c7cb4e5fa4741",
}},
{Path: "/usr/share/doc/libsqlite3-0/changelog.Debian.gz", Digest: &file.Digest{
Algorithm: "md5",
Value: "a58942e742f5056be0595e6ba69a323f",
}},
{Path: "/usr/share/doc/libsqlite3-0/changelog.gz", Digest: &file.Digest{
Algorithm: "md5",
Value: "52317be84c3ca44b7888c6921131e37d",
}},
{Path: "/usr/share/doc/libsqlite3-0/changelog.html.gz", Digest: &file.Digest{
Algorithm: "md5",
Value: "a856310354e6c8768e85b39ae838dd0a",
}},
{Path: "/usr/share/doc/libsqlite3-0/copyright", Digest: &file.Digest{
Algorithm: "md5",
Value: "be64db3e095486e5e105652c51199358",
}},
},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := NewDpkgdbCataloger()
pkgtest.NewCatalogTester().
WithImageResolver(t, "image-dpkg").
WithImageResolver(t, tt.name).
IgnoreLocationLayer(). // this fixture can be rebuilt, thus the layer ID will change
Expects(expected, nil).
Expects(tt.expected, nil).
TestCataloger(t, c)
})
}
}
func TestCataloger_Globs(t *testing.T) {

View File

@ -6,6 +6,7 @@ import (
"path"
"path/filepath"
"sort"
"strings"
"github.com/anchore/packageurl-go"
"github.com/anchore/syft/internal"
@ -176,16 +177,24 @@ func fetchMd5Contents(resolver file.Resolver, dbLocation file.Location, m pkg.Dp
return nil, nil
}
parentPath := filepath.Dir(dbLocation.RealPath)
// for typical debian-base distributions, the installed package info is at /var/lib/dpkg/status
// and the md5sum information is under /var/lib/dpkg/info/; however, for distroless the installed
// package info is across multiple files under /var/lib/dpkg/status.d/ and the md5sums are contained in
// the same directory
searchPath := filepath.Dir(dbLocation.RealPath)
if !strings.HasSuffix(searchPath, "status.d") {
searchPath = path.Join(searchPath, "info")
}
// look for /var/lib/dpkg/info/NAME:ARCH.md5sums
name := md5Key(m)
location := resolver.RelativeFileByPath(dbLocation, path.Join(parentPath, "info", name+md5sumsExt))
location := resolver.RelativeFileByPath(dbLocation, path.Join(searchPath, name+md5sumsExt))
if location == nil {
// the most specific key did not work, fallback to just the name
// look for /var/lib/dpkg/info/NAME.md5sums
location = resolver.RelativeFileByPath(dbLocation, path.Join(parentPath, "info", m.Package+md5sumsExt))
location = resolver.RelativeFileByPath(dbLocation, path.Join(searchPath, m.Package+md5sumsExt))
}
if location == nil {

View File

@ -0,0 +1,2 @@
FROM scratch
COPY . .

View File

@ -0,0 +1,30 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: sqlite3
Source: https://www.sqlite.org/cgi/src/dir?ci=trunk
Files: *
Copyright: D. Richard Hipp <drh@hwaci.com>
License: public-domain
The files listed have been put on the public domain by the sqlite3
contributors.
Files: debian/*
Copyright: 2006- Laszlo Boszormenyi (GCS) <gcs@debian.org>,
2005-2006 Tomas Fasth <tomfa@debian.org>,
2001-2005 Andreas Rottmann <rotty@debian.org>
License: GPL-2+
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 as published
by the Free Software Foundation.
.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
.
You should have received a copy of the GNU General Public License along
with this package; if not, write to the Free Software Foundation, Inc.,
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
.
On Debian systems, the full text of the GNU General Public License
version 2 can be found in the file `/usr/share/common-licenses/GPL-2'.

View File

@ -0,0 +1,16 @@
Package: libsqlite3-0
Source: sqlite3
Version: 3.34.1-3
Architecture: arm64
Maintainer: Laszlo Boszormenyi (GCS) <gcs@debian.org>
Installed-Size: 1490
Depends: libc6 (>= 2.29)
Breaks: python-migrate (<< 0.11.0-4~), python3-migrate (<< 0.11.0-4~)
Section: libs
Priority: optional
Multi-Arch: same
Homepage: https://www.sqlite.org/
Description: SQLite 3 shared library
SQLite is a C library that implements an SQL database engine.
Programs that link with the SQLite library can have SQL database
access without running a separate RDBMS process.

View File

@ -0,0 +1,6 @@
e11d70c96979a1328ae4e7e50542782b usr/lib/aarch64-linux-gnu/libsqlite3.so.0.8.6
9d8facc2fa9d2df52f1c7cb4e5fa4741 usr/share/doc/libsqlite3-0/README.Debian
a58942e742f5056be0595e6ba69a323f usr/share/doc/libsqlite3-0/changelog.Debian.gz
52317be84c3ca44b7888c6921131e37d usr/share/doc/libsqlite3-0/changelog.gz
a856310354e6c8768e85b39ae838dd0a usr/share/doc/libsqlite3-0/changelog.html.gz
be64db3e095486e5e105652c51199358 usr/share/doc/libsqlite3-0/copyright