diff --git a/contrib/analyze-local-images/main.go b/contrib/analyze-local-images/main.go index d08073af..f3c836b8 100644 --- a/contrib/analyze-local-images/main.go +++ b/contrib/analyze-local-images/main.go @@ -154,7 +154,10 @@ func AnalyzeLocalImage(imageName string, minSeverity types.Priority, endpoint, m // Retrieve history. log.Println("Retrieving image history") - layerIDs, err := historyFromCommand(imageName) + layerIDs, err := historyFromManifest(tmpPath) + if err != nil { + layerIDs, err = historyFromCommand(imageName) + } if err != nil || len(layerIDs) == 0 { return fmt.Errorf("Could not get image's history: %s", err) } @@ -269,7 +272,7 @@ func AnalyzeLocalImage(imageName string, minSeverity types.Priority, endpoint, m fmt.Printf("%s No vulnerabilities matching the minimum severity level were detected in your image\n", color.YellowString("NOTE:")) } else { return fmt.Errorf("A total of %d vulnerabilities have been detected in your image", len(vulnerabilities)) - } + } return nil } @@ -306,6 +309,33 @@ func save(imageName, path string) error { return nil } +func historyFromManifest(path string) ([]string, error) { + mf, err := os.Open(path + "/manifest.json") + if err != nil { + return nil, err + } + defer mf.Close() + + // https://github.com/docker/docker/blob/master/image/tarexport/tarexport.go#L17 + type manifestItem struct { + Config string + RepoTags []string + Layers []string + } + + var manifest []manifestItem + if err = json.NewDecoder(mf).Decode(&manifest); err != nil { + return nil, err + } else if len(manifest) != 1 { + return nil, err + } + var layers []string + for _, layer := range manifest[0].Layers { + layers = append(layers, strings.TrimSuffix(layer, "/layer.tar")) + } + return layers, nil +} + func historyFromCommand(imageName string) ([]string, error) { var stderr bytes.Buffer cmd := exec.Command("docker", "history", "-q", "--no-trunc", imageName)