updater: update RHEL fetcher and add not-affected capability

This commit is contained in:
Quentin Machu 2016-01-19 11:03:27 -05:00 committed by Jimmy Zelinskie
parent ea59b0e45f
commit 847c649288

View File

@ -17,6 +17,7 @@ package rhel
import ( import (
"bufio" "bufio"
"encoding/xml" "encoding/xml"
"errors"
"io" "io"
"net/http" "net/http"
"regexp" "regexp"
@ -51,6 +52,9 @@ var (
rhsaRegexp = regexp.MustCompile(`com.redhat.rhsa-(\d+).xml`) rhsaRegexp = regexp.MustCompile(`com.redhat.rhsa-(\d+).xml`)
log = capnslog.NewPackageLogger("github.com/coreos/clair", "updater/fetchers/rhel") log = capnslog.NewPackageLogger("github.com/coreos/clair", "updater/fetchers/rhel")
// ErrCouldNotParse is returned when a fetcher fails to parse the update data.
ErrCouldNotParse = errors.New("updater/fetchers: could not parse")
) )
type oval struct { type oval struct {
@ -84,7 +88,7 @@ type criterion struct {
type RHELFetcher struct{} type RHELFetcher struct{}
func init() { func init() {
//updater.RegisterFetcher("Red Hat", &RHELFetcher{}) updater.RegisterFetcher("Red Hat", &RHELFetcher{})
} }
// FetchUpdate gets vulnerability updates from the Red Hat OVAL definitions. // FetchUpdate gets vulnerability updates from the Red Hat OVAL definitions.
@ -131,14 +135,13 @@ func (f *RHELFetcher) FetchUpdate(datastore database.Datastore) (resp updater.Fe
} }
// Parse the XML. // Parse the XML.
vs, pkgs, err := parseRHSA(r.Body) vs, err := parseRHSA(r.Body)
if err != nil { if err != nil {
return resp, err return resp, err
} }
// Collect vulnerabilities. // Collect vulnerabilities.
resp.Vulnerabilities = append(resp.Vulnerabilities, vs...) resp.Vulnerabilities = append(resp.Vulnerabilities, vs...)
resp.Packages = append(resp.Packages, pkgs...)
} }
// Set the flag if we found anything. // Set the flag if we found anything.
@ -152,7 +155,7 @@ func (f *RHELFetcher) FetchUpdate(datastore database.Datastore) (resp updater.Fe
return resp, nil return resp, nil
} }
func parseRHSA(ovalReader io.Reader) (vulnerabilities []*database.Vulnerability, packages []*database.Package, err error) { func parseRHSA(ovalReader io.Reader) (vulnerabilities []database.Vulnerability, err error) {
// Decode the XML. // Decode the XML.
var ov oval var ov oval
err = xml.NewDecoder(ovalReader).Decode(&ov) err = xml.NewDecoder(ovalReader).Decode(&ov)
@ -165,19 +168,18 @@ func parseRHSA(ovalReader io.Reader) (vulnerabilities []*database.Vulnerability,
// Iterate over the definitions and collect any vulnerabilities that affect // Iterate over the definitions and collect any vulnerabilities that affect
// at least one package. // at least one package.
for _, definition := range ov.Definitions { for _, definition := range ov.Definitions {
pkgs := toPackages(definition.Criteria) pkgs := toFeatureVersions(definition.Criteria)
if len(pkgs) > 0 { if len(pkgs) > 0 {
vulnerability := &database.Vulnerability{ vulnerability := database.Vulnerability{
ID: name(definition), Name: name(definition),
Link: link(definition), Link: link(definition),
Priority: priority(definition), Severity: priority(definition),
Description: description(definition), Description: description(definition),
} }
for _, p := range pkgs { for _, p := range pkgs {
vulnerability.FixedInNodes = append(vulnerability.FixedInNodes, p.GetNode()) vulnerability.FixedIn = append(vulnerability.FixedIn, p)
} }
vulnerabilities = append(vulnerabilities, vulnerability) vulnerabilities = append(vulnerabilities, vulnerability)
packages = append(packages, pkgs...)
} }
} }
@ -259,17 +261,17 @@ func getPossibilities(node criteria) [][]criterion {
return possibilities return possibilities
} }
func toPackages(criteria criteria) []*database.Package { func toFeatureVersions(criteria criteria) []database.FeatureVersion {
// There are duplicates in Red Hat .xml files. // There are duplicates in Red Hat .xml files.
// This map is for deduplication. // This map is for deduplication.
packagesParameters := make(map[string]*database.Package) featureVersionParameters := make(map[string]database.FeatureVersion)
possibilities := getPossibilities(criteria) possibilities := getPossibilities(criteria)
for _, criterions := range possibilities { for _, criterions := range possibilities {
var ( var (
pkg database.Package featureVersion database.FeatureVersion
osVersion int osVersion int
err error err error
) )
// Attempt to parse package data from trees of criterions. // Attempt to parse package data from trees of criterions.
@ -282,8 +284,8 @@ func toPackages(criteria criteria) []*database.Package {
} }
} else if strings.Contains(c.Comment, " is earlier than ") { } else if strings.Contains(c.Comment, " is earlier than ") {
const prefixLen = len(" is earlier than ") const prefixLen = len(" is earlier than ")
pkg.Name = strings.TrimSpace(c.Comment[:strings.Index(c.Comment, " is earlier than ")]) featureVersion.Feature.Name = strings.TrimSpace(c.Comment[:strings.Index(c.Comment, " is earlier than ")])
pkg.Version, err = types.NewVersion(c.Comment[strings.Index(c.Comment, " is earlier than ")+prefixLen:]) featureVersion.Version, err = types.NewVersion(c.Comment[strings.Index(c.Comment, " is earlier than ")+prefixLen:])
if err != nil { if err != nil {
log.Warningf("could not parse package version '%s': %s. skipping", c.Comment[strings.Index(c.Comment, " is earlier than ")+prefixLen:], err.Error()) log.Warningf("could not parse package version '%s': %s. skipping", c.Comment[strings.Index(c.Comment, " is earlier than ")+prefixLen:], err.Error())
} }
@ -291,25 +293,25 @@ func toPackages(criteria criteria) []*database.Package {
} }
if osVersion > firstConsideredRHEL { if osVersion > firstConsideredRHEL {
pkg.OS = "centos" + ":" + strconv.Itoa(osVersion) featureVersion.Feature.Namespace.Name = "centos" + ":" + strconv.Itoa(osVersion)
} else { } else {
continue continue
} }
if pkg.OS != "" && pkg.Name != "" && pkg.Version.String() != "" { if featureVersion.Feature.Namespace.Name != "" && featureVersion.Feature.Name != "" && featureVersion.Version.String() != "" {
packagesParameters[pkg.Key()] = &pkg featureVersionParameters[featureVersion.Feature.Namespace.Name+":"+featureVersion.Feature.Name] = featureVersion
} else { } else {
log.Warningf("could not determine a valid package from criterions: %v", criterions) log.Warningf("could not determine a valid package from criterions: %v", criterions)
} }
} }
// Convert the map to slice. // Convert the map to slice.
var packagesParametersArray []*database.Package var featureVersionParametersArray []database.FeatureVersion
for _, p := range packagesParameters { for _, fv := range featureVersionParameters {
packagesParametersArray = append(packagesParametersArray, p) featureVersionParametersArray = append(featureVersionParametersArray, fv)
} }
return packagesParametersArray return featureVersionParametersArray
} }
func description(def definition) (desc string) { func description(def definition) (desc string) {
@ -335,7 +337,7 @@ func link(def definition) (link string) {
return return
} }
func priority(def definition) types.Severity { func priority(def definition) types.Priority {
// Parse the priority. // Parse the priority.
priority := strings.TrimSpace(def.Title[strings.LastIndex(def.Title, "(")+1 : len(def.Title)-1]) priority := strings.TrimSpace(def.Title[strings.LastIndex(def.Title, "(")+1 : len(def.Title)-1])