github.com/quay/claircore@v1.5.28/rhel/rhcc/rhcc.go (about)

     1  // Package rhcc implements an ecosystem for the Red Hat Container Catalog.
     2  //
     3  // This ecosystem treats an entire container as a package and matches advisories
     4  // against it.
     5  package rhcc
     6  
     7  import (
     8  	"encoding/xml"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/quay/claircore"
    13  	"github.com/quay/claircore/pkg/rhctag"
    14  	"github.com/quay/claircore/toolkit/types/cpe"
    15  )
    16  
    17  var goldRepo = claircore.Repository{
    18  	Name: "Red Hat Container Catalog",
    19  	URI:  `https://catalog.redhat.com/software/containers/explore`,
    20  }
    21  
    22  type cveMap struct {
    23  	XMLName               xml.Name              `xml:"cvemap"`
    24  	RedHatVulnerabilities []redHatVulnerability `xml:"Vulnerability"`
    25  }
    26  
    27  type redHatVulnerability struct {
    28  	XMLName          xml.Name          `xml:"Vulnerability"`
    29  	Name             string            `xml:"name,attr"`
    30  	ThreatSeverity   string            `xml:"ThreatSeverity"`
    31  	AffectedReleases []affectedRelease `xml:"AffectedRelease"`
    32  	Details          []details         `xml:"Details"`
    33  }
    34  
    35  type affectedRelease struct {
    36  	XMLName     xml.Name   `xml:"AffectedRelease"`
    37  	Cpe         string     `xml:"cpe,attr"`
    38  	ReleaseDate customTime `xml:"ReleaseDate"`
    39  	Package     string     `xml:"Package"`
    40  	Impact      string     `xml:"impact,attr"`
    41  	Advisory    advisory   `xml:"Advisory"`
    42  }
    43  
    44  type advisory struct {
    45  	XMLName xml.Name `xml:"Advisory"`
    46  	Text    string   `xml:",cdata"`
    47  	URL     string   `xml:"url,attr"`
    48  }
    49  
    50  type details struct {
    51  	XMLName xml.Name `xml:"Details"`
    52  	Text    string   `xml:",cdata"`
    53  	Source  string   `xml:"source,attr"`
    54  }
    55  
    56  type customTime struct {
    57  	time time.Time
    58  }
    59  
    60  type consolidatedRelease struct {
    61  	Issued          time.Time
    62  	FixedInVersions *rhctag.Versions
    63  	Severity        string
    64  	AdvisoryLink    string
    65  	AdvisoryName    string
    66  	Cpe             cpe.WFN
    67  }
    68  
    69  func (c *customTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
    70  	const shortForm = "2006-01-02"
    71  	var v string
    72  	d.DecodeElement(&v, &start)
    73  	date := strings.Split(v, "T")
    74  	parse, err := time.Parse(shortForm, date[0])
    75  	if err != nil {
    76  		return err
    77  	}
    78  	*c = customTime{parse}
    79  	return nil
    80  }
    81  
    82  func parseContainerPackage(p string) (bool, string, string) {
    83  	parts := strings.Split(p, ":")
    84  	if len(parts) != 2 {
    85  		return false, "", ""
    86  	}
    87  	if !strings.ContainsAny(parts[0], "/") {
    88  		return false, "", ""
    89  	}
    90  	return true, parts[0], parts[1]
    91  }
    92  
    93  // Prefer Red Hat descriptions over Mitre ones
    94  func getDescription(ds []details) string {
    95  	rhDetailsIdx := -1
    96  	mitreDetailsIdx := -1
    97  	result := ""
    98  	for idx, d := range ds {
    99  		if d.Source == "Red Hat" {
   100  			rhDetailsIdx = idx
   101  			break
   102  		} else if d.Source == "Mitre" {
   103  			mitreDetailsIdx = idx
   104  		}
   105  	}
   106  	if rhDetailsIdx != -1 {
   107  		result = ds[rhDetailsIdx].Text
   108  		return strings.TrimSpace(result)
   109  	}
   110  	if mitreDetailsIdx != -1 {
   111  		result = ds[mitreDetailsIdx].Text
   112  		return strings.TrimSpace(result)
   113  	}
   114  	return strings.TrimSpace(result)
   115  }