Skip to content

Commit

Permalink
Fix reg cannot scan vulnerabilities on images with empty layers
Browse files Browse the repository at this point in the history
  • Loading branch information
KeyboardNerd committed Dec 14, 2018
1 parent 56104f3 commit c6db7a4
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 15 deletions.
16 changes: 9 additions & 7 deletions clair/layerutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import (
)

// NewClairLayer will form a layer struct required for a clair scan.
func (c *Clair) NewClairLayer(r *registry.Registry, image string, fsLayers map[int]distribution.Descriptor, index int) (*Layer, error) {
func (c *Clair) NewClairLayer(r *registry.Registry, image string, fsLayers map[int]distribution.Descriptor, index int, parentLayerIndex int) (*Layer, error) {
var parentName string
if index < len(fsLayers)-1 {
parentName = fsLayers[index+1].Digest.String()
if parentLayerIndex != -1 {
parentName = fsLayers[parentLayerIndex].Digest.String()
}

// Form the path.
Expand Down Expand Up @@ -52,7 +52,7 @@ func (c *Clair) NewClairV3Layer(r *registry.Registry, image string, fsLayer dist
}, nil
}

func (c *Clair) getLayers(r *registry.Registry, repo, tag string, filterEmpty bool) (map[int]distribution.Descriptor, string, error) {
func (c *Clair) getLayers(r *registry.Registry, repo, tag string, filterEmpty bool) (map[int]distribution.Descriptor, string, int, error) {
ok := true
// Get the manifest to pass to clair.
mf, err := r.ManifestV2(repo, tag)
Expand All @@ -61,6 +61,7 @@ func (c *Clair) getLayers(r *registry.Registry, repo, tag string, filterEmpty bo
c.Logf("couldn't retrieve manifest v2, falling back to v1")
}

nonFilteredSize := len(mf.Layers)
filteredLayers := map[int]distribution.Descriptor{}

// Filter out the empty layers.
Expand All @@ -73,14 +74,15 @@ func (c *Clair) getLayers(r *registry.Registry, repo, tag string, filterEmpty bo
}
}

return filteredLayers, mf.Config.Digest.String(), nil
return filteredLayers, mf.Config.Digest.String(), nonFilteredSize, nil
}

m, err := r.ManifestV1(repo, tag)
if err != nil {
return nil, "", fmt.Errorf("getting the v1 manifest for %s:%s failed: %v", repo, tag, err)
return nil, "", 0, fmt.Errorf("getting the v1 manifest for %s:%s failed: %v", repo, tag, err)
}

nonFilteredSize = len(m.FSLayers)
for i := 0; i < len(m.FSLayers); i++ {
if filterEmpty && IsEmptyLayer(m.FSLayers[i].BlobSum) {
continue
Expand All @@ -91,5 +93,5 @@ func (c *Clair) getLayers(r *registry.Registry, repo, tag string, filterEmpty bo
}
}

return filteredLayers, filteredLayers[0].Digest.String(), nil
return filteredLayers, filteredLayers[0].Digest.String(), nonFilteredSize, nil
}
23 changes: 15 additions & 8 deletions clair/vulns.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func (c *Clair) Vulnerabilities(r *registry.Registry, repo, tag string) (Vulnera
VulnsBySeverity: make(map[string][]Vulnerability),
}

filteredLayers, _, err := c.getLayers(r, repo, tag, true)
filteredLayers, _, nonFilteredSize, err := c.getLayers(r, repo, tag, true)
if err != nil {
return report, fmt.Errorf("getting filtered layers failed: %v", err)
}
Expand All @@ -29,22 +29,29 @@ func (c *Clair) Vulnerabilities(r *registry.Registry, repo, tag string) (Vulnera
return report, nil
}

for i := len(filteredLayers) - 1; i >= 0; i-- {
// Form the clair layer.
l, err := c.NewClairLayer(r, repo, filteredLayers, i)
parentNonEmptyLayerIndex := -1
for i := nonFilteredSize - 1; i >= 0; i-- {
if _, isNonEmptyLayer := filteredLayers[i]; !isNonEmptyLayer {
continue
}

l, err := c.NewClairLayer(r, repo, filteredLayers, i, parentNonEmptyLayerIndex)
if err != nil {
return report, err
}

// Post the layer.
if _, err := c.PostLayer(l); err != nil {
return report, err
}

parentNonEmptyLayerIndex = i
}

report.Name = filteredLayers[0].Digest.String()
// Post condition, parentNonEmptyLayerIndex must points to the last layer
// that is not empty and the index must not be -1.
report.Name = filteredLayers[parentNonEmptyLayerIndex].Digest.String()

vl, err := c.GetLayer(filteredLayers[0].Digest.String(), true, true)
vl, err := c.GetLayer(filteredLayers[parentNonEmptyLayerIndex].Digest.String(), true, true)
if err != nil {
return report, err
}
Expand Down Expand Up @@ -85,7 +92,7 @@ func (c *Clair) VulnerabilitiesV3(r *registry.Registry, repo, tag string) (Vulne
VulnsBySeverity: make(map[string][]Vulnerability),
}

layers, reportName, err := c.getLayers(r, repo, tag, false)
layers, reportName, _, err := c.getLayers(r, repo, tag, false)
if err != nil {
return report, fmt.Errorf("getting filtered layers failed: %v", err)
}
Expand Down

0 comments on commit c6db7a4

Please sign in to comment.