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