Skip to content

Commit

Permalink
epss: add UUID for customized URL
Browse files Browse the repository at this point in the history
Signed-off-by: daynewlee <[email protected]>
  • Loading branch information
daynewlee committed Dec 9, 2024
1 parent facd28e commit f93b034
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 36 deletions.
56 changes: 28 additions & 28 deletions enricher/epss/epss.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package epss provides a epss enricher.
package epss

import (
Expand All @@ -16,6 +17,7 @@ import (
"strings"
"time"

"github.com/google/uuid"
"github.com/quay/zlog"

"github.com/quay/claircore"
Expand All @@ -42,7 +44,7 @@ type EPSSItem struct {

const (
// Type is the type of data returned from the Enricher's Enrich method.
Type = `message/vnd.clair.map.vulnerability; enricher=clair.epss schema=https://csrc.nist.gov/schema/nvd/baseURL/1.1/cvss-v3.x.json`
Type = `message/vnd.clair.map.vulnerability; enricher=clair.epss schema=none`

// DefaultBaseURL is the default place to look for EPSS feeds.
// epss_scores-YYYY-MM-DD.csv.gz needs to be specified to get all data
Expand All @@ -64,7 +66,7 @@ type Enricher struct {

// Config is the configuration for Enricher.
type Config struct {
BaseURL *string `json:"url" yaml:"url"`
URL *string `json:"url" yaml:"url"`
}

func (e *Enricher) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c *http.Client) error {
Expand All @@ -73,24 +75,23 @@ func (e *Enricher) Configure(ctx context.Context, f driver.ConfigUnmarshaler, c
e.c = c
e.feedPath = currentFeedURL()
if f == nil {
zlog.Debug(ctx).Msg("No configuration provided; proceeding with default settings")
return nil
return fmt.Errorf("configuration is nil")
}
if err := f(&cfg); err != nil {
return err
}
if cfg.BaseURL != nil {
if cfg.URL != nil {
// validate the URL format
if _, err := url.Parse(*cfg.BaseURL); err != nil {
return fmt.Errorf("invalid URL format for BaseURL: %w", err)
if _, err := url.Parse(*cfg.URL); err != nil {
return fmt.Errorf("invalid URL format for URL: %w", err)
}

// only .gz file is supported
if strings.HasSuffix(*cfg.BaseURL, ".gz") {
if strings.HasSuffix(*cfg.URL, ".gz") {
//overwrite feedPath is cfg provides another baseURL path
e.feedPath = *cfg.BaseURL
e.feedPath = *cfg.URL
} else {
return fmt.Errorf("invalid baseURL root: expected a '.gz' file, but got '%q'", *cfg.BaseURL)
return fmt.Errorf("invalid baseURL root: expected a '.gz' file, but got '%q'", *cfg.URL)
}
}

Expand Down Expand Up @@ -128,14 +129,19 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, prevFingerprint driver.F
if err = httputil.CheckResponse(resp, http.StatusOK); err != nil {
return nil, "", fmt.Errorf("unable to fetch file: %w", err)
}

etag := resp.Header.Get("etag")
if etag == "" {
return nil, "", fmt.Errorf("ETag not found in response headers")
var str string
var newFingerprint driver.Fingerprint
str = resp.Header.Get("etag")
if str == "" {
newUUID, err := uuid.NewRandom()
if err != nil {
return nil, "", fmt.Errorf("failed to generate UUID: %w", err)
}
// Generate a UUID for customized URL
str = newUUID.String()
zlog.Warn(ctx).Msg("ETag not found; generated UUID for fingerprint")
}

newFingerprint := driver.Fingerprint(etag)

newFingerprint = driver.Fingerprint(str)
if prevFingerprint == newFingerprint {
zlog.Info(ctx).Str("fingerprint", string(newFingerprint)).Msg("file unchanged; skipping processing")
return nil, prevFingerprint, nil
Expand All @@ -158,7 +164,6 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, prevFingerprint driver.F

var modelVersion, date string
for _, field := range record {
field = strings.TrimSpace(field)
field = strings.TrimPrefix(strings.TrimSpace(field), "#")
key, value, found := strings.Cut(field, ":")
if !found {
Expand All @@ -176,11 +181,8 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, prevFingerprint driver.F
return nil, "", fmt.Errorf("missing metadata fields in record: %v", record)
}
csvReader.Comment = '#'
csvReader.FieldsPerRecord = 3 // Expect exactly 3 fields per record

if modelVersion == "" || date == "" {
return nil, "", fmt.Errorf("missing metadata fields in record: %v", record)
}
csvReader.FieldsPerRecord = 3 // Expect exactly 3 fields per record

// Read and validate header line
record, err = csvReader.Read()
Expand Down Expand Up @@ -230,9 +232,7 @@ func (e *Enricher) FetchEnrichment(ctx context.Context, prevFingerprint driver.F
func (e *Enricher) ParseEnrichment(ctx context.Context, rc io.ReadCloser) ([]driver.EnrichmentRecord, error) {
ctx = zlog.ContextWithValues(ctx, "component", "enricher/epss/Enricher/ParseEnrichment")

defer func() {
_ = rc.Close()
}()
defer rc.Close()

dec := json.NewDecoder(rc)
ret := make([]driver.EnrichmentRecord, 0, 250_000)
Expand Down Expand Up @@ -262,8 +262,8 @@ func (*Enricher) Name() string {
}

func currentFeedURL() string {
currentDate := time.Now()
formattedDate := currentDate.Format("2006-01-02")
yesterday := time.Now().AddDate(0, 0, -1) // Get yesterday's date
formattedDate := yesterday.Format("2006-01-02")
filePath := fmt.Sprintf("epss_scores-%s.csv.gz", formattedDate)

feedURL, err := url.Parse(DefaultBaseURL)
Expand Down Expand Up @@ -354,7 +354,7 @@ func (e *Enricher) Enrich(ctx context.Context, g driver.EnrichmentGetter, r *cla
}

func newItemFeed(record []string, modelVersion string, scoreDate string) (driver.EnrichmentRecord, error) {
// Assuming record has already been validated to have 3 fields
// Validate the record has the expected length
if len(record) != 3 {
return driver.EnrichmentRecord{}, fmt.Errorf("unexpected record length: %d", len(record))
}
Expand Down
16 changes: 8 additions & 8 deletions enricher/epss/epss_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestConfigure(t *testing.T) {
Config: func(i interface{}) error {
cfg := i.(*Config)
s := "http://example.com/"
cfg.BaseURL = &s
cfg.URL = &s
return nil
},
Check: func(t *testing.T, err error) {
Expand All @@ -58,11 +58,11 @@ func TestConfigure(t *testing.T) {
},
},
{
Name: "BadURL", // Malformed URL in BaseURL
Name: "BadURL", // Malformed URL in URL
Config: func(i interface{}) error {
cfg := i.(*Config)
s := "http://[notaurl:/"
cfg.BaseURL = &s
cfg.URL = &s
return nil
},
Check: func(t *testing.T, err error) {
Expand All @@ -72,11 +72,11 @@ func TestConfigure(t *testing.T) {
},
},
{
Name: "ValidGZURL", // Proper .gz URL in BaseURL
Name: "ValidGZURL", // Proper .gz URL in URL
Config: func(i interface{}) error {
cfg := i.(*Config)
s := "http://example.com/epss_scores-2024-10-25.csv.gz"
cfg.BaseURL = &s
cfg.URL = &s
return nil
},
Check: func(t *testing.T, err error) {
Expand Down Expand Up @@ -207,7 +207,7 @@ func (tc fetchTestcase) Run(ctx context.Context, srv *httptest.Server) func(*tes
t.Fatal("expected Config type for i, but got a different type")
}
u := srv.URL + "/data.csv.gz"
cfg.BaseURL = &u
cfg.URL = &u
return nil
}

Expand Down Expand Up @@ -259,7 +259,7 @@ func (tc parseTestcase) Run(ctx context.Context, srv *httptest.Server) func(*tes
t.Fatal("assertion failed")
}
u := srv.URL + "/data.csv.gz"
cfg.BaseURL = &u
cfg.URL = &u
return nil
}
if err := e.Configure(ctx, f, srv.Client()); err != nil {
Expand Down Expand Up @@ -313,7 +313,7 @@ func TestEnrich(t *testing.T) {
t.Fatal("assertion failed")
}
u := srv.URL + "/data.csv.gz"
cfg.BaseURL = &u
cfg.URL = &u
return nil
}
if err := e.Configure(ctx, f, srv.Client()); err != nil {
Expand Down

0 comments on commit f93b034

Please sign in to comment.