Skip to content

Commit

Permalink
added epss enricher
Browse files Browse the repository at this point in the history
  • Loading branch information
daynewlee committed Nov 12, 2024
1 parent 81480f4 commit 760def1
Showing 1 changed file with 108 additions and 0 deletions.
108 changes: 108 additions & 0 deletions enricher/epss/epss.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package epss

import (
"context"
"encoding/json"
"fmt"
"github.com/google/uuid"
"github.com/quay/claircore"
"github.com/quay/claircore/libvuln/driver"
"github.com/quay/zlog"
"io"
"net/http"
"net/url"
"os"
"path"
"strings"
"time"
)

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

defaultFeed *url.URL
)

const (
// DefaultFeeds is the default place to look for EPSS feeds.
// epss_scores-YYYY-MM-DD.csv.gz needs to be specified to get all data
DefaultRootUrl = `https://epss.cyentia.com/`
)

// Enricher provides EPSS data as enrichments to a VulnerabilityReport.
//
// Configure must be called before any other methods.
type Enricher struct {
driver.NoopUpdater
c *http.Client
feed *url.URL
feedPath string
}

func (e Enricher) FetchEnrichment(ctx context.Context, fingerprint driver.Fingerprint) (io.ReadCloser, driver.Fingerprint, error) {
ctx = zlog.ContextWithValues(ctx, "component", "enricher/epss/Enricher/FetchEnrichment")
currentDate := time.Now()
formattedDate := currentDate.Format("2006-01-02")
// Force a new hint, to signal updaters that this is new data.
newUUID := uuid.New()
hint := driver.Fingerprint(newUUID.String())
zlog.Info(ctx).Str("hint", string(hint)).Msg("starting fetch")
out, err := os.CreateTemp("", "enricher.epss.gz")
if err != nil {
return nil, hint, err
}
var success bool
defer func() {
if !success {
if err := out.Close(); err != nil {
zlog.Warn(ctx).Err(err).Msg("unable to close spool")
}
}
}()
if e.feedPath == "" || !strings.HasSuffix(e.feedPath, ".gz") {
filePath := fmt.Sprintf("epss_scores-%s.csv.gz", formattedDate)
e.feedPath = path.Join(DefaultRootUrl, filePath)
}
// Make an HTTP GET request to download the .gz file
resp, err := http.Get(e.feedPath)
if err != nil {
return nil, "", fmt.Errorf("failed to fetch file from %s: %w", e.feedPath, err)
}
defer resp.Body.Close()

// Check for a successful response
if resp.StatusCode != http.StatusOK {
return nil, "", fmt.Errorf("failed to fetch file: received status %d", resp.StatusCode)
}

_, err = io.Copy(out, resp.Body)
if err != nil {
out.Close()
return nil, "", fmt.Errorf("failed to write to temporary file: %w", err)
}

// Reset file pointer to the beginning
_, err = out.Seek(0, io.SeekStart)
if err != nil {
out.Close()
return nil, "", fmt.Errorf("failed to reset file pointer: %w", err)
}
success = true
return out, hint, nil
}

func (e Enricher) ParseEnrichment(ctx context.Context, closer io.ReadCloser) ([]driver.EnrichmentRecord, error) {
//TODO implement me
panic("implement me")
}

func (e Enricher) Name() string {
//TODO implement me
panic("implement me")
}

func (e Enricher) Enrich(ctx context.Context, getter driver.EnrichmentGetter, report *claircore.VulnerabilityReport) (string, []json.RawMessage, error) {
//TODO implement me
panic("implement me")
}

0 comments on commit 760def1

Please sign in to comment.