Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: discover deb file relationships in distroless images #1901

Merged
merged 1 commit into from
Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 132 additions & 62 deletions syft/pkg/cataloger/deb/cataloger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,81 +9,151 @@ 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: "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),
),
Locations: file.NewLocationSet(
file.NewVirtualLocation("/var/lib/dpkg/status", "/var/lib/dpkg/status"),
file.NewVirtualLocation("/var/lib/dpkg/info/libpam-runtime.md5sums", "/var/lib/dpkg/info/libpam-runtime.md5sums"),
file.NewVirtualLocation("/var/lib/dpkg/info/libpam-runtime.conffiles", "/var/lib/dpkg/info/libpam-runtime.conffiles"),
file.NewVirtualLocation("/usr/share/doc/libpam-runtime/copyright", "/usr/share/doc/libpam-runtime/copyright"),
),
Type: pkg.DebPkg,
MetadataType: pkg.DpkgMetadataType,
Metadata: pkg.DpkgMetadata{
Package: "libpam-runtime",
Source: "pam",
Version: "1.1.8-3.6",
Architecture: "all",
Maintainer: "Steve Langasek <vorlon@debian.org>",
InstalledSize: 1016,
Description: `Runtime support for the PAM library
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", 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"),
file.NewVirtualLocation("/var/lib/dpkg/info/libpam-runtime.md5sums", "/var/lib/dpkg/info/libpam-runtime.md5sums"),
file.NewVirtualLocation("/var/lib/dpkg/info/libpam-runtime.conffiles", "/var/lib/dpkg/info/libpam-runtime.conffiles"),
file.NewVirtualLocation("/usr/share/doc/libpam-runtime/copyright", "/usr/share/doc/libpam-runtime/copyright"),
),
Type: pkg.DebPkg,
MetadataType: pkg.DpkgMetadataType,
Metadata: pkg.DpkgMetadata{
Package: "libpam-runtime",
Source: "pam",
Version: "1.1.8-3.6",
Architecture: "all",
Maintainer: "Steve Langasek <vorlon@debian.org>",
InstalledSize: 1016,
Description: `Runtime support for the PAM library
Contains configuration files and directories required for
authentication to work on Debian systems. This package is required
on almost all installations.`,
Files: []pkg.DpkgFileRecord{
{
Path: "/etc/pam.conf",
Digest: &file.Digest{
Algorithm: "md5",
Value: "87fc76f18e98ee7d3848f6b81b3391e5",
Files: []pkg.DpkgFileRecord{
{
Path: "/etc/pam.conf",
Digest: &file.Digest{
Algorithm: "md5",
Value: "87fc76f18e98ee7d3848f6b81b3391e5",
},
IsConfigFile: true,
},
{
Path: "/etc/pam.d/other",
Digest: &file.Digest{
Algorithm: "md5",
Value: "31aa7f2181889ffb00b87df4126d1701",
},
IsConfigFile: true,
},
{Path: "/lib/x86_64-linux-gnu/libz.so.1.2.11", Digest: &file.Digest{
Algorithm: "md5",
Value: "55f905631797551d4d936a34c7e73474",
}},
{Path: "/usr/share/doc/zlib1g/changelog.Debian.gz", Digest: &file.Digest{
Algorithm: "md5",
Value: "cede84bda30d2380217f97753c8ccf3a",
}},
{Path: "/usr/share/doc/zlib1g/changelog.gz", Digest: &file.Digest{
Algorithm: "md5",
Value: "f3c9dafa6da7992c47328b4464f6d122",
}},
{Path: "/usr/share/doc/zlib1g/copyright", Digest: &file.Digest{
Algorithm: "md5",
Value: "a4fae96070439a5209a62ae5b8017ab2",
}},
},
IsConfigFile: true,
},
{
Path: "/etc/pam.d/other",
Digest: &file.Digest{
Algorithm: "md5",
Value: "31aa7f2181889ffb00b87df4126d1701",
},
},
},
{
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",
}},
},
IsConfigFile: true,
},
{Path: "/lib/x86_64-linux-gnu/libz.so.1.2.11", Digest: &file.Digest{
Algorithm: "md5",
Value: "55f905631797551d4d936a34c7e73474",
}},
{Path: "/usr/share/doc/zlib1g/changelog.Debian.gz", Digest: &file.Digest{
Algorithm: "md5",
Value: "cede84bda30d2380217f97753c8ccf3a",
}},
{Path: "/usr/share/doc/zlib1g/changelog.gz", Digest: &file.Digest{
Algorithm: "md5",
Value: "f3c9dafa6da7992c47328b4464f6d122",
}},
{Path: "/usr/share/doc/zlib1g/copyright", Digest: &file.Digest{
Algorithm: "md5",
Value: "a4fae96070439a5209a62ae5b8017ab2",
}},
},
},
},
}

c := NewDpkgdbCataloger()

pkgtest.NewCatalogTester().
WithImageResolver(t, "image-dpkg").
IgnoreLocationLayer(). // this fixture can be rebuilt, thus the layer ID will change
Expects(expected, nil).
TestCataloger(t, c)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := NewDpkgdbCataloger()
pkgtest.NewCatalogTester().
WithImageResolver(t, tt.name).
IgnoreLocationLayer(). // this fixture can be rebuilt, thus the layer ID will change
Expects(tt.expected, nil).
TestCataloger(t, c)
})
}
}

func TestCataloger_Globs(t *testing.T) {
Expand Down
15 changes: 12 additions & 3 deletions syft/pkg/cataloger/deb/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"path"
"path/filepath"
"sort"
"strings"

"github.com/anchore/packageurl-go"
"github.com/anchore/syft/internal"
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM scratch
COPY . .
Original file line number Diff line number Diff line change
@@ -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'.
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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