fix: aggregate k8s events under same package (#249)

This commit is contained in:
chenk 2023-10-02 18:44:10 +03:00 committed by GitHub
parent dfec39ff26
commit f851c7b730
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 75 deletions

View File

@ -2,7 +2,6 @@ package k8s
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
@ -104,34 +103,31 @@ func ParseVulnDBData(db CVE, cvesMap map[string]string) (*VulnDB, error) {
} }
descComponent := getComponentFromDescription(item.ContentText, vulnerability.Package) descComponent := getComponentFromDescription(item.ContentText, vulnerability.Package)
fullVulnerabilities = append(fullVulnerabilities, &osv.OSV{ fullVulnerabilities = append(fullVulnerabilities, &osv.OSV{
ID: cveID, ID: cveID,
Modified: item.DatePublished, Modified: item.DatePublished,
Published: item.DatePublished, Published: item.DatePublished,
Summary: item.Summary, Summary: item.Summary,
Details: vulnerability.Description, Details: vulnerability.Description,
Affected: getAffectedEvents(vulnerability.versions, getComponentName(descComponent, vulnerability.Package), vulnerability.CvssV3), Affected: getAffectedEvents(vulnerability.versions, getComponentName(descComponent, vulnerability.Package), vulnerability.CvssV3),
References: []osv.Reference{{Url: item.URL}, {Url: item.ExternalURL}}, References: []osv.Reference{
{
Url: item.URL, Type: "ADVISORY",
}, {
Url: item.ExternalURL, Type: "ADVISORY",
},
},
}) })
} }
} }
err := validateCvesData(fullVulnerabilities)
if err != nil {
return nil, err
}
return &VulnDB{fullVulnerabilities}, nil return &VulnDB{fullVulnerabilities}, nil
} }
func getAffectedEvents(v []*Version, p string, cvss Cvssv3) []osv.Affected { func getAffectedEvents(v []*Version, p string, cvss Cvssv3) []osv.Affected {
affected := make([]osv.Affected, 0) events := make([]osv.Event, 0)
for _, av := range v { for _, av := range v {
if len(av.Introduced) == 0 { if len(av.Introduced) == 0 {
continue continue
} }
if av.Introduced == "0.0.0" {
av.Introduced = "0"
}
events := make([]osv.Event, 0)
ranges := make([]osv.Range, 0)
if len(av.Introduced) > 0 { if len(av.Introduced) > 0 {
events = append(events, osv.Event{Introduced: av.Introduced}) events = append(events, osv.Event{Introduced: av.Introduced})
} }
@ -142,12 +138,28 @@ func getAffectedEvents(v []*Version, p string, cvss Cvssv3) []osv.Affected {
} else if len(av.Introduced) > 0 && len(av.LastAffected) == 0 && len(av.Fixed) == 0 { } else if len(av.Introduced) > 0 && len(av.LastAffected) == 0 && len(av.Fixed) == 0 {
events = append(events, osv.Event{LastAffected: av.Introduced}) events = append(events, osv.Event{LastAffected: av.Introduced})
} }
ranges = append(ranges, osv.Range{
Events: events,
})
affected = append(affected, osv.Affected{Ranges: ranges, Package: osv.Package{Name: p, Ecosystem: "kubernetes"}, Severities: []osv.Severity{{Type: cvss.Type, Score: cvss.Vector}}})
} }
return affected return []osv.Affected{
{
Ranges: []osv.Range{
{
Events: events,
Type: "SEMVER",
},
},
Package: osv.Package{
Name: p,
Ecosystem: "kubernetes",
},
Severities: []osv.Severity{
{
Type: cvss.Type,
Score: cvss.Vector,
},
},
},
}
} }
func getComponentName(k8sComponent string, mitreComponent string) string { func getComponentName(k8sComponent string, mitreComponent string) string {
@ -160,55 +172,6 @@ func getComponentName(k8sComponent string, mitreComponent string) string {
return strings.ToLower(fmt.Sprintf("%s/%s", upstreamOrgByName(k8sComponent), upstreamRepoByName(k8sComponent))) return strings.ToLower(fmt.Sprintf("%s/%s", upstreamOrgByName(k8sComponent), upstreamRepoByName(k8sComponent)))
} }
func validateCvesData(cves []*osv.OSV) error {
var result error
for _, cve := range cves {
if len(cve.ID) == 0 {
result = errors.Join(result, fmt.Errorf("\nid is mssing on cve #%s", cve.ID))
}
if len(cve.Published) == 0 {
result = errors.Join(result, fmt.Errorf("\nCreatedAt is mssing on cve #%s", cve.ID))
}
if len(cve.Summary) == 0 {
result = errors.Join(result, fmt.Errorf("\nSummary is mssing on cve #%s", cve.ID))
}
for _, af := range cve.Affected {
if len(strings.TrimPrefix(af.Package.Name, upstreamOrgByName(af.Package.Name))) == 0 {
result = errors.Join(result, fmt.Errorf("\nComponent is mssing on cve #%s", cve.ID))
}
}
if len(cve.Details) == 0 {
result = errors.Join(result, fmt.Errorf("\nDescription is mssing on cve #%s", cve.ID))
}
if len(cve.Affected) == 0 {
result = errors.Join(result, fmt.Errorf("\nAffected Version is missing on cve #%s", cve.ID))
}
if len(cve.Affected) > 0 {
for _, v := range cve.Affected {
for _, s := range v.Severities {
if len(s.Type) == 0 {
result = errors.Join(result, fmt.Errorf("\nVector is mssing on cve #%s", cve.ID))
}
}
for _, r := range v.Ranges {
for i := 1; i < len(r.Events); i++ {
if len(r.Events[i-1].Introduced) == 0 {
result = errors.Join(result, fmt.Errorf("\nAffectedVersion Introduced is missing from cve #%s", cve.ID))
}
if len(r.Events[i].Fixed) == 0 && len(r.Events[i].LastAffected) == 0 {
result = errors.Join(result, fmt.Errorf("\nAffectedVersion Fixed and LastAffected are missing from cve #%s", cve.ID))
}
}
}
}
}
if len(cve.References) == 0 {
result = errors.Join(result, fmt.Errorf("\nUrls is mssing on cve #%s", cve.ID))
}
}
return result
}
func cveMissingImportantData(vulnerability *Cve) bool { func cveMissingImportantData(vulnerability *Cve) bool {
return len(vulnerability.versions) == 0 || return len(vulnerability.versions) == 0 ||
len(vulnerability.Package) == 0 || len(vulnerability.Package) == 0 ||

View File

@ -16,8 +16,6 @@ func Test_ParseVulneDB(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
kvd, err := ParseVulnDBData(bi, map[string]string{}) kvd, err := ParseVulnDBData(bi, map[string]string{})
assert.NoError(t, err) assert.NoError(t, err)
err = validateCvesData(kvd.Cves)
assert.NoError(t, err)
gotVulnDB, err := json.Marshal(kvd.Cves) gotVulnDB, err := json.Marshal(kvd.Cves)
assert.NoError(t, err) assert.NoError(t, err)
wantVulnDB, err := os.ReadFile("./testdata/expected-vulndb.json") wantVulnDB, err := os.ReadFile("./testdata/expected-vulndb.json")

File diff suppressed because one or more lines are too long