Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: quay/claircore
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: cb74edd29556ea8da13b4ff4c4718eb2b2125160
Choose a base ref
..
head repository: quay/claircore
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 9e040ff5a418afe8c7b9caf82444a6480f2df8b8
Choose a head ref
2 changes: 1 addition & 1 deletion java/matcher.go
Original file line number Diff line number Diff line change
@@ -40,7 +40,7 @@ func (*Matcher) Vulnerable(ctx context.Context, record *claircore.IndexRecord, v

// Check for missing upper version
if !decodedVersions.Has("fixed") && !decodedVersions.Has("lastAffected") {
return false, fmt.Errorf("maven: missing upper version")
return false, fmt.Errorf("maven: %q missing upper version", vuln.Name)
}

upperVersion := decodedVersions.Get("fixed")
27 changes: 17 additions & 10 deletions libvuln/jsonblob/jsonblob.go
Original file line number Diff line number Diff line change
@@ -85,15 +85,22 @@ func (l *Loader) Next() bool {
l.next.Date = l.de.Date
}
i := len(vs)
vs = append(vs, claircore.Vulnerability{})
if err := json.Unmarshal(l.de.Vuln.buf, &vs[i]); err != nil {
l.err = err
return false
switch l.de.Kind {
case driver.VulnerabilityKind:
vs = append(vs, claircore.Vulnerability{})
if err := json.Unmarshal(l.de.Vuln.buf, &vs[i]); err != nil {
l.err = err
return false
}
l.next.Vuln = append(l.next.Vuln, &vs[i])
case driver.EnrichmentKind:
en := driver.EnrichmentRecord{}
if err := json.Unmarshal(l.de.Enrichment.buf, &en); err != nil {
l.err = err
return false
}
l.next.Enrichment = append(l.next.Enrichment, en)
}
l.next.Vuln = append(l.next.Vuln, &vs[i])

// BUG(hank) The [Loader] type does not handle Enrichments.

// If this was an initial diskEntry, promote the ref.
if id != l.cur {
l.cur = id
@@ -234,8 +241,8 @@ type CommonEntry struct {
Date time.Time
}

// DiskEntry is a single vulnerability. It's made from unpacking an Entry's
// slice and adding a uuid for grouping back into an Entry upon read.
// DiskEntry is a single vulnerability or enrichment. It's made from unpacking an
// Entry's slice and adding an uuid for grouping back into an Entry upon read.
//
// "Vuln" and "Enrichment" are populated from the backing disk immediately
// before being serialized.
53 changes: 47 additions & 6 deletions libvuln/jsonblob/jsonblob_test.go
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ import (
"golang.org/x/sync/errgroup"

"github.com/quay/claircore"
"github.com/quay/claircore/libvuln/driver"
"github.com/quay/claircore/test"
)

@@ -41,8 +42,20 @@ func TestRoundtrip(t *testing.T) {
t.Fatal(err)
}

vs := test.GenUniqueVulnerabilities(10, "test")
ref, err := a.UpdateVulnerabilities(ctx, "test", "", vs)
var want, got struct {
V []*claircore.Vulnerability
E []driver.EnrichmentRecord
}

want.V = test.GenUniqueVulnerabilities(10, "test")
ref, err := a.UpdateVulnerabilities(ctx, "test", "", want.V)
if err != nil {
t.Error(err)
}
t.Logf("ref: %v", ref)

want.E = test.GenEnrichments(15)
ref, err = a.UpdateEnrichments(ctx, "test", "", want.E)
if err != nil {
t.Error(err)
}
@@ -52,7 +65,6 @@ func TestRoundtrip(t *testing.T) {
defer func() {
t.Logf("wrote:\n%s", buf.String())
}()
var got []*claircore.Vulnerability
r, w := io.Pipe()
eg, ctx := errgroup.WithContext(ctx)
eg.Go(func() error { defer w.Close(); return a.Store(w) })
@@ -62,7 +74,16 @@ func TestRoundtrip(t *testing.T) {
return err
}
for l.Next() {
got = append(got, l.Entry().Vuln...)
e := l.Entry()
if e.Vuln != nil && e.Enrichment != nil {
t.Error("expecting entry to have either vulnerability or enrichment, got both")
}
if e.Vuln != nil {
got.V = append(got.V, l.Entry().Vuln...)
}
if e.Enrichment != nil {
got.E = append(got.E, l.Entry().Enrichment...)
}
}
if err := l.Err(); err != nil {
return err
@@ -72,8 +93,28 @@ func TestRoundtrip(t *testing.T) {
if err := eg.Wait(); err != nil {
t.Error(err)
}
if !cmp.Equal(got, want) {
t.Error(cmp.Diff(got, want))
}
}

if !cmp.Equal(got, vs) {
t.Error(cmp.Diff(got, vs))
func TestEnrichments(t *testing.T) {
s, err := New()
if err != nil {
t.Fatal(err)
}
ctx := context.Background()

en := test.GenEnrichments(5)
ref, err := s.UpdateEnrichments(ctx, "test", "", en)
if err != nil {
t.Error(err)
}
t.Logf("ref: %v", ref)

var buf bytes.Buffer
if err := s.Store(&buf); err != nil {
t.Error(err)
}
t.Logf("wrote:\n%s", buf.String())
}
15 changes: 12 additions & 3 deletions libvuln/updates.go
Original file line number Diff line number Diff line change
@@ -2,8 +2,10 @@ package libvuln

import (
"context"
"fmt"
"io"

"github.com/google/uuid"
"github.com/jackc/pgx/v4/pgxpool"
"github.com/quay/zlog"

@@ -47,9 +49,16 @@ Update:
continue Update
}
}
ref, err := s.UpdateVulnerabilities(ctx, e.Updater, e.Fingerprint, e.Vuln)
if err != nil {
return err
var ref uuid.UUID
if e.Enrichment != nil {
if ref, err = s.UpdateEnrichments(ctx, e.Updater, e.Fingerprint, e.Enrichment); err != nil {
return fmt.Errorf("updating enrichements: %w", err)
}
}
if e.Vuln != nil {
if ref, err = s.UpdateVulnerabilities(ctx, e.Updater, e.Fingerprint, e.Vuln); err != nil {
return fmt.Errorf("updating vulnerabilities: %w", err)
}
}
zlog.Info(ctx).
Str("updater", e.Updater).
48 changes: 48 additions & 0 deletions nodejs/coalescer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package nodejs

import (
"context"
"github.com/quay/claircore"

"github.com/quay/claircore/indexer"
)

var _ indexer.Coalescer = (*coalescer)(nil)

type coalescer struct{}

func NewCoalescer(_ context.Context) (indexer.Coalescer, error) {
return &coalescer{}, nil
}

func (c *coalescer) Coalesce(_ context.Context, ls []*indexer.LayerArtifacts) (*claircore.IndexReport, error) {
ir := &claircore.IndexReport{
Environments: map[string][]*claircore.Environment{},
Packages: map[string]*claircore.Package{},
Repositories: map[string]*claircore.Repository{},
}

for _, l := range ls {
// If we didn't find at least one npm repo in this layer
// no point in searching for packages.
if len(l.Repos) == 0 {
continue
}
rs := make([]string, len(l.Repos))
for i, r := range l.Repos {
rs[i] = r.ID
ir.Repositories[r.ID] = r
}
for _, pkg := range l.Pkgs {
ir.Packages[pkg.ID] = pkg
ir.Environments[pkg.ID] = []*claircore.Environment{
{
PackageDB: pkg.PackageDB,
IntroducedIn: l.Hash,
RepositoryIDs: rs,
},
}
}
}
return ir, nil
}
71 changes: 71 additions & 0 deletions nodejs/coalescer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package nodejs

import (
"context"
"strconv"
"testing"

"github.com/quay/zlog"

"github.com/quay/claircore"
"github.com/quay/claircore/indexer"
"github.com/quay/claircore/test"
)

func TestCoalescer(t *testing.T) {
t.Parallel()
ctx := zlog.Test(context.Background(), t)
coalescer := &coalescer{}
pkgs := test.GenUniquePackages(6)
repo := []*claircore.Repository{&Repository}
layerArtifacts := []*indexer.LayerArtifacts{
{
Hash: test.RandomSHA256Digest(t),
Pkgs: pkgs[:1],
},
{
Hash: test.RandomSHA256Digest(t),
Pkgs: pkgs[:2],
},
{
Hash: test.RandomSHA256Digest(t),
Pkgs: pkgs[:3],
Repos: repo,
},
{
Hash: test.RandomSHA256Digest(t),
Pkgs: pkgs[:4],
},
{
Hash: test.RandomSHA256Digest(t),
Pkgs: pkgs[:5],
Repos: repo,
},
{
Hash: test.RandomSHA256Digest(t),
Pkgs: pkgs,
},
}
ir, err := coalescer.Coalesce(ctx, layerArtifacts)
if err != nil {
t.Fatalf("received error from coalesce method: %v", err)
}
// Expect 0-5 to have gotten associated with the repository.
for i := range pkgs {
es, ok := ir.Environments[strconv.Itoa(i)]
if !ok && i == 5 {
// Left out the last package.
continue
}
e := es[0]
if len(e.RepositoryIDs) == 0 {
t.Error("expected some repositories")
}
for _, id := range e.RepositoryIDs {
r := ir.Repositories[id]
if got, want := r.Name, Repository.Name; got != want {
t.Errorf("got: %q, want: %q", got, want)
}
}
}
}
19 changes: 19 additions & 0 deletions nodejs/ecosystem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package nodejs

import (
"context"

"github.com/quay/claircore/indexer"
)

var scanners = []indexer.PackageScanner{&Scanner{}}

// NewEcosystem provides the set of scanners for the nodejs ecosystem.
func NewEcosystem(_ context.Context) *indexer.Ecosystem {
return &indexer.Ecosystem{
PackageScanners: func(_ context.Context) ([]indexer.PackageScanner, error) { return scanners, nil },
DistributionScanners: func(_ context.Context) ([]indexer.DistributionScanner, error) { return nil, nil },
RepositoryScanners: func(_ context.Context) ([]indexer.RepositoryScanner, error) { return nil, nil },
Coalescer: NewCoalescer,
}
}
Loading