Change model ScanResult.ScannedCves.AffectedPackages
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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, "?")
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{},
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user