Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Goodman <[email protected]>
  • Loading branch information
wagoodman committed Dec 12, 2024
1 parent cd9326b commit 5d3cea7
Show file tree
Hide file tree
Showing 10 changed files with 733 additions and 37 deletions.
8 changes: 4 additions & 4 deletions cmd/grype/cli/commands/db_search_pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ func DBSearchPackages(app clio.Application) *cobra.Command {
return nil
},
RunE: func(_ *cobra.Command, _ []string) (err error) {
if len(opts.Vulnerability.VulnerabilityIDs) == 0 {
// TODO: we can relax this over time, but for now make it required
return fmt.Errorf("must specify at least one vulnerability ID")
}
return runDBSearchPackages(*opts)
},
}, opts)
Expand Down Expand Up @@ -86,6 +82,10 @@ func newDBSearchPackages(opts dbSearchPackageOptions) error {
return fmt.Errorf("unable to get providers: %w", err)
}

if err := validateProvidersFilter(reader, opts.Vulnerability.Providers); err != nil {
return err
}

rows, err := dbsearch.AffectedPackages(reader, dbsearch.AffectedPackagesOptions{
Vulnerability: opts.Vulnerability.Specs,
Package: opts.Package.PkgSpecs,
Expand Down
62 changes: 55 additions & 7 deletions cmd/grype/cli/commands/db_search_vuln.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ import (
"errors"
"fmt"
"io"
"sort"
"strings"

"github.com/hashicorp/go-multierror"
"github.com/olekukonko/tablewriter"
"github.com/scylladb/go-set/strset"
"github.com/spf13/cobra"

"github.com/anchore/clio"
"github.com/anchore/grype/cmd/grype/cli/commands/internal/dbsearch"
"github.com/anchore/grype/cmd/grype/cli/options"
v6 "github.com/anchore/grype/grype/db/v6"
"github.com/anchore/grype/grype/db/v6/distribution"
"github.com/anchore/grype/grype/db/v6/installation"
"github.com/anchore/grype/internal/bus"
Expand Down Expand Up @@ -80,6 +84,10 @@ func runNewDBSearchVulnerabilities(opts dbSearchVulnerabilityOptions) error {
return fmt.Errorf("unable to get providers: %w", err)
}

if err := validateProvidersFilter(reader, opts.Vulnerability.Providers); err != nil {
return err
}

rows, err := dbsearch.Vulnerabilities(reader, opts.Vulnerability.Specs)
if err != nil {
return err
Expand All @@ -95,6 +103,32 @@ func runNewDBSearchVulnerabilities(opts dbSearchVulnerabilityOptions) error {
return err
}

func validateProvidersFilter(reader v6.Reader, providers []string) error {
if len(providers) == 0 {
return nil
}
availableProviders, err := reader.AllProviders()
if err != nil {
return fmt.Errorf("unable to get providers: %w", err)
}
activeProviders := strset.New()
for _, p := range availableProviders {
activeProviders.Add(p.ID)
}

provSet := strset.New(providers...)

diff := strset.Difference(provSet, activeProviders)
diffList := diff.List()
sort.Strings(diffList)
var errs error
for _, p := range diffList {
errs = multierror.Append(errs, fmt.Errorf("provider not found: %q", p))
}

return errs
}

func presentDBSearchVulnerabilities(outputFormat string, structuredRows []dbsearch.VulnerabilityRow, output io.Writer) error {
if len(structuredRows) == 0 {
// TODO: show a message that no results were found?
Expand All @@ -108,7 +142,7 @@ func presentDBSearchVulnerabilities(outputFormat string, structuredRows []dbsear
table := tablewriter.NewWriter(output)
commonTableWriterOptions(table)

table.SetHeader([]string{"ID", "Provider", "Severity"})
table.SetHeader([]string{"ID", "Provider", "Published", "Severity", "Reference"})
table.AppendBulk(rows)
table.Render()
case jsonOutputFormat:
Expand All @@ -130,15 +164,29 @@ func renderDBSearchVulnerabilitiesTableRows(structuredRows []dbsearch.Vulnerabil
// get the first severity value (which is ranked highest)
var sev string
if len(rr.Severities) > 0 {
s := rr.Severities[0]
var source string
if s.Source != "" {
source = fmt.Sprintf(" from %s", s.Source)
sev = fmt.Sprintf("%s", rr.Severities[0].Value)
}

prov := rr.Provider
if len(rr.OperatingSystems) > 0 {
var versions []string
for _, os := range rr.OperatingSystems {
versions = append(versions, os.Version)
}
sev = fmt.Sprintf("%s%s", s.Value, source)
prov = fmt.Sprintf("%s (%s)", rr.Provider, strings.Join(versions, ", "))
}

var published string
if rr.PublishedDate != nil && !rr.PublishedDate.IsZero() {
published = rr.PublishedDate.Format("2006-01-02")
}

var ref string
if len(rr.References) > 0 {
ref = rr.References[0].URL
}

rows = append(rows, []string{rr.ID, rr.Provider, sev})
rows = append(rows, []string{rr.ID, prov, published, sev, ref})
}
return rows
}
16 changes: 9 additions & 7 deletions cmd/grype/cli/commands/internal/dbsearch/affected_packages.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

type AffectedPackageTableRow struct {
Vulnerability VulnerabilityRow `json:"vulnerability"`
Vulnerability VulnerabilityInfo `json:"vulnerability"`
OS *OS `json:"os,omitempty"`
Package *Package `json:"package,omitempty"`
CPE *v6.Cpe `json:"cpe,omitempty"`
Expand All @@ -23,14 +23,12 @@ func (r AffectedPackageTableRow) MarshalJSON() ([]byte, error) {
c = r.CPE.String()
}
return json.Marshal(&struct {
Vulnerability VulnerabilityRow `json:"vulnerability"`
OS *OS `json:"os,omitempty"`
Vulnerability VulnerabilityInfo `json:"vulnerability"`
Package *Package `json:"package,omitempty"`
CPE string `json:"cpe,omitempty"`
Detail v6.AffectedPackageBlob `json:"detail"`
}{
Vulnerability: r.Vulnerability,
OS: r.OS,
Package: r.Package,
CPE: c,
Detail: r.Detail,
Expand Down Expand Up @@ -58,8 +56,9 @@ func newAffectedPackageRows(affectedPkgs []v6.AffectedPackageHandle, affectedCPE
log.Errorf("affected package record missing vulnerability: %+v", pkg)
continue
}

rows = append(rows, AffectedPackageTableRow{
Vulnerability: newVulnerabilityRow(*pkg.Vulnerability),
Vulnerability: newVulnerabilityInfo(*pkg.Vulnerability),
OS: toOS(pkg.OperatingSystem),
Package: toPackage(pkg.Package),
Detail: detail,
Expand All @@ -78,7 +77,7 @@ func newAffectedPackageRows(affectedPkgs []v6.AffectedPackageHandle, affectedCPE
}

rows = append(rows, AffectedPackageTableRow{
Vulnerability: newVulnerabilityRow(*ac.Vulnerability),
Vulnerability: newVulnerabilityInfo(*ac.Vulnerability),
CPE: ac.CPE,
Detail: detail,
})
Expand Down Expand Up @@ -118,7 +117,10 @@ type AffectedPackagesOptions struct {
OS v6.OSSpecifiers
}

func AffectedPackages(reader v6.Reader, criteria AffectedPackagesOptions) ([]AffectedPackageTableRow, error) {
func AffectedPackages(reader interface {
v6.AffectedPackageStoreReader
v6.AffectedCPEStoreReader
}, criteria AffectedPackagesOptions) ([]AffectedPackageTableRow, error) {
var allAffectedPkgs []v6.AffectedPackageHandle
var allAffectedCPEs []v6.AffectedCPEHandle

Expand Down
Loading

0 comments on commit 5d3cea7

Please sign in to comment.