Skip to content

Commit

Permalink
add release ID to OS models
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Goodman <[email protected]>
  • Loading branch information
wagoodman committed Dec 22, 2024
1 parent 07e7a21 commit b0f77a3
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 25 deletions.
44 changes: 20 additions & 24 deletions pkg/process/v6/transformers/os/transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,8 @@ func getAffectedPackages(vuln unmarshal.OSVulnerability) []grypeDB.AffectedPacka
}

aph := grypeDB.AffectedPackageHandle{
OperatingSystem: getOperatingSystem(group.osName, group.osVersion),
OperatingSystem: getOperatingSystem(group.osName, group.id, group.osVersion),
Package: getPackage(group),

BlobValue: &grypeDB.AffectedPackageBlob{
CVEs: getAliases(vuln),
Qualifiers: qualifiers,
Expand Down Expand Up @@ -170,14 +169,15 @@ func deriveConstraintFromFix(fixVersion, vulnerabilityID string) string {

type groupIndex struct {
name string
id string
osName string
osVersion string
module string
}

func groupFixedIns(vuln unmarshal.OSVulnerability) map[groupIndex][]unmarshal.OSFixedIn {
grouped := make(map[groupIndex][]unmarshal.OSFixedIn)
osName, osVersion := getOSInfo(vuln.Vulnerability.NamespaceName)
osName, osID, osVersion := getOSInfo(vuln.Vulnerability.NamespaceName)

for _, fixedIn := range vuln.Vulnerability.FixedIn {
var mod string
Expand All @@ -186,6 +186,7 @@ func groupFixedIns(vuln unmarshal.OSVulnerability) map[groupIndex][]unmarshal.OS
}
g := groupIndex{
name: fixedIn.Name,
id: osID,
osName: osName,
osVersion: osVersion,
module: mod,
Expand Down Expand Up @@ -218,42 +219,36 @@ func getPackage(group groupIndex) *grypeDB.Package {
}
}

func getOSInfo(group string) (string, string) {
// derived from enterprise feed groups, expected to be of the form {distroID}:{version}
func getOSInfo(group string) (string, string, string) {
// derived from enterprise feed groups, expected to be of the form {distro release ID}:{version}
feedGroupComponents := strings.Split(group, ":")

return normalizeOsName(feedGroupComponents[0], feedGroupComponents[1]), feedGroupComponents[1]
}

// add new fields to OS schema: release-id, release-version-id
// update vunnel providers to emit these fields (they are based on the /etc/os-release values)
// update this code to STOP parsing namespace and start using those new fields
// now when a user searches by OS (from the /etc/os-release values) they will get the correct results
// what's missing:
// - when to search by major version vs major.minor version...
// - edge/rolling behavior
// - aliases: user has centos 8, but the feed has rhel 8, use that instead
func normalizeOsName(name, version string) string {
if strings.ToLower(name) == "mariner" {
id := feedGroupComponents[0]
version := feedGroupComponents[1]
if strings.ToLower(id) == "mariner" {
verFields := strings.Split(version, ".")
majorVersionStr := verFields[0]
majorVer, err := strconv.Atoi(majorVersionStr)
if err == nil {
if majorVer >= 3 {
name = string(distro.Azure)
id = string(distro.Azure)
}
}
}
d, ok := distro.IDMapping[name]

return normalizeOsName(id), id, version
}

func normalizeOsName(id string) string {
d, ok := distro.IDMapping[id]
if !ok {
log.WithFields("distro", name).Warn("unknown distro name")
log.WithFields("distro", id).Warn("unknown distro name")

return name
return id
}

distroName := d.String()

// TODO: this doesn't seem right
switch d {
case distro.OracleLinux:
distroName = "oracle"
Expand All @@ -263,7 +258,7 @@ func normalizeOsName(name, version string) string {
return distroName
}

func getOperatingSystem(osName, osVersion string) *grypeDB.OperatingSystem {
func getOperatingSystem(osName, osID, osVersion string) *grypeDB.OperatingSystem {
if osName == "" || osVersion == "" {
return nil
}
Expand All @@ -284,6 +279,7 @@ func getOperatingSystem(osName, osVersion string) *grypeDB.OperatingSystem {

return &grypeDB.OperatingSystem{
Name: osName,
ReleaseID: osID,

Check failure on line 282 in pkg/process/v6/transformers/os/transform.go

View workflow job for this annotation

GitHub Actions / CLI tests (Python)

unknown field ReleaseID in struct literal of type v6.OperatingSystem

Check failure on line 282 in pkg/process/v6/transformers/os/transform.go

View workflow job for this annotation

GitHub Actions / Static analysis

unknown field ReleaseID in struct literal of type v6.OperatingSystem (typecheck)

Check failure on line 282 in pkg/process/v6/transformers/os/transform.go

View workflow job for this annotation

GitHub Actions / Static analysis

unknown field ReleaseID in struct literal of type v6.OperatingSystem) (typecheck)

Check failure on line 282 in pkg/process/v6/transformers/os/transform.go

View workflow job for this annotation

GitHub Actions / Unit tests (Go)

unknown field ReleaseID in struct literal of type v6.OperatingSystem

Check failure on line 282 in pkg/process/v6/transformers/os/transform.go

View workflow job for this annotation

GitHub Actions / Acceptance tests (3)

unknown field ReleaseID in struct literal of type v6.OperatingSystem
MajorVersion: majorVersion,
MinorVersion: minorVersion,
LabelVersion: labelVersion,
Expand Down
137 changes: 136 additions & 1 deletion pkg/process/v6/transformers/os/transform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,32 +44,45 @@ func expectedProvider(name string) *grypeDB.Provider {

func TestTransform(t *testing.T) {

alpineOS := &grypeDB.OperatingSystem{
Name: "alpine",
ReleaseID: "alpine",
MajorVersion: "3",
MinorVersion: "9",
}

amazonOS := &grypeDB.OperatingSystem{
Name: "amazon",
ReleaseID: "amzn",
MajorVersion: "2",
}
azure3OS := &grypeDB.OperatingSystem{
Name: "azurelinux",
ReleaseID: "azurelinux",
MajorVersion: "3",
MinorVersion: "0", // TODO: is this right?
}
debian8OS := &grypeDB.OperatingSystem{
Name: "debian",
ReleaseID: "debian",
MajorVersion: "8",
Codename: "jessie",
}

mariner2OS := &grypeDB.OperatingSystem{
Name: "mariner",
ReleaseID: "mariner",
MajorVersion: "2",
MinorVersion: "0", // TODO: is this right?
}
ol8OS := &grypeDB.OperatingSystem{
Name: "oracle",
ReleaseID: "ol",
MajorVersion: "8",
}
rhel8OS := &grypeDB.OperatingSystem{
Name: "redhat",
ReleaseID: "rhel",
MajorVersion: "8",
}
tests := []struct {
Expand Down Expand Up @@ -105,7 +118,7 @@ func TestTransform(t *testing.T) {
},
Related: affectedPkgSlice(
grypeDB.AffectedPackageHandle{
OperatingSystem: &grypeDB.OperatingSystem{Name: "alpine", MajorVersion: "3", MinorVersion: "9"},
OperatingSystem: alpineOS,
Package: &grypeDB.Package{Type: "apk", Name: "xen"},
BlobValue: &grypeDB.AffectedPackageBlob{
Ranges: []grypeDB.AffectedRange{
Expand Down Expand Up @@ -1102,6 +1115,128 @@ func TestTransform(t *testing.T) {
}
}

func TestGetOperatingSystem(t *testing.T) {
tests := []struct {
name string
osName string
osID string
osVersion string
expected *grypeDB.OperatingSystem
}{
{
name: "works with given args",
osName: "alpine",
osID: "alpine",
osVersion: "3.10",
expected: &grypeDB.OperatingSystem{
Name: "alpine",
ReleaseID: "alpine",
MajorVersion: "3",
MinorVersion: "10",
LabelVersion: "",
Codename: "",
},
},
{
name: "does codename lookup (debian)",
osName: "debian",
osID: "debian",
osVersion: "11",
expected: &grypeDB.OperatingSystem{
Name: "debian",
ReleaseID: "debian",
MajorVersion: "11",
MinorVersion: "",
LabelVersion: "",
Codename: "bullseye",
},
},
{
name: "does codename lookup (ubuntu)",
osName: "ubuntu",
osID: "ubuntu",
osVersion: "22.04",
expected: &grypeDB.OperatingSystem{
Name: "ubuntu",
ReleaseID: "ubuntu",
MajorVersion: "22",
MinorVersion: "04",
LabelVersion: "",
Codename: "jammy",
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := getOperatingSystem(tt.osName, tt.osID, tt.osVersion)
require.Equal(t, tt.expected, result)
})
}
}

func TestGetOSInfo(t *testing.T) {
tests := []struct {
name string
group string
expectedOS string
expectedID string
expectedV string
}{
{
name: "alpine 3.10",
group: "alpine:3.10",
expectedOS: "alpine",
expectedID: "alpine",
expectedV: "3.10",
},
{
name: "debian bullseye",
group: "debian:11",
expectedOS: "debian",
expectedID: "debian",
expectedV: "11",
},
{
name: "mariner version 1",
group: "mariner:1.0",
expectedOS: "mariner",
expectedID: "mariner",
expectedV: "1.0",
},
{
name: "mariner version 3 (azurelinux conversion)",
group: "mariner:3.0",
expectedOS: "azurelinux",
expectedID: "azurelinux",
expectedV: "3.0",
},
{
name: "ubuntu focal",
group: "ubuntu:20.04",
expectedOS: "ubuntu",
expectedID: "ubuntu",
expectedV: "20.04",
},
{
name: "oracle linux",
group: "ol:8",
expectedOS: "oracle", // normalize name
expectedID: "ol", // keep original ID
expectedV: "8",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
osName, id, version := getOSInfo(tt.group)
require.Equal(t, tt.expectedOS, osName)
require.Equal(t, tt.expectedID, id)
require.Equal(t, tt.expectedV, version)
})
}
}

func affectedPkgSlice(a ...grypeDB.AffectedPackageHandle) []any {
var r []any
for _, v := range a {
Expand Down

0 comments on commit b0f77a3

Please sign in to comment.