Skip to content

ROX-12226: Fetch RHELv2 unpatched CVE components resolution status and store them in scanner db #935

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion database/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ type RHELv2Package struct {
// Executables lists the executables determined from ExecutableToDependencies and
// LibraryToDependencies. This is only populated when both ExecutableToDependencies and
// LibraryToDependencies are empty.
Executables []*v1.Executable `json:"executables,omitempty"`
Executables []*v1.Executable `json:"executables,omitempty"`
ResolutionState string `json:"resolution_state"`
}

func (p *RHELv2Package) String() string {
Expand Down
12 changes: 12 additions & 0 deletions database/pgsql/migrations/00019_add_vuln_state_rhel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package migrations

import "github.com/remind101/migrate"

func init() {
RegisterMigration(migrate.Migration{
ID: 19,
Up: migrate.Queries([]string{
`ALTER TABLE vuln_v2 ADD COLUMN IF NOT EXISTS package_resolution_state TEXT NOT NULL DEFAULT ''`,
}),
})
}
7 changes: 4 additions & 3 deletions database/pgsql/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,15 +216,15 @@ const (
link, severity, cvss3, cvss2,
package_name, package_module, package_arch,
cpe,
fixed_in_version, arch_operation
fixed_in_version, arch_operation, package_resolution_state
) VALUES (
$1,
$2, $3, $4,
$5, $6,
$7, $8, $9, $10,
$11, $12, $13,
$14,
$15, $16
$15, $16, $17
)
ON CONFLICT (hash) DO NOTHING;`

Expand All @@ -251,7 +251,8 @@ const (
vuln.package_name,
vuln.package_arch,
vuln.fixed_in_version,
vuln.arch_operation
vuln.arch_operation,
vuln.package_resolution_state
FROM
vuln_v2 as vuln
LEFT JOIN vuln_description ON vuln.description_hash = vuln_description.hash
Expand Down
2 changes: 2 additions & 0 deletions database/pgsql/rhelv2_vulnerability.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func (pgSQL *pgSQL) insertRHELv2Vulnerability(vulnStatement, vulnDescriptionStat
pkg.Name, pkg.Module, pkg.Arch,
cpe,
pkgInfo.FixedInVersion, pkgInfo.ArchOperation,
pkg.ResolutionState,
)
if err != nil {
return errors.Wrapf(err, "inserting RHELv2 vulnerability %q for package %q with cpe %q into the DB", vuln.Name, pkg.Name, cpe)
Expand Down Expand Up @@ -268,6 +269,7 @@ func (pgSQL *pgSQL) getRHELv2Vulns(tx *sql.Tx, record *database.RHELv2Record) ([
&pkg.Arch,
&pkgInfo.FixedInVersion,
&pkgInfo.ArchOperation,
&pkg.ResolutionState,
)
if err != nil {
return nil, errors.Wrapf(err, "Scanning row for package: %s, module: %s, cpe: %s", record.Pkg.Name, record.Pkg.Module, record.CPE)
Expand Down
11 changes: 7 additions & 4 deletions database/pgsql/rhelv2_vulnerability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ func TestRHELv2Vulnerability(t *testing.T) {
ArchOperation: archop.OpEquals,
Packages: []*database.RHELv2Package{
{
Name: "package",
Arch: "x86_64",
Name: "package",
Arch: "x86_64",
ResolutionState: "Affected",
},
},
},
Expand All @@ -58,8 +59,9 @@ func TestRHELv2Vulnerability(t *testing.T) {
ArchOperation: archop.OpEquals,
Packages: []*database.RHELv2Package{
{
Name: "package",
Arch: "x86_64",
Name: "package",
Arch: "x86_64",
ResolutionState: "Affected",
},
},
},
Expand Down Expand Up @@ -97,6 +99,7 @@ func TestRHELv2Vulnerability(t *testing.T) {
assert.Equal(t, v2.CVSSv2, vuln.CVSSv2)
assert.Equal(t, v2.PackageInfos[0].Packages[0].Name, vuln.PackageInfos[0].Packages[0].Name)
assert.Equal(t, v2.PackageInfos[0].Packages[0].Arch, vuln.PackageInfos[0].Packages[0].Arch)
assert.Equal(t, v2.PackageInfos[0].Packages[0].ResolutionState, vuln.PackageInfos[0].Packages[0].ResolutionState)
assert.Equal(t, v2.PackageInfos[0].ArchOperation, vuln.PackageInfos[0].ArchOperation)
assert.Equal(t, v2.PackageInfos[0].FixedInVersion, vuln.PackageInfos[0].FixedInVersion)

Expand Down
4 changes: 2 additions & 2 deletions e2etests/testcase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3513,7 +3513,7 @@ Bug Fix(es) and Enhancement(s):
FixedBy: "0:6.0.7-1.el8_6",
},
},
FixedBy: "6.0.8-1.el8_6",
FixedBy: "6.0.9-1.el8_6",
AddedBy: "sha256:16e1dc59de605089610e3be2c77f3cde5eed99b523a0d7a3e3a2f65fa7c60723",
},
{
Expand Down Expand Up @@ -3552,7 +3552,7 @@ Bug Fix(es) and Enhancement(s):
FixedBy: "0:6.0.7-1.el8_6",
},
},
FixedBy: "6.0.8-1.el8_6",
FixedBy: "6.0.9-1.el8_6",
AddedBy: "sha256:16e1dc59de605089610e3be2c77f3cde5eed99b523a0d7a3e3a2f65fa7c60723",
},
},
Expand Down
37 changes: 36 additions & 1 deletion pkg/rhelv2/ovalutil/rpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package ovalutil

import (
"regexp"
"strings"

"github.com/pkg/errors"
"github.com/quay/goval-parser/oval"
Expand Down Expand Up @@ -65,8 +66,11 @@ func RPMDefsToVulns(root *oval.Root, protoVuln ProtoVulnFunc) ([]*database.RHELv
if vuln == nil {
continue
}
// recursively collect criterions for this definition

// parse unpatched CVE component resolution for each def
componentResolutions := ParseUnpatchedCVEComponents(def)

// recursively collect criterions for this definition
cris := cris[:0]
walkCriterion("", &def.Criteria, &cris)
// unpack criterions into vulnerabilities
Expand Down Expand Up @@ -137,6 +141,10 @@ func RPMDefsToVulns(root *oval.Root, protoVuln ProtoVulnFunc) ([]*database.RHELv
pkg.Arch = state.Arch.Body
}

if val, ok := componentResolutions[object.Name]; ok {
pkg.ResolutionState = val
}

pkgInfo.Packages = append(pkgInfo.Packages, pkg)

vuln.PackageInfos = append(vuln.PackageInfos, pkgInfo)
Expand Down Expand Up @@ -223,3 +231,30 @@ func GetDefinitionType(def oval.Definition) (string, error) {
}
return match[1], nil
}

// ParseUnpatchedCVEComponents parse components and resolution states of these components in an OVAL definition
func ParseUnpatchedCVEComponents(def oval.Definition) map[string]string {
resolutions := def.Advisory.Affected.Resolutions
if len(resolutions) == 0 {
return nil
}
result := make(map[string]string)

for _, resolution := range resolutions {
state := resolution.State
components := resolution.Components

for _, component := range components {
stringSlice := strings.Split(component, "/")
var componentName string
if len(stringSlice) > 1 {
componentName = stringSlice[len(stringSlice)-1]
} else {
componentName = stringSlice[0]
}
result[componentName] = state
}
}

return result
}
32 changes: 32 additions & 0 deletions pkg/rhelv2/ovalutil/rpm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
package ovalutil

import (
"encoding/xml"
"os"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/quay/goval-parser/oval"
)

Expand Down Expand Up @@ -76,3 +79,32 @@ func TestGetDefinitionType(t *testing.T) {
}
}
}

func TestParseUnpatchedCVEComponents(t *testing.T) {
f, err := os.Open("../../../testdata/cve/RHEL-8-including-unpatched-test.xml")
if err != nil {
t.Fatal(err)
}
defer f.Close()

var root oval.Root
if err := xml.NewDecoder(f).Decode(&root); err != nil {
t.Fatal(err)
}

definitions := root.Definitions

arr := definitions.Definitions
m := len(arr)
if !cmp.Equal(m, 3) {
t.Errorf("Definition list length is incorrect, current definition list size is: %d", m)
}
exampleSize := [3]int{1, 9, 1}
for i := 0; i < m; i++ {
componentMap := ParseUnpatchedCVEComponents(arr[i])
if !cmp.Equal(exampleSize[i], len(componentMap)) {
t.Errorf("Parsed CVE component map size is incorrect")
}
}

}
Loading