Skip to content

Commit

Permalink
fix(debian): take installed files from the origin layer (#6849)
Browse files Browse the repository at this point in the history
Signed-off-by: knqyf263 <[email protected]>
Co-authored-by: DmitriyLewen <[email protected]>
  • Loading branch information
knqyf263 and DmitriyLewen authored Jun 10, 2024
1 parent cf5aa33 commit 089b953
Show file tree
Hide file tree
Showing 2 changed files with 193 additions and 9 deletions.
20 changes: 11 additions & 9 deletions pkg/fanal/applier/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,24 @@ type History struct {
CreatedBy string `json:"created_by"`
}

func containsPackage(e ftypes.Package, s []ftypes.Package) bool {
func findPackage(e ftypes.Package, s []ftypes.Package) *ftypes.Package {
for _, a := range s {
if a.Name == e.Name && a.Version == e.Version && a.Release == e.Release {
return true
return &a
}
}
return false
return nil
}

func lookupOriginLayerForPkg(pkg ftypes.Package, layers []ftypes.BlobInfo) (string, string, *ftypes.BuildInfo) {
func lookupOriginLayerForPkg(pkg ftypes.Package, layers []ftypes.BlobInfo) (string, string, []string, *ftypes.BuildInfo) {
for i, layer := range layers {
for _, info := range layer.PackageInfos {
if containsPackage(pkg, info.Packages) {
return layer.Digest, layer.DiffID, lookupBuildInfo(i, layers)
if p := findPackage(pkg, info.Packages); p != nil {
return layer.Digest, layer.DiffID, p.InstalledFiles, lookupBuildInfo(i, layers)
}
}
}
return "", "", nil
return "", "", nil, nil
}

// lookupBuildInfo looks up Red Hat content sets from all layers
Expand Down Expand Up @@ -81,7 +81,7 @@ func lookupOriginLayerForLib(filePath string, lib ftypes.Package, layers []ftype
if filePath != layerApp.FilePath {
continue
}
if containsPackage(lib, layerApp.Packages) {
if findPackage(lib, layerApp.Packages) != nil {
return layer.Digest, layer.DiffID
}
}
Expand Down Expand Up @@ -210,12 +210,14 @@ func ApplyLayers(layers []ftypes.BlobInfo) ftypes.ArtifactDetail {
for i, pkg := range mergedLayer.Packages {
// Skip lookup for SBOM
if lo.IsEmpty(pkg.Layer) {
originLayerDigest, originLayerDiffID, buildInfo := lookupOriginLayerForPkg(pkg, layers)
originLayerDigest, originLayerDiffID, installedFiles, buildInfo := lookupOriginLayerForPkg(pkg, layers)
mergedLayer.Packages[i].Layer = ftypes.Layer{
Digest: originLayerDigest,
DiffID: originLayerDiffID,
}
mergedLayer.Packages[i].BuildInfo = buildInfo
// Debian/Ubuntu has the installed files only in the first layer where the package is installed.
mergedLayer.Packages[i].InstalledFiles = installedFiles
}

if mergedLayer.OS.Family != "" {
Expand Down
182 changes: 182 additions & 0 deletions pkg/fanal/applier/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,188 @@ func TestApplyLayers(t *testing.T) {
},
},
},
{
name: "happy path with filling system files for debian packages",
inputLayers: []types.BlobInfo{
{
SchemaVersion: 2,
DiffID: "sha256:cdd7c73923174e45ea648d66996665c288e1b17a0f45efdbeca860f6dafdf731",
OS: types.OS{
Family: "ubuntu",
Name: "24.04",
},
PackageInfos: []types.PackageInfo{
{
FilePath: "var/lib/dpkg/status",
Packages: types.Packages{
{
ID: "[email protected]",
Name: "apt",
Version: "2.4.9",
Arch: "amd64",
SrcName: "apt",
SrcVersion: "2.4.9",
InstalledFiles: []string{
"/etc/apt/apt.conf.d/01-vendor-ubuntu",
"/etc/apt/apt.conf.d/01autoremove",
"/etc/apt/auth.conf.d",
"/etc/apt/keyrings",
},
},
},
},
},
},
// Install `curl`
{
SchemaVersion: 2,
DiffID: "sha256:faf30fa9c41c10f93b3b134d7b2c16e07753320393e020c481f0c97d10db067d",
PackageInfos: []types.PackageInfo{
{
FilePath: "var/lib/dpkg/status",
Packages: types.Packages{
{
ID: "[email protected]",
Name: "apt",
Version: "2.4.9",
Arch: "amd64",
SrcName: "apt",
SrcVersion: "2.4.9",
},
{
ID: "[email protected]",
Name: "curl",
Version: "8.5.0",
Release: "2ubuntu10.1",
Arch: "arm64",
SrcName: "curl",
SrcVersion: "8.5.0",
SrcRelease: "2ubuntu10.1",
InstalledFiles: []string{
"/usr/bin/curl",
"/usr/share/doc/curl/README.Debian",
"/usr/share/doc/curl/changelog.Debian.gz",
"/usr/share/doc/curl/copyright",
"/usr/share/man/man1/curl.1.gz",
"/usr/share/zsh/vendor-completions/_curl",
},
},
},
},
},
},
// Upgrade `apt`
{
SchemaVersion: 2,
DiffID: "sha256:440e26edc0eb9b4fee6e1d40d8af9eb59500d38e25edfc5d5302c55f59394c1e",
PackageInfos: []types.PackageInfo{
{
FilePath: "var/lib/dpkg/status",
Packages: types.Packages{
{
ID: "[email protected]",
Name: "apt",
Version: "2.4.12",
Arch: "amd64",
SrcName: "apt",
SrcVersion: "2.4.12",
InstalledFiles: []string{
"/etc/apt/apt.conf.d/01-vendor-ubuntu",
"/etc/apt/apt.conf.d/01autoremove",
"/etc/apt/auth.conf.d",
"/etc/apt/keyrings",
"/usr/share/man/it/man5/sources.list.5.gz",
},
},
{
ID: "[email protected]",
Name: "curl",
Version: "8.5.0",
Release: "2ubuntu10.1",
Arch: "arm64",
SrcName: "curl",
SrcVersion: "8.5.0",
SrcRelease: "2ubuntu10.1",
},
},
},
},
},
// Remove curl
{
SchemaVersion: 2,
DiffID: "sha256:cb04e1d437de723d8d04bc7df89dc42271530c5f8ea1724c6072e3f0e7d6d38a",
WhiteoutFiles: []string{
"usr/bin/curl",
"usr/share/doc/curl",
"usr/share/zsh",
"var/lib/dpkg/info/curl.list",
"var/lib/dpkg/info/curl.md5sums",
},
PackageInfos: []types.PackageInfo{
{
FilePath: "var/lib/dpkg/status",
Packages: types.Packages{
{
ID: "[email protected]",
Name: "apt",
Version: "2.4.12",
Arch: "amd64",
SrcName: "apt",
SrcVersion: "2.4.12",
},
},
},
},
},
},
want: types.ArtifactDetail{
OS: types.OS{
Family: "ubuntu",
Name: "24.04",
},
Packages: types.Packages{
{
ID: "[email protected]",
Name: "apt",
Version: "2.4.12",
Arch: "amd64",
SrcName: "apt",
SrcVersion: "2.4.12",

Identifier: types.PkgIdentifier{
UID: "80bc98a8f3159db9",
PURL: &packageurl.PackageURL{
Type: packageurl.TypeDebian,
Namespace: "ubuntu",
Name: "apt",
Version: "2.4.12",
Qualifiers: packageurl.Qualifiers{
{
Key: "arch",
Value: "amd64",
},
{
Key: "distro",
Value: "ubuntu-24.04",
},
},
},
},
Layer: types.Layer{
DiffID: "sha256:440e26edc0eb9b4fee6e1d40d8af9eb59500d38e25edfc5d5302c55f59394c1e",
},
InstalledFiles: []string{
"/etc/apt/apt.conf.d/01-vendor-ubuntu",
"/etc/apt/apt.conf.d/01autoremove",
"/etc/apt/auth.conf.d",
"/etc/apt/keyrings",
"/usr/share/man/it/man5/sources.list.5.gz",
},
},
},
},
},
{
name: "happy path, opaque dirs with the trailing slash",
inputLayers: []types.BlobInfo{
Expand Down

0 comments on commit 089b953

Please sign in to comment.