Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow grype db diff to specify local db directories #1058

Merged
merged 2 commits into from
Jan 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 28 additions & 27 deletions cmd/db_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package cmd

import (
"fmt"
"net/url"
"os"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -35,7 +34,7 @@ func init() {
dbCmd.AddCommand(dbDiffCmd)
}

func startDBDiffCmd(dbURL []*url.URL, deleteDatabases bool) <-chan error {
func startDBDiffCmd(base string, target string, deleteDatabases bool) <-chan error {
errs := make(chan error)
go func() {
defer close(errs)
Expand All @@ -45,10 +44,12 @@ func startDBDiffCmd(dbURL []*url.URL, deleteDatabases bool) <-chan error {
return
}

baseURL := dbURL[0]
targetURL := dbURL[1]
if err := d.SetBaseDB(base); err != nil {
errs <- err
return
}

if err := d.DownloadDatabases(baseURL, targetURL); err != nil {
if err := d.SetTargetDB(target); err != nil {
errs <- err
return
}
Expand Down Expand Up @@ -96,55 +97,55 @@ func runDBDiffCmd(cmd *cobra.Command, args []string) error {
return err
}

var dbURL []*url.URL
var base, target string

if len(args) < 2 {
switch len(args) {
case 0:
log.Info("base_db_url and target_db_url not provided; fetching most recent")
dbURL, err = getDefaultURL()
base, target, err = getDefaultURLs()
if err != nil {
return fmt.Errorf("could not fetch most recent database URL: %w", err)
return err
}
} else {
for _, arg := range args {
u, err := url.Parse(arg)
if err != nil {
return fmt.Errorf("url argument is malformed: %w", err)
}

dbURL = append(dbURL, u)
case 1:
log.Info("target_db_url not provided; fetching most recent")
base = args[0]
_, target, err = getDefaultURLs()
if err != nil {
return err
}
default:
base = args[0]
target = args[1]
}

return eventLoop(
startDBDiffCmd(dbURL, deleteDatabases),
startDBDiffCmd(base, target, deleteDatabases),
setupSignals(),
eventSubscription,
stereoscope.Cleanup,
ui.Select(isVerbose(), appConfig.Quiet, reporter)...,
)
}

func getDefaultURL() (defaultURL []*url.URL, err error) {
func getDefaultURLs() (baseURL string, targetURL string, err error) {
dbCurator, err := db.NewCurator(appConfig.DB.ToCuratorConfig())
if err != nil {
return nil, err
return "", "", err
}

listing, err := dbCurator.ListingFromURL()
if err != nil {
return nil, err
return "", "", err
}

supportedSchema := dbCurator.SupportedSchema()
available, exists := listing.Available[supportedSchema]
if len(available) < 2 || !exists {
return nil, stderrPrintLnf("Not enough databases available for the current schema to diff (%d)", supportedSchema)
return "", "", stderrPrintLnf("Not enough databases available for the current schema to diff (%d)", supportedSchema)
}

recent := available[:2]
for _, entry := range recent {
defaultURL = append([]*url.URL{entry.URL}, defaultURL...)
}
targetURL = available[0].URL.String()
baseURL = available[1].URL.String()

return defaultURL, nil
return baseURL, targetURL, nil
}
63 changes: 37 additions & 26 deletions grype/differ/differ.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,40 +49,51 @@ func NewDiffer(config db.Config) (*Differ, error) {
}, nil
}

func (d *Differ) DownloadDatabases(baseURL, targetURL *url.URL) error {
listing, err := d.baseCurator.ListingFromURL()
if err != nil {
return err
}
func (d *Differ) SetBaseDB(base string) error {
return d.setOrDownload(&d.baseCurator, base)
}

listings := listing.Available
dbs := listings[v5.SchemaVersion]
func (d *Differ) SetTargetDB(target string) error {
return d.setOrDownload(&d.targetCurator, target)
}

var baseListing *db.ListingEntry
var targetListing *db.ListingEntry
func (d *Differ) setOrDownload(curator *db.Curator, filenameOrURL string) error {
u, err := url.ParseRequestURI(filenameOrURL)

for _, db := range dbs {
database := db
if *db.URL == *baseURL {
baseListing = &database
if err != nil || u.Scheme == "" {
*curator, err = db.NewCurator(db.Config{
DBRootDir: filenameOrURL,
})
if err != nil {
return err
}
if *db.URL == *targetURL {
targetListing = &database
} else {
listings, err := d.baseCurator.ListingFromURL()
if err != nil {
return err
}
}

if baseListing == nil {
return fmt.Errorf("unable to find listing for base url: %s", baseURL.String())
} else if targetListing == nil {
return fmt.Errorf("unable to find listing for target url: %s", targetURL.String())
}
available := listings.Available
dbs := available[v5.SchemaVersion]

if err := download(&d.baseCurator, baseListing); err != nil {
return fmt.Errorf("unable to update base vulnerability database: %+v", err)
}
if err := download(&d.targetCurator, targetListing); err != nil {
return fmt.Errorf("unable to update target vulnerability database: %+v", err)
var listing *db.ListingEntry

for _, d := range dbs {
database := d
if *d.URL == *u {
listing = &database
}
}

if listing == nil {
return fmt.Errorf("unable to find listing for url: %s", filenameOrURL)
}

if err := download(curator, listing); err != nil {
return fmt.Errorf("unable to download vulnerability database: %+v", err)
}
}

return nil
}

Expand Down
21 changes: 21 additions & 0 deletions grype/differ/differ_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package differ
import (
"bytes"
"flag"
"strconv"
"testing"

"github.com/sergi/go-diff/diffmatchpatch"
Expand All @@ -11,6 +12,7 @@ import (
"github.com/anchore/go-testutils"
"github.com/anchore/grype/grype/db"
v5 "github.com/anchore/grype/grype/db/v5"
"github.com/anchore/grype/grype/vulnerability"
)

var update = flag.Bool("update", false, "update the *.golden files for diff presenter")
Expand All @@ -27,6 +29,25 @@ func TestNewDiffer(t *testing.T) {
require.NotNil(t, differ.baseCurator)
}

func Test_DifferDirectory(t *testing.T) {
d, err := NewDiffer(db.Config{
DBRootDir: "root-dir",
})
require.NoError(t, err)

err = d.SetBaseDB("test-fixtures/dbs/base")
require.NoError(t, err)

baseStatus := d.baseCurator.Status()
require.Equal(t, "test-fixtures/dbs/base/"+strconv.Itoa(vulnerability.SchemaVersion), baseStatus.Location)

err = d.SetTargetDB("test-fixtures/dbs/target")
require.NoError(t, err)

targetStatus := d.targetCurator.Status()
require.Equal(t, "test-fixtures/dbs/target/"+strconv.Itoa(vulnerability.SchemaVersion), targetStatus.Location)
}

func TestPresent_Json(t *testing.T) {
//GIVEN
diffs := []v5.Diff{
Expand Down
5 changes: 5 additions & 0 deletions grype/differ/test-fixtures/dbs/base/5/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"built": "2022-12-18T08:18:18Z",
"version": 5,
"checksum": "sha256:9d979f7320c575e7ac41c4384e9f55d578cdddd701822563cabc6b913fde7b80"
}
1 change: 1 addition & 0 deletions grype/differ/test-fixtures/dbs/base/5/vulnerability.db
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
an older vulnerability db
5 changes: 5 additions & 0 deletions grype/differ/test-fixtures/dbs/target/5/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"built": "2022-12-18T08:18:18Z",
"version": 5,
"checksum": "sha256:da2141ae7415abe5cf5390faeed60e164c5a919370ee823c8cc3ad9f4698f56e"
}
1 change: 1 addition & 0 deletions grype/differ/test-fixtures/dbs/target/5/vulnerability.db
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a vulnerability db