Skip to content

Commit

Permalink
feat: Add Csaf load and cache
Browse files Browse the repository at this point in the history
RHINENG-7868
  • Loading branch information
michalslomczynski authored and psegedy committed Apr 4, 2024
1 parent 45a60fa commit efc388e
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 13 deletions.
Binary file modified example/vmaas.db
Binary file not shown.
4 changes: 4 additions & 0 deletions vmaas/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ type Cache struct {
OvalTestID2States map[TestID][]OvalState
OvalDefinitionID2ErrataIDs map[DefinitionID][]ErratumID
CpeID2Label map[CpeID]string

// CSAF
CSAFProductStatus map[int]string
CSAFCVEs map[CSAFProduct]CSAFCVEs
}

func ShouldReload(c *Cache, latestDumpEndpoint string) bool {
Expand Down
98 changes: 98 additions & 0 deletions vmaas/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ var loadFuncs = []func(c *Cache){
loadContentSet2Cpes, loadCpeID2DefinitionIDs, loadOvalCriteriaDependency, loadOvalCriteriaID2Type,
loadOvalStateID2Arches, loadOvalModuleTestDetail, loadOvalTestDetail, loadOvalTestID2States,
loadOvalDefinitionErrata, loadCpeID2Label,
// CSAF
loadCSAFCVE,
}

func openDB(path string) error {
Expand Down Expand Up @@ -1086,3 +1088,99 @@ func loadCpeID2Label(c *Cache) {
}
c.CpeID2Label = ret
}

func loadCSAFProductStatus(c *Cache) {
defer utils.TimeTrack(time.Now(), "CSAF product status")

cnt := getCount("csaf_product_status", "*")
rows := getAllRows("csaf_product_status", "id,name")

cache := make(map[int]string, cnt)

type ProductStatusRow struct {
ID int
label string
}
psr := ProductStatusRow{}

for rows.Next() {
if err := rows.Scan(&psr.ID, &psr.label); err != nil {
panic(fmt.Errorf("failed to scan csaf_product_status row: %s", err.Error()))
}
cache[psr.ID] = psr.label
}

c.CSAFProductStatus = cache
}

func loadCSAFCVEProducts() map[CSAFProductID][]CSAFCVEProduct {
cnt := getCount("csaf_cve_product", "*")
rows := getAllRows("csaf_cve_product", "id,cve_id,csaf_product_id,csaf_product_status_id")

csafCVEProducts := make(map[CSAFProductID][]CSAFCVEProduct, cnt)
ccp := CSAFCVEProduct{}

for rows.Next() {
if err := rows.Scan(&ccp.ID, &ccp.CVEID, &ccp.CSAFProductID, &ccp.CSAFProductStatusID); err != nil {
panic(fmt.Errorf("failed to scan csaf_cve_product row: %s", err.Error()))
}
csafCVEProducts[ccp.CSAFProductID] = append(csafCVEProducts[ccp.CSAFProductID], ccp)
}

return csafCVEProducts
}

func loadCSAFCVE(c *Cache) {
loadCSAFProductStatus(c) // Load statuses before other CSAF load functions

defer utils.TimeTrack(time.Now(), "CSAF CVEs")

csafCVEProducts := loadCSAFCVEProducts()

rows := getAllRows("csaf_product", "id,cpe_id,package_name_id,package_id,module_stream")
cnt := getCount("csaf_product", "*")

cveCache := make(map[CSAFProduct]CSAFCVEs, cnt)

type CSAFProductRow struct {
ID int
Product CSAFProduct
}

cpr := CSAFProductRow{}
for rows.Next() {
if err := rows.Scan(&cpr.ID,
&cpr.Product.CpeID,
&cpr.Product.PackageNameID,
&cpr.Product.PackageID,
&cpr.Product.ModuleStream); err != nil {
panic(fmt.Errorf("failed to scan csaf_product row: %s", err.Error()))
}

cveProducts := csafCVEProducts[CSAFProductID(cpr.ID)]
cves := CSAFCVEs{
Fixed: make([]CVEID, 0),
Unfixed: make([]CVEID, 0),
}

for _, cveProduct := range cveProducts {
switch c.CSAFProductStatus[cveProduct.CSAFProductStatusID] {
case "fixed":
cves.Fixed = append(cves.Fixed, cveProduct.CVEID)
case "known_affected":
cves.Unfixed = append(cves.Unfixed, cveProduct.CVEID)
default:
panic(fmt.Sprintf("unknown product status: %s", c.CSAFProductStatus[cveProduct.CSAFProductStatusID]))
}
}

cveCache[CSAFProduct{
CpeID: cpr.Product.CpeID,
PackageNameID: cpr.Product.PackageNameID,
PackageID: cpr.Product.PackageID,
ModuleStream: cpr.Product.ModuleStream,
}] = cves
}

c.CSAFCVEs = cveCache
}
74 changes: 61 additions & 13 deletions vmaas/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,31 @@ package vmaas

import (
"encoding/json"
"fmt"
"sort"
"strings"
"time"

"github.com/redhatinsights/vmaas-lib/vmaas/utils"
)

type (
RepoID int
PkgID int
NameID int
EvrID int
ArchID int
ErratumID int
ContentSetID int
DefinitionID int
CpeID int
CriteriaID int
TestID int
ModuleTestID int
OvalStateID int
RepoID int
PkgID int
NameID int
EvrID int
ArchID int
ErratumID int
ContentSetID int
DefinitionID int
CpeID int
CriteriaID int
TestID int
ModuleTestID int
OvalStateID int
CSAFProductID int
CSAFCVEID int
CVEID int
)

type Request struct {
Expand Down Expand Up @@ -264,3 +269,46 @@ type NevraString struct {
Nevra utils.Nevra
Pkg string
}

type CSAFProduct struct {
CpeID CpeID
PackageNameID NameID
PackageID PkgID
ModuleStream ModuleStream
}

type CSAFCVEProduct struct {
ID CSAFCVEID
CVEID CVEID
CSAFProductID CSAFProductID
CSAFProductStatusID int
}

type CSAFCVEs struct {
Fixed []CVEID
Unfixed []CVEID
}

// Implement the Scan method for the ModuleStream type
func (ms *ModuleStream) Scan(value interface{}) error {
if value == nil || value == "" {
return nil
}

// Convert the value to string
strValue, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for ModuleStream", value)
}

// Split the string into module and stream parts
parts := strings.Split(strValue, ":")
if len(parts) != 2 {
return fmt.Errorf("invalid format for ModuleStream: %s", strValue)
}

ms.Module = parts[0]
ms.Stream = parts[1]

return nil
}

0 comments on commit efc388e

Please sign in to comment.