github.com/quay/claircore@v1.5.28/rhel/parser.go (about) 1 package rhel 2 3 import ( 4 "context" 5 "encoding/xml" 6 "fmt" 7 "io" 8 9 "github.com/quay/goval-parser/oval" 10 "github.com/quay/zlog" 11 12 "github.com/quay/claircore" 13 "github.com/quay/claircore/internal/xmlutil" 14 "github.com/quay/claircore/pkg/ovalutil" 15 "github.com/quay/claircore/rhel/internal/common" 16 "github.com/quay/claircore/toolkit/types/cpe" 17 ) 18 19 // Parse implements [driver.Updater]. 20 // 21 // Parse treats the data inside the provided io.ReadCloser as Red Hat 22 // flavored OVAL XML. The distribution associated with vulnerabilities 23 // is configured via the Updater. The repository associated with 24 // vulnerabilies is based on the affected CPE list. 25 func (u *Updater) Parse(ctx context.Context, r io.ReadCloser) ([]*claircore.Vulnerability, error) { 26 ctx = zlog.ContextWithValues(ctx, "component", "rhel/Updater.Parse") 27 zlog.Info(ctx).Msg("starting parse") 28 defer r.Close() 29 root := oval.Root{} 30 dec := xml.NewDecoder(r) 31 dec.CharsetReader = xmlutil.CharsetReader 32 if err := dec.Decode(&root); err != nil { 33 return nil, fmt.Errorf("rhel: unable to decode OVAL document: %w", err) 34 } 35 zlog.Debug(ctx).Msg("xml decoded") 36 protoVulns := func(def oval.Definition) ([]*claircore.Vulnerability, error) { 37 vs := []*claircore.Vulnerability{} 38 39 defType, err := ovalutil.GetDefinitionType(def) 40 if err != nil { 41 return nil, err 42 } 43 // Red Hat OVAL data include information about vulnerabilities, 44 // that actually don't affect the package in any way. Storing them 45 // would increase number of records in DB without adding any value. 46 if isSkippableDefinitionType(defType, u.ignoreUnpatched) { 47 return vs, nil 48 } 49 50 for _, affected := range def.Advisory.AffectedCPEList { 51 // Work around having empty entries. This seems to be some issue 52 // with the tool used to produce the database but only seems to 53 // appear sometimes, like RHSA-2018:3140 in the rhel-7-alt database. 54 if affected == "" { 55 continue 56 } 57 58 wfn, err := cpe.Unbind(affected) 59 if err != nil { 60 return nil, err 61 } 62 v := &claircore.Vulnerability{ 63 Updater: u.Name(), 64 Name: def.Title, 65 Description: def.Description, 66 Issued: def.Advisory.Issued.Date, 67 Links: ovalutil.Links(def), 68 Severity: def.Advisory.Severity, 69 NormalizedSeverity: common.NormalizeSeverity(def.Advisory.Severity), 70 Repo: &claircore.Repository{ 71 Name: affected, 72 CPE: wfn, 73 Key: repositoryKey, 74 }, 75 Dist: u.dist, 76 } 77 vs = append(vs, v) 78 } 79 return vs, nil 80 } 81 vulns, err := ovalutil.RPMDefsToVulns(ctx, &root, protoVulns) 82 if err != nil { 83 return nil, err 84 } 85 return vulns, nil 86 } 87 88 func isSkippableDefinitionType(defType ovalutil.DefinitionType, ignoreUnpatched bool) bool { 89 return defType == ovalutil.UnaffectedDefinition || 90 defType == ovalutil.NoneDefinition || 91 (ignoreUnpatched && defType == ovalutil.CVEDefinition) 92 }