mirror of
https://github.com/anchore/syft.git
synced 2025-11-18 00:43:20 +01:00
Add support for older CentOS versions (6 & 5) by checking additional release files for information
Signed-off-by: Samuel Dacanay <sam.dacanay@anchore.com>
This commit is contained in:
parent
5de1a0a236
commit
0799fd9d46
@ -35,6 +35,16 @@ var identityFiles = []parseEntry{
|
|||||||
path: "/bin/busybox",
|
path: "/bin/busybox",
|
||||||
fn: parseBusyBox,
|
fn: parseBusyBox,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// check for centos:6
|
||||||
|
path: "/etc/system-release-cpe",
|
||||||
|
fn: parseSystemReleaseCPE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// last ditch effort for determining older centos version distro information
|
||||||
|
path: "/etc/redhat-release",
|
||||||
|
fn: parseRedhatRelease,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identify parses distro-specific files to determine distro metadata like version and release.
|
// Identify parses distro-specific files to determine distro metadata like version and release.
|
||||||
@ -145,3 +155,48 @@ func parseBusyBox(contents string) *Distro {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: we should update parseSystemReleaseCPE to use the CPE struct, pkg.CPE, which requires a refactor to avoid a circular import:
|
||||||
|
// TODO: pkg depends on distro to support pURLs. To avoid the circular import, either try to make pkg to not depend on distro (medium lift-ish)
|
||||||
|
// TODO: or migrate the cpe code out of the pkg package (small lift).
|
||||||
|
// example CPE: cpe:/o:centos:linux:6:GA
|
||||||
|
var systemReleaseCpeMatcher = regexp.MustCompile(`cpe:\/o:(.*?):.*?:(.*?):.*?$`)
|
||||||
|
|
||||||
|
// parseSystemReleaseCPE parses the older centos (6) file to determine distro metadata
|
||||||
|
func parseSystemReleaseCPE(contents string) *Distro {
|
||||||
|
matches := systemReleaseCpeMatcher.FindAllStringSubmatch(contents, -1)
|
||||||
|
for _, match := range matches {
|
||||||
|
if len(match) < 3 {
|
||||||
|
log.Warnf("system release cpe does not match expected format")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// note: in SubMatches (capture groups), the 0th index is the full match string
|
||||||
|
// see https://pkg.go.dev/regexp#pkg-overview for more info
|
||||||
|
distro := assemble(match[1], match[2], "")
|
||||||
|
if distro != nil {
|
||||||
|
return distro
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// example: "CentOS release 6.10 (Final)"
|
||||||
|
var redhatReleaseMatcher = regexp.MustCompile(`(.*?)\srelease\s(\d\.\d+)`)
|
||||||
|
|
||||||
|
// parseRedhatRelease is a fallback parsing method for determining distro information in older redhat versions
|
||||||
|
func parseRedhatRelease(contents string) *Distro {
|
||||||
|
matches := redhatReleaseMatcher.FindAllStringSubmatch(contents, -1)
|
||||||
|
for _, match := range matches {
|
||||||
|
if len(match) < 3 {
|
||||||
|
log.Warnf("failed to parse redhat-release file, unexpected format")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// note: in SubMatches (capture groups), the 0th index is the full match string
|
||||||
|
// see https://pkg.go.dev/regexp#pkg-overview for more info
|
||||||
|
distro := assemble(strings.ToLower(match[1]), match[2], "")
|
||||||
|
if distro != nil {
|
||||||
|
return distro
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package distro
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
hashiVer "github.com/hashicorp/go-version"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
@ -103,6 +104,16 @@ func TestIdentifyDistro(t *testing.T) {
|
|||||||
fixture: "test-fixtures/partial-fields/missing-version",
|
fixture: "test-fixtures/partial-fields/missing-version",
|
||||||
Type: UnknownDistroType,
|
Type: UnknownDistroType,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fixture: "test-fixtures/os/centos6",
|
||||||
|
Type: CentOS,
|
||||||
|
Version: "6.0.0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fixture: "test-fixtures/os/centos5",
|
||||||
|
Type: CentOS,
|
||||||
|
Version: "5.7.0",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
observedDistros := internal.NewStringSet()
|
observedDistros := internal.NewStringSet()
|
||||||
@ -205,18 +216,7 @@ func TestParseOsRelease(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
name := fmt.Sprintf("%s:%s", test.name, test.RawVersion)
|
name := fmt.Sprintf("%s:%s", test.name, test.RawVersion)
|
||||||
fixture, err := os.Open(test.fixture)
|
contents := retrieveFixtureContentsAsString(test.fixture, t)
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not open test fixture=%s: %+v", test.fixture, err)
|
|
||||||
}
|
|
||||||
defer fixture.Close()
|
|
||||||
|
|
||||||
b, err := ioutil.ReadAll(fixture)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to read fixture file: %+v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
contents := string(b)
|
|
||||||
|
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
distro := parseOsRelease(contents)
|
distro := parseOsRelease(contents)
|
||||||
@ -245,18 +245,7 @@ func TestParseOsReleaseFailures(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
name := fmt.Sprintf("%s:%s", test.name, test.fixture)
|
name := fmt.Sprintf("%s:%s", test.name, test.fixture)
|
||||||
fixture, err := os.Open(test.fixture)
|
contents := retrieveFixtureContentsAsString(test.fixture, t)
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("could not open test fixture=%s: %+v", test.fixture, err)
|
|
||||||
}
|
|
||||||
defer fixture.Close()
|
|
||||||
|
|
||||||
b, err := ioutil.ReadAll(fixture)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to read fixture file: %+v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
contents := string(b)
|
|
||||||
|
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
distro := parseOsRelease(contents)
|
distro := parseOsRelease(contents)
|
||||||
@ -265,5 +254,101 @@ func TestParseOsReleaseFailures(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseSystemReleaseCPE(t *testing.T) {
|
||||||
|
centos6Version, _ := hashiVer.NewVersion("6")
|
||||||
|
tests := []struct {
|
||||||
|
fixture string
|
||||||
|
name string
|
||||||
|
expected *Distro
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
fixture: "test-fixtures/os/centos6/etc/system-release-cpe",
|
||||||
|
name: "Centos 6",
|
||||||
|
expected: &Distro{
|
||||||
|
Type: CentOS,
|
||||||
|
Version: centos6Version,
|
||||||
|
RawVersion: "6",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fixture: "test-fixtures/bad-system-release-cpe",
|
||||||
|
name: "Centos 6 Bad CPE",
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
contents := retrieveFixtureContentsAsString(test.fixture, t)
|
||||||
|
actual := parseSystemReleaseCPE(contents)
|
||||||
|
|
||||||
|
if test.expected == nil {
|
||||||
|
assert.Nil(t, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// not comparing the full distro object because the hashiVer is a pointer
|
||||||
|
assert.Equal(t, test.expected.Type, actual.Type)
|
||||||
|
assert.Equal(t, &test.expected.Version, &actual.Version)
|
||||||
|
assert.Equal(t, test.expected.RawVersion, actual.RawVersion)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseRedhatRelease(t *testing.T) {
|
||||||
|
centos5Version, _ := hashiVer.NewVersion("5.7")
|
||||||
|
tests := []struct {
|
||||||
|
fixture string
|
||||||
|
name string
|
||||||
|
expected *Distro
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
fixture: "test-fixtures/os/centos5/etc/redhat-release",
|
||||||
|
name: "Centos 5",
|
||||||
|
expected: &Distro{
|
||||||
|
Type: CentOS,
|
||||||
|
Version: centos5Version,
|
||||||
|
RawVersion: "5.7",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fixture: "test-fixtures/bad-redhat-release",
|
||||||
|
name: "Centos 5 Bad Redhat Release",
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
contents := retrieveFixtureContentsAsString(test.fixture, t)
|
||||||
|
actual := parseRedhatRelease(contents)
|
||||||
|
|
||||||
|
if test.expected == nil {
|
||||||
|
assert.Nil(t, actual)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// not comparing the full distro object because the hashiVer is a pointer
|
||||||
|
assert.Equal(t, test.expected.Type, actual.Type)
|
||||||
|
assert.Equal(t, &test.expected.Version, &actual.Version)
|
||||||
|
assert.Equal(t, test.expected.RawVersion, actual.RawVersion)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func retrieveFixtureContentsAsString(fixturePath string, t *testing.T) string {
|
||||||
|
fixture, err := os.Open(fixturePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not open test fixture=%s: %+v", fixturePath, err)
|
||||||
|
}
|
||||||
|
defer fixture.Close()
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(fixture)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to read fixture file: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|||||||
1
syft/distro/test-fixtures/bad-redhat-release
Normal file
1
syft/distro/test-fixtures/bad-redhat-release
Normal file
@ -0,0 +1 @@
|
|||||||
|
CentOS release 5 (Final)
|
||||||
1
syft/distro/test-fixtures/bad-system-release-cpe
Normal file
1
syft/distro/test-fixtures/bad-system-release-cpe
Normal file
@ -0,0 +1 @@
|
|||||||
|
cpe:/o:centos:6:GA
|
||||||
1
syft/distro/test-fixtures/os/centos5/etc/redhat-release
Normal file
1
syft/distro/test-fixtures/os/centos5/etc/redhat-release
Normal file
@ -0,0 +1 @@
|
|||||||
|
CentOS release 5.7 (Final)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
cpe:/o:centos:linux:6:GA
|
||||||
Loading…
x
Reference in New Issue
Block a user