mirror of
https://github.com/anchore/grype
synced 2024-09-20 06:21:56 +00:00
remove desc
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
7c9090a6be
commit
a8947447b3
4 changed files with 369 additions and 180 deletions
|
@ -3,10 +3,46 @@ package v6
|
|||
import (
|
||||
"fmt"
|
||||
"github.com/OneOfOne/xxhash"
|
||||
"github.com/anchore/grype/internal/log"
|
||||
)
|
||||
|
||||
func BlobDigest(content string) string {
|
||||
h := xxhash.New64()
|
||||
h.Write([]byte(content)) // TODO: handle error?
|
||||
return fmt.Sprintf("xx64:%x", h.Sum(nil))
|
||||
h.Write([]byte(content)) // TODO: handle error?
|
||||
return fmt.Sprintf("%x", h.Sum(nil)) // by the size we can surmise that this is a xxh64 hash
|
||||
}
|
||||
|
||||
type BlobStore interface {
|
||||
AddBlobs(blobs ...*Blob) error
|
||||
GetBlob(digest string) (*Blob, error)
|
||||
}
|
||||
|
||||
type blobStore struct {
|
||||
*StoreConfig
|
||||
*state
|
||||
}
|
||||
|
||||
func NewBlobStore(cfg *StoreConfig) BlobStore {
|
||||
return &blobStore{
|
||||
StoreConfig: cfg,
|
||||
state: cfg.state(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *blobStore) GetBlob(digest string) (*Blob, error) {
|
||||
log.WithFields("digest", digest).Trace("fetching Blob record")
|
||||
|
||||
var model Blob
|
||||
|
||||
result := s.db.Where("digest = ?", digest).Find(&model)
|
||||
return &model, result.Error
|
||||
}
|
||||
|
||||
func (s *blobStore) AddBlobs(blobs ...*Blob) error {
|
||||
for _, b := range blobs {
|
||||
if err := s.db.FirstOrCreate(b).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -2,36 +2,47 @@ package v6
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
func All() []any {
|
||||
return []any{
|
||||
&CpeWithoutVersion{},
|
||||
&Cpe{},
|
||||
&PlatformCpe{},
|
||||
&Digest{},
|
||||
&Affected{},
|
||||
&Alias{},
|
||||
&Blob{},
|
||||
&DbMetadata{},
|
||||
&DbSpecificNvd{},
|
||||
//&DbSpecificNvd{},
|
||||
&Epss{},
|
||||
&KnownExploitedVulnerability{},
|
||||
&OperatingSystem{},
|
||||
&Provider{},
|
||||
&Reference{},
|
||||
&Severity{},
|
||||
&Affected{},
|
||||
&Vulnerability{},
|
||||
}
|
||||
}
|
||||
|
||||
// core vulnerability types
|
||||
|
||||
type Advisory struct {
|
||||
ID string
|
||||
// TODO: this will probably be shipped as another DB and attached on as-needed basis
|
||||
type Blob struct {
|
||||
Digest string `gorm:"column:digest;primaryKey"`
|
||||
Value string `gorm:"column:value;not null"`
|
||||
}
|
||||
|
||||
VulnerabilityIDs []string
|
||||
func (b *Blob) BeforeCreate(tx *gorm.DB) (err error) {
|
||||
// if the name, major version, and minor version already exist in the table then we should not insert a new record
|
||||
var existing Blob
|
||||
result := tx.Where("digest = ?", b.Digest).First(&existing)
|
||||
if result.Error == nil {
|
||||
// if the record already exists, then we should use the existing record
|
||||
*b = existing
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Vulnerability represents the core advisory record for a single known vulnerability from a specific provider. There
|
||||
|
@ -62,8 +73,10 @@ type Vulnerability struct {
|
|||
|
||||
Status string `gorm:"column:status"` // example: "active, withdrawn, rejected, ..." could be an enum
|
||||
|
||||
Summary string `gorm:"column:summary"`
|
||||
Detail string `gorm:"column:detail;index,unique"`
|
||||
//Summary string `gorm:"column:summary"`
|
||||
//Detail string `gorm:"column:detail;index,unique"`
|
||||
DetailDigest string `gorm:"column:detail_digest;index,unique"`
|
||||
//Detail *Blob `gorm:"foreignKey:DetailDigest"`
|
||||
|
||||
// References are URLs to external resources that provide more information about the vulnerability (mirrors the OSV field)
|
||||
References *[]Reference `gorm:"foreignKey:VulnerabilityID"`
|
||||
|
@ -75,10 +88,10 @@ type Vulnerability struct {
|
|||
Aliases *[]Alias `gorm:"many2many:vulnerability_aliases"`
|
||||
|
||||
// Severities is a list of severity indications (quantitative or qualitative) for the vulnerability (mirrors the OSV field, but the semantics are different. We allow for qualitative string severity, where OSV does not)
|
||||
Severities *datatypes.JSONSlice[Severity] `gorm:"column:severities"`
|
||||
Severities *[]Severity `gorm:"many2many:vulnerability_severities"`
|
||||
|
||||
// DB specific info
|
||||
DbSpecific *datatypes.JSON `gorm:"column:db_specific"`
|
||||
//DbSpecific *datatypes.JSON `gorm:"many2many:vulnerability_db_specific"`
|
||||
|
||||
// Affected is a list of affected entries related to this vulnerability
|
||||
Affected *[]Affected `gorm:"foreignKey:VulnerabilityID"`
|
||||
|
@ -86,6 +99,36 @@ type Vulnerability struct {
|
|||
batchWriteAffected *[]Affected `gorm:"-"`
|
||||
}
|
||||
|
||||
func (a *Vulnerability) BeforeSave(tx *gorm.DB) (err error) {
|
||||
if a.Severities != nil {
|
||||
uniqueSevs, err := a.uniqueSevs(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.Severities = uniqueSevs
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Vulnerability) uniqueSevs(tx *gorm.DB) (*[]Severity, error) {
|
||||
var uniqueSevs []Severity
|
||||
for _, sev := range *a.Severities {
|
||||
var existing Severity
|
||||
result := tx.Where("type = ? AND score = ? AND source = ? AND rank = ?", sev.Type, sev.Score, sev.Source, sev.Rank).First(&existing)
|
||||
if result.Error == nil {
|
||||
uniqueSevs = append(uniqueSevs, existing)
|
||||
} else {
|
||||
err := tx.Create(&sev).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uniqueSevs = append(uniqueSevs, sev)
|
||||
}
|
||||
}
|
||||
return &uniqueSevs, nil
|
||||
}
|
||||
|
||||
func (c *Vulnerability) BeforeCreate(tx *gorm.DB) error {
|
||||
// if the len of Affected is > 500, then create those in batches and then attach those to the Vulnerability
|
||||
if c.Affected != nil && len(*c.Affected) > 500 {
|
||||
|
@ -181,18 +224,29 @@ type Severity struct {
|
|||
ID int64 `gorm:"column:id;primaryKey"`
|
||||
|
||||
// Type describes the quantitative method used to determine the Score, such as "CVSS_V3". Alternatively this makes claim that Score is qualitative, such as just simply "string"
|
||||
Type string `gorm:"column:type;not null"`
|
||||
Type string `gorm:"column:type;index:idx_severity,unique"`
|
||||
|
||||
// Score is the quantitative or qualitative severity score (e.g. "CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N" or "high")
|
||||
Score string `gorm:"column:score;not null"`
|
||||
Score string `gorm:"column:score;not null;index:idx_severity,unique"`
|
||||
|
||||
// Source is the name of the source of the severity score (e.g. "nvd@nist.gov" or "security-advisories@github.com")
|
||||
Source string `gorm:"column:source"`
|
||||
Source string `gorm:"column:source;index:idx_severity,unique"`
|
||||
|
||||
// Rank is a free-form organizational field to convey priority over other severities
|
||||
Rank int `gorm:"column:priority"`
|
||||
Rank int `gorm:"column:rank;index:idx_severity,unique"`
|
||||
}
|
||||
|
||||
//func (c *Severity) BeforeCreate(tx *gorm.DB) (err error) {
|
||||
// // if the name, major version, and minor version already exist in the table then we should not insert a new record
|
||||
// var existing Severity
|
||||
// result := tx.Where("type = ? AND score = ? AND source = ? AND rank = ?", c.Type, c.Score, c.Source, c.Rank).First(&existing)
|
||||
// if result.Error == nil {
|
||||
// // if the record already exists, then we should use the existing record
|
||||
// *c = existing
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
|
||||
type Reference struct {
|
||||
ID int64 `gorm:"column:id;primaryKey"`
|
||||
VulnerabilityID int64 `gorm:"column:vulnerability_id;not null"`
|
||||
|
@ -226,24 +280,90 @@ type Affected struct {
|
|||
|
||||
// package qualifiers
|
||||
|
||||
PlatformCpeID *int64 `gorm:"column:platform_cpe_id"`
|
||||
PlatformCpe *CpeWithoutVersion `gorm:"foreignKey:PlatformCpeID"`
|
||||
PlatformCpes *[]PlatformCpe `gorm:"many2many:affected_platform_cpes"`
|
||||
|
||||
RpmModularity string `gorm:"column:rpm_modularity"`
|
||||
|
||||
// identifiers
|
||||
|
||||
Package *Package `gorm:"embedded;embeddedPrefix:package_"`
|
||||
Digest *Digest `gorm:"embedded;embeddedPrefix:digest_"`
|
||||
//Cpe *Cpe `gorm:"embedded;embeddedPrefix:cpe_"`
|
||||
CpeID *int64 `gorm:"column:cpe_id"`
|
||||
Cpe *CpeWithoutVersion `gorm:"foreignKey:CpeID"`
|
||||
//Digests *[]Digest `gorm:"many2many:affected_digests"`
|
||||
Cpes *[]Cpe `gorm:"many2many:affected_cpes"`
|
||||
|
||||
// fix
|
||||
|
||||
Fix *Fix `gorm:"embedded;embeddedPrefix:fix_"`
|
||||
}
|
||||
|
||||
func (a *Affected) BeforeSave(tx *gorm.DB) (err error) {
|
||||
if a.Cpes != nil {
|
||||
uniqueCpes, err := a.uniqueCpes(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.Cpes = uniqueCpes
|
||||
}
|
||||
|
||||
if a.PlatformCpes != nil {
|
||||
uniqueCpes, err := a.uniquePlatformCpes(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.PlatformCpes = uniqueCpes
|
||||
}
|
||||
|
||||
if a.OperatingSystem != nil {
|
||||
result := tx.Where("name = ? AND major_version = ? AND minor_version = ?", a.OperatingSystem.Name, a.OperatingSystem.MajorVersion, a.OperatingSystem.MinorVersion).First(&a.OperatingSystem)
|
||||
if result.Error != nil {
|
||||
err := tx.Create(&a.OperatingSystem).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Affected) uniquePlatformCpes(tx *gorm.DB) (*[]PlatformCpe, error) {
|
||||
var uniqueCpes []PlatformCpe
|
||||
for _, cpe := range *a.PlatformCpes {
|
||||
var existing PlatformCpe
|
||||
result := tx.Where("type = ? AND vendor = ? AND product = ? AND edition = ? AND language = ? AND version = ? AND version_update = ? AND software_edition = ? AND target_hardware = ? AND target_software = ? AND other = ?",
|
||||
cpe.Type, cpe.Vendor, cpe.Product, cpe.Edition, cpe.Language, cpe.Version, cpe.VersionUpdate, cpe.SoftwareEdition, cpe.TargetHardware, cpe.TargetSoftware, cpe.Other).First(&existing)
|
||||
if result.Error == nil {
|
||||
uniqueCpes = append(uniqueCpes, existing)
|
||||
} else {
|
||||
err := tx.Create(&cpe).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uniqueCpes = append(uniqueCpes, cpe)
|
||||
}
|
||||
}
|
||||
return &uniqueCpes, nil
|
||||
}
|
||||
|
||||
func (a *Affected) uniqueCpes(tx *gorm.DB) (*[]Cpe, error) {
|
||||
var uniqueCpes []Cpe
|
||||
for _, cpe := range *a.Cpes {
|
||||
var existing Cpe
|
||||
result := tx.Where("type = ? AND vendor = ? AND product = ? AND edition = ? AND language = ? AND software_edition = ? AND target_hardware = ? AND target_software = ? AND other = ?",
|
||||
cpe.Type, cpe.Vendor, cpe.Product, cpe.Edition, cpe.Language, cpe.SoftwareEdition, cpe.TargetHardware, cpe.TargetSoftware, cpe.Other).First(&existing)
|
||||
if result.Error == nil {
|
||||
uniqueCpes = append(uniqueCpes, existing)
|
||||
} else {
|
||||
err := tx.Create(&cpe).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uniqueCpes = append(uniqueCpes, cpe)
|
||||
}
|
||||
}
|
||||
return &uniqueCpes, nil
|
||||
}
|
||||
|
||||
// TODO: add later and reuse existing similar tables with many2many
|
||||
//type NotAffected struct {
|
||||
// ID int64 `gorm:"column:id;primaryKey"`
|
||||
|
@ -257,7 +377,7 @@ type Affected struct {
|
|||
// Range *[]Range `gorm:"foreignKey:AffectedID"`
|
||||
//
|
||||
// // Digests that are known to correspond to this vulnerability, but cannot be closely associated with a package
|
||||
// Digests *[]Digest `gorm:"many2many:not_affected_digests"`
|
||||
// Digests *[]Digests `gorm:"many2many:not_affected_digests"`
|
||||
//}
|
||||
|
||||
type Fix struct {
|
||||
|
@ -277,7 +397,7 @@ type Fix struct {
|
|||
|
||||
// primary package identifiers (search entrypoints)
|
||||
|
||||
type CpeWithoutVersion struct {
|
||||
type Cpe struct {
|
||||
// TODO: what about different CPE versions?
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
|
||||
|
@ -292,14 +412,46 @@ type CpeWithoutVersion struct {
|
|||
Other string `gorm:"column:other;index:idx_cpe,unique"`
|
||||
}
|
||||
|
||||
func (c CpeWithoutVersion) String() string {
|
||||
func (c Cpe) String() string {
|
||||
return fmt.Sprintf("%s:%s:%s:%s:%s:%s:%s:%s:%s", c.Type, c.Vendor, c.Product, c.Edition, c.Language, c.SoftwareEdition, c.TargetHardware, c.TargetSoftware, c.Other)
|
||||
}
|
||||
|
||||
//func (c *Cpe) BeforeCreate(tx *gorm.DB) (err error) {
|
||||
// // if the name, major version, and minor version already exist in the table then we should not insert a new record
|
||||
// var existing Cpe
|
||||
// result := tx.Where("schema = ? AND type = ? AND vendor = ? AND product = ? AND version = ? AND version_update = ? AND target_software = ?", c.Schema, c.Type, c.Vendor, c.Product, c.Version, c.Update, c.TargetSoftware).First(&existing)
|
||||
// result := tx.Where("type = ? AND vendor = ? AND product = ? AND edition = ? AND language = ? AND software_edition = ? AND target_hardware = ? AND target_software = ? AND other = ?", c.Type, c.Vendor, c.Product, c.Edition, c.Language, c.SoftwareEdition, c.TargetHardware, c.TargetSoftware, c.Other).First(&existing)
|
||||
// if result.Error == nil {
|
||||
// // if the record already exists, then we should use the existing record
|
||||
// *c = existing
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
|
||||
type PlatformCpe struct {
|
||||
// TODO: what about different CPE versions?
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
|
||||
Type string `gorm:"column:type;not null;index:idx_platform_cpe,unique"`
|
||||
Vendor string `gorm:"column:vendor;index:idx_platform_cpe,unique"`
|
||||
Product string `gorm:"column:product;not null;index:idx_platform_cpe,unique"`
|
||||
Edition string `gorm:"column:edition;index:idx_platform_cpe,unique"`
|
||||
Language string `gorm:"column:language;index:idx_platform_cpe,unique"`
|
||||
Version string `gorm:"column:version;index:idx_platform_cpe,unique"`
|
||||
VersionUpdate string `gorm:"column:version_update;index:idx_platform_cpe,unique"`
|
||||
SoftwareEdition string `gorm:"column:software_edition;index:idx_platform_cpe,unique"`
|
||||
TargetHardware string `gorm:"column:target_hardware;index:idx_platform_cpe,unique"`
|
||||
TargetSoftware string `gorm:"column:target_software;index:idx_platform_cpe,unique"`
|
||||
Other string `gorm:"column:other;index:idx_platform_cpe,unique"`
|
||||
}
|
||||
|
||||
func (c PlatformCpe) String() string {
|
||||
return fmt.Sprintf("%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s", c.Type, c.Vendor, c.Product, c.Edition, c.Language, c.Version, c.VersionUpdate, c.SoftwareEdition, c.TargetHardware, c.TargetSoftware, c.Other)
|
||||
}
|
||||
|
||||
//func (c *PlatformCpe) BeforeCreate(tx *gorm.DB) (err error) {
|
||||
// // if the name, major version, and minor version already exist in the table then we should not insert a new record
|
||||
// var existing PlatformCpe
|
||||
// result := tx.Where("type = ? AND vendor = ? AND product = ? AND edition = ? AND language = ? AND version = ? AND version_update = ? AND software_edition = ? AND target_hardware = ? AND target_software = ? AND other = ?", c.Type, c.Vendor, c.Product, c.Edition, c.Language, c.Version, c.VersionUpdate, c.SoftwareEdition, c.TargetHardware, c.TargetSoftware, c.Other).First(&existing)
|
||||
// if result.Error == nil {
|
||||
// // if the record already exists, then we should use the existing record
|
||||
// *c = existing
|
||||
|
@ -324,7 +476,7 @@ type Package struct {
|
|||
//OperatingSystem *OperatingSystem `gorm:"foreignKey:OperatingSystemID"`
|
||||
//
|
||||
//Purls *[]Purl `gorm:"many2many:package_purls"`
|
||||
//Cpes *[]Cpe `gorm:"many2many:package_cpes"`
|
||||
//Cpes *[]Cpes `gorm:"many2many:package_cpes"`
|
||||
|
||||
}
|
||||
|
||||
|
@ -388,12 +540,6 @@ type DbMetadata struct {
|
|||
Addition int `gorm:"column:addition;not null"`
|
||||
}
|
||||
|
||||
// TODO: this will probably be shipped as another DB and attached on as-needed basis
|
||||
type Blob struct {
|
||||
Digest string `gorm:"column:digest;primaryKey"`
|
||||
Value string `gorm:"column:value;not null"`
|
||||
}
|
||||
|
||||
// TODO: not clear that we need this...
|
||||
//type Comment struct {
|
||||
// ID int64 `gorm:"column:id;primaryKey"`
|
||||
|
|
|
@ -24,6 +24,7 @@ type Store interface {
|
|||
AffectedPackageStore
|
||||
ProviderStore
|
||||
OperatingSystemStore
|
||||
BlobStore
|
||||
io.Closer
|
||||
}
|
||||
|
||||
|
@ -36,6 +37,7 @@ type store struct {
|
|||
AffectedPackageStore
|
||||
ProviderStore
|
||||
OperatingSystemStore
|
||||
BlobStore
|
||||
}
|
||||
|
||||
func (c *StoreConfig) state() *state {
|
||||
|
@ -63,6 +65,7 @@ func New(cfg StoreConfig) (Store, error) {
|
|||
AffectedStore: NewAffectedStore(&cfg),
|
||||
VulnerabilityStore: NewVulnerabilityStore(&cfg),
|
||||
AffectedPackageStore: NewAffectedPackageStore(&cfg),
|
||||
BlobStore: NewBlobStore(&cfg),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package v6
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/anchore/grype/internal/log"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type VulnerabilityStore interface {
|
||||
|
@ -42,9 +40,9 @@ func (s *vulnerabilityStore) GetVulnerability(id string, loadAuxInfo bool) ([]Vu
|
|||
|
||||
func (s *vulnerabilityStore) AddVulnerabilities(vulnerabilities ...*Vulnerability) error {
|
||||
for _, h := range []func([]*Vulnerability) error{
|
||||
s.handleOSs,
|
||||
//s.handleOSs,
|
||||
//s.handleRangeEvents,
|
||||
s.handleCPEs,
|
||||
//s.handleCPEs,
|
||||
//s.handlePackages,
|
||||
} {
|
||||
if err := h(vulnerabilities); err != nil {
|
||||
|
@ -53,7 +51,13 @@ func (s *vulnerabilityStore) AddVulnerabilities(vulnerabilities ...*Vulnerabilit
|
|||
|
||||
}
|
||||
|
||||
return s.db.CreateInBatches(vulnerabilities, s.BatchSize).Error
|
||||
for _, v := range vulnerabilities {
|
||||
if err := s.db.Create(v).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//func (s *vulnerabilityStore) handlePackages(vulns []*Vulnerability) error {
|
||||
|
@ -130,83 +134,83 @@ func (s *vulnerabilityStore) AddVulnerabilities(vulnerabilities ...*Vulnerabilit
|
|||
//
|
||||
//}
|
||||
|
||||
func (s *vulnerabilityStore) handleCPEs(vulns []*Vulnerability) error {
|
||||
// ensure unique cpes
|
||||
unique, err := ensureUniqueCPEs(s.db, vulns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// update vulnerabilities with cpes IDs
|
||||
updateAffectedsWithCPEs(vulns, unique)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateAffectedsWithCPEs(vulns []*Vulnerability, uniqueCPEs []*CpeWithoutVersion) {
|
||||
cpeMap := make(map[string]int64)
|
||||
for _, c := range uniqueCPEs {
|
||||
cpeKey := c.String()
|
||||
cpeMap[cpeKey] = c.ID
|
||||
}
|
||||
|
||||
for i, v := range vulns {
|
||||
if v.Affected == nil {
|
||||
continue
|
||||
}
|
||||
for j, a := range *v.Affected {
|
||||
if a.Cpe != nil {
|
||||
cpeKey := a.Cpe.String()
|
||||
val := cpeMap[cpeKey]
|
||||
(*(*vulns[i].Affected)[j].Cpe).ID = val
|
||||
}
|
||||
if a.PlatformCpe != nil {
|
||||
cpeKey := a.PlatformCpe.String()
|
||||
val := cpeMap[cpeKey]
|
||||
(*(*vulns[i].Affected)[j].PlatformCpe).ID = val
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ensureUniqueCPEs(db *gorm.DB, vulns []*Vulnerability) ([]*CpeWithoutVersion, error) {
|
||||
cpeMap := make(map[string]CpeWithoutVersion)
|
||||
for _, v := range vulns {
|
||||
if v.Affected == nil {
|
||||
continue
|
||||
}
|
||||
for _, a := range *v.Affected {
|
||||
if a.Cpe != nil {
|
||||
cpeKey := a.Cpe.String()
|
||||
cpeMap[cpeKey] = *a.Cpe
|
||||
}
|
||||
if a.PlatformCpe != nil {
|
||||
cpeKey := a.PlatformCpe.String()
|
||||
cpeMap[cpeKey] = *a.PlatformCpe
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// extract unique CPEs
|
||||
var uniqueCPEs []*CpeWithoutVersion
|
||||
for i := range cpeMap {
|
||||
c := cpeMap[i]
|
||||
uniqueCPEs = append(uniqueCPEs, &c)
|
||||
}
|
||||
|
||||
// insert unique CPEs into the database or fetch existing ones
|
||||
for i, c := range uniqueCPEs {
|
||||
var existing CpeWithoutVersion
|
||||
err := db.Where("type = ? AND vendor = ? AND product = ? AND edition = ? AND language = ? AND software_edition = ? AND target_software = ? AND target_hardware = ? AND other = ?", c.Type, c.Vendor, c.Product, c.Edition, c.Language, c.SoftwareEdition, c.TargetSoftware, c.TargetHardware, c.Other).
|
||||
FirstOrCreate(&existing, c).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uniqueCPEs[i] = &existing
|
||||
}
|
||||
|
||||
return uniqueCPEs, nil
|
||||
}
|
||||
//func (s *vulnerabilityStore) handleCPEs(vulns []*Vulnerability) error {
|
||||
// // ensure unique cpes
|
||||
// unique, err := ensureUniqueCPEs(s.db, vulns)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// // update vulnerabilities with cpes IDs
|
||||
// updateAffectedsWithCPEs(vulns, unique)
|
||||
//
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func updateAffectedsWithCPEs(vulns []*Vulnerability, uniqueCPEs []*Cpes) {
|
||||
// cpeMap := make(map[string]int64)
|
||||
// for _, c := range uniqueCPEs {
|
||||
// cpeKey := c.String()
|
||||
// cpeMap[cpeKey] = c.ID
|
||||
// }
|
||||
//
|
||||
// for i, v := range vulns {
|
||||
// if v.Affected == nil {
|
||||
// continue
|
||||
// }
|
||||
// for j, a := range *v.Affected {
|
||||
// if a.Cpes != nil {
|
||||
// cpeKey := a.Cpes.String()
|
||||
// val := cpeMap[cpeKey]
|
||||
// (*(*vulns[i].Affected)[j].Cpes).ID = val
|
||||
// }
|
||||
// if a.PlatformCpes != nil {
|
||||
// cpeKey := a.PlatformCpes.String()
|
||||
// val := cpeMap[cpeKey]
|
||||
// (*(*vulns[i].Affected)[j].PlatformCpes).ID = val
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//func ensureUniqueCPEs(db *gorm.DB, vulns []*Vulnerability) ([]*Cpes, error) {
|
||||
// cpeMap := make(map[string]Cpes)
|
||||
// for _, v := range vulns {
|
||||
// if v.Affected == nil {
|
||||
// continue
|
||||
// }
|
||||
// for _, a := range *v.Affected {
|
||||
// if a.Cpes != nil {
|
||||
// cpeKey := a.Cpes.String()
|
||||
// cpeMap[cpeKey] = *a.Cpes
|
||||
// }
|
||||
// if a.PlatformCpes != nil {
|
||||
// cpeKey := a.PlatformCpes.String()
|
||||
// cpeMap[cpeKey] = *a.PlatformCpes
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // extract unique CPEs
|
||||
// var uniqueCPEs []*Cpes
|
||||
// for i := range cpeMap {
|
||||
// c := cpeMap[i]
|
||||
// uniqueCPEs = append(uniqueCPEs, &c)
|
||||
// }
|
||||
//
|
||||
// // insert unique CPEs into the database or fetch existing ones
|
||||
// for i, c := range uniqueCPEs {
|
||||
// var existing Cpes
|
||||
// err := db.Where("type = ? AND vendor = ? AND product = ? AND edition = ? AND language = ? AND software_edition = ? AND target_software = ? AND target_hardware = ? AND other = ?", c.Type, c.Vendor, c.Product, c.Edition, c.Language, c.SoftwareEdition, c.TargetSoftware, c.TargetHardware, c.Other).
|
||||
// FirstOrCreate(&existing, c).Error
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// uniqueCPEs[i] = &existing
|
||||
// }
|
||||
//
|
||||
// return uniqueCPEs, nil
|
||||
//}
|
||||
|
||||
//func (s *vulnerabilityStore) handleRangeEvents(vulns []*Vulnerability) error {
|
||||
// // ensure unique operating systems
|
||||
|
@ -295,67 +299,67 @@ func ensureUniqueCPEs(db *gorm.DB, vulns []*Vulnerability) ([]*CpeWithoutVersion
|
|||
// return *s
|
||||
//}
|
||||
|
||||
func (s *vulnerabilityStore) handleOSs(vulns []*Vulnerability) error {
|
||||
// ensure unique operating systems
|
||||
uniqueOSList, err := ensureUniqueOperatingSystems(s.db, vulns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// update vulnerabilities with operating system IDs
|
||||
updateAffectedsWithOperatingSystems(vulns, uniqueOSList)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ensureUniqueOperatingSystems(db *gorm.DB, vulns []*Vulnerability) ([]*OperatingSystem, error) {
|
||||
// map to track unique operating systems
|
||||
osMap := make(map[string]*OperatingSystem)
|
||||
for _, v := range vulns {
|
||||
for _, a := range *v.Affected {
|
||||
if a.OperatingSystem == nil {
|
||||
continue
|
||||
}
|
||||
osKey := fmt.Sprintf("%s:%s:%s", a.OperatingSystem.Name, a.OperatingSystem.MajorVersion, a.OperatingSystem.MinorVersion)
|
||||
osMap[osKey] = a.OperatingSystem
|
||||
}
|
||||
}
|
||||
|
||||
// extract unique operating systems
|
||||
var uniqueOSList []*OperatingSystem
|
||||
for _, os := range osMap {
|
||||
uniqueOSList = append(uniqueOSList, os)
|
||||
}
|
||||
|
||||
// insert unique operating systems into the database or fetch existing ones
|
||||
for i, os := range uniqueOSList {
|
||||
var existing OperatingSystem
|
||||
err := db.Where("name = ? AND major_version = ? AND minor_version = ?", os.Name, os.MajorVersion, os.MinorVersion).
|
||||
FirstOrCreate(&existing, os).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uniqueOSList[i].ID = existing.ID
|
||||
}
|
||||
|
||||
return uniqueOSList, nil
|
||||
}
|
||||
|
||||
func updateAffectedsWithOperatingSystems(vulns []*Vulnerability, uniqueOSList []*OperatingSystem) {
|
||||
osMap := make(map[string]int64)
|
||||
for _, os := range uniqueOSList {
|
||||
osKey := fmt.Sprintf("%s:%s:%s", os.Name, os.MajorVersion, os.MinorVersion)
|
||||
osMap[osKey] = os.ID
|
||||
}
|
||||
|
||||
for i, v := range vulns {
|
||||
for j, a := range *v.Affected {
|
||||
if a.OperatingSystem == nil {
|
||||
continue
|
||||
}
|
||||
osKey := fmt.Sprintf("%s:%s:%s", a.OperatingSystem.Name, a.OperatingSystem.MajorVersion, a.OperatingSystem.MinorVersion)
|
||||
val := osMap[osKey]
|
||||
(*vulns[i].Affected)[j].OperatingSystemID = &val
|
||||
}
|
||||
}
|
||||
}
|
||||
//func (s *vulnerabilityStore) handleOSs(vulns []*Vulnerability) error {
|
||||
// // ensure unique operating systems
|
||||
// uniqueOSList, err := ensureUniqueOperatingSystems(s.db, vulns)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// // update vulnerabilities with operating system IDs
|
||||
// updateAffectedsWithOperatingSystems(vulns, uniqueOSList)
|
||||
//
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func ensureUniqueOperatingSystems(db *gorm.DB, vulns []*Vulnerability) ([]*OperatingSystem, error) {
|
||||
// // map to track unique operating systems
|
||||
// osMap := make(map[string]*OperatingSystem)
|
||||
// for _, v := range vulns {
|
||||
// for _, a := range *v.Affected {
|
||||
// if a.OperatingSystem == nil {
|
||||
// continue
|
||||
// }
|
||||
// osKey := fmt.Sprintf("%s:%s:%s", a.OperatingSystem.Name, a.OperatingSystem.MajorVersion, a.OperatingSystem.MinorVersion)
|
||||
// osMap[osKey] = a.OperatingSystem
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // extract unique operating systems
|
||||
// var uniqueOSList []*OperatingSystem
|
||||
// for _, os := range osMap {
|
||||
// uniqueOSList = append(uniqueOSList, os)
|
||||
// }
|
||||
//
|
||||
// // insert unique operating systems into the database or fetch existing ones
|
||||
// for i, os := range uniqueOSList {
|
||||
// var existing OperatingSystem
|
||||
// err := db.Where("name = ? AND major_version = ? AND minor_version = ?", os.Name, os.MajorVersion, os.MinorVersion).
|
||||
// FirstOrCreate(&existing, os).Error
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// uniqueOSList[i].ID = existing.ID
|
||||
// }
|
||||
//
|
||||
// return uniqueOSList, nil
|
||||
//}
|
||||
//
|
||||
//func updateAffectedsWithOperatingSystems(vulns []*Vulnerability, uniqueOSList []*OperatingSystem) {
|
||||
// osMap := make(map[string]int64)
|
||||
// for _, os := range uniqueOSList {
|
||||
// osKey := fmt.Sprintf("%s:%s:%s", os.Name, os.MajorVersion, os.MinorVersion)
|
||||
// osMap[osKey] = os.ID
|
||||
// }
|
||||
//
|
||||
// for i, v := range vulns {
|
||||
// for j, a := range *v.Affected {
|
||||
// if a.OperatingSystem == nil {
|
||||
// continue
|
||||
// }
|
||||
// osKey := fmt.Sprintf("%s:%s:%s", a.OperatingSystem.Name, a.OperatingSystem.MajorVersion, a.OperatingSystem.MinorVersion)
|
||||
// val := osMap[osKey]
|
||||
// (*vulns[i].Affected)[j].OperatingSystemID = &val
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
Loading…
Reference in a new issue