github.com/quay/claircore@v1.5.28/enricher/cvss/feed.go (about)

     1  package cvss
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"io"
     7  
     8  	"github.com/quay/zlog"
     9  
    10  	"github.com/quay/claircore/libvuln/driver"
    11  )
    12  
    13  type cveFeed struct {
    14  	Count int             `json:"CVE_data_numberOfCVEs,string"`
    15  	Items json.RawMessage `json:"CVE_Items"`
    16  }
    17  
    18  // This is an envelope type so we can get at the cvssv3 object way in there.
    19  type cve struct {
    20  	CVE struct {
    21  		Meta struct {
    22  			ID string `json:"ID"`
    23  		} `json:"CVE_data_meta"`
    24  	} `json:"cve"`
    25  	Impact struct {
    26  		V3 struct {
    27  			CVSS json.RawMessage `json:"cvssV3"`
    28  		} `json:"baseMetricV3"`
    29  	} `json:"impact"`
    30  }
    31  
    32  type itemFeed struct {
    33  	year  int
    34  	items []cve
    35  }
    36  
    37  func newItemFeed(year int, r io.Reader) (*itemFeed, error) {
    38  	var feed cveFeed
    39  	err := json.NewDecoder(r).Decode(&feed)
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	items := make([]cve, 0, feed.Count)
    44  	err = json.Unmarshal(feed.Items, &items)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  	return &itemFeed{
    49  		year:  year,
    50  		items: items,
    51  	}, nil
    52  }
    53  
    54  // Enricher data is written as a series of objects instead of a slice (JSON
    55  // array) of objects to avoid needing to construct the slice and buffer the
    56  // entire serialization in memory.
    57  
    58  func (f *itemFeed) WriteCVSS(ctx context.Context, w io.Writer) error {
    59  	ctx = zlog.ContextWithValues(ctx, "component", "enricher/cvss/itemFeed/WriteCVSS")
    60  	// Use records directly because our parse step doesn't actually parse
    61  	// anything -- the Fetch step rips out the relevant JSON.
    62  	var skip, wrote uint
    63  	enc := json.NewEncoder(w)
    64  	for _, c := range f.items {
    65  		if c.Impact.V3.CVSS == nil {
    66  			skip++
    67  			continue
    68  		}
    69  		r := driver.EnrichmentRecord{
    70  			Tags:       []string{c.CVE.Meta.ID},
    71  			Enrichment: c.Impact.V3.CVSS,
    72  		}
    73  		if err := enc.Encode(&r); err != nil {
    74  			return err
    75  		}
    76  		wrote++
    77  	}
    78  	zlog.Debug(ctx).
    79  		Int("year", f.year).
    80  		Uint("skip", skip).
    81  		Uint("wrote", wrote).
    82  		Msg("wrote cvss items")
    83  	return nil
    84  }