/
parser.go
92 lines (84 loc) · 2.83 KB
/
parser.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
85
86
87
88
89
90
91
92
package rhel
import (
"context"
"encoding/xml"
"fmt"
"io"
"github.com/quay/goval-parser/oval"
"github.com/quay/zlog"
"github.com/quay/claircore"
"github.com/quay/claircore/internal/xmlutil"
"github.com/quay/claircore/pkg/ovalutil"
"github.com/quay/claircore/rhel/internal/common"
"github.com/quay/claircore/toolkit/types/cpe"
)
// Parse implements [driver.Updater].
//
// Parse treats the data inside the provided io.ReadCloser as Red Hat
// flavored OVAL XML. The distribution associated with vulnerabilities
// is configured via the Updater. The repository associated with
// vulnerabilies is based on the affected CPE list.
func (u *Updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vulnerability, error) {
ctx = zlog.ContextWithValues(ctx, "component", "rhel/Updater.Parse")
zlog.Info(ctx).Msg("starting parse")
defer r.Close()
root := oval.Root{}
dec := xml.NewDecoder(r)
dec.CharsetReader = xmlutil.CharsetReader
if err := dec.Decode(&root); err != nil {
return nil, fmt.Errorf("rhel: unable to decode OVAL document: %w", err)
}
zlog.Debug(ctx).Msg("xml decoded")
protoVulns := func(def oval.Definition) ([]*claircore.Vulnerability, error) {
vs := []*claircore.Vulnerability{}
defType, err := ovalutil.GetDefinitionType(def)
if err != nil {
return nil, err
}
// Red Hat OVAL data include information about vulnerabilities,
// that actually don't affect the package in any way. Storing them
// would increase number of records in DB without adding any value.
if isSkippableDefinitionType(defType, u.ignoreUnpatched) {
return vs, nil
}
for _, affected := range def.Advisory.AffectedCPEList {
// Work around having empty entries. This seems to be some issue
// with the tool used to produce the database but only seems to
// appear sometimes, like RHSA-2018:3140 in the rhel-7-alt database.
if affected == "" {
continue
}
wfn, err := cpe.Unbind(affected)
if err != nil {
return nil, err
}
v := &claircore.Vulnerability{
Updater: u.Name(),
Name: def.Title,
Description: def.Description,
Issued: def.Advisory.Issued.Date,
Links: ovalutil.Links(def),
Severity: def.Advisory.Severity,
NormalizedSeverity: common.NormalizeSeverity(def.Advisory.Severity),
Repo: &claircore.Repository{
Name: affected,
CPE: wfn,
Key: repositoryKey,
},
Dist: u.dist,
}
vs = append(vs, v)
}
return vs, nil
}
vulns, err := ovalutil.RPMDefsToVulns(ctx, &root, protoVulns)
if err != nil {
return nil, err
}
return vulns, nil
}
func isSkippableDefinitionType(defType ovalutil.DefinitionType, ignoreUnpatched bool) bool {
return defType == ovalutil.UnaffectedDefinition ||
defType == ovalutil.NoneDefinition ||
(ignoreUnpatched && defType == ovalutil.CVEDefinition)
}