mirror of
https://github.com/anchore/syft.git
synced 2026-02-12 02:26:42 +01:00
fix: snap cataloger incorrectly identifies snap container as deb package (#4500)
Signed-off-by: Alan Pope <alan@popey.com> Signed-off-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com> Co-authored-by: Christopher Phillips <32073428+spiffcs@users.noreply.github.com>
This commit is contained in:
parent
8d836fb8b0
commit
0bca34f986
@ -118,29 +118,3 @@ catalogers:
|
||||
default: false
|
||||
- name: package_manager.package_integrity_hash
|
||||
default: false
|
||||
- function: parseSnapYaml
|
||||
detector: # AUTO-GENERATED
|
||||
method: glob # AUTO-GENERATED
|
||||
criteria: # AUTO-GENERATED
|
||||
- '**/meta/snap.yaml'
|
||||
metadata_types: # AUTO-GENERATED
|
||||
- pkg.SnapEntry
|
||||
package_types: # AUTO-GENERATED
|
||||
- deb
|
||||
json_schema_types: # AUTO-GENERATED
|
||||
- SnapEntry
|
||||
capabilities: # MANUAL - preserved across regeneration
|
||||
- name: license
|
||||
default: false
|
||||
- name: dependency.depth
|
||||
default: []
|
||||
- name: dependency.edges
|
||||
default: ""
|
||||
- name: dependency.kinds
|
||||
default: []
|
||||
- name: package_manager.files.listing
|
||||
default: false
|
||||
- name: package_manager.files.digests
|
||||
default: false
|
||||
- name: package_manager.package_integrity_hash
|
||||
default: false
|
||||
|
||||
@ -15,8 +15,6 @@ const catalogerName = "snap-cataloger"
|
||||
// NewCataloger returns a new Snap cataloger object that can parse snap package metadata.
|
||||
func NewCataloger() pkg.Cataloger {
|
||||
return generic.NewCataloger(catalogerName).
|
||||
// Look for snap.yaml to identify snap type and base snap info
|
||||
WithParserByGlobs(parseSnapYaml, "**/meta/snap.yaml").
|
||||
// Base snaps: dpkg.yaml files containing package manifests
|
||||
WithParserByGlobs(parseBaseDpkgYaml, "**/usr/share/snappy/dpkg.yaml").
|
||||
// Kernel snaps: changelog files for kernel version info
|
||||
|
||||
@ -19,17 +19,13 @@ func TestCataloger_Globs(t *testing.T) {
|
||||
name: "system snap with manifest.yaml",
|
||||
fixture: "test-fixtures/glob-paths/system",
|
||||
},
|
||||
{
|
||||
name: "snap with meta/snap.yaml",
|
||||
fixture: "test-fixtures/glob-paths/meta",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
pkgtest.NewCatalogTester().
|
||||
FromDirectory(t, test.fixture).
|
||||
IgnoreUnfulfilledPathResponses("**/meta/snap.yaml", "**/usr/share/snappy/dpkg.yaml", "**/doc/linux-modules-*/changelog.Debian.gz", "**/snap/manifest.yaml", "**/snap/snapcraft.yaml").
|
||||
IgnoreUnfulfilledPathResponses("**/usr/share/snappy/dpkg.yaml", "**/doc/linux-modules-*/changelog.Debian.gz", "**/snap/manifest.yaml", "**/snap/snapcraft.yaml").
|
||||
TestCataloger(t, NewCataloger())
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,30 +8,6 @@ import (
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
|
||||
)
|
||||
|
||||
func TestParseSnapYaml(t *testing.T) {
|
||||
fixture := "test-fixtures/snap.yaml"
|
||||
locations := file.NewLocationSet(file.NewLocation(fixture))
|
||||
|
||||
expected := []pkg.Package{
|
||||
{
|
||||
Name: "test-snap",
|
||||
Version: "1.0.0",
|
||||
Type: pkg.DebPkg,
|
||||
PURL: "pkg:generic/snap/test-snap@1.0.0?arch=amd64&base=core20&type=app",
|
||||
Locations: locations,
|
||||
Metadata: pkg.SnapEntry{
|
||||
SnapType: pkg.SnapTypeApp,
|
||||
Base: "core20",
|
||||
SnapName: "test-snap",
|
||||
SnapVersion: "1.0.0",
|
||||
Architecture: "amd64",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pkgtest.TestFileParser(t, fixture, parseSnapYaml, expected, nil)
|
||||
}
|
||||
|
||||
func TestParseSystemManifest(t *testing.T) {
|
||||
fixture := "test-fixtures/manifest.yaml"
|
||||
locations := file.NewLocationSet(file.NewLocation(fixture))
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"compress/gzip"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
@ -58,7 +59,7 @@ func readChangelogLines(reader file.LocationReadCloser) ([]string, error) {
|
||||
}
|
||||
defer gzReader.Close()
|
||||
|
||||
content, err := readAll(gzReader)
|
||||
content, err := io.ReadAll(gzReader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read changelog content: %w", err)
|
||||
}
|
||||
|
||||
@ -1,68 +0,0 @@
|
||||
package snap
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/generic"
|
||||
)
|
||||
|
||||
// snapYaml represents the structure of meta/snap.yaml files
|
||||
type snapYaml struct {
|
||||
Name string `yaml:"name"`
|
||||
Version string `yaml:"version"`
|
||||
Base string `yaml:"base"`
|
||||
Type string `yaml:"type"`
|
||||
Architecture string `yaml:"architecture"`
|
||||
Summary string `yaml:"summary"`
|
||||
Description string `yaml:"description"`
|
||||
}
|
||||
|
||||
// parseSnapYaml parses meta/snap.yaml files to identify snap type and basic metadata
|
||||
func parseSnapYaml(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||
var snap snapYaml
|
||||
|
||||
decoder := yaml.NewDecoder(reader)
|
||||
if err := decoder.Decode(&snap); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to parse snap.yaml: %w", err)
|
||||
}
|
||||
|
||||
if snap.Name == "" {
|
||||
return nil, nil, fmt.Errorf("snap.yaml missing required 'name' field")
|
||||
}
|
||||
|
||||
// Determine snap type - default to "app" if not specified
|
||||
snapType := snap.Type
|
||||
if snapType == "" {
|
||||
snapType = pkg.SnapTypeApp
|
||||
}
|
||||
|
||||
metadata := pkg.SnapEntry{
|
||||
SnapType: snapType,
|
||||
Base: snap.Base,
|
||||
SnapName: snap.Name,
|
||||
SnapVersion: snap.Version,
|
||||
Architecture: snap.Architecture,
|
||||
}
|
||||
|
||||
// Create a package representing the snap itself
|
||||
snapPkg := newPackage(
|
||||
snap.Name,
|
||||
snap.Version,
|
||||
metadata,
|
||||
reader.Location,
|
||||
)
|
||||
|
||||
return []pkg.Package{snapPkg}, nil, nil
|
||||
}
|
||||
|
||||
// readAll reads all content from a reader and returns it as bytes
|
||||
func readAll(r io.Reader) ([]byte, error) {
|
||||
return io.ReadAll(r)
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
name: test-snap
|
||||
version: 1.0
|
||||
type: app
|
||||
@ -1,7 +0,0 @@
|
||||
name: test-snap
|
||||
version: 1.0.0
|
||||
summary: A test snap
|
||||
description: This is a test snap for testing purposes
|
||||
base: core20
|
||||
type: app
|
||||
architecture: amd64
|
||||
Loading…
x
Reference in New Issue
Block a user