replace search key from table with severity (#107)

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
Alex Goodman 2020-08-10 10:24:29 -04:00 committed by GitHub
parent 37ceb170e4
commit f98e3cdf90
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 91 additions and 34 deletions

View file

@ -23,7 +23,7 @@ func GetPresenter(option Option, results result.Result, catalog *pkg.Catalog, th
case JSONPresenter:
return json.NewPresenter(results, catalog, theScope, metadataProvider)
case TablePresenter:
return table.NewPresenter(results, catalog)
return table.NewPresenter(results, catalog, metadataProvider)
default:
return nil
}

View file

@ -1,25 +1,29 @@
package table
import (
"fmt"
"io"
"sort"
"github.com/anchore/grype/grype/result"
"github.com/anchore/grype/grype/vulnerability"
"github.com/anchore/syft/syft/pkg"
"github.com/olekukonko/tablewriter"
)
// Presenter is a generic struct for holding fields needed for reporting
type Presenter struct {
results result.Result
catalog *pkg.Catalog
results result.Result
catalog *pkg.Catalog
metadataProvider vulnerability.MetadataProvider
}
// NewPresenter is a *Presenter constructor
func NewPresenter(results result.Result, catalog *pkg.Catalog) *Presenter {
func NewPresenter(results result.Result, catalog *pkg.Catalog, metadataProvider vulnerability.MetadataProvider) *Presenter {
return &Presenter{
results: results,
catalog: catalog,
results: results,
catalog: catalog,
metadataProvider: metadataProvider,
}
}
@ -27,13 +31,24 @@ func NewPresenter(results result.Result, catalog *pkg.Catalog) *Presenter {
func (pres *Presenter) Present(output io.Writer) error {
rows := make([][]string, 0)
columns := []string{"Name", "Installed", "Vulnerability", "Found-By"}
for p := range pres.results.Enumerate() {
columns := []string{"Name", "Installed", "Vulnerability", "Severity"}
for m := range pres.results.Enumerate() {
var severity string
metadata, err := pres.metadataProvider.GetMetadata(m.Vulnerability.ID, m.Vulnerability.RecordSource)
if err != nil {
return fmt.Errorf("unable to fetch vuln=%q metadata: %+v", m.Vulnerability.ID, err)
}
if metadata != nil {
severity = metadata.Severity
}
row := []string{
p.Package.Name,
p.Package.Version,
p.Vulnerability.ID,
p.SearchKey,
m.Package.Name,
m.Package.Version,
m.Vulnerability.ID,
severity,
}
rows = append(rows, row)
}
@ -60,7 +75,6 @@ func (pres *Presenter) Present(output io.Writer) error {
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
table.SetAlignment(tablewriter.ALIGN_LEFT)
// these options allow for a more greppable table
table.SetHeaderLine(false)
table.SetBorder(false)
table.SetAutoFormatHeaders(true)
@ -70,13 +84,6 @@ func (pres *Presenter) Present(output io.Writer) error {
table.SetTablePadding(" ")
table.SetNoWhiteSpace(true)
// these options allow for a more human-readable (but not greppable) table
//table.SetRowLine(true)
//table.SetAutoMergeCells(true)
//table.SetCenterSeparator("·") // + ┼ ╎ ┆ ┊ · •
//table.SetColumnSeparator("│")
//table.SetRowSeparator("─")
table.AppendBulk(rows)
table.Render()

View file

@ -15,6 +15,50 @@ import (
var update = flag.Bool("update", false, "update the *.golden files for json presenters")
type metadataMock struct {
store map[string]map[string]vulnerability.Metadata
}
func newMetadataMock() *metadataMock {
return &metadataMock{
store: map[string]map[string]vulnerability.Metadata{
"CVE-1999-0001": {
"source-1": {
Description: "1999-01 description",
Severity: "Low",
CvssV3: &vulnerability.Cvss{
BaseScore: 4,
Vector: "another vector",
},
},
},
"CVE-1999-0002": {
"source-2": {
Description: "1999-02 description",
Severity: "Critical",
CvssV2: &vulnerability.Cvss{
BaseScore: 1,
ExploitabilityScore: 2,
ImpactScore: 3,
Vector: "vector",
},
},
},
"CVE-1999-0003": {
"source-1": {
Description: "1999-03 description",
Severity: "High",
},
},
},
}
}
func (m *metadataMock) GetMetadata(id, recordSource string) (*vulnerability.Metadata, error) {
value := m.store[id][recordSource]
return &value, nil
}
func TestTablePresenter(t *testing.T) {
var buffer bytes.Buffer
@ -32,18 +76,24 @@ func TestTablePresenter(t *testing.T) {
}
var match1 = match.Match{
Type: match.ExactDirectMatch,
Vulnerability: vulnerability.Vulnerability{ID: "CVE-1999-0001"},
Package: &pkg1,
Matcher: match.DpkgMatcher,
Type: match.ExactDirectMatch,
Vulnerability: vulnerability.Vulnerability{
ID: "CVE-1999-0001",
RecordSource: "source-1",
},
Package: &pkg1,
Matcher: match.DpkgMatcher,
}
var match2 = match.Match{
Type: match.ExactIndirectMatch,
Vulnerability: vulnerability.Vulnerability{ID: "CVE-1999-0002"},
Package: &pkg2,
Matcher: match.DpkgMatcher,
SearchKey: "a search key...",
Type: match.ExactIndirectMatch,
Vulnerability: vulnerability.Vulnerability{
ID: "CVE-1999-0002",
RecordSource: "source-2",
},
Package: &pkg2,
Matcher: match.DpkgMatcher,
SearchKey: "a search key...",
}
results := result.NewResult()
@ -56,7 +106,7 @@ func TestTablePresenter(t *testing.T) {
catalog.Add(pkg1)
catalog.Add(pkg2)
pres := NewPresenter(results, catalog)
pres := NewPresenter(results, catalog, newMetadataMock())
// TODO: add a constructor for a match.Match when the data is better shaped
@ -90,7 +140,7 @@ func TestEmptyTablePresenter(t *testing.T) {
results := result.NewResult()
catalog := pkg.NewCatalog()
pres := NewPresenter(results, catalog)
pres := NewPresenter(results, catalog, newMetadataMock())
// run presenter
err := pres.Present(&buffer)

View file

@ -1,3 +1,3 @@
NAME INSTALLED VULNERABILITY FOUND-BY
package-1 1.0.1 CVE-1999-0001
package-2 2.0.1 CVE-1999-0002 a search key...
NAME INSTALLED VULNERABILITY SEVERITY
package-1 1.0.1 CVE-1999-0001 Low
package-2 2.0.1 CVE-1999-0002 Critical