Check existence and last modified time of local OVAL database when reporting
This commit is contained in:
@@ -25,7 +25,7 @@ func (o DebianBase) fillFromOvalDB(r *models.ScanResult) error {
|
||||
} else {
|
||||
ovalconf.Conf.DBPath = config.Conf.OvalDBURL
|
||||
}
|
||||
util.Log.Infof("open oval-dictionary db (%s): %s",
|
||||
util.Log.Infof("Open oval-dictionary db (%s): %s",
|
||||
ovalconf.Conf.DBType, ovalconf.Conf.DBPath)
|
||||
|
||||
ovallog.Initialize(config.Conf.LogDir)
|
||||
@@ -68,7 +68,7 @@ func (o DebianBase) update(r *models.ScanResult, definition *ovalmodels.Definiti
|
||||
ovalContent.Type = models.NewCveContentType(r.Family)
|
||||
vinfo, ok := r.ScannedCves[definition.Debian.CveID]
|
||||
if !ok {
|
||||
util.Log.Infof("%s is newly detected by OVAL", definition.Debian.CveID)
|
||||
util.Log.Debugf("%s is newly detected by OVAL", definition.Debian.CveID)
|
||||
vinfo = models.VulnInfo{
|
||||
CveID: definition.Debian.CveID,
|
||||
Confidence: models.OvalMatch,
|
||||
@@ -79,9 +79,9 @@ func (o DebianBase) update(r *models.ScanResult, definition *ovalmodels.Definiti
|
||||
cveContents := vinfo.CveContents
|
||||
ctype := models.NewCveContentType(r.Family)
|
||||
if _, ok := vinfo.CveContents[ctype]; ok {
|
||||
util.Log.Infof("%s will be updated by OVAL", definition.Debian.CveID)
|
||||
util.Log.Debugf("%s will be updated by OVAL", definition.Debian.CveID)
|
||||
} else {
|
||||
util.Log.Infof("%s is also detected by OVAL", definition.Debian.CveID)
|
||||
util.Log.Debugf("%s is also detected by OVAL", definition.Debian.CveID)
|
||||
cveContents = models.CveContents{}
|
||||
}
|
||||
if vinfo.Confidence.Score < models.OvalMatch.Score {
|
||||
|
||||
88
oval/oval.go
88
oval/oval.go
@@ -11,21 +11,27 @@ import (
|
||||
"github.com/future-architect/vuls/models"
|
||||
"github.com/future-architect/vuls/util"
|
||||
ver "github.com/knqyf263/go-deb-version"
|
||||
"github.com/kotakanbe/goval-dictionary/db"
|
||||
ovallog "github.com/kotakanbe/goval-dictionary/log"
|
||||
ovalmodels "github.com/kotakanbe/goval-dictionary/models"
|
||||
"github.com/parnurzeal/gorequest"
|
||||
)
|
||||
|
||||
// Client is the interface of OVAL client.
|
||||
type Client interface {
|
||||
CheckHealth() error
|
||||
CheckHTTPHealth() error
|
||||
FillWithOval(r *models.ScanResult) error
|
||||
|
||||
// CheckIfOvalFetched checks if oval entries are in DB by family, release.
|
||||
CheckIfOvalFetched(string, string) (bool, error)
|
||||
CheckIfOvalFresh(string, string) (bool, error)
|
||||
}
|
||||
|
||||
// Base is a base struct
|
||||
type Base struct{}
|
||||
|
||||
// CheckHealth do health check
|
||||
func (b Base) CheckHealth() error {
|
||||
// CheckHTTPHealth do health check
|
||||
func (b Base) CheckHTTPHealth() error {
|
||||
if !b.isFetchViaHTTP() {
|
||||
return nil
|
||||
}
|
||||
@@ -43,6 +49,82 @@ func (b Base) CheckHealth() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckIfOvalFetched checks if oval entries are in DB by family, release.
|
||||
func (b Base) CheckIfOvalFetched(osFamily, release string) (fetched bool, err error) {
|
||||
ovallog.Initialize(config.Conf.LogDir)
|
||||
if !b.isFetchViaHTTP() {
|
||||
var ovaldb db.DB
|
||||
if ovaldb, err = db.NewDB(
|
||||
osFamily,
|
||||
config.Conf.OvalDBType,
|
||||
config.Conf.OvalDBPath,
|
||||
config.Conf.DebugSQL,
|
||||
); err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer ovaldb.CloseDB()
|
||||
count, err := ovaldb.CountDefs(osFamily, release)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Failed to count OVAL defs: %s, %s, %v",
|
||||
osFamily, release, err)
|
||||
}
|
||||
return 0 < count, nil
|
||||
}
|
||||
|
||||
url, _ := util.URLPathJoin(config.Conf.OvalDBURL, "count", osFamily, release)
|
||||
resp, body, errs := gorequest.New().Get(url).End()
|
||||
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
|
||||
return false, fmt.Errorf("HTTP GET error: %v, url: %s, resp: %v",
|
||||
errs, url, resp)
|
||||
}
|
||||
count := 0
|
||||
if err := json.Unmarshal([]byte(body), &count); err != nil {
|
||||
return false, fmt.Errorf("Failed to Unmarshall. body: %s, err: %s",
|
||||
body, err)
|
||||
}
|
||||
return 0 < count, nil
|
||||
}
|
||||
|
||||
// CheckIfOvalFresh checks if oval entries are fresh enough
|
||||
func (b Base) CheckIfOvalFresh(osFamily, release string) (ok bool, err error) {
|
||||
ovallog.Initialize(config.Conf.LogDir)
|
||||
var lastModified time.Time
|
||||
if !b.isFetchViaHTTP() {
|
||||
var ovaldb db.DB
|
||||
if ovaldb, err = db.NewDB(
|
||||
osFamily,
|
||||
config.Conf.OvalDBType,
|
||||
config.Conf.OvalDBPath,
|
||||
config.Conf.DebugSQL,
|
||||
); err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer ovaldb.CloseDB()
|
||||
lastModified = ovaldb.GetLastModified(osFamily, release)
|
||||
} else {
|
||||
url, _ := util.URLPathJoin(config.Conf.OvalDBURL, "lastmodified", osFamily, release)
|
||||
resp, body, errs := gorequest.New().Get(url).End()
|
||||
if 0 < len(errs) || resp == nil || resp.StatusCode != 200 {
|
||||
return false, fmt.Errorf("HTTP GET error: %v, url: %s, resp: %v",
|
||||
errs, url, resp)
|
||||
}
|
||||
|
||||
if err := json.Unmarshal([]byte(body), &lastModified); err != nil {
|
||||
return false, fmt.Errorf("Failed to Unmarshall. body: %s, err: %s",
|
||||
body, err)
|
||||
}
|
||||
}
|
||||
|
||||
since := time.Now()
|
||||
since = since.AddDate(0, 0, -3)
|
||||
if lastModified.Before(since) {
|
||||
util.Log.Warnf("%s-%s OVAL is old, last modified is %s. It's recommended to update OVAL to improve scanning accuracy. To update OVAL database, see https://github.com/kotakanbe/goval-dictionary#usage",
|
||||
osFamily, release, lastModified)
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (b Base) isFetchViaHTTP() bool {
|
||||
// Default value of OvalDBType is sqlite3
|
||||
if config.Conf.OvalDBURL != "" && config.Conf.OvalDBType == "sqlite3" {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/future-architect/vuls/config"
|
||||
"github.com/future-architect/vuls/models"
|
||||
"github.com/future-architect/vuls/util"
|
||||
ver "github.com/knqyf263/go-deb-version"
|
||||
ver "github.com/knqyf263/go-rpm-version"
|
||||
ovalconf "github.com/kotakanbe/goval-dictionary/config"
|
||||
db "github.com/kotakanbe/goval-dictionary/db"
|
||||
ovallog "github.com/kotakanbe/goval-dictionary/log"
|
||||
@@ -63,7 +63,7 @@ func (o RedHatBase) getDefsByPackNameFromOvalDB(osRelease string,
|
||||
} else {
|
||||
ovalconf.Conf.DBPath = config.Conf.OvalDBURL
|
||||
}
|
||||
util.Log.Infof("open oval-dictionary db (%s): %s",
|
||||
util.Log.Infof("Open oval-dictionary db (%s): %s",
|
||||
ovalconf.Conf.DBType, ovalconf.Conf.DBPath)
|
||||
|
||||
ovallog.Initialize(config.Conf.LogDir)
|
||||
@@ -84,9 +84,9 @@ func (o RedHatBase) getDefsByPackNameFromOvalDB(osRelease string,
|
||||
return nil, fmt.Errorf("Failed to get RedHat OVAL info by package name: %v", err)
|
||||
}
|
||||
for _, def := range definitions {
|
||||
current, _ := ver.NewVersion(fmt.Sprintf("%s-%s", pack.Version, pack.Release))
|
||||
current := ver.NewVersion(fmt.Sprintf("%s-%s", pack.Version, pack.Release))
|
||||
for _, p := range def.AffectedPacks {
|
||||
affected, _ := ver.NewVersion(p.Version)
|
||||
affected := ver.NewVersion(p.Version)
|
||||
if pack.Name != p.Name || !current.LessThan(affected) {
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user