Skip to content

Commit 089b953

Browse files
fix(debian): take installed files from the origin layer (#6849)
Signed-off-by: knqyf263 <[email protected]> Co-authored-by: DmitriyLewen <[email protected]>
1 parent cf5aa33 commit 089b953

File tree

2 files changed

+193
-9
lines changed

2 files changed

+193
-9
lines changed

pkg/fanal/applier/docker.go

+11-9
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,24 @@ type History struct {
3030
CreatedBy string `json:"created_by"`
3131
}
3232

33-
func containsPackage(e ftypes.Package, s []ftypes.Package) bool {
33+
func findPackage(e ftypes.Package, s []ftypes.Package) *ftypes.Package {
3434
for _, a := range s {
3535
if a.Name == e.Name && a.Version == e.Version && a.Release == e.Release {
36-
return true
36+
return &a
3737
}
3838
}
39-
return false
39+
return nil
4040
}
4141

42-
func lookupOriginLayerForPkg(pkg ftypes.Package, layers []ftypes.BlobInfo) (string, string, *ftypes.BuildInfo) {
42+
func lookupOriginLayerForPkg(pkg ftypes.Package, layers []ftypes.BlobInfo) (string, string, []string, *ftypes.BuildInfo) {
4343
for i, layer := range layers {
4444
for _, info := range layer.PackageInfos {
45-
if containsPackage(pkg, info.Packages) {
46-
return layer.Digest, layer.DiffID, lookupBuildInfo(i, layers)
45+
if p := findPackage(pkg, info.Packages); p != nil {
46+
return layer.Digest, layer.DiffID, p.InstalledFiles, lookupBuildInfo(i, layers)
4747
}
4848
}
4949
}
50-
return "", "", nil
50+
return "", "", nil, nil
5151
}
5252

5353
// lookupBuildInfo looks up Red Hat content sets from all layers
@@ -81,7 +81,7 @@ func lookupOriginLayerForLib(filePath string, lib ftypes.Package, layers []ftype
8181
if filePath != layerApp.FilePath {
8282
continue
8383
}
84-
if containsPackage(lib, layerApp.Packages) {
84+
if findPackage(lib, layerApp.Packages) != nil {
8585
return layer.Digest, layer.DiffID
8686
}
8787
}
@@ -210,12 +210,14 @@ func ApplyLayers(layers []ftypes.BlobInfo) ftypes.ArtifactDetail {
210210
for i, pkg := range mergedLayer.Packages {
211211
// Skip lookup for SBOM
212212
if lo.IsEmpty(pkg.Layer) {
213-
originLayerDigest, originLayerDiffID, buildInfo := lookupOriginLayerForPkg(pkg, layers)
213+
originLayerDigest, originLayerDiffID, installedFiles, buildInfo := lookupOriginLayerForPkg(pkg, layers)
214214
mergedLayer.Packages[i].Layer = ftypes.Layer{
215215
Digest: originLayerDigest,
216216
DiffID: originLayerDiffID,
217217
}
218218
mergedLayer.Packages[i].BuildInfo = buildInfo
219+
// Debian/Ubuntu has the installed files only in the first layer where the package is installed.
220+
mergedLayer.Packages[i].InstalledFiles = installedFiles
219221
}
220222

221223
if mergedLayer.OS.Family != "" {

pkg/fanal/applier/docker_test.go

+182
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,188 @@ func TestApplyLayers(t *testing.T) {
843843
},
844844
},
845845
},
846+
{
847+
name: "happy path with filling system files for debian packages",
848+
inputLayers: []types.BlobInfo{
849+
{
850+
SchemaVersion: 2,
851+
DiffID: "sha256:cdd7c73923174e45ea648d66996665c288e1b17a0f45efdbeca860f6dafdf731",
852+
OS: types.OS{
853+
Family: "ubuntu",
854+
Name: "24.04",
855+
},
856+
PackageInfos: []types.PackageInfo{
857+
{
858+
FilePath: "var/lib/dpkg/status",
859+
Packages: types.Packages{
860+
{
861+
862+
Name: "apt",
863+
Version: "2.4.9",
864+
Arch: "amd64",
865+
SrcName: "apt",
866+
SrcVersion: "2.4.9",
867+
InstalledFiles: []string{
868+
"/etc/apt/apt.conf.d/01-vendor-ubuntu",
869+
"/etc/apt/apt.conf.d/01autoremove",
870+
"/etc/apt/auth.conf.d",
871+
"/etc/apt/keyrings",
872+
},
873+
},
874+
},
875+
},
876+
},
877+
},
878+
// Install `curl`
879+
{
880+
SchemaVersion: 2,
881+
DiffID: "sha256:faf30fa9c41c10f93b3b134d7b2c16e07753320393e020c481f0c97d10db067d",
882+
PackageInfos: []types.PackageInfo{
883+
{
884+
FilePath: "var/lib/dpkg/status",
885+
Packages: types.Packages{
886+
{
887+
888+
Name: "apt",
889+
Version: "2.4.9",
890+
Arch: "amd64",
891+
SrcName: "apt",
892+
SrcVersion: "2.4.9",
893+
},
894+
{
895+
896+
Name: "curl",
897+
Version: "8.5.0",
898+
Release: "2ubuntu10.1",
899+
Arch: "arm64",
900+
SrcName: "curl",
901+
SrcVersion: "8.5.0",
902+
SrcRelease: "2ubuntu10.1",
903+
InstalledFiles: []string{
904+
"/usr/bin/curl",
905+
"/usr/share/doc/curl/README.Debian",
906+
"/usr/share/doc/curl/changelog.Debian.gz",
907+
"/usr/share/doc/curl/copyright",
908+
"/usr/share/man/man1/curl.1.gz",
909+
"/usr/share/zsh/vendor-completions/_curl",
910+
},
911+
},
912+
},
913+
},
914+
},
915+
},
916+
// Upgrade `apt`
917+
{
918+
SchemaVersion: 2,
919+
DiffID: "sha256:440e26edc0eb9b4fee6e1d40d8af9eb59500d38e25edfc5d5302c55f59394c1e",
920+
PackageInfos: []types.PackageInfo{
921+
{
922+
FilePath: "var/lib/dpkg/status",
923+
Packages: types.Packages{
924+
{
925+
926+
Name: "apt",
927+
Version: "2.4.12",
928+
Arch: "amd64",
929+
SrcName: "apt",
930+
SrcVersion: "2.4.12",
931+
InstalledFiles: []string{
932+
"/etc/apt/apt.conf.d/01-vendor-ubuntu",
933+
"/etc/apt/apt.conf.d/01autoremove",
934+
"/etc/apt/auth.conf.d",
935+
"/etc/apt/keyrings",
936+
"/usr/share/man/it/man5/sources.list.5.gz",
937+
},
938+
},
939+
{
940+
941+
Name: "curl",
942+
Version: "8.5.0",
943+
Release: "2ubuntu10.1",
944+
Arch: "arm64",
945+
SrcName: "curl",
946+
SrcVersion: "8.5.0",
947+
SrcRelease: "2ubuntu10.1",
948+
},
949+
},
950+
},
951+
},
952+
},
953+
// Remove curl
954+
{
955+
SchemaVersion: 2,
956+
DiffID: "sha256:cb04e1d437de723d8d04bc7df89dc42271530c5f8ea1724c6072e3f0e7d6d38a",
957+
WhiteoutFiles: []string{
958+
"usr/bin/curl",
959+
"usr/share/doc/curl",
960+
"usr/share/zsh",
961+
"var/lib/dpkg/info/curl.list",
962+
"var/lib/dpkg/info/curl.md5sums",
963+
},
964+
PackageInfos: []types.PackageInfo{
965+
{
966+
FilePath: "var/lib/dpkg/status",
967+
Packages: types.Packages{
968+
{
969+
970+
Name: "apt",
971+
Version: "2.4.12",
972+
Arch: "amd64",
973+
SrcName: "apt",
974+
SrcVersion: "2.4.12",
975+
},
976+
},
977+
},
978+
},
979+
},
980+
},
981+
want: types.ArtifactDetail{
982+
OS: types.OS{
983+
Family: "ubuntu",
984+
Name: "24.04",
985+
},
986+
Packages: types.Packages{
987+
{
988+
989+
Name: "apt",
990+
Version: "2.4.12",
991+
Arch: "amd64",
992+
SrcName: "apt",
993+
SrcVersion: "2.4.12",
994+
995+
Identifier: types.PkgIdentifier{
996+
UID: "80bc98a8f3159db9",
997+
PURL: &packageurl.PackageURL{
998+
Type: packageurl.TypeDebian,
999+
Namespace: "ubuntu",
1000+
Name: "apt",
1001+
Version: "2.4.12",
1002+
Qualifiers: packageurl.Qualifiers{
1003+
{
1004+
Key: "arch",
1005+
Value: "amd64",
1006+
},
1007+
{
1008+
Key: "distro",
1009+
Value: "ubuntu-24.04",
1010+
},
1011+
},
1012+
},
1013+
},
1014+
Layer: types.Layer{
1015+
DiffID: "sha256:440e26edc0eb9b4fee6e1d40d8af9eb59500d38e25edfc5d5302c55f59394c1e",
1016+
},
1017+
InstalledFiles: []string{
1018+
"/etc/apt/apt.conf.d/01-vendor-ubuntu",
1019+
"/etc/apt/apt.conf.d/01autoremove",
1020+
"/etc/apt/auth.conf.d",
1021+
"/etc/apt/keyrings",
1022+
"/usr/share/man/it/man5/sources.list.5.gz",
1023+
},
1024+
},
1025+
},
1026+
},
1027+
},
8461028
{
8471029
name: "happy path, opaque dirs with the trailing slash",
8481030
inputLayers: []types.BlobInfo{

0 commit comments

Comments
 (0)