mirror of
https://github.com/anchore/syft.git
synced 2026-02-12 02:26:42 +01:00
Add portage support for Gentoo Linux (#1076)
Co-authored-by: Christopher Phillips <christopher.phillips@anchore.com>
This commit is contained in:
parent
ba685eada8
commit
4c55c62834
@ -6,5 +6,5 @@ const (
|
|||||||
|
|
||||||
// JSONSchemaVersion is the current schema version output by the JSON encoder
|
// JSONSchemaVersion is the current schema version output by the JSON encoder
|
||||||
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
|
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
|
||||||
JSONSchemaVersion = "3.3.0"
|
JSONSchemaVersion = "3.3.1"
|
||||||
)
|
)
|
||||||
|
|||||||
@ -37,6 +37,8 @@ func SourceInfo(p pkg.Package) string {
|
|||||||
answer = "acquired package info from PHP composer manifest"
|
answer = "acquired package info from PHP composer manifest"
|
||||||
case pkg.ConanPkg:
|
case pkg.ConanPkg:
|
||||||
answer = "acquired package info from conan manifest"
|
answer = "acquired package info from conan manifest"
|
||||||
|
case pkg.PortagePkg:
|
||||||
|
answer = "acquired package info from portage DB"
|
||||||
default:
|
default:
|
||||||
answer = "acquired package info from the following paths"
|
answer = "acquired package info from the following paths"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -158,6 +158,14 @@ func Test_SourceInfo(t *testing.T) {
|
|||||||
"from conan manifest",
|
"from conan manifest",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: pkg.Package{
|
||||||
|
Type: pkg.PortagePkg,
|
||||||
|
},
|
||||||
|
expected: []string{
|
||||||
|
"from portage DB",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
var pkgTypes []pkg.Type
|
var pkgTypes []pkg.Type
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|||||||
@ -157,6 +157,12 @@ func unpackMetadata(p *Package, unpacker packageMetadataUnpacker) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p.Metadata = payload
|
p.Metadata = payload
|
||||||
|
case pkg.PortageMetadataType:
|
||||||
|
var payload pkg.PortageMetadata
|
||||||
|
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.Metadata = payload
|
||||||
default:
|
default:
|
||||||
log.Warnf("unknown package metadata type=%q for packageID=%q", p.MetadataType, p.ID)
|
log.Warnf("unknown package metadata type=%q for packageID=%q", p.MetadataType, p.ID)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -88,7 +88,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.1",
|
||||||
"url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-3.3.0.json"
|
"url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-3.3.1.json"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -184,7 +184,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.1",
|
||||||
"url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-3.3.0.json"
|
"url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-3.3.1.json"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -111,7 +111,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"schema": {
|
"schema": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.1",
|
||||||
"url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-3.3.0.json"
|
"url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-3.3.1.json"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ Given a version number format `MODEL.REVISION.ADDITION`:
|
|||||||
When adding a new `pkg.*Metadata` that is assigned to the `pkg.Package.Metadata` struct field it is important that a few things
|
When adding a new `pkg.*Metadata` that is assigned to the `pkg.Package.Metadata` struct field it is important that a few things
|
||||||
are done:
|
are done:
|
||||||
|
|
||||||
- a new integration test case is added to `test/integration/pkg_cases_test.go` that exercises the new package type with the new metadata
|
- a new integration test case is added to `test/integration/catalog_packages_cases_test.go` that exercises the new package type with the new metadata
|
||||||
- the new metadata struct is added to the `artifactMetadataContainer` struct within `schema/json/generate.go`
|
- the new metadata struct is added to the `artifactMetadataContainer` struct within `schema/json/generate.go`
|
||||||
|
|
||||||
## Generating a New Schema
|
## Generating a New Schema
|
||||||
|
|||||||
@ -40,6 +40,7 @@ type artifactMetadataContainer struct {
|
|||||||
Php pkg.PhpComposerJSONMetadata
|
Php pkg.PhpComposerJSONMetadata
|
||||||
Dart pkg.DartPubMetadata
|
Dart pkg.DartPubMetadata
|
||||||
Dotnet pkg.DotnetDepsMetadata
|
Dotnet pkg.DotnetDepsMetadata
|
||||||
|
Portage pkg.PortageMetadata
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
1463
schema/json/schema-3.3.1.json
Normal file
1463
schema/json/schema-3.3.1.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
|
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/php"
|
"github.com/anchore/syft/syft/pkg/cataloger/php"
|
||||||
|
"github.com/anchore/syft/syft/pkg/cataloger/portage"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/python"
|
"github.com/anchore/syft/syft/pkg/cataloger/python"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/rpmdb"
|
"github.com/anchore/syft/syft/pkg/cataloger/rpmdb"
|
||||||
"github.com/anchore/syft/syft/pkg/cataloger/ruby"
|
"github.com/anchore/syft/syft/pkg/cataloger/ruby"
|
||||||
@ -54,6 +55,7 @@ func ImageCatalogers(cfg Config) []Cataloger {
|
|||||||
apkdb.NewApkdbCataloger(),
|
apkdb.NewApkdbCataloger(),
|
||||||
golang.NewGoModuleBinaryCataloger(),
|
golang.NewGoModuleBinaryCataloger(),
|
||||||
dotnet.NewDotnetDepsCataloger(),
|
dotnet.NewDotnetDepsCataloger(),
|
||||||
|
portage.NewPortageCataloger(),
|
||||||
}, cfg.Catalogers)
|
}, cfg.Catalogers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +79,7 @@ func DirectoryCatalogers(cfg Config) []Cataloger {
|
|||||||
dart.NewPubspecLockCataloger(),
|
dart.NewPubspecLockCataloger(),
|
||||||
dotnet.NewDotnetDepsCataloger(),
|
dotnet.NewDotnetDepsCataloger(),
|
||||||
cpp.NewConanfileCataloger(),
|
cpp.NewConanfileCataloger(),
|
||||||
|
portage.NewPortageCataloger(),
|
||||||
}, cfg.Catalogers)
|
}, cfg.Catalogers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +106,7 @@ func AllCatalogers(cfg Config) []Cataloger {
|
|||||||
php.NewPHPComposerInstalledCataloger(),
|
php.NewPHPComposerInstalledCataloger(),
|
||||||
php.NewPHPComposerLockCataloger(),
|
php.NewPHPComposerLockCataloger(),
|
||||||
cpp.NewConanfileCataloger(),
|
cpp.NewConanfileCataloger(),
|
||||||
|
portage.NewPortageCataloger(),
|
||||||
}, cfg.Catalogers)
|
}, cfg.Catalogers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
151
syft/pkg/cataloger/portage/cataloger.go
Normal file
151
syft/pkg/cataloger/portage/cataloger.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
Package portage provides a concrete Cataloger implementation for Gentoo Portage.
|
||||||
|
*/
|
||||||
|
package portage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal"
|
||||||
|
"github.com/anchore/syft/internal/log"
|
||||||
|
"github.com/anchore/syft/syft/artifact"
|
||||||
|
"github.com/anchore/syft/syft/file"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/source"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
cpvRe = regexp.MustCompile(`/([^/]*/[\w+][\w+-]*)-((\d+)((\.\d+)*)([a-z]?)((_(pre|p|beta|alpha|rc)\d*)*)(-r\d+)?)/CONTENTS$`)
|
||||||
|
)
|
||||||
|
|
||||||
|
type Cataloger struct{}
|
||||||
|
|
||||||
|
// NewPortageCataloger returns a new Portage package cataloger object.
|
||||||
|
func NewPortageCataloger() *Cataloger {
|
||||||
|
return &Cataloger{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns a string that uniquely describes a cataloger
|
||||||
|
func (c *Cataloger) Name() string {
|
||||||
|
return "portage-cataloger"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Catalog is given an object to resolve file references and content, this function returns any discovered Packages after analyzing portage support files.
|
||||||
|
func (c *Cataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
|
dbFileMatches, err := resolver.FilesByGlob(pkg.PortageDBGlob)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("failed to find portage files by glob: %w", err)
|
||||||
|
}
|
||||||
|
var allPackages []pkg.Package
|
||||||
|
for _, dbLocation := range dbFileMatches {
|
||||||
|
cpvMatch := cpvRe.FindStringSubmatch(dbLocation.RealPath)
|
||||||
|
if cpvMatch == nil {
|
||||||
|
return nil, nil, fmt.Errorf("failed to match package and version in %s", dbLocation.RealPath)
|
||||||
|
}
|
||||||
|
entry := pkg.PortageMetadata{
|
||||||
|
// ensure the default value for a collection is never nil since this may be shown as JSON
|
||||||
|
Files: make([]pkg.PortageFileRecord, 0),
|
||||||
|
Package: cpvMatch[1],
|
||||||
|
Version: cpvMatch[2],
|
||||||
|
}
|
||||||
|
|
||||||
|
err = addFiles(resolver, dbLocation, &entry)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
addSize(resolver, dbLocation, &entry)
|
||||||
|
|
||||||
|
p := pkg.Package{
|
||||||
|
Name: entry.Package,
|
||||||
|
Version: entry.Version,
|
||||||
|
Type: pkg.PortagePkg,
|
||||||
|
MetadataType: pkg.PortageMetadataType,
|
||||||
|
Metadata: entry,
|
||||||
|
}
|
||||||
|
addLicenses(resolver, dbLocation, &p)
|
||||||
|
p.FoundBy = c.Name()
|
||||||
|
p.Locations.Add(dbLocation)
|
||||||
|
p.SetID()
|
||||||
|
allPackages = append(allPackages, p)
|
||||||
|
}
|
||||||
|
return allPackages, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func addFiles(resolver source.FileResolver, dbLocation source.Location, entry *pkg.PortageMetadata) error {
|
||||||
|
contentsReader, err := resolver.FileContentsByLocation(dbLocation)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(contentsReader)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := strings.Trim(scanner.Text(), "\n")
|
||||||
|
fields := strings.Split(line, " ")
|
||||||
|
|
||||||
|
if fields[0] == "obj" {
|
||||||
|
record := pkg.PortageFileRecord{
|
||||||
|
Path: fields[1],
|
||||||
|
}
|
||||||
|
record.Digest = &file.Digest{
|
||||||
|
Algorithm: "md5",
|
||||||
|
Value: fields[2],
|
||||||
|
}
|
||||||
|
entry.Files = append(entry.Files, record)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func addLicenses(resolver source.FileResolver, dbLocation source.Location, p *pkg.Package) {
|
||||||
|
parentPath := filepath.Dir(dbLocation.RealPath)
|
||||||
|
|
||||||
|
location := resolver.RelativeFileByPath(dbLocation, path.Join(parentPath, "LICENSE"))
|
||||||
|
|
||||||
|
if location != nil {
|
||||||
|
licenseReader, err := resolver.FileContentsByLocation(*location)
|
||||||
|
if err == nil {
|
||||||
|
findings := internal.NewStringSet()
|
||||||
|
scanner := bufio.NewScanner(licenseReader)
|
||||||
|
scanner.Split(bufio.ScanWords)
|
||||||
|
for scanner.Scan() {
|
||||||
|
token := scanner.Text()
|
||||||
|
if token != "||" && token != "(" && token != ")" {
|
||||||
|
findings.Add(token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.Licenses = findings.ToSlice()
|
||||||
|
|
||||||
|
sort.Strings(p.Licenses)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func addSize(resolver source.FileResolver, dbLocation source.Location, entry *pkg.PortageMetadata) {
|
||||||
|
parentPath := filepath.Dir(dbLocation.RealPath)
|
||||||
|
|
||||||
|
location := resolver.RelativeFileByPath(dbLocation, path.Join(parentPath, "SIZE"))
|
||||||
|
|
||||||
|
if location != nil {
|
||||||
|
sizeReader, err := resolver.FileContentsByLocation(*location)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("failed to fetch portage SIZE (package=%s): %+v", entry.Package, err)
|
||||||
|
} else {
|
||||||
|
scanner := bufio.NewScanner(sizeReader)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := strings.Trim(scanner.Text(), "\n")
|
||||||
|
size, err := strconv.Atoi(line)
|
||||||
|
if err == nil {
|
||||||
|
entry.InstalledSize = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
106
syft/pkg/cataloger/portage/cataloger_test.go
Normal file
106
syft/pkg/cataloger/portage/cataloger_test.go
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
package portage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/file"
|
||||||
|
|
||||||
|
"github.com/anchore/stereoscope/pkg/imagetest"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/source"
|
||||||
|
"github.com/go-test/deep"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPortageCataloger(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
expected []pkg.Package
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "go-case",
|
||||||
|
expected: []pkg.Package{
|
||||||
|
{
|
||||||
|
Name: "app-containers/skopeo",
|
||||||
|
Version: "1.5.1",
|
||||||
|
FoundBy: "portage-cataloger",
|
||||||
|
Licenses: []string{"Apache-2.0", "BSD", "BSD-2", "CC-BY-SA-4.0", "ISC", "MIT"},
|
||||||
|
Type: pkg.PortagePkg,
|
||||||
|
MetadataType: pkg.PortageMetadataType,
|
||||||
|
Metadata: pkg.PortageMetadata{
|
||||||
|
Package: "app-containers/skopeo",
|
||||||
|
Version: "1.5.1",
|
||||||
|
InstalledSize: 27937835,
|
||||||
|
Files: []pkg.PortageFileRecord{
|
||||||
|
{
|
||||||
|
Path: "/usr/bin/skopeo",
|
||||||
|
Digest: &file.Digest{
|
||||||
|
Algorithm: "md5",
|
||||||
|
Value: "376c02bd3b22804df8fdfdc895e7dbfb",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: "/etc/containers/policy.json",
|
||||||
|
Digest: &file.Digest{
|
||||||
|
Algorithm: "md5",
|
||||||
|
Value: "c01eb6950f03419e09d4fc88cb42ff6f",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: "/etc/containers/registries.d/default.yaml",
|
||||||
|
Digest: &file.Digest{
|
||||||
|
Algorithm: "md5",
|
||||||
|
Value: "e6e66cd3c24623e0667f26542e0e08f6",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: "/var/lib/atomic/sigstore/.keep_app-containers_skopeo-0",
|
||||||
|
Digest: &file.Digest{
|
||||||
|
Algorithm: "md5",
|
||||||
|
Value: "d41d8cd98f00b204e9800998ecf8427e",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
|
||||||
|
img := imagetest.GetFixtureImage(t, "docker-archive", "image-portage")
|
||||||
|
|
||||||
|
s, err := source.NewFromImage(img, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := NewPortageCataloger()
|
||||||
|
|
||||||
|
resolver, err := s.FileResolver(source.SquashedScope)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("could not get resolver error: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual, _, err := c.Catalog(resolver)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to catalog: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(actual) != len(test.expected) {
|
||||||
|
for _, a := range actual {
|
||||||
|
t.Logf(" %+v", a)
|
||||||
|
}
|
||||||
|
t.Fatalf("unexpected package count: %d!=%d", len(actual), len(test.expected))
|
||||||
|
}
|
||||||
|
|
||||||
|
// test remaining fields...
|
||||||
|
for _, d := range deep.Equal(actual, test.expected) {
|
||||||
|
t.Errorf("diff: %+v", d)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
FROM scratch
|
||||||
|
COPY . .
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
dir /usr
|
||||||
|
dir /usr/bin
|
||||||
|
obj /usr/bin/skopeo 376c02bd3b22804df8fdfdc895e7dbfb 1649284374
|
||||||
|
dir /etc
|
||||||
|
dir /etc/containers
|
||||||
|
obj /etc/containers/policy.json c01eb6950f03419e09d4fc88cb42ff6f 1649284375
|
||||||
|
dir /etc/containers/registries.d
|
||||||
|
obj /etc/containers/registries.d/default.yaml e6e66cd3c24623e0667f26542e0e08f6 1649284375
|
||||||
|
dir /var
|
||||||
|
dir /var/lib
|
||||||
|
dir /var/lib/atomic
|
||||||
|
dir /var/lib/atomic/sigstore
|
||||||
|
obj /var/lib/atomic/sigstore/.keep_app-containers_skopeo-0 d41d8cd98f00b204e9800998ecf8427e 1649284375
|
||||||
@ -0,0 +1 @@
|
|||||||
|
Apache-2.0 BSD BSD-2 CC-BY-SA-4.0 ISC MIT
|
||||||
@ -0,0 +1 @@
|
|||||||
|
27937835
|
||||||
@ -26,6 +26,7 @@ const (
|
|||||||
GolangBinMetadataType MetadataType = "GolangBinMetadata"
|
GolangBinMetadataType MetadataType = "GolangBinMetadata"
|
||||||
PhpComposerJSONMetadataType MetadataType = "PhpComposerJsonMetadata"
|
PhpComposerJSONMetadataType MetadataType = "PhpComposerJsonMetadata"
|
||||||
ConanaMetadataType MetadataType = "ConanaMetadataType"
|
ConanaMetadataType MetadataType = "ConanaMetadataType"
|
||||||
|
PortageMetadataType MetadataType = "PortageMetadata"
|
||||||
)
|
)
|
||||||
|
|
||||||
var AllMetadataTypes = []MetadataType{
|
var AllMetadataTypes = []MetadataType{
|
||||||
@ -44,6 +45,7 @@ var AllMetadataTypes = []MetadataType{
|
|||||||
GolangBinMetadataType,
|
GolangBinMetadataType,
|
||||||
PhpComposerJSONMetadataType,
|
PhpComposerJSONMetadataType,
|
||||||
ConanaMetadataType,
|
ConanaMetadataType,
|
||||||
|
PortageMetadataType,
|
||||||
}
|
}
|
||||||
|
|
||||||
var MetadataTypeByName = map[MetadataType]reflect.Type{
|
var MetadataTypeByName = map[MetadataType]reflect.Type{
|
||||||
@ -62,4 +64,5 @@ var MetadataTypeByName = map[MetadataType]reflect.Type{
|
|||||||
GolangBinMetadataType: reflect.TypeOf(GolangBinMetadata{}),
|
GolangBinMetadataType: reflect.TypeOf(GolangBinMetadata{}),
|
||||||
PhpComposerJSONMetadataType: reflect.TypeOf(PhpComposerJSONMetadata{}),
|
PhpComposerJSONMetadataType: reflect.TypeOf(PhpComposerJSONMetadata{}),
|
||||||
ConanaMetadataType: reflect.TypeOf(ConanMetadata{}),
|
ConanaMetadataType: reflect.TypeOf(ConanMetadata{}),
|
||||||
|
PortageMetadataType: reflect.TypeOf(PortageMetadata{}),
|
||||||
}
|
}
|
||||||
|
|||||||
21
syft/pkg/portage_metadata.go
Normal file
21
syft/pkg/portage_metadata.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package pkg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/anchore/syft/syft/file"
|
||||||
|
)
|
||||||
|
|
||||||
|
const PortageDBGlob = "**/var/db/pkg/*/*/CONTENTS"
|
||||||
|
|
||||||
|
// PortageMetadata represents all captured data for a Package package DB entry.
|
||||||
|
type PortageMetadata struct {
|
||||||
|
Package string `mapstructure:"Package" json:"package"`
|
||||||
|
Version string `mapstructure:"Version" json:"version"`
|
||||||
|
InstalledSize int `mapstructure:"InstalledSize" json:"installedSize" cyclonedx:"installedSize"`
|
||||||
|
Files []PortageFileRecord `json:"files"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PortageFileRecord represents a single file attributed to a portage package.
|
||||||
|
type PortageFileRecord struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Digest *file.Digest `json:"digest,omitempty"`
|
||||||
|
}
|
||||||
@ -24,6 +24,7 @@ const (
|
|||||||
DartPubPkg Type = "dart-pub"
|
DartPubPkg Type = "dart-pub"
|
||||||
DotnetPkg Type = "dotnet"
|
DotnetPkg Type = "dotnet"
|
||||||
ConanPkg Type = "conan"
|
ConanPkg Type = "conan"
|
||||||
|
PortagePkg Type = "portage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AllPkgs represents all supported package types
|
// AllPkgs represents all supported package types
|
||||||
@ -44,6 +45,7 @@ var AllPkgs = []Type{
|
|||||||
DartPubPkg,
|
DartPubPkg,
|
||||||
DotnetPkg,
|
DotnetPkg,
|
||||||
ConanPkg,
|
ConanPkg,
|
||||||
|
PortagePkg,
|
||||||
}
|
}
|
||||||
|
|
||||||
// PackageURLType returns the PURL package type for the current package.
|
// PackageURLType returns the PURL package type for the current package.
|
||||||
@ -77,6 +79,8 @@ func (t Type) PackageURLType() string {
|
|||||||
return packageurl.TypeDotnet
|
return packageurl.TypeDotnet
|
||||||
case ConanPkg:
|
case ConanPkg:
|
||||||
return packageurl.TypeConan
|
return packageurl.TypeConan
|
||||||
|
case PortagePkg:
|
||||||
|
return "portage"
|
||||||
default:
|
default:
|
||||||
// TODO: should this be a "generic" purl type instead?
|
// TODO: should this be a "generic" purl type instead?
|
||||||
return ""
|
return ""
|
||||||
@ -122,6 +126,8 @@ func TypeByName(name string) Type {
|
|||||||
return DotnetPkg
|
return DotnetPkg
|
||||||
case packageurl.TypeConan:
|
case packageurl.TypeConan:
|
||||||
return ConanPkg
|
return ConanPkg
|
||||||
|
case "portage":
|
||||||
|
return PortagePkg
|
||||||
default:
|
default:
|
||||||
return UnknownPkg
|
return UnknownPkg
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,6 +83,7 @@ func TestTypeFromPURL(t *testing.T) {
|
|||||||
// testing microsoft packages and jenkins-plugins is not valid for purl at this time
|
// testing microsoft packages and jenkins-plugins is not valid for purl at this time
|
||||||
expectedTypes.Remove(string(KbPkg))
|
expectedTypes.Remove(string(KbPkg))
|
||||||
expectedTypes.Remove(string(JenkinsPluginPkg))
|
expectedTypes.Remove(string(JenkinsPluginPkg))
|
||||||
|
expectedTypes.Remove(string(PortagePkg))
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(string(test.expected), func(t *testing.T) {
|
t.Run(string(test.expected), func(t *testing.T) {
|
||||||
|
|||||||
@ -233,6 +233,7 @@ func TestPackageURL(t *testing.T) {
|
|||||||
|
|
||||||
// testing microsoft packages is not valid for purl at this time
|
// testing microsoft packages is not valid for purl at this time
|
||||||
expectedTypes.Remove(string(KbPkg))
|
expectedTypes.Remove(string(KbPkg))
|
||||||
|
expectedTypes.Remove(string(PortagePkg))
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
|||||||
@ -96,7 +96,7 @@ func TestPackagesCmdFlags(t *testing.T) {
|
|||||||
name: "squashed-scope-flag",
|
name: "squashed-scope-flag",
|
||||||
args: []string{"packages", "-o", "json", "-s", "squashed", coverageImage},
|
args: []string{"packages", "-o", "json", "-s", "squashed", coverageImage},
|
||||||
assertions: []traitAssertion{
|
assertions: []traitAssertion{
|
||||||
assertPackageCount(33),
|
assertPackageCount(34),
|
||||||
assertSuccessfulReturnCode,
|
assertSuccessfulReturnCode,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -277,6 +277,14 @@ var commonTestCases = []testCase{
|
|||||||
"netbase": "5.4",
|
"netbase": "5.4",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "find portage packages",
|
||||||
|
pkgType: pkg.PortagePkg,
|
||||||
|
pkgInfo: map[string]string{
|
||||||
|
"app-containers/skopeo": "1.5.1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "find jenkins plugins",
|
name: "find jenkins plugins",
|
||||||
pkgType: pkg.JenkinsPluginPkg,
|
pkgType: pkg.JenkinsPluginPkg,
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
dir /usr
|
||||||
|
dir /usr/bin
|
||||||
|
obj /usr/bin/skopeo 376c02bd3b22804df8fdfdc895e7dbfb 1649284374
|
||||||
|
dir /etc
|
||||||
|
dir /etc/containers
|
||||||
|
obj /etc/containers/policy.json c01eb6950f03419e09d4fc88cb42ff6f 1649284375
|
||||||
|
dir /etc/containers/registries.d
|
||||||
|
obj /etc/containers/registries.d/default.yaml e6e66cd3c24623e0667f26542e0e08f6 1649284375
|
||||||
|
dir /var
|
||||||
|
dir /var/lib
|
||||||
|
dir /var/lib/atomic
|
||||||
|
dir /var/lib/atomic/sigstore
|
||||||
|
obj /var/lib/atomic/sigstore/.keep_app-containers_skopeo-0 d41d8cd98f00b204e9800998ecf8427e 1649284375
|
||||||
@ -0,0 +1 @@
|
|||||||
|
Apache-2.0 BSD BSD-2 CC-BY-SA-4.0 ISC MIT
|
||||||
@ -0,0 +1 @@
|
|||||||
|
27937835
|
||||||
Loading…
x
Reference in New Issue
Block a user