Skip to content

Commit 244c9db

Browse files
erikvargacopybara-github
authored andcommitted
Move inventories + findings under a top-level struct inside ScanResults.
This allows us to add new result types for things that are not software packages or security findings (e.g. running processes, open ports). In a follow-up change we'll make extractor plugins return generic inventory types instead of just software packages. Note that we still use the software package struct to store non-software inventory such as containerd runtimes. Moving that to a separate type will be done in a follow-up change. PiperOrigin-RevId: 733262169
1 parent e020e49 commit 244c9db

File tree

197 files changed

+3836
-3672
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

197 files changed

+3836
-3672
lines changed

artifact/image/file.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ package image
1616

1717
import "io/fs"
1818

19-
// History holds the creation, modification, and deletion history of a file or inventory. Each field
19+
// History holds the creation, modification, and deletion history of a file or package. Each field
2020
// holds an array of integers representing layer indices.
2121
type History struct {
2222
Created []int

artifact/image/layerscanning/trace/trace.go

+42-42
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
// Package trace provides functionality to trace the origin of an inventory in a container image.
15+
// Package trace provides functionality to trace the origin of a package in a container image.
1616
package trace
1717

1818
import (
@@ -36,8 +36,8 @@ type locationAndIndex struct {
3636
index int
3737
}
3838

39-
// PopulateLayerDetails populates the LayerDetails field of the inventory with the origin details
40-
// obtained by tracing the inventory in the image.
39+
// PopulateLayerDetails populates the LayerDetails field of the package with the origin details
40+
// obtained by tracing the package in the image.
4141
//
4242
// It does this by looking at each consecutive pair (n, n+1) of chain layers in reverse order and
4343
// checking if a package is present in layer n+1, but not layer n. For example, consider the chain
@@ -54,10 +54,10 @@ type locationAndIndex struct {
5454
//
5555
// Note that a precondition of this algorithm is that the chain layers are ordered by order of
5656
// creation.
57-
func PopulateLayerDetails(ctx context.Context, inventory []*extractor.Inventory, chainLayers []scalibrImage.ChainLayer, config *filesystem.Config) {
57+
func PopulateLayerDetails(ctx context.Context, pkgs []*extractor.Package, chainLayers []scalibrImage.ChainLayer, config *filesystem.Config) {
5858
chainLayerDetailsList := []*extractor.LayerDetails{}
5959

60-
// Create list of layer details struct to be referenced by inventory.
60+
// Create list of layer details struct to be referenced by package.
6161
for i, chainLayer := range chainLayers {
6262
var diffID string
6363
if chainLayer.Layer().IsEmpty() {
@@ -85,112 +85,112 @@ func PopulateLayerDetails(ctx context.Context, inventory []*extractor.Inventory,
8585
}
8686
}
8787

88-
// locationIndexToInventory is used as an inventory cache to avoid re-extracting the same
89-
// inventory from a file multiple times.
90-
locationIndexToInventory := map[locationAndIndex][]*extractor.Inventory{}
88+
// locationIndexToPackage is used as a package cache to avoid re-extracting the same
89+
// package from a file multiple times.
90+
locationIndexToPackage := map[locationAndIndex][]*extractor.Package{}
9191
lastLayerIndex := len(chainLayers) - 1
9292

93-
for _, inv := range inventory {
93+
for _, pkg := range pkgs {
9494
layerDetails := chainLayerDetailsList[lastLayerIndex]
95-
invExtractor, isFilesystemExtractor := inv.Extractor.(filesystem.Extractor)
95+
pkgExtractor, isFilesystemExtractor := pkg.Extractor.(filesystem.Extractor)
9696

97-
// Only filesystem extractors are supported for layer scanning. Also, if the inventory has no
97+
// Only filesystem extractors are supported for layer scanning. Also, if the package has no
9898
// locations, it cannot be traced.
99-
isInventoryTraceable := isFilesystemExtractor && len(inv.Locations) > 0
100-
if !isInventoryTraceable {
99+
isPackageTraceable := isFilesystemExtractor && len(pkg.Locations) > 0
100+
if !isPackageTraceable {
101101
continue
102102
}
103103

104104
var foundOrigin bool
105-
fileLocation := inv.Locations[0]
105+
fileLocation := pkg.Locations[0]
106106

107-
// Go backwards through the chain layers and find the first layer where the inventory is not
108-
// present. Such layer is the layer in which the inventory was introduced. If the inventory is
107+
// Go backwards through the chain layers and find the first layer where the package is not
108+
// present. Such layer is the layer in which the package was introduced. If the package is
109109
// present in all layers, then it means it was introduced in the first layer.
110110
for i := len(chainLayers) - 2; i >= 0; i-- {
111111
oldChainLayer := chainLayers[i]
112112

113-
invLocationAndIndex := locationAndIndex{
113+
pkgLocationAndIndex := locationAndIndex{
114114
location: fileLocation,
115115
index: i,
116116
}
117117

118-
var oldInventory []*extractor.Inventory
119-
if cachedInventory, ok := locationIndexToInventory[invLocationAndIndex]; ok {
120-
oldInventory = cachedInventory
118+
var oldPackages []*extractor.Package
119+
if cachedPackage, ok := locationIndexToPackage[pkgLocationAndIndex]; ok {
120+
oldPackages = cachedPackage
121121
} else if _, err := oldChainLayer.FS().Stat(fileLocation); errors.Is(err, fs.ErrNotExist) {
122122
// Check if file still exist in this layer, if not skip extraction.
123123
// This is both an optimization, and avoids polluting the log output with false file not found errors.
124-
oldInventory = []*extractor.Inventory{}
125-
} else if filesExistInLayer(oldChainLayer, inv.Locations) {
124+
oldPackages = []*extractor.Package{}
125+
} else if filesExistInLayer(oldChainLayer, pkg.Locations) {
126126
// Update the extractor config to use the files from the current layer.
127127
// We only take extract the first location because other locations are derived from the initial
128128
// extraction location. If other locations can no longer be determined from the first location
129129
// they should not be included here, and the trace for those packages stops here.
130-
updateExtractorConfig([]string{fileLocation}, invExtractor, oldChainLayer.FS())
130+
updateExtractorConfig([]string{fileLocation}, pkgExtractor, oldChainLayer.FS())
131131

132132
var err error
133133
// Runs SCALIBR extraction on the file of interest in oldChainLayer.
134-
oldInventory, _, err = filesystem.Run(ctx, config)
134+
oldPackages, _, err = filesystem.Run(ctx, config)
135135
if err != nil {
136136
break
137137
}
138138
} else {
139-
// If none of the files from the inventory are present in the underlying layer, then there
140-
// will be no difference in the extracted inventory from oldChainLayer, so extraction can be
141-
// skipped in the chain layer. This is an optimization to avoid extracting the same inventory
139+
// If none of the files from the packages are present in the underlying layer, then there
140+
// will be no difference in the extracted packages from oldChainLayer, so extraction can be
141+
// skipped in the chain layer. This is an optimization to avoid extracting the same package
142142
// multiple times.
143143
continue
144144
}
145145

146-
// Cache the inventory for future use.
147-
locationIndexToInventory[invLocationAndIndex] = oldInventory
146+
// Cache the packages for future use.
147+
locationIndexToPackage[pkgLocationAndIndex] = oldPackages
148148

149149
foundPackage := false
150-
for _, oldInv := range oldInventory {
151-
if areInventoriesEqual(inv, oldInv) {
150+
for _, oldPKG := range oldPackages {
151+
if arePackagesEqual(pkg, oldPKG) {
152152
foundPackage = true
153153
break
154154
}
155155
}
156156

157-
// If the inventory is not present in the old layer, then it was introduced in layer i+1.
157+
// If the package is not present in the old layer, then it was introduced in layer i+1.
158158
if !foundPackage {
159159
layerDetails = chainLayerDetailsList[i+1]
160160
foundOrigin = true
161161
break
162162
}
163163
}
164164

165-
// If the inventory is present in every layer, then it means it was introduced in the first
165+
// If the package is present in every layer, then it means it was introduced in the first
166166
// layer.
167167
if !foundOrigin {
168168
layerDetails = chainLayerDetailsList[0]
169169
}
170-
inv.LayerDetails = layerDetails
170+
pkg.LayerDetails = layerDetails
171171
}
172172
}
173173

174-
// areInventoriesEqual checks if two inventories are equal. It does this by comparing the PURLs and
175-
// the locations of the inventories.
176-
func areInventoriesEqual(inv1 *extractor.Inventory, inv2 *extractor.Inventory) bool {
177-
if inv1.Extractor == nil || inv2.Extractor == nil {
174+
// arePackagesEqual checks if two packages are equal. It does this by comparing the PURLs and
175+
// the locations of the packages.
176+
func arePackagesEqual(pkg1 *extractor.Package, pkg2 *extractor.Package) bool {
177+
if pkg1.Extractor == nil || pkg2.Extractor == nil {
178178
return false
179179
}
180180

181181
// Check if the PURLs are equal.
182-
purl1 := inv1.Extractor.ToPURL(inv1)
183-
purl2 := inv2.Extractor.ToPURL(inv2)
182+
purl1 := pkg1.Extractor.ToPURL(pkg1)
183+
purl2 := pkg2.Extractor.ToPURL(pkg2)
184184

185185
if purl1.String() != purl2.String() {
186186
return false
187187
}
188188

189189
// Check if the locations are equal.
190-
locations1 := inv1.Locations[:]
190+
locations1 := pkg1.Locations[:]
191191
sort.Strings(locations1)
192192

193-
locations2 := inv2.Locations[:]
193+
locations2 := pkg2.Locations[:]
194194
sort.Strings(locations2)
195195

196196
if !slices.Equal(locations1, locations2) {

0 commit comments

Comments
 (0)