feat(fedora): support fedora (#1367)

* feat(fedora): support fedora

* fix(fedora): fix modular package scan

* fix(fedora): check needs-restarting, oval arch, add source link

Co-authored-by: MaineK00n <mainek00n.1229@gmail.com>
This commit is contained in:
maito1201
2022-02-09 09:30:44 +09:00
committed by GitHub
parent 2923cbc645
commit 1cfe155a3a
17 changed files with 454 additions and 72 deletions

View File

@@ -15,7 +15,7 @@ import (
ovalmodels "github.com/vulsio/goval-dictionary/models"
)
// RedHatBase is the base struct for RedHat, CentOS, Alma and Rocky
// RedHatBase is the base struct for RedHat, CentOS, Alma, Rocky and Fedora
type RedHatBase struct {
Base
}
@@ -57,6 +57,15 @@ func (o RedHatBase) FillWithOval(r *models.ScanResult) (nCVEs int, err error) {
vuln.CveContents[models.RedHat][i] = cont
}
}
case models.Fedora:
for _, d := range vuln.DistroAdvisories {
if conts, ok := vuln.CveContents[models.Fedora]; ok {
for i, cont := range conts {
cont.SourceLink = "https://bodhi.fedoraproject.org/updates/" + d.AdvisoryID
vuln.CveContents[models.Fedora][i] = cont
}
}
}
case models.Oracle:
if conts, ok := vuln.CveContents[models.Oracle]; ok {
for i, cont := range conts {
@@ -390,3 +399,21 @@ func NewRocky(cnf config.VulnDictInterface) Rocky {
},
}
}
// Fedora is the interface for RedhatBase OVAL
type Fedora struct {
// Base
RedHatBase
}
// NewFedora creates OVAL client for Fedora Linux
func NewFedora(cnf config.VulnDictInterface) Fedora {
return Fedora{
RedHatBase{
Base{
family: constant.Fedora,
Cnf: cnf,
},
},
}
}

View File

@@ -5,6 +5,7 @@ package oval
import (
"encoding/json"
"fmt"
"net/http"
"regexp"
"sort"
@@ -308,6 +309,8 @@ func getDefsByPackNameFromOvalDB(driver db.DB, r *models.ScanResult) (relatedDef
return
}
var modularVersionPattern = regexp.MustCompile(`.+\.module(?:\+el|_f)\d{1,2}.*`)
func isOvalDefAffected(def ovalmodels.Definition, req request, family string, running models.Kernel, enabledMods []string) (affected, notFixedYet bool, fixedIn string, err error) {
for _, ovalPack := range def.AffectedPacks {
if req.packName != ovalPack.Name {
@@ -315,9 +318,9 @@ func isOvalDefAffected(def ovalmodels.Definition, req request, family string, ru
}
switch family {
case constant.Oracle, constant.Amazon:
case constant.Oracle, constant.Amazon, constant.Fedora:
if ovalPack.Arch == "" {
logging.Log.Infof("Arch is needed to detect Vulns for Amazon and Oracle Linux, but empty. You need refresh OVAL maybe. oval: %#v, defID: %s", ovalPack, def.DefinitionID)
logging.Log.Infof("Arch is needed to detect Vulns for Amazon Linux, Oracle Linux and Fedora, but empty. You need refresh OVAL maybe. oval: %#v, defID: %s", ovalPack, def.DefinitionID)
continue
}
}
@@ -331,10 +334,24 @@ func isOvalDefAffected(def ovalmodels.Definition, req request, family string, ru
continue
}
// There is a modular package and a non-modular package with the same name. (e.g. fedora 35 community-mysql)
if ovalPack.ModularityLabel == "" && modularVersionPattern.MatchString(req.versionRelease) {
continue
} else if ovalPack.ModularityLabel != "" && !modularVersionPattern.MatchString(req.versionRelease) {
continue
}
isModularityLabelEmptyOrSame := false
if ovalPack.ModularityLabel != "" {
// expect ovalPack.ModularityLabel e.g. RedHat: nginx:1.16, Fedora: mysql:8.0:3520211031142409:f27b74a8
ss := strings.Split(ovalPack.ModularityLabel, ":")
if len(ss) < 2 {
logging.Log.Warnf("Invalid modularitylabel format in oval package. Maybe it is necessary to fix modularitylabel of goval-dictionary. expected: ${name}:${stream}(:${version}:${context}:${arch}), actual: %s", ovalPack.ModularityLabel)
continue
}
modularityNameStreamLabel := fmt.Sprintf("%s:%s", ss[0], ss[1])
for _, mod := range enabledMods {
if mod == ovalPack.ModularityLabel {
if mod == modularityNameStreamLabel {
isModularityLabelEmptyOrSame = true
break
}
@@ -348,7 +365,7 @@ func isOvalDefAffected(def ovalmodels.Definition, req request, family string, ru
if running.Release != "" {
switch family {
case constant.RedHat, constant.CentOS, constant.Alma, constant.Rocky, constant.Oracle:
case constant.RedHat, constant.CentOS, constant.Alma, constant.Rocky, constant.Oracle, constant.Fedora:
// For kernel related packages, ignore OVAL information with different major versions
if _, ok := kernelRelatedPackNames[ovalPack.Name]; ok {
if util.Major(ovalPack.Version) != util.Major(running.Release) {
@@ -378,12 +395,13 @@ func isOvalDefAffected(def ovalmodels.Definition, req request, family string, ru
// If the version of installed is less than in OVAL
switch family {
case constant.RedHat,
constant.Fedora,
constant.Amazon,
constant.Oracle,
constant.SUSEEnterpriseServer,
constant.Debian,
constant.Ubuntu,
constant.Raspbian,
constant.Oracle:
constant.Ubuntu:
// Use fixed state in OVAL for these distros.
return true, false, ovalPack.Version, nil
}
@@ -440,7 +458,8 @@ func lessThan(family, newVer string, packInOVAL ovalmodels.Package) (bool, error
case constant.Oracle,
constant.SUSEEnterpriseServer,
constant.Amazon:
constant.Amazon,
constant.Fedora:
vera := rpmver.NewVersion(newVer)
verb := rpmver.NewVersion(packInOVAL.Version)
return vera.LessThan(verb), nil
@@ -488,6 +507,8 @@ func NewOVALClient(family string, cnf config.GovalDictConf) (Client, error) {
return NewAlpine(&cnf), nil
case constant.Amazon:
return NewAmazon(&cnf), nil
case constant.Fedora:
return NewFedora(&cnf), nil
case constant.FreeBSD, constant.Windows:
return nil, nil
case constant.ServerTypePseudo:
@@ -510,6 +531,8 @@ func GetFamilyInOval(familyInScanResult string) (string, error) {
return constant.Ubuntu, nil
case constant.RedHat, constant.CentOS, constant.Alma, constant.Rocky:
return constant.RedHat, nil
case constant.Fedora:
return constant.Fedora, nil
case constant.Oracle:
return constant.Oracle, nil
case constant.SUSEEnterpriseServer:

View File

@@ -1621,6 +1621,88 @@ func TestIsOvalDefAffected(t *testing.T) {
affected: false,
notFixedYet: false,
},
// dnf module 4 (long modularitylabel)
{
in: in{
family: constant.Fedora,
def: ovalmodels.Definition{
AffectedPacks: []ovalmodels.Package{
{
Name: "community-mysql",
Version: "0:8.0.27-1.module_f35+13269+c9322734",
Arch: "x86_64",
NotFixedYet: false,
ModularityLabel: "mysql:8.0:3520211031142409:f27b74a8",
},
},
},
req: request{
packName: "community-mysql",
arch: "x86_64",
versionRelease: "8.0.26-1.module_f35+12627+b26747dd",
},
mods: []string{
"mysql:8.0",
},
},
affected: true,
notFixedYet: false,
fixedIn: "0:8.0.27-1.module_f35+13269+c9322734",
},
// dnf module 5 (req is non-modular package, oval is modular package)
{
in: in{
family: constant.Fedora,
def: ovalmodels.Definition{
AffectedPacks: []ovalmodels.Package{
{
Name: "community-mysql",
Version: "0:8.0.27-1.module_f35+13269+c9322734",
Arch: "x86_64",
NotFixedYet: false,
ModularityLabel: "mysql:8.0:3520211031142409:f27b74a8",
},
},
},
req: request{
packName: "community-mysql",
arch: "x86_64",
versionRelease: "8.0.26-1.fc35",
},
mods: []string{
"mysql:8.0",
},
},
affected: false,
notFixedYet: false,
},
// dnf module 6 (req is modular package, oval is non-modular package)
{
in: in{
family: constant.Fedora,
def: ovalmodels.Definition{
AffectedPacks: []ovalmodels.Package{
{
Name: "community-mysql",
Version: "0:8.0.27-1.fc35",
Arch: "x86_64",
NotFixedYet: false,
ModularityLabel: "",
},
},
},
req: request{
packName: "community-mysql",
arch: "x86_64",
versionRelease: "8.0.26-1.module_f35+12627+b26747dd",
},
mods: []string{
"mysql:8.0",
},
},
affected: false,
notFixedYet: false,
},
// .ksplice1.
{
in: in{