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:
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
37
oval/util.go
37
oval/util.go
@@ -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:
|
||||
|
||||
@@ -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{
|
||||
|
||||
Reference in New Issue
Block a user