* Support Alpine Linux #194 * Fix testcase * Fix README * Fix dep files * Fix changelog * Bump up version
This commit is contained in:
82
oval/alpine.go
Normal file
82
oval/alpine.go
Normal file
@@ -0,0 +1,82 @@
|
||||
/* Vuls - Vulnerability Scanner
|
||||
Copyright (C) 2016 Future Architect, Inc. Japan.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package oval
|
||||
|
||||
import (
|
||||
"github.com/future-architect/vuls/config"
|
||||
"github.com/future-architect/vuls/models"
|
||||
"github.com/future-architect/vuls/util"
|
||||
ovalmodels "github.com/kotakanbe/goval-dictionary/models"
|
||||
)
|
||||
|
||||
// Alpine is the struct of Alpine Linux
|
||||
type Alpine struct {
|
||||
Base
|
||||
}
|
||||
|
||||
// NewAlpine creates OVAL client for SUSE
|
||||
func NewAlpine() Alpine {
|
||||
return Alpine{
|
||||
Base{
|
||||
family: config.Alpine,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// FillWithOval returns scan result after updating CVE info by OVAL
|
||||
func (o Alpine) FillWithOval(r *models.ScanResult) (err error) {
|
||||
var relatedDefs ovalResult
|
||||
if o.isFetchViaHTTP() {
|
||||
if relatedDefs, err = getDefsByPackNameViaHTTP(r); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if relatedDefs, err = getDefsByPackNameFromOvalDB(r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, defPacks := range relatedDefs.entries {
|
||||
o.update(r, defPacks)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o Alpine) update(r *models.ScanResult, defPacks defPacks) {
|
||||
ovalContent := *o.convertToModel(&defPacks.def)
|
||||
cveID := defPacks.def.Advisory.Cves[0].CveID
|
||||
vinfo, ok := r.ScannedCves[cveID]
|
||||
if !ok {
|
||||
util.Log.Debugf("%s is newly detected by OVAL", cveID)
|
||||
vinfo = models.VulnInfo{
|
||||
CveID: cveID,
|
||||
Confidence: models.OvalMatch,
|
||||
CveContents: models.NewCveContents(ovalContent),
|
||||
}
|
||||
}
|
||||
|
||||
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family)
|
||||
vinfo.AffectedPackages.Sort()
|
||||
r.ScannedCves[cveID] = vinfo
|
||||
}
|
||||
|
||||
func (o Alpine) convertToModel(def *ovalmodels.Definition) *models.CveContent {
|
||||
return &models.CveContent{
|
||||
CveID: def.Advisory.Cves[0].CveID,
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ func (o DebianBase) update(r *models.ScanResult, defPacks defPacks) {
|
||||
defPacks.actuallyAffectedPackNames[pack.Name] = notFixedYet
|
||||
}
|
||||
|
||||
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family, r.Packages)
|
||||
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family)
|
||||
vinfo.AffectedPackages.Sort()
|
||||
r.ScannedCves[defPacks.def.Debian.CveID] = vinfo
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/future-architect/vuls/config"
|
||||
@@ -132,15 +131,14 @@ func (b Base) CheckIfOvalFresh(osFamily, release string) (ok bool, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
major := strings.Split(release, ".")[0]
|
||||
since := time.Now()
|
||||
since = since.AddDate(0, 0, -3)
|
||||
if lastModified.Before(since) {
|
||||
util.Log.Warnf("OVAL for %s %s is old, last modified is %s. It's recommended to update OVAL to improve scanning accuracy. How to update OVAL database, see https://github.com/kotakanbe/goval-dictionary#usage",
|
||||
osFamily, major, lastModified)
|
||||
osFamily, release, lastModified)
|
||||
return false, nil
|
||||
}
|
||||
util.Log.Infof("OVAL is fresh: %s %s ", osFamily, major)
|
||||
util.Log.Infof("OVAL is fresh: %s %s ", osFamily, release)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ func (o RedHatBase) update(r *models.ScanResult, defPacks defPacks) {
|
||||
notFixedYet, _ := defPacks.actuallyAffectedPackNames[pack.Name]
|
||||
defPacks.actuallyAffectedPackNames[pack.Name] = notFixedYet
|
||||
}
|
||||
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family, r.Packages)
|
||||
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family)
|
||||
vinfo.AffectedPackages.Sort()
|
||||
r.ScannedCves[cve.CveID] = vinfo
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ func (o SUSE) update(r *models.ScanResult, defPacks defPacks) {
|
||||
notFixedYet, _ := defPacks.actuallyAffectedPackNames[pack.Name]
|
||||
defPacks.actuallyAffectedPackNames[pack.Name] = notFixedYet
|
||||
}
|
||||
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family, r.Packages)
|
||||
vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family)
|
||||
vinfo.AffectedPackages.Sort()
|
||||
r.ScannedCves[defPacks.def.Title] = vinfo
|
||||
}
|
||||
|
||||
15
oval/util.go
15
oval/util.go
@@ -48,7 +48,7 @@ type defPacks struct {
|
||||
actuallyAffectedPackNames map[string]bool
|
||||
}
|
||||
|
||||
func (e defPacks) toPackStatuses(family string, packs models.Packages) (ps models.PackageStatuses) {
|
||||
func (e defPacks) toPackStatuses(family string) (ps models.PackageStatuses) {
|
||||
for name, notFixedYet := range e.actuallyAffectedPackNames {
|
||||
ps = append(ps, models.PackageStatus{
|
||||
Name: name,
|
||||
@@ -59,10 +59,13 @@ func (e defPacks) toPackStatuses(family string, packs models.Packages) (ps model
|
||||
}
|
||||
|
||||
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] = notFixedYet
|
||||
return true
|
||||
// alpine's entry is empty since Alpine secdb is not OVAL format
|
||||
if def.DefinitionID != "" {
|
||||
for i, entry := range e.entries {
|
||||
if entry.def.DefinitionID == def.DefinitionID {
|
||||
e.entries[i].actuallyAffectedPackNames[packName] = notFixedYet
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
e.entries = append(e.entries, defPacks{
|
||||
@@ -345,7 +348,7 @@ func lessThan(family, versionRelease string, packB ovalmodels.Package) (bool, er
|
||||
return false, err
|
||||
}
|
||||
return vera.LessThan(verb), nil
|
||||
case config.Oracle, config.SUSEEnterpriseServer:
|
||||
case config.Oracle, config.SUSEEnterpriseServer, config.Alpine:
|
||||
vera := rpmver.NewVersion(versionRelease)
|
||||
verb := rpmver.NewVersion(packB.Version)
|
||||
return vera.LessThan(verb), nil
|
||||
|
||||
@@ -117,7 +117,6 @@ func TestDefpacksToPackStatuses(t *testing.T) {
|
||||
{
|
||||
in: in{
|
||||
family: "ubuntu",
|
||||
packs: models.Packages{},
|
||||
dp: defPacks{
|
||||
def: ovalmodels.Definition{
|
||||
AffectedPacks: []ovalmodels.Package{
|
||||
@@ -155,7 +154,7 @@ func TestDefpacksToPackStatuses(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
actual := tt.in.dp.toPackStatuses(tt.in.family, tt.in.packs)
|
||||
actual := tt.in.dp.toPackStatuses(tt.in.family)
|
||||
sort.Slice(actual, func(i, j int) bool {
|
||||
return actual[i].Name < actual[j].Name
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user