mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
add remaining debian & el distro support (#99)
This commit is contained in:
parent
5ccd6d5f6a
commit
63ba7ae47d
@ -12,21 +12,38 @@ import (
|
||||
// returns a distro or nil
|
||||
type parseFunc func(string) *Distro
|
||||
|
||||
type parseEntry struct {
|
||||
path file.Path
|
||||
fn parseFunc
|
||||
}
|
||||
|
||||
// Identify parses distro-specific files to determine distro metadata like version and release
|
||||
func Identify(s scope.Scope) Distro {
|
||||
distro := NewUnknownDistro()
|
||||
|
||||
identityFiles := map[file.Path]parseFunc{
|
||||
"/etc/os-release": parseOsRelease,
|
||||
// Debian and Debian-based distros have the same contents linked from this path
|
||||
"/usr/lib/os-release": parseOsRelease,
|
||||
"/bin/busybox": parseBusyBox,
|
||||
identityFiles := []parseEntry{
|
||||
{
|
||||
// most distros provide a link at this location
|
||||
path: "/etc/os-release",
|
||||
fn: parseOsRelease,
|
||||
},
|
||||
{
|
||||
// standard location for rhel & debian distros
|
||||
path: "/usr/lib/os-release",
|
||||
fn: parseOsRelease,
|
||||
},
|
||||
{
|
||||
// check for busybox (important to check this last since other distros contain the busybox binary)
|
||||
path: "/bin/busybox",
|
||||
fn: parseBusyBox,
|
||||
},
|
||||
}
|
||||
|
||||
for path, fn := range identityFiles {
|
||||
refs, err := s.FilesByPath(path)
|
||||
identifyLoop:
|
||||
for _, entry := range identityFiles {
|
||||
refs, err := s.FilesByPath(entry.path)
|
||||
if err != nil {
|
||||
log.Errorf("unable to get path refs from %s: %s", path, err)
|
||||
log.Errorf("unable to get path refs from %s: %s", entry.path, err)
|
||||
break
|
||||
}
|
||||
|
||||
@ -44,18 +61,18 @@ func Identify(s scope.Scope) Distro {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Debugf("unable to get contents from %s: %s", path, err)
|
||||
log.Debugf("unable to get contents from %s: %s", entry.path, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if content == "" {
|
||||
log.Debugf("no contents in file, skipping: %s", path)
|
||||
log.Debugf("no contents in file, skipping: %s", entry.path)
|
||||
continue
|
||||
}
|
||||
|
||||
if candidateDistro := fn(content); candidateDistro != nil {
|
||||
if candidateDistro := entry.fn(content); candidateDistro != nil {
|
||||
distro = *candidateDistro
|
||||
break
|
||||
break identifyLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -64,7 +81,7 @@ func Identify(s scope.Scope) Distro {
|
||||
}
|
||||
|
||||
func assemble(name, version string) *Distro {
|
||||
distroType, ok := Mappings[name]
|
||||
distroType, ok := IDMapping[name]
|
||||
|
||||
// Both distro and version must be present
|
||||
if len(name) == 0 || len(version) == 0 {
|
||||
|
||||
@ -6,45 +6,103 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/imgbom/internal"
|
||||
|
||||
"github.com/anchore/imgbom/imgbom/scope"
|
||||
)
|
||||
|
||||
func TestIdentifyDistro(t *testing.T) {
|
||||
tests := []struct {
|
||||
fixture string
|
||||
name string
|
||||
RawVersion string
|
||||
Type Type
|
||||
Version string
|
||||
}{
|
||||
{
|
||||
fixture: "test-fixtures/os/ubuntu-20.04",
|
||||
name: "ubuntu",
|
||||
fixture: "test-fixtures/os/alpine",
|
||||
Type: Alpine,
|
||||
Version: "3.11.6",
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/os/amazon",
|
||||
Type: AmazonLinux,
|
||||
Version: "2.0.0",
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/os/busybox",
|
||||
Type: Busybox,
|
||||
Version: "1.31.1",
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/os/centos",
|
||||
Type: CentOS,
|
||||
Version: "8.0.0",
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/os/debian",
|
||||
Type: Debian,
|
||||
Version: "8.0.0",
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/os/fedora",
|
||||
Type: Fedora,
|
||||
Version: "31.0.0",
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/os/redhat",
|
||||
Type: RedHat,
|
||||
Version: "7.3.0",
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/os/ubuntu",
|
||||
Type: Ubuntu,
|
||||
Version: "20.4.0",
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/os/empty",
|
||||
name: "No OS files",
|
||||
Type: UnknownDistroType,
|
||||
},
|
||||
{
|
||||
fixture: "test-fixtures/os/unmatchable",
|
||||
name: "Unmatchable distro",
|
||||
Type: UnknownDistroType,
|
||||
},
|
||||
}
|
||||
|
||||
observedDistros := internal.NewStringSet()
|
||||
definedDistros := internal.NewStringSet()
|
||||
for _, d := range All {
|
||||
definedDistros.Add(d.String())
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Run(test.fixture, func(t *testing.T) {
|
||||
s, err := scope.NewScopeFromDir(test.fixture, scope.AllLayersScope)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to produce a new scope for testing: %s", test.fixture)
|
||||
}
|
||||
distro := Identify(s)
|
||||
if distro.Type != test.Type {
|
||||
t.Errorf("expected distro doesn't match: %v != %v", distro.Type, test.Type)
|
||||
|
||||
d := Identify(s)
|
||||
observedDistros.Add(d.String())
|
||||
|
||||
if d.Type != test.Type {
|
||||
t.Errorf("expected distro doesn't match: %v != %v", d.Type, test.Type)
|
||||
}
|
||||
|
||||
if d.Type == UnknownDistroType && d.Version != nil {
|
||||
t.Fatalf("version should be nil for unknown distros")
|
||||
} else if d.Type == UnknownDistroType && d.Version == nil {
|
||||
// don't check versions for unknown distro types
|
||||
return
|
||||
}
|
||||
|
||||
if d.Version.String() != test.Version {
|
||||
t.Errorf("expected distro version doesn't match: %v != %v", d.Version.String(), test.Version)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// ensure that test cases stay in sync with the distros that can be identified
|
||||
if len(observedDistros) < len(definedDistros) {
|
||||
t.Errorf("distro coverage incomplete (distro=%d, coverage=%d)", len(definedDistros), len(observedDistros))
|
||||
}
|
||||
|
||||
}
|
||||
@ -86,11 +144,10 @@ func TestParseOsRelease(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
name := fmt.Sprintf("%s:%s", test.name, test.RawVersion)
|
||||
fixture, err := os.Open(test.fixture)
|
||||
defer fixture.Close()
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open fixture: %+v", err)
|
||||
t.Fatalf("could not open test fixture=%s: %+v", test.fixture, err)
|
||||
}
|
||||
defer fixture.Close()
|
||||
|
||||
b, err := ioutil.ReadAll(fixture)
|
||||
if err != nil {
|
||||
@ -131,11 +188,10 @@ func TestParseOsReleaseFailures(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
name := fmt.Sprintf("%s:%s", test.name, test.fixture)
|
||||
fixture, err := os.Open(test.fixture)
|
||||
defer fixture.Close()
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open fixture: %+v", err)
|
||||
t.Fatalf("could not open test fixture=%s: %+v", test.fixture, err)
|
||||
}
|
||||
defer fixture.Close()
|
||||
|
||||
b, err := ioutil.ReadAll(fixture)
|
||||
if err != nil {
|
||||
|
||||
6
imgbom/distro/test-fixtures/os/alpine/etc/os-release
Normal file
6
imgbom/distro/test-fixtures/os/alpine/etc/os-release
Normal file
@ -0,0 +1,6 @@
|
||||
NAME="Alpine Linux"
|
||||
ID=alpine
|
||||
VERSION_ID=3.11.6
|
||||
PRETTY_NAME="Alpine Linux v3.11"
|
||||
HOME_URL="https://alpinelinux.org/"
|
||||
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
|
||||
9
imgbom/distro/test-fixtures/os/amazon/etc/os-release
Normal file
9
imgbom/distro/test-fixtures/os/amazon/etc/os-release
Normal file
@ -0,0 +1,9 @@
|
||||
NAME="Amazon Linux"
|
||||
VERSION="2"
|
||||
ID="amzn"
|
||||
ID_LIKE="centos rhel fedora"
|
||||
VERSION_ID="2"
|
||||
PRETTY_NAME="Amazon Linux 2"
|
||||
ANSI_COLOR="0;33"
|
||||
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
|
||||
HOME_URL="https://amazonlinux.com/"
|
||||
1
imgbom/distro/test-fixtures/os/busybox/bin/busybox
Normal file
1
imgbom/distro/test-fixtures/os/busybox/bin/busybox
Normal file
@ -0,0 +1 @@
|
||||
junk...BusyBox v1.31.1more junk
|
||||
16
imgbom/distro/test-fixtures/os/centos/usr/lib/os-release
Normal file
16
imgbom/distro/test-fixtures/os/centos/usr/lib/os-release
Normal file
@ -0,0 +1,16 @@
|
||||
NAME="CentOS Linux"
|
||||
VERSION="8 (Core)"
|
||||
ID="centos"
|
||||
ID_LIKE="rhel fedora"
|
||||
VERSION_ID="8"
|
||||
PLATFORM_ID="platform:el8"
|
||||
PRETTY_NAME="CentOS Linux 8 (Core)"
|
||||
ANSI_COLOR="0;31"
|
||||
CPE_NAME="cpe:/o:centos:centos:8"
|
||||
HOME_URL="https://www.centos.org/"
|
||||
BUG_REPORT_URL="https://bugs.centos.org/"
|
||||
|
||||
CENTOS_MANTISBT_PROJECT="CentOS-8"
|
||||
CENTOS_MANTISBT_PROJECT_VERSION="8"
|
||||
REDHAT_SUPPORT_PRODUCT="centos"
|
||||
REDHAT_SUPPORT_PRODUCT_VERSION="8"
|
||||
8
imgbom/distro/test-fixtures/os/debian/usr/lib/os-release
Normal file
8
imgbom/distro/test-fixtures/os/debian/usr/lib/os-release
Normal file
@ -0,0 +1,8 @@
|
||||
PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
|
||||
NAME="Debian GNU/Linux"
|
||||
VERSION_ID="8"
|
||||
VERSION="8 (jessie)"
|
||||
ID=debian
|
||||
HOME_URL="http://www.debian.org/"
|
||||
SUPPORT_URL="http://www.debian.org/support"
|
||||
BUG_REPORT_URL="https://bugs.debian.org/"
|
||||
21
imgbom/distro/test-fixtures/os/fedora/usr/lib/os-release
Normal file
21
imgbom/distro/test-fixtures/os/fedora/usr/lib/os-release
Normal file
@ -0,0 +1,21 @@
|
||||
NAME=Fedora
|
||||
VERSION="31 (Container Image)"
|
||||
ID=fedora
|
||||
VERSION_ID=31
|
||||
VERSION_CODENAME=""
|
||||
PLATFORM_ID="platform:f31"
|
||||
PRETTY_NAME="Fedora 31 (Container Image)"
|
||||
ANSI_COLOR="0;34"
|
||||
LOGO=fedora-logo-icon
|
||||
CPE_NAME="cpe:/o:fedoraproject:fedora:31"
|
||||
HOME_URL="https://fedoraproject.org/"
|
||||
DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f31/system-administrators-guide/"
|
||||
SUPPORT_URL="https://fedoraproject.org/wiki/Communicating_and_getting_help"
|
||||
BUG_REPORT_URL="https://bugzilla.redhat.com/"
|
||||
REDHAT_BUGZILLA_PRODUCT="Fedora"
|
||||
REDHAT_BUGZILLA_PRODUCT_VERSION=31
|
||||
REDHAT_SUPPORT_PRODUCT="Fedora"
|
||||
REDHAT_SUPPORT_PRODUCT_VERSION=31
|
||||
PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
|
||||
VARIANT="Container Image"
|
||||
VARIANT_ID=container
|
||||
15
imgbom/distro/test-fixtures/os/redhat/usr/lib/os-release
Normal file
15
imgbom/distro/test-fixtures/os/redhat/usr/lib/os-release
Normal file
@ -0,0 +1,15 @@
|
||||
NAME="Red Hat Enterprise Linux Server"
|
||||
VERSION="7.3 (Maipo)"
|
||||
ID="rhel"
|
||||
ID_LIKE="fedora"
|
||||
VERSION_ID="7.3"
|
||||
PRETTY_NAME="Red Hat Enterprise Linux Server 7.3 (Maipo)"
|
||||
ANSI_COLOR="0;31"
|
||||
CPE_NAME="cpe:/o:redhat:enterprise_linux:7.3:GA:server"
|
||||
HOME_URL="https://www.redhat.com/"
|
||||
BUG_REPORT_URL="https://bugzilla.redhat.com/"
|
||||
|
||||
REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 7"
|
||||
REDHAT_BUGZILLA_PRODUCT_VERSION=7.3
|
||||
REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
|
||||
REDHAT_SUPPORT_PRODUCT_VERSION="7.3"
|
||||
@ -6,17 +6,12 @@ const (
|
||||
Ubuntu
|
||||
RedHat
|
||||
CentOS
|
||||
// Fedora
|
||||
// Alpine
|
||||
Fedora
|
||||
Alpine
|
||||
Busybox
|
||||
// AmazonLinux
|
||||
// OracleLinux
|
||||
// ArchLinux
|
||||
)
|
||||
|
||||
const (
|
||||
// UnknownVersion is a default of 0.0.0 when it can't be parsed
|
||||
UnknownVersion string = "0.0.0"
|
||||
AmazonLinux
|
||||
OracleLinux
|
||||
//ArchLinux
|
||||
)
|
||||
|
||||
type Type int
|
||||
@ -27,12 +22,12 @@ var distroStr = []string{
|
||||
"ubuntu",
|
||||
"redhat",
|
||||
"centos",
|
||||
// "fedora",
|
||||
// "alpine",
|
||||
"fedora",
|
||||
"alpine",
|
||||
"busybox",
|
||||
// "amazn",
|
||||
// "oraclelinux",
|
||||
// "archlinux",
|
||||
"amazn",
|
||||
"oraclelinux",
|
||||
//"archlinux",
|
||||
}
|
||||
|
||||
var All = []Type{
|
||||
@ -40,12 +35,12 @@ var All = []Type{
|
||||
Ubuntu,
|
||||
RedHat,
|
||||
CentOS,
|
||||
// Fedora,
|
||||
// Alpine,
|
||||
Fedora,
|
||||
Alpine,
|
||||
Busybox,
|
||||
// AmazonLinux,
|
||||
// OracleLinux,
|
||||
// ArchLinux,
|
||||
AmazonLinux,
|
||||
OracleLinux,
|
||||
//ArchLinux,
|
||||
}
|
||||
|
||||
func (t Type) String() string {
|
||||
@ -56,16 +51,16 @@ func (t Type) String() string {
|
||||
return distroStr[t]
|
||||
}
|
||||
|
||||
// Mappings connects a distro ID like "ubuntu" to a Distro type
|
||||
var Mappings = map[string]Type{
|
||||
// IDMapping connects a distro ID like "ubuntu" to a Distro type
|
||||
var IDMapping = map[string]Type{
|
||||
"debian": Debian,
|
||||
"ubuntu": Ubuntu,
|
||||
"rhel": RedHat,
|
||||
"centos": CentOS,
|
||||
// "fedora": Fedora,
|
||||
// "alpine": Alpine,
|
||||
"fedora": Fedora,
|
||||
"alpine": Alpine,
|
||||
"busybox": Busybox,
|
||||
// "amazn": AmazonLinux,
|
||||
// "oraclelinux": OracleLinux,
|
||||
// "archlinux": ArchLinux,
|
||||
"amzn": AmazonLinux,
|
||||
"ol": OracleLinux,
|
||||
//"arch": ArchLinux,
|
||||
}
|
||||
|
||||
@ -29,8 +29,13 @@ func Catalog(userInput string, scoptOpt scope.Option) (*pkg.Catalog, *scope.Scop
|
||||
}
|
||||
|
||||
func IdentifyDistro(s scope.Scope) distro.Distro {
|
||||
log.Info("Identifying Distro")
|
||||
return distro.Identify(s)
|
||||
d := distro.Identify(s)
|
||||
if d.Type != distro.UnknownDistroType {
|
||||
log.Infof("Identified Distro: %s", d.String())
|
||||
} else {
|
||||
log.Info("Could not identify distro")
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func CatalogFromScope(s scope.Scope) (*pkg.Catalog, error) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user