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
|
default: false
|
||||||
- name: package_manager.package_integrity_hash
|
- name: package_manager.package_integrity_hash
|
||||||
default: false
|
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.
|
// NewCataloger returns a new Snap cataloger object that can parse snap package metadata.
|
||||||
func NewCataloger() pkg.Cataloger {
|
func NewCataloger() pkg.Cataloger {
|
||||||
return generic.NewCataloger(catalogerName).
|
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
|
// Base snaps: dpkg.yaml files containing package manifests
|
||||||
WithParserByGlobs(parseBaseDpkgYaml, "**/usr/share/snappy/dpkg.yaml").
|
WithParserByGlobs(parseBaseDpkgYaml, "**/usr/share/snappy/dpkg.yaml").
|
||||||
// Kernel snaps: changelog files for kernel version info
|
// Kernel snaps: changelog files for kernel version info
|
||||||
|
|||||||
@ -19,17 +19,13 @@ func TestCataloger_Globs(t *testing.T) {
|
|||||||
name: "system snap with manifest.yaml",
|
name: "system snap with manifest.yaml",
|
||||||
fixture: "test-fixtures/glob-paths/system",
|
fixture: "test-fixtures/glob-paths/system",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "snap with meta/snap.yaml",
|
|
||||||
fixture: "test-fixtures/glob-paths/meta",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
pkgtest.NewCatalogTester().
|
pkgtest.NewCatalogTester().
|
||||||
FromDirectory(t, test.fixture).
|
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())
|
TestCataloger(t, NewCataloger())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,30 +8,6 @@ import (
|
|||||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
|
"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) {
|
func TestParseSystemManifest(t *testing.T) {
|
||||||
fixture := "test-fixtures/manifest.yaml"
|
fixture := "test-fixtures/manifest.yaml"
|
||||||
locations := file.NewLocationSet(file.NewLocation(fixture))
|
locations := file.NewLocationSet(file.NewLocation(fixture))
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ func readChangelogLines(reader file.LocationReadCloser) ([]string, error) {
|
|||||||
}
|
}
|
||||||
defer gzReader.Close()
|
defer gzReader.Close()
|
||||||
|
|
||||||
content, err := readAll(gzReader)
|
content, err := io.ReadAll(gzReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read changelog content: %w", err)
|
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