fix: aggregate k8s events under same package (#249)
This commit is contained in:
parent
dfec39ff26
commit
f851c7b730
107
k8s/k8s.go
107
k8s/k8s.go
@ -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 ||
|
||||||
|
@ -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")
|
||||||
|
2
k8s/testdata/expected-vulndb.json
vendored
2
k8s/testdata/expected-vulndb.json
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user