Skip to content

Commit

Permalink
enricher: add RHCC enricher
Browse files Browse the repository at this point in the history
This change introduces a new enricher that reports where rhcc packages
exist (if at all), it allows callers to discount vulnerabilities /
packages that come from the same layers. This approach
helps to keep the index report unchanged and therefore state is less
of an issue, it also builds on existing machinary.

Signed-off-by: crozzy <[email protected]>
  • Loading branch information
crozzy committed Jun 11, 2024
1 parent ecc9d8d commit 90a888a
Show file tree
Hide file tree
Showing 8 changed files with 277 additions and 14 deletions.
45 changes: 45 additions & 0 deletions enricher/rhcc/rhcc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package rhcc

import (
"context"
"encoding/json"

"github.com/quay/claircore"
"github.com/quay/claircore/libvuln/driver"
"github.com/quay/claircore/rhel/rhcc"
)

type Enricher struct{}

var (
_ driver.Enricher = (*Enricher)(nil)
)

const (
// Type is the type of data returned from the Enricher's Enrich method.
Type = `message/vnd.clair.map.layer; enricher=clair.rhcc`
)

func (e *Enricher) Name() string { return "rhcc" }

func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *claircore.VulnerabilityReport) (string, []json.RawMessage, error) {
problematicPkgs := make(map[string]string)
for id, _ := range r.Packages {
if envs, ok := r.Environments[id]; ok {
for _, e := range envs {
for _, repoID := range e.RepositoryIDs {
repo := r.Repositories[repoID]
if repo.Name == rhcc.GoldRepo.Name {
problematicPkgs[id] = e.IntroducedIn.String()
}
}
}
}
}

b, err := json.Marshal(problematicPkgs)
if err != nil {
return Type, nil, err

Check warning on line 42 in enricher/rhcc/rhcc.go

View check run for this annotation

Codecov / codecov/patch

enricher/rhcc/rhcc.go#L42

Added line #L42 was not covered by tests
}
return Type, []json.RawMessage{b}, nil
}
218 changes: 218 additions & 0 deletions enricher/rhcc/rhcc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
package rhcc

import (
"context"
"crypto/sha256"
"encoding/json"
"io"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/quay/zlog"

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

func Digest(name string) claircore.Digest {
h := sha256.New()
io.WriteString(h, name)
d, err := claircore.NewDigest("sha256", h.Sum(nil))
if err != nil {
panic(err)
}
return d
}

func TestEnrich(t *testing.T) {
t.Parallel()
ctx := zlog.Test(context.Background(), t)
firstLayerHash := Digest("first layer")
secondLayerHash := Digest("second layer")
tests := []struct {
name string
vr *claircore.VulnerabilityReport
layers []*claircore.Layer
want map[string]string
}{
{
name: "one package that is a layer one that isn't",
vr: &claircore.VulnerabilityReport{
Packages: map[string]*claircore.Package{
"1": {
Name: "some-rh-package-slash-image",
Version: "v1.0.0",
Kind: claircore.BINARY,
},
"2": {
Name: "grafana",
Version: "v4.7.0",
Kind: claircore.BINARY,
},
},
Environments: map[string][]*claircore.Environment{
"1": {{IntroducedIn: firstLayerHash, RepositoryIDs: []string{"1"}}},
"2": {{IntroducedIn: secondLayerHash}},
},
Repositories: map[string]*claircore.Repository{
"1": {
ID: "1",
Name: "Red Hat Container Catalog",
URI: "https://catalog.redhat.com/software/containers/explore",
},
},
},
layers: []*claircore.Layer{
{Hash: firstLayerHash},
{Hash: secondLayerHash},
},
want: map[string]string{"1": firstLayerHash.String()},
},
{
name: "two packages, neither are layers",
vr: &claircore.VulnerabilityReport{
Packages: map[string]*claircore.Package{
"1": {
Name: "cool app",
Version: "v1.0.0",
Kind: claircore.BINARY,
},
"2": {
Name: "grafana",
Version: "v4.7.0",
Kind: claircore.BINARY,
},
},
Environments: map[string][]*claircore.Environment{
"1": {{IntroducedIn: firstLayerHash}},
"2": {{IntroducedIn: firstLayerHash}},
},
},
layers: []*claircore.Layer{
{Hash: firstLayerHash},
{Hash: secondLayerHash},
},
want: map[string]string{},
},
{
name: "multiple rhcc packages in different layers",
vr: &claircore.VulnerabilityReport{
Packages: map[string]*claircore.Package{
"1": {
Name: "some-rh-package-slash-image",
RepositoryHint: "rhcc",
Version: "v1.0.0",
Kind: claircore.BINARY,
},
"2": {
Name: "some-other-rh-package-slash-image",
RepositoryHint: "rhcc",
Version: "v1.0.0",
Kind: claircore.BINARY,
},
"3": {
Name: "grafana",
Version: "v4.7.0",
Kind: claircore.BINARY,
},
},
Environments: map[string][]*claircore.Environment{
"1": {{IntroducedIn: firstLayerHash, RepositoryIDs: []string{"1"}}},
"2": {{IntroducedIn: secondLayerHash, RepositoryIDs: []string{"1"}}},
"3": {{IntroducedIn: firstLayerHash}},
},
Repositories: map[string]*claircore.Repository{
"1": {
ID: "1",
Name: "Red Hat Container Catalog",
URI: "https://catalog.redhat.com/software/containers/explore",
},
},
},
layers: []*claircore.Layer{
{Hash: firstLayerHash},
{Hash: secondLayerHash},
},
want: map[string]string{"1": firstLayerHash.String(), "2": secondLayerHash.String()},
},
{
name: "multiple rhcc packages in same layers (source and binary)",
vr: &claircore.VulnerabilityReport{
Packages: map[string]*claircore.Package{
"1": {
Name: "some-rh-package-slash-image-binary",
Version: "v1.0.0",
Kind: claircore.BINARY,
Source: &claircore.Package{
Name: "some-rh-package-slash-image-source",
Version: "v1.0.0",
Kind: claircore.SOURCE,
},
},
"2": {
Name: "some-rh-package-slash-image-source",
Version: "v1.0.0",
Kind: claircore.SOURCE,
},
"3": {
Name: "grafana",
Version: "v4.7.0",
Kind: claircore.BINARY,
},
},
Environments: map[string][]*claircore.Environment{
"1": {{IntroducedIn: firstLayerHash, RepositoryIDs: []string{"1"}}},
"2": {{IntroducedIn: firstLayerHash, RepositoryIDs: []string{"1"}}},
"3": {{IntroducedIn: secondLayerHash}},
},
Repositories: map[string]*claircore.Repository{
"1": {
ID: "1",
Name: "Red Hat Container Catalog",
URI: "https://catalog.redhat.com/software/containers/explore",
},
},
},
layers: []*claircore.Layer{
{Hash: firstLayerHash},
{Hash: secondLayerHash},
},
want: map[string]string{"1": firstLayerHash.String(), "2": firstLayerHash.String()},
},
}

e := &Enricher{}
nog := &noopGetter{}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
tp, data, err := e.Enrich(ctx, nog, tc.vr)
if err != nil {
t.Fatal(err)
}
if tp != "message/vnd.clair.map.layer; enricher=clair.rhcc" {
t.Fatal("wrong type")
}
got := make(map[string]string)
if err := json.Unmarshal(data[0], &got); err != nil {
t.Error(err)
}
if !cmp.Equal(got, tc.want) {
t.Error(cmp.Diff(got, tc.want))
}
})

}
}

func TestName(t *testing.T) {
e := &Enricher{}
if e.Name() != "rhcc" {
t.Fatal("name should be rhcc")
}
}

type noopGetter struct{}

func (f *noopGetter) GetEnrichment(ctx context.Context, tags []string) ([]driver.EnrichmentRecord, error) {
return nil, nil
}
4 changes: 2 additions & 2 deletions rhel/rhcc/coalescer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestCoalescer(t *testing.T) {
// Mark them as if they came from this package's package scanner
p.RepositoryHint = `rhcc`
}
repo := []*claircore.Repository{&goldRepo}
repo := []*claircore.Repository{&GoldRepo}
layerArtifacts := []*indexer.LayerArtifacts{
{
Hash: test.RandomSHA256Digest(t),
Expand Down Expand Up @@ -67,7 +67,7 @@ func TestCoalescer(t *testing.T) {
}
for _, id := range e.RepositoryIDs {
r := ir.Repositories[id]
if got, want := r.Name, goldRepo.Name; got != want {
if got, want := r.Name, GoldRepo.Name; got != want {
t.Errorf("got: %q, want: %q", got, want)
}
}
Expand Down
2 changes: 1 addition & 1 deletion rhel/rhcc/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (*matcher) Name() string { return "rhel-container-matcher" }
// Filter implements [driver.Matcher].
func (*matcher) Filter(r *claircore.IndexRecord) bool {
return r.Repository != nil &&
r.Repository.Name == goldRepo.Name
r.Repository.Name == GoldRepo.Name
}

// Query implements [driver.Matcher].
Expand Down
16 changes: 8 additions & 8 deletions rhel/rhcc/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestDB(t *testing.T) {
Links: "https://access.redhat.com/errata/RHSA-2021:3665 https://access.redhat.com/security/cve/CVE-2021-3762",
NormalizedSeverity: claircore.High,
FixedInVersion: "v3.5.7-8",
Repo: &goldRepo,
Repo: &GoldRepo,
Range: &claircore.Range{
Lower: claircore.Version{
Kind: "rhctag",
Expand Down Expand Up @@ -81,7 +81,7 @@ func TestDB(t *testing.T) {
},
},
FixedInVersion: "v4.6.0-202112140546.p0.g8b9da97.assembly.stream",
Repo: &goldRepo,
Repo: &GoldRepo,
},
{
Name: "RHSA-2021:5107",
Expand All @@ -103,7 +103,7 @@ func TestDB(t *testing.T) {
},
},
FixedInVersion: "v4.7.0-202112140553.p0.g091bb99.assembly.stream",
Repo: &goldRepo,
Repo: &GoldRepo,
},
{
Name: "RHSA-2021:5108",
Expand All @@ -125,7 +125,7 @@ func TestDB(t *testing.T) {
},
},
FixedInVersion: "v4.8.0-202112132154.p0.g57dd03a.assembly.stream",
Repo: &goldRepo,
Repo: &GoldRepo,
},
},
},
Expand Down Expand Up @@ -153,7 +153,7 @@ func TestDB(t *testing.T) {
},
},
FixedInVersion: "v6.8.1-65",
Repo: &goldRepo,
Repo: &GoldRepo,
},
{
Name: "RHSA-2021:5137",
Expand All @@ -175,7 +175,7 @@ func TestDB(t *testing.T) {
},
},
FixedInVersion: "v5.0.10-1",
Repo: &goldRepo,
Repo: &GoldRepo,
},
},
},
Expand Down Expand Up @@ -203,7 +203,7 @@ func TestDB(t *testing.T) {
},
},
FixedInVersion: "4.8-167.9a9db5f.release_4.8",
Repo: &goldRepo,
Repo: &GoldRepo,
},
{
Name: "RHSA-2021:2041",
Expand All @@ -225,7 +225,7 @@ func TestDB(t *testing.T) {
},
},
FixedInVersion: "4.7-140.49a6fcf.release_4.7",
Repo: &goldRepo,
Repo: &GoldRepo,
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion rhel/rhcc/rhcc.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"github.com/quay/claircore/toolkit/types/cpe"
)

var goldRepo = claircore.Repository{
var GoldRepo = claircore.Repository{
Name: "Red Hat Container Catalog",
URI: `https://catalog.redhat.com/software/containers/explore`,
}
Expand Down
2 changes: 1 addition & 1 deletion rhel/rhcc/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,5 +299,5 @@ func (s *reposcanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircor
}
zlog.Debug(ctx).
Msg("found buildinfo Dockerfile")
return []*claircore.Repository{&goldRepo}, nil
return []*claircore.Repository{&GoldRepo}, nil

Check warning on line 302 in rhel/rhcc/scanner.go

View check run for this annotation

Codecov / codecov/patch

rhel/rhcc/scanner.go#L302

Added line #L302 was not covered by tests
}
2 changes: 1 addition & 1 deletion rhel/rhcc/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ func (u *updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vuln
Severity: releasesByMinor[minor].Severity,
NormalizedSeverity: common.NormalizeSeverity(releasesByMinor[minor].Severity),
Package: p,
Repo: &goldRepo,
Repo: &GoldRepo,
Links: links,
FixedInVersion: firstPatch.Original,
Range: r,
Expand Down

0 comments on commit 90a888a

Please sign in to comment.