From 6129ac7bd47601eac192d7dd161666ac00cd46d1 Mon Sep 17 00:00:00 2001 From: kota kanbe Date: Thu, 17 Aug 2017 12:18:06 +0900 Subject: [PATCH] Change model ScanResult.ScannedCves.AffectedPackages --- models/packages.go | 17 ++++++++--------- models/vulninfos.go | 23 ++++++++++++++++++++--- models/vulninfos_test.go | 24 ++++++++++++++++++++++++ oval/debian.go | 10 ++++------ oval/debian_test.go | 12 ++++++------ oval/redhat.go | 9 ++++----- oval/redhat_test.go | 12 ++++++------ oval/util.go | 8 ++++---- report/slack.go | 10 +++++----- report/tui.go | 10 +++++----- report/util.go | 12 ++++++------ report/util_test.go | 12 ++++++------ scan/debian.go | 11 ++++++++--- scan/freebsd.go | 8 +++++--- scan/redhat.go | 19 ++++++++++--------- 15 files changed, 121 insertions(+), 76 deletions(-) diff --git a/models/packages.go b/models/packages.go index 827ca103..6f67f7fa 100644 --- a/models/packages.go +++ b/models/packages.go @@ -92,15 +92,14 @@ func (ps Packages) FindOne(f func(Package) bool) (string, Package, bool) { // Package has installed packages. type Package struct { - Name string - Version string - Release string - NewVersion string - NewRelease string - Arch string - Repository string - Changelog Changelog - NotFixedYet bool // Ubuntu OVAL Only + Name string + Version string + Release string + NewVersion string + NewRelease string + Arch string + Repository string + Changelog Changelog } // FormatVer returns package version-release diff --git a/models/vulninfos.go b/models/vulninfos.go index 735e89b2..b7451231 100644 --- a/models/vulninfos.go +++ b/models/vulninfos.go @@ -104,11 +104,28 @@ func (v VulnInfos) FormatCveSummary() string { m["High"], m["Medium"], m["Low"], m["Unknown"]) } +// PackageStatuses is a list of PackageStatus +type PackageStatuses []PackageStatus + +// Sort by Name +func (p PackageStatuses) Sort() { + sort.Slice(p, func(i, j int) bool { + return p[i].Name < p[j].Name + }) + return +} + +// PackageStatus has name and other status abount the package +type PackageStatus struct { + Name string + NotFixedYet bool +} + // VulnInfo has a vulnerability information and unsecure packages type VulnInfo struct { CveID string Confidence Confidence - PackageNames []string + AffectedPackages PackageStatuses DistroAdvisories []DistroAdvisory // for Aamazon, RHEL, FreeBSD CpeNames []string CveContents CveContents @@ -547,8 +564,8 @@ func (v *VulnInfo) NilToEmpty() *VulnInfo { if v.DistroAdvisories == nil { v.DistroAdvisories = []DistroAdvisory{} } - if v.PackageNames == nil { - v.PackageNames = []string{} + if v.AffectedPackages == nil { + v.AffectedPackages = PackageStatuses{} } if v.CveContents == nil { v.CveContents = NewCveContents() diff --git a/models/vulninfos_test.go b/models/vulninfos_test.go index 99e054ee..93adaddb 100644 --- a/models/vulninfos_test.go +++ b/models/vulninfos_test.go @@ -910,3 +910,27 @@ func TestFormatMaxCvssScore(t *testing.T) { } } } + +func TestSortPackageStatues(t *testing.T) { + var tests = []struct { + in PackageStatuses + out PackageStatuses + }{ + { + in: PackageStatuses{ + {Name: "b"}, + {Name: "a"}, + }, + out: PackageStatuses{ + {Name: "a"}, + {Name: "b"}, + }, + }, + } + for _, tt := range tests { + tt.in.Sort() + if !reflect.DeepEqual(tt.in, tt.out) { + t.Errorf("\nexpected: %v\n actual: %v\n", tt.out, tt.in) + } + } +} diff --git a/oval/debian.go b/oval/debian.go index 5137467b..f2cd8760 100644 --- a/oval/debian.go +++ b/oval/debian.go @@ -18,8 +18,6 @@ along with this program. If not, see . package oval import ( - "sort" - "github.com/future-architect/vuls/config" "github.com/future-architect/vuls/models" "github.com/future-architect/vuls/util" @@ -95,11 +93,11 @@ func (o DebianBase) update(r *models.ScanResult, defPacks defPacks) { } // uniq(vinfo.PackNames + defPacks.actuallyAffectedPackNames) - for _, name := range vinfo.PackageNames { - defPacks.actuallyAffectedPackNames[name] = true + for _, pack := range vinfo.AffectedPackages { + defPacks.actuallyAffectedPackNames[pack.Name] = true } - vinfo.PackageNames = defPacks.packNames() - sort.Strings(vinfo.PackageNames) + vinfo.AffectedPackages = defPacks.toPackStatuses() + vinfo.AffectedPackages.Sort() r.ScannedCves[defPacks.def.Debian.CveID] = vinfo } diff --git a/oval/debian_test.go b/oval/debian_test.go index d3630acc..f522d1c6 100644 --- a/oval/debian_test.go +++ b/oval/debian_test.go @@ -36,7 +36,7 @@ func TestPackNamesOfUpdateDebian(t *testing.T) { in: models.ScanResult{ ScannedCves: models.VulnInfos{ "CVE-2000-1000": models.VulnInfo{ - PackageNames: []string{"packA"}, + AffectedPackages: models.PackageStatuses{{Name: "packA"}}, }, }, }, @@ -53,9 +53,9 @@ func TestPackNamesOfUpdateDebian(t *testing.T) { out: models.ScanResult{ ScannedCves: models.VulnInfos{ "CVE-2000-1000": models.VulnInfo{ - PackageNames: []string{ - "packA", - "packB", + AffectedPackages: models.PackageStatuses{ + {Name: "packA"}, + {Name: "packB"}, }, }, }, @@ -66,8 +66,8 @@ func TestPackNamesOfUpdateDebian(t *testing.T) { util.Log = util.NewCustomLogger(config.ServerInfo{}) for i, tt := range tests { Debian{}.update(&tt.in, tt.defPacks) - e := tt.out.ScannedCves["CVE-2000-1000"].PackageNames - a := tt.in.ScannedCves["CVE-2000-1000"].PackageNames + e := tt.out.ScannedCves["CVE-2000-1000"].AffectedPackages + a := tt.in.ScannedCves["CVE-2000-1000"].AffectedPackages if !reflect.DeepEqual(a, e) { t.Errorf("[%d] expected: %v\n actual: %v\n", i, e, a) } diff --git a/oval/redhat.go b/oval/redhat.go index c48f42b3..1b24e91a 100644 --- a/oval/redhat.go +++ b/oval/redhat.go @@ -19,7 +19,6 @@ package oval import ( "fmt" - "sort" "strconv" "strings" @@ -98,11 +97,11 @@ func (o RedHatBase) update(r *models.ScanResult, defPacks defPacks) { } // uniq(vinfo.PackNames + defPacks.actuallyAffectedPackNames) - for _, name := range vinfo.PackageNames { - defPacks.actuallyAffectedPackNames[name] = true + for _, pack := range vinfo.AffectedPackages { + defPacks.actuallyAffectedPackNames[pack.Name] = true } - vinfo.PackageNames = defPacks.packNames() - sort.Strings(vinfo.PackageNames) + vinfo.AffectedPackages = defPacks.toPackStatuses() + vinfo.AffectedPackages.Sort() r.ScannedCves[cve.CveID] = vinfo } } diff --git a/oval/redhat_test.go b/oval/redhat_test.go index a69bf838..7914686c 100644 --- a/oval/redhat_test.go +++ b/oval/redhat_test.go @@ -102,7 +102,7 @@ func TestPackNamesOfUpdate(t *testing.T) { in: models.ScanResult{ ScannedCves: models.VulnInfos{ "CVE-2000-1000": models.VulnInfo{ - PackageNames: []string{"packA"}, + AffectedPackages: models.PackageStatuses{{Name: "packA"}}, }, }, }, @@ -123,9 +123,9 @@ func TestPackNamesOfUpdate(t *testing.T) { out: models.ScanResult{ ScannedCves: models.VulnInfos{ "CVE-2000-1000": models.VulnInfo{ - PackageNames: []string{ - "packA", - "packB", + AffectedPackages: models.PackageStatuses{ + {Name: "packA"}, + {Name: "packB"}, }, }, }, @@ -136,8 +136,8 @@ func TestPackNamesOfUpdate(t *testing.T) { util.Log = util.NewCustomLogger(config.ServerInfo{}) for i, tt := range tests { RedHat{}.update(&tt.in, tt.defPacks) - e := tt.out.ScannedCves["CVE-2000-1000"].PackageNames - a := tt.in.ScannedCves["CVE-2000-1000"].PackageNames + e := tt.out.ScannedCves["CVE-2000-1000"].AffectedPackages + a := tt.in.ScannedCves["CVE-2000-1000"].AffectedPackages if !reflect.DeepEqual(a, e) { t.Errorf("[%d] expected: %v\n actual: %v\n", i, e, a) } diff --git a/oval/util.go b/oval/util.go index ffdce94e..bbbf671d 100644 --- a/oval/util.go +++ b/oval/util.go @@ -44,9 +44,9 @@ type defPacks struct { actuallyAffectedPackNames map[string]bool } -func (e defPacks) packNames() (names []string) { +func (e defPacks) toPackStatuses() (ps models.PackageStatuses) { for k := range e.actuallyAffectedPackNames { - names = append(names, k) + ps = append(ps, models.PackageStatus{Name: k}) } return } @@ -192,7 +192,7 @@ func httpGet(url string, pack *models.Package, resChan chan<- response, errChan } func getDefsByPackNameFromOvalDB(family, osRelease string, - packs models.Packages) (relatedDefs ovalResult, err error) { + installedPacks models.Packages) (relatedDefs ovalResult, err error) { ovallog.Initialize(config.Conf.LogDir) path := config.Conf.OvalDBURL @@ -211,7 +211,7 @@ func getDefsByPackNameFromOvalDB(family, osRelease string, return } defer ovaldb.CloseDB() - for _, pack := range packs { + for _, pack := range installedPacks { definitions, err := ovaldb.GetByPackName(osRelease, pack.Name) if err != nil { return relatedDefs, fmt.Errorf("Failed to get %s OVAL info by package name: %v", family, err) diff --git a/report/slack.go b/report/slack.go index ffac39e5..6926dfb2 100644 --- a/report/slack.go +++ b/report/slack.go @@ -174,12 +174,12 @@ func toSlackAttachments(r models.ScanResult) (attaches []*attachment) { for _, vinfo := range vinfos { curent := []string{} - for _, name := range vinfo.PackageNames { - if p, ok := r.Packages[name]; ok { + for _, affected := range vinfo.AffectedPackages { + if p, ok := r.Packages[affected.Name]; ok { curent = append(curent, fmt.Sprintf("%s-%s", p.Name, p.FormatVer())) } else { - curent = append(curent, name) + curent = append(curent, affected.Name) } } for _, n := range vinfo.CpeNames { @@ -187,8 +187,8 @@ func toSlackAttachments(r models.ScanResult) (attaches []*attachment) { } new := []string{} - for _, name := range vinfo.PackageNames { - if p, ok := r.Packages[name]; ok { + for _, affected := range vinfo.AffectedPackages { + if p, ok := r.Packages[affected.Name]; ok { new = append(new, p.FormatNewVer()) } else { new = append(new, "?") diff --git a/report/tui.go b/report/tui.go index 1364a6b8..5796dddc 100644 --- a/report/tui.go +++ b/report/tui.go @@ -713,8 +713,8 @@ func setChangelogLayout(g *gocui.Gui) error { lines = append(lines, adv.Format()) } - for _, name := range vinfo.PackageNames { - pack := currentScanResult.Packages[name] + for _, affected := range vinfo.AffectedPackages { + pack := currentScanResult.Packages[affected.Name] for _, p := range currentScanResult.Packages { if pack.Name == p.Name { lines = append(lines, p.FormatChangelog(), "\n") @@ -763,10 +763,10 @@ func detailLines() (string, error) { vinfo := vinfos[currentVinfo] packsVer := []string{} - sort.Strings(vinfo.PackageNames) - for _, name := range vinfo.PackageNames { + vinfo.AffectedPackages.Sort() + for _, affected := range vinfo.AffectedPackages { // packages detected by OVAL may not be actually installed - if pack, ok := r.Packages[name]; ok { + if pack, ok := r.Packages[affected.Name]; ok { packsVer = append(packsVer, pack.FormatVersionFromTo()) } } diff --git a/report/util.go b/report/util.go index 5cbf43c5..c90f23bc 100644 --- a/report/util.go +++ b/report/util.go @@ -216,9 +216,9 @@ No CVE-IDs are found in updatable packages. } packsVer := []string{} - sort.Strings(vuln.PackageNames) - for _, name := range vuln.PackageNames { - if pack, ok := r.Packages[name]; ok { + vuln.AffectedPackages.Sort() + for _, affected := range vuln.AffectedPackages { + if pack, ok := r.Packages[affected.Name]; ok { packsVer = append(packsVer, pack.FormatVersionFromTo()) } } @@ -322,9 +322,9 @@ func diff(curResults, preResults models.ScanResults) (diffed models.ScanResults, current.ScannedCves = getDiffCves(previous, current) packages := models.Packages{} for _, s := range current.ScannedCves { - for _, name := range s.PackageNames { - p := current.Packages[name] - packages[name] = p + for _, affected := range s.AffectedPackages { + p := current.Packages[affected.Name] + packages[affected.Name] = p } } current.Packages = packages diff --git a/report/util_test.go b/report/util_test.go index 6cf3c1f9..4deb6934 100644 --- a/report/util_test.go +++ b/report/util_test.go @@ -183,13 +183,13 @@ func TestDiff(t *testing.T) { ScannedCves: models.VulnInfos{ "CVE-2012-6702": { CveID: "CVE-2012-6702", - PackageNames: []string{"libexpat1"}, + AffectedPackages: models.PackageStatuses{{Name: "libexpat1"}}, DistroAdvisories: []models.DistroAdvisory{}, CpeNames: []string{}, }, "CVE-2014-9761": { CveID: "CVE-2014-9761", - PackageNames: []string{"libc-bin"}, + AffectedPackages: models.PackageStatuses{{Name: "libc-bin"}}, DistroAdvisories: []models.DistroAdvisory{}, CpeNames: []string{}, }, @@ -208,13 +208,13 @@ func TestDiff(t *testing.T) { ScannedCves: models.VulnInfos{ "CVE-2012-6702": { CveID: "CVE-2012-6702", - PackageNames: []string{"libexpat1"}, + AffectedPackages: models.PackageStatuses{{Name: "libexpat1"}}, DistroAdvisories: []models.DistroAdvisory{}, CpeNames: []string{}, }, "CVE-2014-9761": { CveID: "CVE-2014-9761", - PackageNames: []string{"libc-bin"}, + AffectedPackages: models.PackageStatuses{{Name: "libc-bin"}}, DistroAdvisories: []models.DistroAdvisory{}, CpeNames: []string{}, }, @@ -245,7 +245,7 @@ func TestDiff(t *testing.T) { ScannedCves: models.VulnInfos{ "CVE-2016-6662": { CveID: "CVE-2016-6662", - PackageNames: []string{"mysql-libs"}, + AffectedPackages: models.PackageStatuses{{Name: "mysql-libs"}}, DistroAdvisories: []models.DistroAdvisory{}, CpeNames: []string{}, }, @@ -283,7 +283,7 @@ func TestDiff(t *testing.T) { ScannedCves: models.VulnInfos{ "CVE-2016-6662": { CveID: "CVE-2016-6662", - PackageNames: []string{"mysql-libs"}, + AffectedPackages: models.PackageStatuses{{Name: "mysql-libs"}}, DistroAdvisories: []models.DistroAdvisory{}, CpeNames: []string{}, }, diff --git a/scan/debian.go b/scan/debian.go index 20c9fa98..1e787b98 100644 --- a/scan/debian.go +++ b/scan/debian.go @@ -508,10 +508,15 @@ func (o *debian) scanVulnInfos(updatablePacks models.Packages, meta *cache.Meta) o.log.Debugf("%d Cves are found. cves: %v", len(cveIDs), cveIDs) vinfos := models.VulnInfos{} for cveID, names := range cvePackages { + affected := models.PackageStatuses{} + for _, n := range names { + affected = append(affected, models.PackageStatus{Name: n}) + } + vinfos[cveID.CveID] = models.VulnInfo{ - CveID: cveID.CveID, - Confidence: cveID.Confidence, - PackageNames: names, + CveID: cveID.CveID, + Confidence: cveID.Confidence, + AffectedPackages: affected, } } diff --git a/scan/freebsd.go b/scan/freebsd.go index 17f7d415..597a83e1 100644 --- a/scan/freebsd.go +++ b/scan/freebsd.go @@ -164,13 +164,15 @@ func (o *bsd) scanUnsecurePackages() (models.VulnInfos, error) { }) } - names := []string{} + affected := models.PackageStatuses{} for name := range packs { - names = append(names, name) + affected = append(affected, models.PackageStatus{ + Name: name, + }) } vinfos[cveID] = models.VulnInfo{ CveID: cveID, - PackageNames: names, + AffectedPackages: affected, DistroAdvisories: disAdvs, Confidence: models.PkgAuditMatch, } diff --git a/scan/redhat.go b/scan/redhat.go index 716fbdff..ee68cfbc 100644 --- a/scan/redhat.go +++ b/scan/redhat.go @@ -610,13 +610,13 @@ func (o *redhat) scanCveIDsInChangelog(updatable models.Packages) (models.VulnIn for name, cveIDs := range packCveIDs { for _, cid := range cveIDs { if v, ok := vinfos[cid]; ok { - v.PackageNames = append(v.PackageNames, name) + v.AffectedPackages = append(v.AffectedPackages, models.PackageStatus{Name: name}) vinfos[cid] = v } else { vinfos[cid] = models.VulnInfo{ - CveID: cid, - PackageNames: []string{name}, - Confidence: models.ChangelogExactMatch, + CveID: cid, + AffectedPackages: models.PackageStatuses{{Name: name}}, + Confidence: models.ChangelogExactMatch, } } } @@ -703,18 +703,19 @@ func (o *redhat) scanCveIDsByCommands(updatable models.Packages) (models.VulnInf packs := dict[advIDCveIDs.DistroAdvisory.AdvisoryID] for _, pack := range packs { - vinfo.PackageNames = append(vinfo.PackageNames, pack.Name) + vinfo.AffectedPackages = append(vinfo.AffectedPackages, + models.PackageStatus{Name: pack.Name}) } } else { - names := []string{} packs := dict[advIDCveIDs.DistroAdvisory.AdvisoryID] - for _, pack := range packs { - names = append(names, pack.Name) + affected := models.PackageStatuses{} + for _, p := range packs { + affected = append(affected, models.PackageStatus{Name: p.Name}) } vinfo = models.VulnInfo{ CveID: cveID, DistroAdvisories: []models.DistroAdvisory{advIDCveIDs.DistroAdvisory}, - PackageNames: names, + AffectedPackages: affected, Confidence: models.YumUpdateSecurityMatch, } }