From 5e2723187df0aff2e4f80c2e74d9d2471bf04d9a Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 26 Feb 2025 07:42:29 -0500 Subject: [PATCH] Fix /etc/redhat-release file parsing when resolving distro details (#3688) --- syft/linux/identify_release.go | 34 ++++++++++++++----- syft/linux/identify_release_test.go | 21 +++++++++--- .../{ => from-os-release}/usr/lib/os-release | 0 .../from-redhat-release/etc/redhat-release | 1 + 4 files changed, 43 insertions(+), 13 deletions(-) rename syft/linux/test-fixtures/os/redhat/{ => from-os-release}/usr/lib/os-release (100%) create mode 100644 syft/linux/test-fixtures/os/redhat/from-redhat-release/etc/redhat-release diff --git a/syft/linux/identify_release.go b/syft/linux/identify_release.go index aac9313a2..6f0fd3a5c 100644 --- a/syft/linux/identify_release.go +++ b/syft/linux/identify_release.go @@ -171,18 +171,36 @@ func parseSystemReleaseCPE(contents string) (*Release, error) { } // example: "CentOS release 6.10 (Final)" -var redhatReleaseMatcher = regexp.MustCompile(`(.*?)\srelease\s(\d\.\d+)`) +var redhatReleaseMatcher = regexp.MustCompile(`(?P.*?)\srelease\s(?P(?P\d\.\d+).*)`) // parseRedhatRelease is a fallback parsing method for determining distro information in older redhat versions func parseRedhatRelease(contents string) (*Release, error) { - matches := redhatReleaseMatcher.FindAllStringSubmatch(contents, -1) - for _, match := range matches { - if len(match) < 3 { - continue - } - return simpleRelease(match[1], strings.ToLower(match[1]), match[2], ""), nil + contents = strings.TrimSpace(contents) + matches := internal.MatchNamedCaptureGroups(redhatReleaseMatcher, contents) + name := matches["name"] + version := matches["version"] + versionID := matches["versionid"] + if name == "" || versionID == "" { + return nil, nil } - return nil, nil + + id := strings.ToLower(name) + switch { + case strings.HasPrefix(id, "red hat enterprise linux"): + id = "rhel" + case strings.HasPrefix(id, "centos"): + // ignore the parenthetical version information + version = versionID + } + + return &Release{ + PrettyName: contents, + Name: name, + ID: id, + IDLike: []string{id}, + Version: version, + VersionID: versionID, + }, nil } func simpleRelease(prettyName, name, version, cpe string) *Release { diff --git a/syft/linux/identify_release_test.go b/syft/linux/identify_release_test.go index 724f038df..e6e39f5aa 100644 --- a/syft/linux/identify_release_test.go +++ b/syft/linux/identify_release_test.go @@ -107,7 +107,7 @@ func TestIdentifyRelease(t *testing.T) { }, }, { - fixture: "test-fixtures/os/redhat", + fixture: "test-fixtures/os/redhat/from-os-release", release: &Release{ PrettyName: "Red Hat Enterprise Linux Server 7.3 (Maipo)", Name: "Red Hat Enterprise Linux Server", @@ -120,6 +120,17 @@ func TestIdentifyRelease(t *testing.T) { CPEName: "cpe:/o:redhat:enterprise_linux:7.3:GA:server", }, }, + { + fixture: "test-fixtures/os/redhat/from-redhat-release", + release: &Release{ + PrettyName: "Red Hat Enterprise Linux release 8.10 (Ootpa)", + Name: "Red Hat Enterprise Linux", + ID: "rhel", + IDLike: []string{"rhel"}, + Version: "8.10 (Ootpa)", + VersionID: "8.10", + }, + }, { fixture: "test-fixtures/os/ubuntu", release: &Release{ @@ -266,8 +277,8 @@ func TestIdentifyRelease(t *testing.T) { { fixture: "test-fixtures/os/centos5", release: &Release{ - PrettyName: "CentOS", - Name: "centos", + PrettyName: "CentOS release 5.7 (Final)", + Name: "CentOS", ID: "centos", IDLike: []string{"centos"}, Version: "5.7", @@ -506,8 +517,8 @@ func TestParseRedhatRelease(t *testing.T) { fixture: "test-fixtures/os/centos5/etc/redhat-release", name: "Centos 5", release: &Release{ - PrettyName: "CentOS", - Name: "centos", + PrettyName: "CentOS release 5.7 (Final)", + Name: "CentOS", ID: "centos", IDLike: []string{"centos"}, Version: "5.7", diff --git a/syft/linux/test-fixtures/os/redhat/usr/lib/os-release b/syft/linux/test-fixtures/os/redhat/from-os-release/usr/lib/os-release similarity index 100% rename from syft/linux/test-fixtures/os/redhat/usr/lib/os-release rename to syft/linux/test-fixtures/os/redhat/from-os-release/usr/lib/os-release diff --git a/syft/linux/test-fixtures/os/redhat/from-redhat-release/etc/redhat-release b/syft/linux/test-fixtures/os/redhat/from-redhat-release/etc/redhat-release new file mode 100644 index 000000000..4fbbf1291 --- /dev/null +++ b/syft/linux/test-fixtures/os/redhat/from-redhat-release/etc/redhat-release @@ -0,0 +1 @@ +Red Hat Enterprise Linux release 8.10 (Ootpa) \ No newline at end of file