Fix OVAL detection on Debian and Ubuntu (#509)
* Add filter options to tui subcommand (#508) * Capture version of source packages on Debian based linux * Change makefile, gofmt -s * Refactoring * Implement OVAL detection of source packages for Debian, Ubuntu
This commit is contained in:
@@ -60,8 +60,10 @@ func (o DebianBase) update(r *models.ScanResult, defPacks defPacks) {
|
||||
|
||||
// uniq(vinfo.PackNames + defPacks.actuallyAffectedPackNames)
|
||||
for _, pack := range vinfo.AffectedPackages {
|
||||
defPacks.actuallyAffectedPackNames[pack.Name] = true
|
||||
notFixedYet, _ := defPacks.actuallyAffectedPackNames[pack.Name]
|
||||
defPacks.actuallyAffectedPackNames[pack.Name] = notFixedYet
|
||||
}
|
||||
|
||||
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family, r.Packages)
|
||||
vinfo.AffectedPackages.Sort()
|
||||
r.ScannedCves[defPacks.def.Debian.CveID] = vinfo
|
||||
@@ -107,11 +109,17 @@ func (o Debian) FillWithOval(r *models.ScanResult) (err error) {
|
||||
|
||||
//Debian's uname gives both of kernel release(uname -r), version(kernel-image version)
|
||||
linuxImage := "linux-image-" + r.RunningKernel.Release
|
||||
|
||||
// Add linux and set the version of running kernel to search OVAL.
|
||||
newVer := ""
|
||||
if p, ok := r.Packages[linuxImage]; ok {
|
||||
newVer = p.NewVersion
|
||||
}
|
||||
if r.Container.ContainerID == "" {
|
||||
r.Packages["linux"] = models.Package{
|
||||
Name: "linux",
|
||||
Version: r.RunningKernel.Version,
|
||||
Name: "linux",
|
||||
Version: r.RunningKernel.Version,
|
||||
NewVersion: newVer,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +129,7 @@ func (o Debian) FillWithOval(r *models.ScanResult) (err error) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if relatedDefs, err = getDefsByPackNameFromOvalDB(o.family, r.Release, r.Packages); err != nil {
|
||||
if relatedDefs, err = getDefsByPackNameFromOvalDB(r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -129,10 +137,10 @@ func (o Debian) FillWithOval(r *models.ScanResult) (err error) {
|
||||
delete(r.Packages, "linux")
|
||||
|
||||
for _, defPacks := range relatedDefs.entries {
|
||||
// Remove linux added above to search for oval
|
||||
// Remove "linux" added above for oval search
|
||||
// linux is not a real package name (key of affected packages in OVAL)
|
||||
if _, ok := defPacks.actuallyAffectedPackNames["linux"]; ok {
|
||||
defPacks.actuallyAffectedPackNames[linuxImage] = true
|
||||
if notFixedYet, ok := defPacks.actuallyAffectedPackNames["linux"]; ok {
|
||||
defPacks.actuallyAffectedPackNames[linuxImage] = notFixedYet
|
||||
delete(defPacks.actuallyAffectedPackNames, "linux")
|
||||
for i, p := range defPacks.def.AffectedPacks {
|
||||
if p.Name == "linux" {
|
||||
@@ -141,6 +149,7 @@ func (o Debian) FillWithOval(r *models.ScanResult) (err error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
o.update(r, defPacks)
|
||||
}
|
||||
|
||||
@@ -230,7 +239,7 @@ func (o Ubuntu) FillWithOval(r *models.ScanResult) (err error) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if relatedDefs, err = getDefsByPackNameFromOvalDB(o.family, r.Release, r.Packages); err != nil {
|
||||
if relatedDefs, err = getDefsByPackNameFromOvalDB(r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -240,7 +249,6 @@ func (o Ubuntu) FillWithOval(r *models.ScanResult) (err error) {
|
||||
}
|
||||
|
||||
for _, defPacks := range relatedDefs.entries {
|
||||
|
||||
// Remove "linux" added above to search for oval
|
||||
// "linux" is not a real package name (key of affected packages in OVAL)
|
||||
if _, ok := defPacks.actuallyAffectedPackNames["linux"]; !found && ok {
|
||||
@@ -253,6 +261,7 @@ func (o Ubuntu) FillWithOval(r *models.ScanResult) (err error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
o.update(r, defPacks)
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,10 @@ func TestPackNamesOfUpdateDebian(t *testing.T) {
|
||||
in: models.ScanResult{
|
||||
ScannedCves: models.VulnInfos{
|
||||
"CVE-2000-1000": models.VulnInfo{
|
||||
AffectedPackages: models.PackageStatuses{{Name: "packA"}},
|
||||
AffectedPackages: models.PackageStatuses{
|
||||
{Name: "packA"},
|
||||
{Name: "packC"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -55,7 +58,8 @@ func TestPackNamesOfUpdateDebian(t *testing.T) {
|
||||
"CVE-2000-1000": models.VulnInfo{
|
||||
AffectedPackages: models.PackageStatuses{
|
||||
{Name: "packA"},
|
||||
{Name: "packB"},
|
||||
{Name: "packB", NotFixedYet: true},
|
||||
{Name: "packC"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -41,8 +41,7 @@ func (o RedHatBase) FillWithOval(r *models.ScanResult) (err error) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if relatedDefs, err = getDefsByPackNameFromOvalDB(
|
||||
o.family, r.Release, r.Packages); err != nil {
|
||||
if relatedDefs, err = getDefsByPackNameFromOvalDB(r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -98,7 +97,8 @@ func (o RedHatBase) update(r *models.ScanResult, defPacks defPacks) {
|
||||
|
||||
// uniq(vinfo.PackNames + defPacks.actuallyAffectedPackNames)
|
||||
for _, pack := range vinfo.AffectedPackages {
|
||||
defPacks.actuallyAffectedPackNames[pack.Name] = true
|
||||
notFixedYet, _ := defPacks.actuallyAffectedPackNames[pack.Name]
|
||||
defPacks.actuallyAffectedPackNames[pack.Name] = notFixedYet
|
||||
}
|
||||
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family, r.Packages)
|
||||
vinfo.AffectedPackages.Sort()
|
||||
@@ -156,7 +156,7 @@ func (o RedHatBase) parseCvss2(scoreVector string) (score float64, vector string
|
||||
if score, err = strconv.ParseFloat(ss[0], 64); err != nil {
|
||||
return 0, ""
|
||||
}
|
||||
return score, strings.Join(ss[1:len(ss)], "/")
|
||||
return score, strings.Join(ss[1:], "/")
|
||||
}
|
||||
return 0, ""
|
||||
}
|
||||
@@ -170,7 +170,7 @@ func (o RedHatBase) parseCvss3(scoreVector string) (score float64, vector string
|
||||
if score, err = strconv.ParseFloat(ss[0], 64); err != nil {
|
||||
return 0, ""
|
||||
}
|
||||
return score, strings.Join(ss[1:len(ss)], "/")
|
||||
return score, strings.Join(ss[1:], "/")
|
||||
}
|
||||
return 0, ""
|
||||
}
|
||||
|
||||
@@ -102,7 +102,10 @@ func TestPackNamesOfUpdate(t *testing.T) {
|
||||
in: models.ScanResult{
|
||||
ScannedCves: models.VulnInfos{
|
||||
"CVE-2000-1000": models.VulnInfo{
|
||||
AffectedPackages: models.PackageStatuses{{Name: "packA"}},
|
||||
AffectedPackages: models.PackageStatuses{
|
||||
{Name: "packA"},
|
||||
{Name: "packB", NotFixedYet: false},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -125,7 +128,7 @@ func TestPackNamesOfUpdate(t *testing.T) {
|
||||
"CVE-2000-1000": models.VulnInfo{
|
||||
AffectedPackages: models.PackageStatuses{
|
||||
{Name: "packA"},
|
||||
{Name: "packB"},
|
||||
{Name: "packB", NotFixedYet: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -47,7 +47,7 @@ func (o SUSE) FillWithOval(r *models.ScanResult) (err error) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if relatedDefs, err = getDefsByPackNameFromOvalDB(o.family, r.Release, r.Packages); err != nil {
|
||||
if relatedDefs, err = getDefsByPackNameFromOvalDB(r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,8 @@ func (o SUSE) update(r *models.ScanResult, defPacks defPacks) {
|
||||
|
||||
// uniq(vinfo.PackNames + defPacks.actuallyAffectedPackNames)
|
||||
for _, pack := range vinfo.AffectedPackages {
|
||||
defPacks.actuallyAffectedPackNames[pack.Name] = true
|
||||
notFixedYet, _ := defPacks.actuallyAffectedPackNames[pack.Name]
|
||||
defPacks.actuallyAffectedPackNames[pack.Name] = notFixedYet
|
||||
}
|
||||
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family, r.Packages)
|
||||
vinfo.AffectedPackages.Sort()
|
||||
|
||||
255
oval/util.go
255
oval/util.go
@@ -40,105 +40,48 @@ type ovalResult struct {
|
||||
}
|
||||
|
||||
type defPacks struct {
|
||||
def ovalmodels.Definition
|
||||
def ovalmodels.Definition
|
||||
|
||||
// BinaryPackageName : NotFixedYet
|
||||
actuallyAffectedPackNames map[string]bool
|
||||
}
|
||||
|
||||
func (e defPacks) toPackStatuses(family string, packs models.Packages) (ps models.PackageStatuses) {
|
||||
switch family {
|
||||
case config.Ubuntu:
|
||||
packNotFixedYet := map[string]bool{}
|
||||
for _, p := range e.def.AffectedPacks {
|
||||
packNotFixedYet[p.Name] = p.NotFixedYet
|
||||
}
|
||||
for k := range e.actuallyAffectedPackNames {
|
||||
ps = append(ps, models.PackageStatus{
|
||||
Name: k,
|
||||
NotFixedYet: packNotFixedYet[k],
|
||||
})
|
||||
}
|
||||
|
||||
case config.CentOS, config.Debian:
|
||||
// There are many packages that has been fixed in RedHat, but not been fixed in CentOS
|
||||
for name := range e.actuallyAffectedPackNames {
|
||||
pack, ok := packs[name]
|
||||
if !ok {
|
||||
util.Log.Warnf("Failed to find in Package list: %s", name)
|
||||
return
|
||||
}
|
||||
|
||||
ovalPackVer := ""
|
||||
for _, p := range e.def.AffectedPacks {
|
||||
if p.Name == name {
|
||||
ovalPackVer = p.Version
|
||||
break
|
||||
}
|
||||
}
|
||||
if ovalPackVer == "" {
|
||||
util.Log.Warnf("Failed to find in Oval Package list: %s", name)
|
||||
return
|
||||
}
|
||||
|
||||
if pack.NewVersion == "" {
|
||||
// compare version: installed vs oval
|
||||
vera := rpmver.NewVersion(fmt.Sprintf("%s-%s", pack.Version, pack.Release))
|
||||
verb := rpmver.NewVersion(ovalPackVer)
|
||||
notFixedYet := false
|
||||
if vera.LessThan(verb) {
|
||||
notFixedYet = true
|
||||
}
|
||||
ps = append(ps, models.PackageStatus{
|
||||
Name: name,
|
||||
NotFixedYet: notFixedYet,
|
||||
})
|
||||
} else {
|
||||
// compare version: newVer vs oval
|
||||
packNewVer := fmt.Sprintf("%s-%s", pack.NewVersion, pack.NewRelease)
|
||||
vera := rpmver.NewVersion(packNewVer)
|
||||
verb := rpmver.NewVersion(ovalPackVer)
|
||||
notFixedYet := false
|
||||
if vera.LessThan(verb) {
|
||||
notFixedYet = true
|
||||
}
|
||||
ps = append(ps, models.PackageStatus{
|
||||
Name: name,
|
||||
NotFixedYet: notFixedYet,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
for k := range e.actuallyAffectedPackNames {
|
||||
ps = append(ps, models.PackageStatus{
|
||||
Name: k,
|
||||
})
|
||||
}
|
||||
for name, notFixedYet := range e.actuallyAffectedPackNames {
|
||||
ps = append(ps, models.PackageStatus{
|
||||
Name: name,
|
||||
NotFixedYet: notFixedYet,
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (e *ovalResult) upsert(def ovalmodels.Definition, packName string) (upserted bool) {
|
||||
func (e *ovalResult) upsert(def ovalmodels.Definition, packName string, notFixedYet bool) (upserted bool) {
|
||||
for i, entry := range e.entries {
|
||||
if entry.def.DefinitionID == def.DefinitionID {
|
||||
e.entries[i].actuallyAffectedPackNames[packName] = true
|
||||
e.entries[i].actuallyAffectedPackNames[packName] = notFixedYet
|
||||
return true
|
||||
}
|
||||
}
|
||||
e.entries = append(e.entries, defPacks{
|
||||
def: def,
|
||||
actuallyAffectedPackNames: map[string]bool{packName: true},
|
||||
actuallyAffectedPackNames: map[string]bool{packName: notFixedYet},
|
||||
})
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type request struct {
|
||||
pack models.Package
|
||||
packName string
|
||||
versionRelease string
|
||||
NewVersionRelease string
|
||||
binaryPackNames []string
|
||||
isSrcPack bool
|
||||
}
|
||||
|
||||
type response struct {
|
||||
pack *models.Package
|
||||
defs []ovalmodels.Definition
|
||||
request request
|
||||
defs []ovalmodels.Definition
|
||||
}
|
||||
|
||||
// getDefsByPackNameViaHTTP fetches OVAL information via HTTP
|
||||
@@ -152,17 +95,32 @@ func getDefsByPackNameViaHTTP(r *models.ScanResult) (
|
||||
defer close(resChan)
|
||||
defer close(errChan)
|
||||
|
||||
names := []string{}
|
||||
go func() {
|
||||
for _, pack := range r.Packages {
|
||||
names = append(names, pack.Name)
|
||||
reqChan <- request{
|
||||
pack: pack,
|
||||
packName: pack.Name,
|
||||
versionRelease: pack.FormatVer(),
|
||||
NewVersionRelease: pack.FormatVer(),
|
||||
isSrcPack: false,
|
||||
}
|
||||
for _, pack := range r.SrcPackages {
|
||||
names = append(names, pack.Name)
|
||||
reqChan <- request{
|
||||
packName: pack.Name,
|
||||
binaryPackNames: pack.BinaryNames,
|
||||
versionRelease: pack.Version,
|
||||
isSrcPack: true,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}()
|
||||
|
||||
concurrency := 10
|
||||
tasks := util.GenWorkers(concurrency)
|
||||
for range r.Packages {
|
||||
for range names {
|
||||
tasks <- func() {
|
||||
select {
|
||||
case req := <-reqChan:
|
||||
@@ -171,13 +129,13 @@ func getDefsByPackNameViaHTTP(r *models.ScanResult) (
|
||||
"packs",
|
||||
r.Family,
|
||||
r.Release,
|
||||
req.pack.Name,
|
||||
req.packName,
|
||||
)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
} else {
|
||||
util.Log.Debugf("HTTP Request to %s", url)
|
||||
httpGet(url, &req.pack, resChan, errChan)
|
||||
httpGet(url, req, resChan, errChan)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,26 +143,21 @@ func getDefsByPackNameViaHTTP(r *models.ScanResult) (
|
||||
|
||||
timeout := time.After(2 * 60 * time.Second)
|
||||
var errs []error
|
||||
for range r.Packages {
|
||||
for range names {
|
||||
select {
|
||||
case res := <-resChan:
|
||||
for _, def := range res.defs {
|
||||
for _, p := range def.AffectedPacks {
|
||||
if res.pack.Name != p.Name {
|
||||
continue
|
||||
}
|
||||
affected, notFixedYet := isOvalDefAffected(def, r.Family, res.request)
|
||||
if !affected {
|
||||
continue
|
||||
}
|
||||
|
||||
if p.NotFixedYet {
|
||||
relatedDefs.upsert(def, p.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
if less, err := lessThan(r.Family, *res.pack, p); err != nil {
|
||||
util.Log.Debugf("Failed to parse versions: %s", err)
|
||||
util.Log.Debugf("%#v\n%#v", *res.pack, p)
|
||||
} else if less {
|
||||
relatedDefs.upsert(def, p.Name)
|
||||
if res.request.isSrcPack {
|
||||
for _, n := range res.request.binaryPackNames {
|
||||
relatedDefs.upsert(def, n, false)
|
||||
}
|
||||
} else {
|
||||
relatedDefs.upsert(def, res.request.packName, notFixedYet)
|
||||
}
|
||||
}
|
||||
case err := <-errChan:
|
||||
@@ -219,7 +172,7 @@ func getDefsByPackNameViaHTTP(r *models.ScanResult) (
|
||||
return
|
||||
}
|
||||
|
||||
func httpGet(url string, pack *models.Package, resChan chan<- response, errChan chan<- error) {
|
||||
func httpGet(url string, req request, resChan chan<- response, errChan chan<- error) {
|
||||
var body string
|
||||
var errs []error
|
||||
var resp *http.Response
|
||||
@@ -257,14 +210,12 @@ func httpGet(url string, pack *models.Package, resChan chan<- response, errChan
|
||||
return
|
||||
}
|
||||
resChan <- response{
|
||||
pack: pack,
|
||||
defs: defs,
|
||||
request: req,
|
||||
defs: defs,
|
||||
}
|
||||
}
|
||||
|
||||
func getDefsByPackNameFromOvalDB(family, osRelease string,
|
||||
installedPacks models.Packages) (relatedDefs ovalResult, err error) {
|
||||
|
||||
func getDefsByPackNameFromOvalDB(r *models.ScanResult) (relatedDefs ovalResult, err error) {
|
||||
ovallog.Initialize(config.Conf.LogDir)
|
||||
path := config.Conf.OvalDBURL
|
||||
if config.Conf.OvalDBType == "sqlite3" {
|
||||
@@ -273,48 +224,96 @@ func getDefsByPackNameFromOvalDB(family, osRelease string,
|
||||
util.Log.Debugf("Open oval-dictionary db (%s): %s", config.Conf.OvalDBType, path)
|
||||
|
||||
var ovaldb db.DB
|
||||
if ovaldb, err = db.NewDB(
|
||||
family,
|
||||
config.Conf.OvalDBType,
|
||||
path,
|
||||
config.Conf.DebugSQL,
|
||||
); err != nil {
|
||||
if ovaldb, err = db.NewDB(r.Family, config.Conf.OvalDBType,
|
||||
path, config.Conf.DebugSQL); err != nil {
|
||||
return
|
||||
}
|
||||
defer ovaldb.CloseDB()
|
||||
for _, installedPack := range installedPacks {
|
||||
definitions, err := ovaldb.GetByPackName(osRelease, installedPack.Name)
|
||||
|
||||
requests := []request{}
|
||||
for _, pack := range r.Packages {
|
||||
requests = append(requests, request{
|
||||
packName: pack.Name,
|
||||
versionRelease: pack.FormatVer(),
|
||||
NewVersionRelease: pack.FormatNewVer(),
|
||||
isSrcPack: false,
|
||||
})
|
||||
}
|
||||
for _, pack := range r.SrcPackages {
|
||||
requests = append(requests, request{
|
||||
packName: pack.Name,
|
||||
binaryPackNames: pack.BinaryNames,
|
||||
versionRelease: pack.Version,
|
||||
isSrcPack: true,
|
||||
})
|
||||
}
|
||||
|
||||
for _, req := range requests {
|
||||
definitions, err := ovaldb.GetByPackName(r.Release, req.packName)
|
||||
if err != nil {
|
||||
return relatedDefs, fmt.Errorf("Failed to get %s OVAL info by package name: %v", family, err)
|
||||
return relatedDefs, fmt.Errorf("Failed to get %s OVAL info by package name: %v", r.Family, err)
|
||||
}
|
||||
for _, def := range definitions {
|
||||
for _, ovalPack := range def.AffectedPacks {
|
||||
if installedPack.Name != ovalPack.Name {
|
||||
continue
|
||||
}
|
||||
affected, notFixedYet := isOvalDefAffected(def, r.Family, req)
|
||||
if !affected {
|
||||
continue
|
||||
}
|
||||
|
||||
if ovalPack.NotFixedYet {
|
||||
relatedDefs.upsert(def, installedPack.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
less, err := lessThan(family, installedPack, ovalPack)
|
||||
if err != nil {
|
||||
util.Log.Debugf("Failed to parse versions: %s", err)
|
||||
util.Log.Debugf("%#v\n%#v", installedPack, ovalPack)
|
||||
} else if less {
|
||||
relatedDefs.upsert(def, installedPack.Name)
|
||||
if req.isSrcPack {
|
||||
for _, n := range req.binaryPackNames {
|
||||
relatedDefs.upsert(def, n, false)
|
||||
}
|
||||
} else {
|
||||
relatedDefs.upsert(def, req.packName, notFixedYet)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func lessThan(family string, packA models.Package, packB ovalmodels.Package) (bool, error) {
|
||||
func isOvalDefAffected(def ovalmodels.Definition, family string, req request) (affected, notFixedYet bool) {
|
||||
for _, ovalPack := range def.AffectedPacks {
|
||||
if req.packName != ovalPack.Name {
|
||||
continue
|
||||
}
|
||||
|
||||
if ovalPack.NotFixedYet {
|
||||
return true, true
|
||||
}
|
||||
|
||||
less, err := lessThan(family, req.versionRelease, ovalPack)
|
||||
if err != nil {
|
||||
util.Log.Debugf("Failed to parse versions: %s, Ver: %#v, OVAL: %#v, DefID: %s",
|
||||
err, req.versionRelease, ovalPack, def.DefinitionID)
|
||||
return false, false
|
||||
}
|
||||
|
||||
if less {
|
||||
if req.isSrcPack {
|
||||
// Unable to judge whether fixed or not fixed of src package(Ubuntu, Debian)
|
||||
return true, false
|
||||
}
|
||||
if req.NewVersionRelease == "" {
|
||||
return true, true
|
||||
}
|
||||
|
||||
// compare version: newVer vs oval
|
||||
less, err := lessThan(family, req.NewVersionRelease, ovalPack)
|
||||
if err != nil {
|
||||
util.Log.Debugf("Failed to parse versions: %s, NewVer: %#v, OVAL: %#v, DefID: %s",
|
||||
err, req.NewVersionRelease, ovalPack, def.DefinitionID)
|
||||
return false, false
|
||||
}
|
||||
return true, less
|
||||
}
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func lessThan(family, versionRelease string, packB ovalmodels.Package) (bool, error) {
|
||||
switch family {
|
||||
case config.Debian, config.Ubuntu:
|
||||
vera, err := debver.NewVersion(packA.Version)
|
||||
vera, err := debver.NewVersion(versionRelease)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -324,7 +323,7 @@ func lessThan(family string, packA models.Package, packB ovalmodels.Package) (bo
|
||||
}
|
||||
return vera.LessThan(verb), nil
|
||||
case config.RedHat, config.CentOS, config.Oracle, config.SUSEEnterpriseServer:
|
||||
vera := rpmver.NewVersion(fmt.Sprintf("%s-%s", packA.Version, packA.Release))
|
||||
vera := rpmver.NewVersion(versionRelease)
|
||||
verb := rpmver.NewVersion(packB.Version)
|
||||
return vera.LessThan(verb), nil
|
||||
default:
|
||||
|
||||
@@ -11,11 +11,12 @@ import (
|
||||
|
||||
func TestUpsert(t *testing.T) {
|
||||
var tests = []struct {
|
||||
res ovalResult
|
||||
def ovalmodels.Definition
|
||||
packName string
|
||||
upserted bool
|
||||
out ovalResult
|
||||
res ovalResult
|
||||
def ovalmodels.Definition
|
||||
packName string
|
||||
notFixedYet bool
|
||||
upserted bool
|
||||
out ovalResult
|
||||
}{
|
||||
//insert
|
||||
{
|
||||
@@ -23,8 +24,9 @@ func TestUpsert(t *testing.T) {
|
||||
def: ovalmodels.Definition{
|
||||
DefinitionID: "1111",
|
||||
},
|
||||
packName: "pack1",
|
||||
upserted: false,
|
||||
packName: "pack1",
|
||||
notFixedYet: true,
|
||||
upserted: false,
|
||||
out: ovalResult{
|
||||
[]defPacks{
|
||||
{
|
||||
@@ -63,8 +65,9 @@ func TestUpsert(t *testing.T) {
|
||||
def: ovalmodels.Definition{
|
||||
DefinitionID: "1111",
|
||||
},
|
||||
packName: "pack2",
|
||||
upserted: true,
|
||||
packName: "pack2",
|
||||
notFixedYet: false,
|
||||
upserted: true,
|
||||
out: ovalResult{
|
||||
[]defPacks{
|
||||
{
|
||||
@@ -73,7 +76,7 @@ func TestUpsert(t *testing.T) {
|
||||
},
|
||||
actuallyAffectedPackNames: map[string]bool{
|
||||
"pack1": true,
|
||||
"pack2": true,
|
||||
"pack2": false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -89,7 +92,7 @@ func TestUpsert(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
upserted := tt.res.upsert(tt.def, tt.packName)
|
||||
upserted := tt.res.upsert(tt.def, tt.packName, tt.notFixedYet)
|
||||
if tt.upserted != upserted {
|
||||
t.Errorf("[%d]\nexpected: %t\n actual: %t\n", i, tt.upserted, upserted)
|
||||
}
|
||||
@@ -127,90 +130,6 @@ func TestDefpacksToPackStatuses(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
actuallyAffectedPackNames: map[string]bool{
|
||||
"a": true,
|
||||
"b": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
out: models.PackageStatuses{
|
||||
{
|
||||
Name: "a",
|
||||
NotFixedYet: true,
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
NotFixedYet: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// RedHat, Amazon, Debian
|
||||
{
|
||||
in: in{
|
||||
family: "redhat",
|
||||
packs: models.Packages{},
|
||||
dp: defPacks{
|
||||
def: ovalmodels.Definition{
|
||||
AffectedPacks: []ovalmodels.Package{
|
||||
{
|
||||
Name: "a",
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
},
|
||||
},
|
||||
},
|
||||
actuallyAffectedPackNames: map[string]bool{
|
||||
"a": true,
|
||||
"b": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
out: models.PackageStatuses{
|
||||
{
|
||||
Name: "a",
|
||||
NotFixedYet: false,
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
NotFixedYet: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// CentOS
|
||||
{
|
||||
in: in{
|
||||
family: "centos",
|
||||
packs: models.Packages{
|
||||
"a": {Version: "1.0.0"},
|
||||
"b": {
|
||||
Version: "1.0.0",
|
||||
NewVersion: "2.0.0",
|
||||
},
|
||||
"c": {
|
||||
Version: "1.0.0",
|
||||
NewVersion: "1.5.0",
|
||||
},
|
||||
},
|
||||
dp: defPacks{
|
||||
def: ovalmodels.Definition{
|
||||
AffectedPacks: []ovalmodels.Package{
|
||||
{
|
||||
Name: "a",
|
||||
Version: "1.0.1",
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
Version: "1.5.0",
|
||||
},
|
||||
{
|
||||
Name: "c",
|
||||
Version: "2.0.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
actuallyAffectedPackNames: map[string]bool{
|
||||
"a": true,
|
||||
"b": true,
|
||||
@@ -225,7 +144,7 @@ func TestDefpacksToPackStatuses(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
NotFixedYet: false,
|
||||
NotFixedYet: true,
|
||||
},
|
||||
{
|
||||
Name: "c",
|
||||
@@ -244,3 +163,171 @@ func TestDefpacksToPackStatuses(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsOvalDefAffected(t *testing.T) {
|
||||
type in struct {
|
||||
def ovalmodels.Definition
|
||||
family string
|
||||
req request
|
||||
}
|
||||
var tests = []struct {
|
||||
in in
|
||||
affected bool
|
||||
notFixedYet bool
|
||||
}{
|
||||
// 0. Ubuntu ovalpack.NotFixedYet == true
|
||||
{
|
||||
in: in{
|
||||
family: "ubuntu",
|
||||
def: ovalmodels.Definition{
|
||||
AffectedPacks: []ovalmodels.Package{
|
||||
{
|
||||
Name: "a",
|
||||
NotFixedYet: true,
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
NotFixedYet: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
req: request{
|
||||
packName: "b",
|
||||
},
|
||||
},
|
||||
affected: true,
|
||||
notFixedYet: true,
|
||||
},
|
||||
// 1. Ubuntu
|
||||
// ovalpack.NotFixedYet == false
|
||||
// req.isSrcPack == true
|
||||
// Version comparison
|
||||
// oval vs installed
|
||||
{
|
||||
in: in{
|
||||
family: "ubuntu",
|
||||
def: ovalmodels.Definition{
|
||||
AffectedPacks: []ovalmodels.Package{
|
||||
{
|
||||
Name: "a",
|
||||
NotFixedYet: false,
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
NotFixedYet: false,
|
||||
Version: "1.0.0-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
req: request{
|
||||
packName: "b",
|
||||
isSrcPack: true,
|
||||
versionRelease: "1.0.0-0",
|
||||
},
|
||||
},
|
||||
affected: true,
|
||||
notFixedYet: false,
|
||||
},
|
||||
// 2. Ubuntu
|
||||
// ovalpack.NotFixedYet == false
|
||||
// Version comparison not hit
|
||||
// oval vs installed
|
||||
{
|
||||
in: in{
|
||||
family: "ubuntu",
|
||||
def: ovalmodels.Definition{
|
||||
AffectedPacks: []ovalmodels.Package{
|
||||
{
|
||||
Name: "a",
|
||||
NotFixedYet: false,
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
NotFixedYet: false,
|
||||
Version: "1.0.0-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
req: request{
|
||||
packName: "b",
|
||||
versionRelease: "1.0.0-2",
|
||||
},
|
||||
},
|
||||
affected: false,
|
||||
notFixedYet: false,
|
||||
},
|
||||
// 3. Ubuntu
|
||||
// ovalpack.NotFixedYet == false
|
||||
// req.isSrcPack == false
|
||||
// Version comparison
|
||||
// oval vs NewVersion
|
||||
// oval.version < installed.newVersion
|
||||
{
|
||||
in: in{
|
||||
family: "ubuntu",
|
||||
def: ovalmodels.Definition{
|
||||
AffectedPacks: []ovalmodels.Package{
|
||||
{
|
||||
Name: "a",
|
||||
NotFixedYet: false,
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
NotFixedYet: false,
|
||||
Version: "1.0.0-3",
|
||||
},
|
||||
},
|
||||
},
|
||||
req: request{
|
||||
packName: "b",
|
||||
isSrcPack: false,
|
||||
versionRelease: "1.0.0-0",
|
||||
NewVersionRelease: "1.0.0-2",
|
||||
},
|
||||
},
|
||||
affected: true,
|
||||
notFixedYet: true,
|
||||
},
|
||||
// 4. Ubuntu
|
||||
// ovalpack.NotFixedYet == false
|
||||
// req.isSrcPack == false
|
||||
// Version comparison
|
||||
// oval vs NewVersion
|
||||
// oval.version < installed.newVersion
|
||||
{
|
||||
in: in{
|
||||
family: "ubuntu",
|
||||
def: ovalmodels.Definition{
|
||||
AffectedPacks: []ovalmodels.Package{
|
||||
{
|
||||
Name: "a",
|
||||
NotFixedYet: false,
|
||||
},
|
||||
{
|
||||
Name: "b",
|
||||
NotFixedYet: false,
|
||||
Version: "1.0.0-2",
|
||||
},
|
||||
},
|
||||
},
|
||||
req: request{
|
||||
packName: "b",
|
||||
isSrcPack: false,
|
||||
versionRelease: "1.0.0-0",
|
||||
NewVersionRelease: "1.0.0-3",
|
||||
},
|
||||
},
|
||||
affected: true,
|
||||
notFixedYet: false,
|
||||
},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
affected, notFixedYet := isOvalDefAffected(tt.in.def, tt.in.family, tt.in.req)
|
||||
if tt.affected != affected {
|
||||
t.Errorf("[%d] affected\nexpected: %v\n actual: %v\n", i, tt.affected, affected)
|
||||
}
|
||||
if tt.notFixedYet != notFixedYet {
|
||||
t.Errorf("[%d] notfixedyet\nexpected: %v\n actual: %v\n", i, tt.notFixedYet, notFixedYet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user