From cd4e362d84a59c840c7f0ce17e7f722b46aa45bf Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Fri, 7 Apr 2023 11:04:39 -0400 Subject: [PATCH 01/12] add location annotations + deb evidence annotations Signed-off-by: Alex Goodman --- .../common/spdxhelpers/to_syft_model.go | 6 +- syft/formats/syftjson/model/package.go | 20 +-- syft/formats/syftjson/to_format_model.go | 8 +- syft/formats/syftjson/to_syft_model.go | 7 +- syft/pkg/cataloger/deb/cataloger.go | 2 +- syft/pkg/cataloger/deb/package.go | 33 ++--- syft/pkg/evidence.go | 7 ++ syft/source/location.go | 117 ++++++++++++++---- syft/source/location_set.go | 30 +++-- syft/source/mock_resolver.go | 11 +- 10 files changed, 165 insertions(+), 76 deletions(-) create mode 100644 syft/pkg/evidence.go diff --git a/syft/formats/common/spdxhelpers/to_syft_model.go b/syft/formats/common/spdxhelpers/to_syft_model.go index 4993eea7e87..e66d014a2d4 100644 --- a/syft/formats/common/spdxhelpers/to_syft_model.go +++ b/syft/formats/common/spdxhelpers/to_syft_model.go @@ -220,10 +220,8 @@ func toSyftCoordinates(f *spdx.File) source.Coordinates { } func toSyftLocation(f *spdx.File) *source.Location { - return &source.Location{ - Coordinates: toSyftCoordinates(f), - VirtualPath: f.FileName, - } + l := source.NewVirtualLocationFromCoordinates(toSyftCoordinates(f), f.FileName) + return &l } func requireAndTrimPrefix(val interface{}, prefix string) string { diff --git a/syft/formats/syftjson/model/package.go b/syft/formats/syftjson/model/package.go index 4567a139aeb..608b2be3ca2 100644 --- a/syft/formats/syftjson/model/package.go +++ b/syft/formats/syftjson/model/package.go @@ -21,16 +21,16 @@ type Package struct { // PackageBasicData contains non-ambiguous values (type-wise) from pkg.Package. type PackageBasicData struct { - ID string `json:"id"` - Name string `json:"name"` - Version string `json:"version"` - Type pkg.Type `json:"type"` - FoundBy string `json:"foundBy"` - Locations []source.Coordinates `json:"locations"` - Licenses []string `json:"licenses"` - Language pkg.Language `json:"language"` - CPEs []string `json:"cpes"` - PURL string `json:"purl"` + ID string `json:"id"` + Name string `json:"name"` + Version string `json:"version"` + Type pkg.Type `json:"type"` + FoundBy string `json:"foundBy"` + Locations []source.Location `json:"locations"` + Licenses []string `json:"licenses"` + Language pkg.Language `json:"language"` + CPEs []string `json:"cpes"` + PURL string `json:"purl"` } // PackageCustomData contains ambiguous values (type-wise) from pkg.Package. diff --git a/syft/formats/syftjson/to_format_model.go b/syft/formats/syftjson/to_format_model.go index b5067d6aef6..61ebe1007ef 100644 --- a/syft/formats/syftjson/to_format_model.go +++ b/syft/formats/syftjson/to_format_model.go @@ -195,12 +195,6 @@ func toPackageModel(p pkg.Package) model.Package { licenses = p.Licenses } - locations := p.Locations.ToSlice() - var coordinates = make([]source.Coordinates, len(locations)) - for i, l := range locations { - coordinates[i] = l.Coordinates - } - return model.Package{ PackageBasicData: model.PackageBasicData{ ID: string(p.ID()), @@ -208,7 +202,7 @@ func toPackageModel(p pkg.Package) model.Package { Version: p.Version, Type: p.Type, FoundBy: p.FoundBy, - Locations: coordinates, + Locations: p.Locations.ToSlice(), Licenses: licenses, Language: p.Language, CPEs: cpes, diff --git a/syft/formats/syftjson/to_syft_model.go b/syft/formats/syftjson/to_syft_model.go index 0418a41c187..cbad53fb0fd 100644 --- a/syft/formats/syftjson/to_syft_model.go +++ b/syft/formats/syftjson/to_syft_model.go @@ -202,16 +202,11 @@ func toSyftPackage(p model.Package, idAliases map[string]string) pkg.Package { cpes = append(cpes, value) } - var locations = make([]source.Location, len(p.Locations)) - for i, c := range p.Locations { - locations[i] = source.NewLocationFromCoordinates(c) - } - out := pkg.Package{ Name: p.Name, Version: p.Version, FoundBy: p.FoundBy, - Locations: source.NewLocationSet(locations...), + Locations: source.NewLocationSet(p.Locations...), Licenses: p.Licenses, Language: p.Language, Type: p.Type, diff --git a/syft/pkg/cataloger/deb/cataloger.go b/syft/pkg/cataloger/deb/cataloger.go index fb25550c404..70bd8e4260a 100644 --- a/syft/pkg/cataloger/deb/cataloger.go +++ b/syft/pkg/cataloger/deb/cataloger.go @@ -1,5 +1,5 @@ /* -Package dpkg provides a concrete Cataloger implementation for Debian package DB status files. +Package deb provides a concrete Cataloger implementation for Debian package DB status files. */ package deb diff --git a/syft/pkg/cataloger/deb/package.go b/syft/pkg/cataloger/deb/package.go index 3f10dbe3fe1..f0e159b8d6f 100644 --- a/syft/pkg/cataloger/deb/package.go +++ b/syft/pkg/cataloger/deb/package.go @@ -22,10 +22,11 @@ const ( ) func newDpkgPackage(d pkg.DpkgMetadata, dbLocation source.Location, resolver source.FileResolver, release *linux.Release) pkg.Package { + p := pkg.Package{ Name: d.Package, Version: d.Version, - Locations: source.NewLocationSet(dbLocation), + Locations: source.NewLocationSet(*dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(d, release), Type: pkg.DebPkg, MetadataType: pkg.DpkgMetadataType, @@ -182,15 +183,17 @@ func fetchMd5Contents(resolver source.FileResolver, dbLocation source.Location, location = resolver.RelativeFileByPath(dbLocation, path.Join(parentPath, "info", m.Package+md5sumsExt)) } + if location == nil { + return nil, nil + } + // this is unexpected, but not a show-stopper - if location != nil { - md5Reader, err = resolver.FileContentsByLocation(*location) - if err != nil { - log.Warnf("failed to fetch deb md5 contents (package=%s): %+v", m.Package, err) - } + md5Reader, err = resolver.FileContentsByLocation(*location) + if err != nil { + log.Warnf("failed to fetch deb md5 contents (package=%s): %+v", m.Package, err) } - return md5Reader, location + return md5Reader, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) } func fetchConffileContents(resolver source.FileResolver, dbLocation source.Location, m pkg.DpkgMetadata) (io.ReadCloser, *source.Location) { @@ -213,15 +216,17 @@ func fetchConffileContents(resolver source.FileResolver, dbLocation source.Locat location = resolver.RelativeFileByPath(dbLocation, path.Join(parentPath, "info", m.Package+conffilesExt)) } + if location == nil { + return nil, nil + } + // this is unexpected, but not a show-stopper - if location != nil { - reader, err = resolver.FileContentsByLocation(*location) - if err != nil { - log.Warnf("failed to fetch deb conffiles contents (package=%s): %+v", m.Package, err) - } + reader, err = resolver.FileContentsByLocation(*location) + if err != nil { + log.Warnf("failed to fetch deb conffiles contents (package=%s): %+v", m.Package, err) } - return reader, location + return reader, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) } func fetchCopyrightContents(resolver source.FileResolver, dbLocation source.Location, m pkg.DpkgMetadata) (io.ReadCloser, *source.Location) { @@ -243,7 +248,7 @@ func fetchCopyrightContents(resolver source.FileResolver, dbLocation source.Loca log.Warnf("failed to fetch deb copyright contents (package=%s): %w", m.Package, err) } - return reader, location + return reader, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) } func md5Key(metadata pkg.DpkgMetadata) string { diff --git a/syft/pkg/evidence.go b/syft/pkg/evidence.go new file mode 100644 index 00000000000..9a7ae5f52bf --- /dev/null +++ b/syft/pkg/evidence.go @@ -0,0 +1,7 @@ +package pkg + +const ( + EvidenceAnnotationKey = "evidence" + PrimaryEvidenceAnnotation = "primary" + SupportingEvidenceAnnotation = "supporting" +) diff --git a/syft/source/location.go b/syft/source/location.go index b4f1b267a4a..ce3df5835d2 100644 --- a/syft/source/location.go +++ b/syft/source/location.go @@ -2,6 +2,7 @@ package source import ( "fmt" + "github.com/hashicorp/go-multierror" "github.com/anchore/stereoscope/pkg/file" "github.com/anchore/stereoscope/pkg/image" @@ -10,18 +11,55 @@ import ( // Location represents a path relative to a particular filesystem resolved to a specific file.Reference. This struct is used as a key // in content fetching to uniquely identify a file relative to a request (the VirtualPath). type Location struct { + PositionInfo `cyclonedx:""` + LocationMetadata `cyclonedx:""` +} + +type PositionInfo struct { Coordinates `cyclonedx:""` // Empty string here means there is no intermediate property name, e.g. syft:locations:0:path without "coordinates" // note: it is IMPORTANT to ignore anything but the coordinates for a Location when considering the ID (hash value) // since the coordinates are the minimally correct ID for a location (symlinks should not come into play) - VirtualPath string `hash:"ignore" json:"virtualPath,omitempty"` // The path to the file which may or may not have hardlinks / symlinks - ref file.Reference `hash:"ignore"` // The file reference relative to the stereoscope.FileCatalog that has more information about this location. + VirtualPath string `hash:"ignore" json:"-"` // The path to the file which may or may not have hardlinks / symlinks + ref file.Reference `hash:"ignore"` // The file reference relative to the stereoscope.FileCatalog that has more information about this location. +} + +type LocationMetadata struct { + Annotations map[string]string `json:"annotations,omitempty"` // Arbitrary key-value pairs that can be used to annotate a location +} + +func (m *LocationMetadata) merge(other LocationMetadata) error { + var errs error + for k, v := range other.Annotations { + if otherV, ok := m.Annotations[k]; ok { + if v != otherV { + err := fmt.Errorf("unable to merge location metadata: conflicting values for key=%q: %q != %q", k, v, otherV) + errs = multierror.Append(errs, err) + continue + } + } + m.Annotations[k] = v + } + return errs +} + +func (l *Location) WithAnnotation(key, value string) *Location { + if l.LocationMetadata.Annotations == nil { + l.LocationMetadata.Annotations = map[string]string{} + } + l.LocationMetadata.Annotations[key] = value + return l } // NewLocation creates a new Location representing a path without denoting a filesystem or FileCatalog reference. func NewLocation(realPath string) Location { return Location{ - Coordinates: Coordinates{ - RealPath: realPath, + PositionInfo: PositionInfo{ + Coordinates: Coordinates{ + RealPath: realPath, + }, + }, + LocationMetadata: LocationMetadata{ + Annotations: map[string]string{}, }, } } @@ -29,40 +67,70 @@ func NewLocation(realPath string) Location { // NewVirtualLocation creates a new location for a path accessed by a virtual path (a path with a symlink or hardlink somewhere in the path) func NewVirtualLocation(realPath, virtualPath string) Location { return Location{ - Coordinates: Coordinates{ - RealPath: realPath, + PositionInfo: PositionInfo{ + Coordinates: Coordinates{ + RealPath: realPath, + }, + VirtualPath: virtualPath, }, - VirtualPath: virtualPath, - } + LocationMetadata: LocationMetadata{ + Annotations: map[string]string{}, + }} } // NewLocationFromCoordinates creates a new location for the given Coordinates. func NewLocationFromCoordinates(coordinates Coordinates) Location { return Location{ - Coordinates: coordinates, - } + PositionInfo: PositionInfo{ + Coordinates: coordinates, + }, + LocationMetadata: LocationMetadata{ + Annotations: map[string]string{}, + }} +} + +// NewVirtualLocationFromCoordinates creates a new location for the given Coordinates via a virtual path. +func NewVirtualLocationFromCoordinates(coordinates Coordinates, virtualPath string) Location { + return Location{ + PositionInfo: PositionInfo{ + Coordinates: coordinates, + VirtualPath: virtualPath, + }, + LocationMetadata: LocationMetadata{ + Annotations: map[string]string{}, + }} } // NewLocationFromImage creates a new Location representing the given path (extracted from the ref) relative to the given image. func NewLocationFromImage(virtualPath string, ref file.Reference, img *image.Image) Location { layer := img.FileCatalog.Layer(ref) return Location{ - Coordinates: Coordinates{ - RealPath: string(ref.RealPath), - FileSystemID: layer.Metadata.Digest, + PositionInfo: PositionInfo{ + Coordinates: Coordinates{ + RealPath: string(ref.RealPath), + FileSystemID: layer.Metadata.Digest, + }, + VirtualPath: virtualPath, + ref: ref, + }, + LocationMetadata: LocationMetadata{ + Annotations: map[string]string{}, }, - VirtualPath: virtualPath, - ref: ref, } } // NewLocationFromDirectory creates a new Location representing the given path (extracted from the ref) relative to the given directory. func NewLocationFromDirectory(responsePath string, ref file.Reference) Location { return Location{ - Coordinates: Coordinates{ - RealPath: responsePath, + PositionInfo: PositionInfo{ + Coordinates: Coordinates{ + RealPath: responsePath, + }, + ref: ref, + }, + LocationMetadata: LocationMetadata{ + Annotations: map[string]string{}, }, - ref: ref, } } @@ -72,11 +140,16 @@ func NewVirtualLocationFromDirectory(responsePath, virtualResponsePath string, r return NewLocationFromDirectory(responsePath, ref) } return Location{ - Coordinates: Coordinates{ - RealPath: responsePath, + PositionInfo: PositionInfo{ + Coordinates: Coordinates{ + RealPath: responsePath, + }, + VirtualPath: virtualResponsePath, + ref: ref, + }, + LocationMetadata: LocationMetadata{ + Annotations: map[string]string{}, }, - VirtualPath: virtualResponsePath, - ref: ref, } } diff --git a/syft/source/location_set.go b/syft/source/location_set.go index c2e915921b7..bfbad5ada50 100644 --- a/syft/source/location_set.go +++ b/syft/source/location_set.go @@ -1,13 +1,15 @@ package source import ( + "github.com/anchore/syft/internal/log" "sort" "github.com/mitchellh/hashstructure/v2" ) type LocationSet struct { - set map[Location]struct{} + set map[PositionInfo]struct{} + metadata map[PositionInfo]LocationMetadata } func NewLocationSet(locations ...Location) (s LocationSet) { @@ -20,10 +22,20 @@ func NewLocationSet(locations ...Location) (s LocationSet) { func (s *LocationSet) Add(locations ...Location) { if s.set == nil { - s.set = make(map[Location]struct{}) + s.set = make(map[PositionInfo]struct{}) + s.metadata = make(map[PositionInfo]LocationMetadata) } for _, l := range locations { - s.set[l] = struct{}{} + s.set[l.PositionInfo] = struct{}{} + if m, ok := s.metadata[l.PositionInfo]; ok { + err := m.merge(l.LocationMetadata) + if err != nil { + log.Warnf("partial merge of location metadata: %+v", err) + } + s.metadata[l.PositionInfo] = m + } else { + s.metadata[l.PositionInfo] = l.LocationMetadata + } } } @@ -32,7 +44,8 @@ func (s LocationSet) Remove(locations ...Location) { return } for _, l := range locations { - delete(s.set, l) + delete(s.set, l.PositionInfo) + delete(s.metadata, l.PositionInfo) } } @@ -40,7 +53,7 @@ func (s LocationSet) Contains(l Location) bool { if s.set == nil { return false } - _, ok := s.set[l] + _, ok := s.set[l.PositionInfo] return ok } @@ -50,8 +63,11 @@ func (s LocationSet) ToSlice() []Location { } locations := make([]Location, len(s.set)) idx := 0 - for v := range s.set { - locations[idx] = v + for dir := range s.set { + locations[idx] = Location{ + PositionInfo: dir, + LocationMetadata: s.metadata[dir], + } idx++ } sort.Sort(Locations(locations)) diff --git a/syft/source/mock_resolver.go b/syft/source/mock_resolver.go index f0e95cc38a6..89960d6bdd0 100644 --- a/syft/source/mock_resolver.go +++ b/syft/source/mock_resolver.go @@ -18,7 +18,7 @@ var _ FileResolver = (*MockResolver)(nil) // paths, which are typically paths to test fixtures. type MockResolver struct { locations []Location - metadata map[Location]FileMetadata + metadata map[Coordinates]FileMetadata mimeTypeIndex map[string][]Location extension map[string][]Location basename map[string][]Location @@ -41,18 +41,19 @@ func NewMockResolverForPaths(paths ...string) *MockResolver { return &MockResolver{ locations: locations, - metadata: make(map[Location]FileMetadata), + metadata: make(map[Coordinates]FileMetadata), extension: extension, basename: basename, } } -func NewMockResolverForPathsWithMetadata(metadata map[Location]FileMetadata) *MockResolver { +func NewMockResolverForPathsWithMetadata(metadata map[Coordinates]FileMetadata) *MockResolver { var locations []Location var mimeTypeIndex = make(map[string][]Location) extension := make(map[string][]Location) basename := make(map[string][]Location) - for l, m := range metadata { + for c, m := range metadata { + l := NewLocationFromCoordinates(c) locations = append(locations, l) mimeTypeIndex[m.MIMEType] = append(mimeTypeIndex[m.MIMEType], l) ext := path.Ext(l.RealPath) @@ -89,7 +90,7 @@ func (r MockResolver) String() string { // path does not exist, an error is returned. func (r MockResolver) FileContentsByLocation(location Location) (io.ReadCloser, error) { for _, l := range r.locations { - if l == location { + if l.Coordinates == location.Coordinates { return os.Open(location.RealPath) } } From de226b1eb64dfe572c1c0386cce642186b300b75 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 12 Apr 2023 13:28:31 -0400 Subject: [PATCH 02/12] rename LocationData struct and Annotation helper function Signed-off-by: Alex Goodman --- syft/pkg/cataloger/deb/package.go | 8 ++++---- syft/source/location.go | 20 ++++++++++---------- syft/source/location_set.go | 24 ++++++++++++------------ 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/syft/pkg/cataloger/deb/package.go b/syft/pkg/cataloger/deb/package.go index f0e159b8d6f..b544dc7821d 100644 --- a/syft/pkg/cataloger/deb/package.go +++ b/syft/pkg/cataloger/deb/package.go @@ -26,7 +26,7 @@ func newDpkgPackage(d pkg.DpkgMetadata, dbLocation source.Location, resolver sou p := pkg.Package{ Name: d.Package, Version: d.Version, - Locations: source.NewLocationSet(*dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Locations: source.NewLocationSet(*dbLocation.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(d, release), Type: pkg.DebPkg, MetadataType: pkg.DpkgMetadataType, @@ -193,7 +193,7 @@ func fetchMd5Contents(resolver source.FileResolver, dbLocation source.Location, log.Warnf("failed to fetch deb md5 contents (package=%s): %+v", m.Package, err) } - return md5Reader, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) + return md5Reader, location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) } func fetchConffileContents(resolver source.FileResolver, dbLocation source.Location, m pkg.DpkgMetadata) (io.ReadCloser, *source.Location) { @@ -226,7 +226,7 @@ func fetchConffileContents(resolver source.FileResolver, dbLocation source.Locat log.Warnf("failed to fetch deb conffiles contents (package=%s): %+v", m.Package, err) } - return reader, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) + return reader, location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) } func fetchCopyrightContents(resolver source.FileResolver, dbLocation source.Location, m pkg.DpkgMetadata) (io.ReadCloser, *source.Location) { @@ -248,7 +248,7 @@ func fetchCopyrightContents(resolver source.FileResolver, dbLocation source.Loca log.Warnf("failed to fetch deb copyright contents (package=%s): %w", m.Package, err) } - return reader, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) + return reader, location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) } func md5Key(metadata pkg.DpkgMetadata) string { diff --git a/syft/source/location.go b/syft/source/location.go index ce3df5835d2..74ba98f2951 100644 --- a/syft/source/location.go +++ b/syft/source/location.go @@ -11,11 +11,11 @@ import ( // Location represents a path relative to a particular filesystem resolved to a specific file.Reference. This struct is used as a key // in content fetching to uniquely identify a file relative to a request (the VirtualPath). type Location struct { - PositionInfo `cyclonedx:""` + LocationData `cyclonedx:""` LocationMetadata `cyclonedx:""` } -type PositionInfo struct { +type LocationData struct { Coordinates `cyclonedx:""` // Empty string here means there is no intermediate property name, e.g. syft:locations:0:path without "coordinates" // note: it is IMPORTANT to ignore anything but the coordinates for a Location when considering the ID (hash value) // since the coordinates are the minimally correct ID for a location (symlinks should not come into play) @@ -42,7 +42,7 @@ func (m *LocationMetadata) merge(other LocationMetadata) error { return errs } -func (l *Location) WithAnnotation(key, value string) *Location { +func (l *Location) Annotate(key, value string) *Location { if l.LocationMetadata.Annotations == nil { l.LocationMetadata.Annotations = map[string]string{} } @@ -53,7 +53,7 @@ func (l *Location) WithAnnotation(key, value string) *Location { // NewLocation creates a new Location representing a path without denoting a filesystem or FileCatalog reference. func NewLocation(realPath string) Location { return Location{ - PositionInfo: PositionInfo{ + LocationData: LocationData{ Coordinates: Coordinates{ RealPath: realPath, }, @@ -67,7 +67,7 @@ func NewLocation(realPath string) Location { // NewVirtualLocation creates a new location for a path accessed by a virtual path (a path with a symlink or hardlink somewhere in the path) func NewVirtualLocation(realPath, virtualPath string) Location { return Location{ - PositionInfo: PositionInfo{ + LocationData: LocationData{ Coordinates: Coordinates{ RealPath: realPath, }, @@ -81,7 +81,7 @@ func NewVirtualLocation(realPath, virtualPath string) Location { // NewLocationFromCoordinates creates a new location for the given Coordinates. func NewLocationFromCoordinates(coordinates Coordinates) Location { return Location{ - PositionInfo: PositionInfo{ + LocationData: LocationData{ Coordinates: coordinates, }, LocationMetadata: LocationMetadata{ @@ -92,7 +92,7 @@ func NewLocationFromCoordinates(coordinates Coordinates) Location { // NewVirtualLocationFromCoordinates creates a new location for the given Coordinates via a virtual path. func NewVirtualLocationFromCoordinates(coordinates Coordinates, virtualPath string) Location { return Location{ - PositionInfo: PositionInfo{ + LocationData: LocationData{ Coordinates: coordinates, VirtualPath: virtualPath, }, @@ -105,7 +105,7 @@ func NewVirtualLocationFromCoordinates(coordinates Coordinates, virtualPath stri func NewLocationFromImage(virtualPath string, ref file.Reference, img *image.Image) Location { layer := img.FileCatalog.Layer(ref) return Location{ - PositionInfo: PositionInfo{ + LocationData: LocationData{ Coordinates: Coordinates{ RealPath: string(ref.RealPath), FileSystemID: layer.Metadata.Digest, @@ -122,7 +122,7 @@ func NewLocationFromImage(virtualPath string, ref file.Reference, img *image.Ima // NewLocationFromDirectory creates a new Location representing the given path (extracted from the ref) relative to the given directory. func NewLocationFromDirectory(responsePath string, ref file.Reference) Location { return Location{ - PositionInfo: PositionInfo{ + LocationData: LocationData{ Coordinates: Coordinates{ RealPath: responsePath, }, @@ -140,7 +140,7 @@ func NewVirtualLocationFromDirectory(responsePath, virtualResponsePath string, r return NewLocationFromDirectory(responsePath, ref) } return Location{ - PositionInfo: PositionInfo{ + LocationData: LocationData{ Coordinates: Coordinates{ RealPath: responsePath, }, diff --git a/syft/source/location_set.go b/syft/source/location_set.go index bfbad5ada50..910e629773a 100644 --- a/syft/source/location_set.go +++ b/syft/source/location_set.go @@ -8,8 +8,8 @@ import ( ) type LocationSet struct { - set map[PositionInfo]struct{} - metadata map[PositionInfo]LocationMetadata + set map[LocationData]struct{} + metadata map[LocationData]LocationMetadata } func NewLocationSet(locations ...Location) (s LocationSet) { @@ -22,19 +22,19 @@ func NewLocationSet(locations ...Location) (s LocationSet) { func (s *LocationSet) Add(locations ...Location) { if s.set == nil { - s.set = make(map[PositionInfo]struct{}) - s.metadata = make(map[PositionInfo]LocationMetadata) + s.set = make(map[LocationData]struct{}) + s.metadata = make(map[LocationData]LocationMetadata) } for _, l := range locations { - s.set[l.PositionInfo] = struct{}{} - if m, ok := s.metadata[l.PositionInfo]; ok { + s.set[l.LocationData] = struct{}{} + if m, ok := s.metadata[l.LocationData]; ok { err := m.merge(l.LocationMetadata) if err != nil { log.Warnf("partial merge of location metadata: %+v", err) } - s.metadata[l.PositionInfo] = m + s.metadata[l.LocationData] = m } else { - s.metadata[l.PositionInfo] = l.LocationMetadata + s.metadata[l.LocationData] = l.LocationMetadata } } } @@ -44,8 +44,8 @@ func (s LocationSet) Remove(locations ...Location) { return } for _, l := range locations { - delete(s.set, l.PositionInfo) - delete(s.metadata, l.PositionInfo) + delete(s.set, l.LocationData) + delete(s.metadata, l.LocationData) } } @@ -53,7 +53,7 @@ func (s LocationSet) Contains(l Location) bool { if s.set == nil { return false } - _, ok := s.set[l.PositionInfo] + _, ok := s.set[l.LocationData] return ok } @@ -65,7 +65,7 @@ func (s LocationSet) ToSlice() []Location { idx := 0 for dir := range s.set { locations[idx] = Location{ - PositionInfo: dir, + LocationData: dir, LocationMetadata: s.metadata[dir], } idx++ From e17ebd67b678ff2ca49de4f42176bb47cfe3edea Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 12 Apr 2023 14:43:02 -0400 Subject: [PATCH 03/12] add failing integration test for evidence coverage Signed-off-by: Alex Goodman --- test/integration/catalog_packages_test.go | 59 +++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/test/integration/catalog_packages_test.go b/test/integration/catalog_packages_test.go index 128b585aa8b..ff7497942d2 100644 --- a/test/integration/catalog_packages_test.go +++ b/test/integration/catalog_packages_test.go @@ -1,6 +1,7 @@ package integration import ( + "github.com/scylladb/go-set/strset" "strings" "testing" @@ -254,3 +255,61 @@ func TestPkgCoverageCatalogerConfiguration(t *testing.T) { c.Catalogers = []string{"rust"} assert.Len(t, cataloger.ImageCatalogers(c), 0) } + +func TestPkgCoverageImage_HasEvidence(t *testing.T) { + sbom, _ := catalogFixtureImage(t, "image-pkg-coverage", source.SquashedScope, nil) + + var cases []testCase + cases = append(cases, commonTestCases...) + cases = append(cases, imageOnlyTestCases...) + + pkgTypesMissingEvidence := strset.New() + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + + for a := range sbom.Artifacts.PackageCatalog.Enumerate(c.pkgType) { + for _, l := range a.Locations.ToSlice() { + if _, exists := l.Annotations[pkg.EvidenceAnnotationKey]; !exists { + pkgTypesMissingEvidence.Add(string(a.Type)) + t.Errorf("missing evidence annotation (pkg=%s type=%s)", a.Name, a.Type) + } + } + } + + }) + } + + if pkgTypesMissingEvidence.Size() > 0 { + t.Log("Package types missing evidence (img resolver): ", pkgTypesMissingEvidence.List()) + } +} + +func TestPkgCoverageDirectory_HasEvidence(t *testing.T) { + sbom, _ := catalogDirectory(t, "test-fixtures/image-pkg-coverage") + + var cases []testCase + cases = append(cases, commonTestCases...) + cases = append(cases, imageOnlyTestCases...) + + pkgTypesMissingEvidence := strset.New() + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + + for a := range sbom.Artifacts.PackageCatalog.Enumerate(c.pkgType) { + for _, l := range a.Locations.ToSlice() { + if _, exists := l.Annotations[pkg.EvidenceAnnotationKey]; !exists { + pkgTypesMissingEvidence.Add(string(a.Type)) + t.Errorf("missing evidence annotation (pkg=%s type=%s)", a.Name, a.Type) + } + } + } + + }) + } + + if pkgTypesMissingEvidence.Size() > 0 { + t.Log("Package types missing evidence (dir resolver): ", pkgTypesMissingEvidence.List()) + } +} From 403696cce27ddf9131e06c6cf25a8684ffcab82a Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 12 Apr 2023 14:43:28 -0400 Subject: [PATCH 04/12] add evidence to aplm cataloger locations Signed-off-by: Alex Goodman --- syft/pkg/cataloger/alpm/parse_alpm_db.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/syft/pkg/cataloger/alpm/parse_alpm_db.go b/syft/pkg/cataloger/alpm/parse_alpm_db.go index 9de9620b429..0862412bb8c 100644 --- a/syft/pkg/cataloger/alpm/parse_alpm_db.go +++ b/syft/pkg/cataloger/alpm/parse_alpm_db.go @@ -70,7 +70,11 @@ func parseAlpmDB(resolver source.FileResolver, env *generic.Environment, reader } return []pkg.Package{ - newPackage(*metadata, env.LinuxRelease, reader.Location), + newPackage( + *metadata, + env.LinuxRelease, + *reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), }, nil, nil } From 82817bb7922d6c3c71d7ea5f300cab22cc2870af Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 12 Apr 2023 14:50:38 -0400 Subject: [PATCH 05/12] change location annotation helper to return a location copy Signed-off-by: Alex Goodman --- syft/pkg/cataloger/alpm/parse_alpm_db.go | 2 +- syft/pkg/cataloger/apkdb/parse_apk_db.go | 2 +- syft/pkg/cataloger/deb/package.go | 14 ++++++++++---- syft/source/location.go | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/syft/pkg/cataloger/alpm/parse_alpm_db.go b/syft/pkg/cataloger/alpm/parse_alpm_db.go index 0862412bb8c..301d6a09d8f 100644 --- a/syft/pkg/cataloger/alpm/parse_alpm_db.go +++ b/syft/pkg/cataloger/alpm/parse_alpm_db.go @@ -73,7 +73,7 @@ func parseAlpmDB(resolver source.FileResolver, env *generic.Environment, reader newPackage( *metadata, env.LinuxRelease, - *reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), }, nil, nil } diff --git a/syft/pkg/cataloger/apkdb/parse_apk_db.go b/syft/pkg/cataloger/apkdb/parse_apk_db.go index 1587a9eaaf0..9e6c3a8a415 100644 --- a/syft/pkg/cataloger/apkdb/parse_apk_db.go +++ b/syft/pkg/cataloger/apkdb/parse_apk_db.go @@ -123,7 +123,7 @@ func parseApkDB(resolver source.FileResolver, env *generic.Environment, reader s pkgs := make([]pkg.Package, 0, len(apks)) for _, apk := range apks { - pkgs = append(pkgs, newPackage(apk, r, reader.Location)) + pkgs = append(pkgs, newPackage(apk, r, reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))) } return pkgs, discoverPackageDependencies(pkgs), nil diff --git a/syft/pkg/cataloger/deb/package.go b/syft/pkg/cataloger/deb/package.go index b544dc7821d..27395a73a67 100644 --- a/syft/pkg/cataloger/deb/package.go +++ b/syft/pkg/cataloger/deb/package.go @@ -26,7 +26,7 @@ func newDpkgPackage(d pkg.DpkgMetadata, dbLocation source.Location, resolver sou p := pkg.Package{ Name: d.Package, Version: d.Version, - Locations: source.NewLocationSet(*dbLocation.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Locations: source.NewLocationSet(dbLocation.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(d, release), Type: pkg.DebPkg, MetadataType: pkg.DpkgMetadataType, @@ -193,7 +193,9 @@ func fetchMd5Contents(resolver source.FileResolver, dbLocation source.Location, log.Warnf("failed to fetch deb md5 contents (package=%s): %+v", m.Package, err) } - return md5Reader, location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) + l := location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) + + return md5Reader, &l } func fetchConffileContents(resolver source.FileResolver, dbLocation source.Location, m pkg.DpkgMetadata) (io.ReadCloser, *source.Location) { @@ -226,7 +228,9 @@ func fetchConffileContents(resolver source.FileResolver, dbLocation source.Locat log.Warnf("failed to fetch deb conffiles contents (package=%s): %+v", m.Package, err) } - return reader, location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) + l := location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) + + return reader, &l } func fetchCopyrightContents(resolver source.FileResolver, dbLocation source.Location, m pkg.DpkgMetadata) (io.ReadCloser, *source.Location) { @@ -248,7 +252,9 @@ func fetchCopyrightContents(resolver source.FileResolver, dbLocation source.Loca log.Warnf("failed to fetch deb copyright contents (package=%s): %w", m.Package, err) } - return reader, location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) + l := location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) + + return reader, &l } func md5Key(metadata pkg.DpkgMetadata) string { diff --git a/syft/source/location.go b/syft/source/location.go index 74ba98f2951..e99b57640fd 100644 --- a/syft/source/location.go +++ b/syft/source/location.go @@ -42,7 +42,7 @@ func (m *LocationMetadata) merge(other LocationMetadata) error { return errs } -func (l *Location) Annotate(key, value string) *Location { +func (l Location) Annotate(key, value string) Location { if l.LocationMetadata.Annotations == nil { l.LocationMetadata.Annotations = map[string]string{} } From 1ab02fa7135f807fd59adfcc627e0ae82b387541 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 12 Apr 2023 14:50:57 -0400 Subject: [PATCH 06/12] add evidence to binary cataloger locations Signed-off-by: Alex Goodman --- syft/pkg/cataloger/binary/classifier.go | 61 ++---------------------- syft/pkg/cataloger/binary/package.go | 62 +++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 57 deletions(-) create mode 100644 syft/pkg/cataloger/binary/package.go diff --git a/syft/pkg/cataloger/binary/classifier.go b/syft/pkg/cataloger/binary/classifier.go index 458b2857770..e5a2509e299 100644 --- a/syft/pkg/cataloger/binary/classifier.go +++ b/syft/pkg/cataloger/binary/classifier.go @@ -7,7 +7,6 @@ import ( "debug/pe" "fmt" "io" - "reflect" "regexp" "strings" "text/template" @@ -107,7 +106,7 @@ func fileNameTemplateVersionMatcher(fileNamePattern string, contentTemplate stri } matchMetadata := internal.MatchNamedCaptureGroups(tmplPattern, string(contents)) - return singlePackage(classifier, location, matchMetadata), nil + return newPackage(classifier, location, matchMetadata), nil } } @@ -120,7 +119,7 @@ func fileContentsVersionMatcher(pattern string) evidenceMatcher { } matchMetadata := internal.MatchNamedCaptureGroups(pat, string(contents)) - return singlePackage(classifier, location, matchMetadata), nil + return newPackage(classifier, location, matchMetadata), nil } } @@ -141,8 +140,8 @@ func sharedLibraryLookup(sharedLibraryPattern string, sharedLibraryMatcher evide if err != nil { return nil, err } - for _, libraryLication := range locations { - pkgs, err := sharedLibraryMatcher(resolver, classifier, libraryLication) + for _, libraryLocation := range locations { + pkgs, err := sharedLibraryMatcher(resolver, classifier, libraryLocation) if err != nil { return nil, err } @@ -176,58 +175,6 @@ func mustPURL(purl string) packageurl.PackageURL { return p } -func singlePackage(classifier classifier, location source.Location, matchMetadata map[string]string) []pkg.Package { - version, ok := matchMetadata["version"] - if !ok { - return nil - } - - update := matchMetadata["update"] - - var cpes []cpe.CPE - for _, c := range classifier.CPEs { - c.Version = version - c.Update = update - cpes = append(cpes, c) - } - - p := pkg.Package{ - Name: classifier.Package, - Version: version, - Locations: source.NewLocationSet(location), - Type: pkg.BinaryPkg, - CPEs: cpes, - FoundBy: catalogerName, - MetadataType: pkg.BinaryMetadataType, - Metadata: pkg.BinaryMetadata{ - Matches: []pkg.ClassifierMatch{ - { - Classifier: classifier.Class, - Location: location, - }, - }, - }, - } - - if classifier.Type != "" { - p.Type = classifier.Type - } - - if !reflect.DeepEqual(classifier.PURL, emptyPURL) { - purl := classifier.PURL - purl.Version = version - p.PURL = purl.ToString() - } - - if classifier.Language != "" { - p.Language = classifier.Language - } - - p.SetID() - - return []pkg.Package{p} -} - func getContents(resolver source.FileResolver, location source.Location) ([]byte, error) { reader, err := resolver.FileContentsByLocation(location) if err != nil { diff --git a/syft/pkg/cataloger/binary/package.go b/syft/pkg/cataloger/binary/package.go new file mode 100644 index 00000000000..8ee04189b81 --- /dev/null +++ b/syft/pkg/cataloger/binary/package.go @@ -0,0 +1,62 @@ +package binary + +import ( + "github.com/anchore/syft/syft/cpe" + "github.com/anchore/syft/syft/pkg" + "github.com/anchore/syft/syft/source" + "reflect" +) + +func newPackage(classifier classifier, location source.Location, matchMetadata map[string]string) []pkg.Package { + version, ok := matchMetadata["version"] + if !ok { + return nil + } + + update := matchMetadata["update"] + + var cpes []cpe.CPE + for _, c := range classifier.CPEs { + c.Version = version + c.Update = update + cpes = append(cpes, c) + } + + p := pkg.Package{ + Name: classifier.Package, + Version: version, + Locations: source.NewLocationSet( + location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + Type: pkg.BinaryPkg, + CPEs: cpes, + FoundBy: catalogerName, + MetadataType: pkg.BinaryMetadataType, + Metadata: pkg.BinaryMetadata{ + Matches: []pkg.ClassifierMatch{ + { + Classifier: classifier.Class, + Location: location, + }, + }, + }, + } + + if classifier.Type != "" { + p.Type = classifier.Type + } + + if !reflect.DeepEqual(classifier.PURL, emptyPURL) { + purl := classifier.PURL + purl.Version = version + p.PURL = purl.ToString() + } + + if classifier.Language != "" { + p.Language = classifier.Language + } + + p.SetID() + + return []pkg.Package{p} +} From 2d74bb37f9c4855987eed91de9aa42ff7c70f58b Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 12 Apr 2023 15:23:35 -0400 Subject: [PATCH 07/12] updated remaining catalogers with location annotations Signed-off-by: Alex Goodman --- syft/pkg/cataloger/cpp/parse_conanfile.go | 5 ++++- syft/pkg/cataloger/cpp/parse_conanlock.go | 5 ++++- syft/pkg/cataloger/dart/parse_pubspec_lock.go | 8 +++++++- .../pkg/cataloger/dotnet/parse_dotnet_deps.go | 6 +++++- syft/pkg/cataloger/elixir/parse_mix_lock.go | 17 ++++++++++------ syft/pkg/cataloger/erlang/parse_rebar_lock.go | 11 ++++++---- syft/pkg/cataloger/golang/parse_go_binary.go | 20 +++++++++++++++++-- syft/pkg/cataloger/golang/parse_go_mod.go | 4 ++-- .../cataloger/haskell/parse_cabal_freeze.go | 10 +++++++++- .../pkg/cataloger/haskell/parse_stack_lock.go | 16 +++++++++++---- .../pkg/cataloger/haskell/parse_stack_yaml.go | 14 ++++++++++--- syft/pkg/cataloger/java/archive_parser.go | 20 +++++++++++-------- .../cataloger/java/parse_gradle_lockfile.go | 8 +++++--- syft/pkg/cataloger/java/parse_pom_xml.go | 6 +++++- syft/pkg/cataloger/javascript/package.go | 8 ++++---- .../javascript/parse_package_json.go | 6 +++++- .../javascript/parse_package_lock.go | 5 ++++- syft/pkg/cataloger/nix/cataloger.go | 2 +- syft/pkg/cataloger/php/parse_composer_lock.go | 8 +++++++- .../pkg/cataloger/php/parse_installed_json.go | 7 ++++++- .../portage/parse_portage_contents.go | 14 +++++++------ .../pkg/cataloger/python/parse_poetry_lock.go | 9 ++++++++- .../cataloger/python/parse_requirements.go | 9 ++++++++- syft/pkg/cataloger/python/parse_setup.go | 9 ++++++++- syft/pkg/cataloger/python/parse_wheel_egg.go | 12 ++++++----- syft/pkg/cataloger/rpm/package.go | 4 ++-- syft/pkg/cataloger/ruby/parse_gemfile_lock.go | 2 +- syft/pkg/cataloger/ruby/parse_gemspec.go | 5 ++++- syft/pkg/cataloger/rust/package.go | 2 +- syft/pkg/cataloger/rust/parse_cargo_lock.go | 8 +++++++- syft/pkg/cataloger/sbom/cataloger.go | 4 +++- .../pkg/cataloger/swift/parse_podfile_lock.go | 10 +++++++++- test/integration/catalog_packages_test.go | 6 ++++-- 33 files changed, 209 insertions(+), 71 deletions(-) diff --git a/syft/pkg/cataloger/cpp/parse_conanfile.go b/syft/pkg/cataloger/cpp/parse_conanfile.go index eaa2d1b5b3d..bdcca82d049 100644 --- a/syft/pkg/cataloger/cpp/parse_conanfile.go +++ b/syft/pkg/cataloger/cpp/parse_conanfile.go @@ -48,7 +48,10 @@ func parseConanfile(_ source.FileResolver, _ *generic.Environment, reader source continue } - p := newConanfilePackage(m, reader.Location) + p := newConanfilePackage( + m, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ) if p == nil { continue } diff --git a/syft/pkg/cataloger/cpp/parse_conanlock.go b/syft/pkg/cataloger/cpp/parse_conanlock.go index e7310c22fdb..c8adaf02eaa 100644 --- a/syft/pkg/cataloger/cpp/parse_conanlock.go +++ b/syft/pkg/cataloger/cpp/parse_conanlock.go @@ -44,7 +44,10 @@ func parseConanlock(_ source.FileResolver, _ *generic.Environment, reader source Context: node.Context, } - p := newConanlockPackage(metadata, reader.Location) + p := newConanlockPackage( + metadata, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ) if p != nil { pkgs = append(pkgs, *p) diff --git a/syft/pkg/cataloger/dart/parse_pubspec_lock.go b/syft/pkg/cataloger/dart/parse_pubspec_lock.go index 0f12b0a4106..d2acc338863 100644 --- a/syft/pkg/cataloger/dart/parse_pubspec_lock.go +++ b/syft/pkg/cataloger/dart/parse_pubspec_lock.go @@ -58,7 +58,13 @@ func parsePubspecLock(_ source.FileResolver, _ *generic.Environment, reader sour for _, name := range names { pubPkg := p.Packages[name] - pkgs = append(pkgs, newPubspecLockPackage(name, pubPkg, reader.Location)) + pkgs = append(pkgs, + newPubspecLockPackage( + name, + pubPkg, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } return pkgs, nil, nil diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go b/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go index 49a23067cc2..13c617ffa7a 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go @@ -45,7 +45,11 @@ func parseDotnetDeps(_ source.FileResolver, _ *generic.Environment, reader sourc for _, nameVersion := range names { lib := p.Libraries[nameVersion] - dotnetPkg := newDotnetDepsPackage(nameVersion, lib, reader.Location) + dotnetPkg := newDotnetDepsPackage( + nameVersion, + lib, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ) if dotnetPkg != nil { pkgs = append(pkgs, *dotnetPkg) diff --git a/syft/pkg/cataloger/elixir/parse_mix_lock.go b/syft/pkg/cataloger/elixir/parse_mix_lock.go index 075e5fa5e9d..be4daff0e89 100644 --- a/syft/pkg/cataloger/elixir/parse_mix_lock.go +++ b/syft/pkg/cataloger/elixir/parse_mix_lock.go @@ -43,11 +43,16 @@ func parseMixLock(_ source.FileResolver, _ *generic.Environment, reader source.L continue } - packages = append(packages, newPackage(pkg.MixLockMetadata{ - Name: name, - Version: version, - PkgHash: hash, - PkgHashExt: hashExt, - })) + packages = append(packages, + newPackage( + pkg.MixLockMetadata{ + Name: name, + Version: version, + PkgHash: hash, + PkgHashExt: hashExt, + }, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } } diff --git a/syft/pkg/cataloger/erlang/parse_rebar_lock.go b/syft/pkg/cataloger/erlang/parse_rebar_lock.go index 8ff1dc5f92d..407ea716221 100644 --- a/syft/pkg/cataloger/erlang/parse_rebar_lock.go +++ b/syft/pkg/cataloger/erlang/parse_rebar_lock.go @@ -48,10 +48,13 @@ func parseRebarLock(_ source.FileResolver, _ *generic.Environment, reader source version = versionNode.Get(2).Get(1).String() } - p := newPackage(pkg.RebarLockMetadata{ - Name: name, - Version: version, - }) + p := newPackage( + pkg.RebarLockMetadata{ + Name: name, + Version: version, + }, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ) pkgMap[name] = &p } diff --git a/syft/pkg/cataloger/golang/parse_go_binary.go b/syft/pkg/cataloger/golang/parse_go_binary.go index 81e8c3d562c..15bb45f3f09 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary.go +++ b/syft/pkg/cataloger/golang/parse_go_binary.go @@ -62,7 +62,15 @@ func (c *goBinaryCataloger) parseGoBinary(resolver source.FileResolver, _ *gener func (c *goBinaryCataloger) makeGoMainPackage(resolver source.FileResolver, mod *debug.BuildInfo, arch string, location source.Location) pkg.Package { gbs := getBuildSettings(mod.Settings) - main := c.newGoBinaryPackage(resolver, &mod.Main, mod.Main.Path, mod.GoVersion, arch, gbs, location) + main := c.newGoBinaryPackage( + resolver, + &mod.Main, + mod.Main.Path, + mod.GoVersion, + arch, + gbs, + location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ) if main.Version == devel { if version, ok := gbs["vcs.revision"]; ok { if timestamp, ok := gbs["vcs.time"]; ok { @@ -204,7 +212,15 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver source.FileResolver, locatio if dep == nil { continue } - p := c.newGoBinaryPackage(resolver, dep, mod.Main.Path, mod.GoVersion, arch, nil, location) + p := c.newGoBinaryPackage( + resolver, + dep, + mod.Main.Path, + mod.GoVersion, + arch, + nil, + location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ) if pkg.IsValid(&p) { pkgs = append(pkgs, p) } diff --git a/syft/pkg/cataloger/golang/parse_go_mod.go b/syft/pkg/cataloger/golang/parse_go_mod.go index 8846cf90438..92b417dc3fe 100644 --- a/syft/pkg/cataloger/golang/parse_go_mod.go +++ b/syft/pkg/cataloger/golang/parse_go_mod.go @@ -51,7 +51,7 @@ func (c *goModCataloger) parseGoModFile(resolver source.FileResolver, _ *generic Name: m.Mod.Path, Version: m.Mod.Version, Licenses: licenses, - Locations: source.NewLocationSet(reader.Location), + Locations: source.NewLocationSet(reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(m.Mod.Path, m.Mod.Version), Language: pkg.Go, Type: pkg.GoModulePkg, @@ -73,7 +73,7 @@ func (c *goModCataloger) parseGoModFile(resolver source.FileResolver, _ *generic Name: m.New.Path, Version: m.New.Version, Licenses: licenses, - Locations: source.NewLocationSet(reader.Location), + Locations: source.NewLocationSet(reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(m.New.Path, m.New.Version), Language: pkg.Go, Type: pkg.GoModulePkg, diff --git a/syft/pkg/cataloger/haskell/parse_cabal_freeze.go b/syft/pkg/cataloger/haskell/parse_cabal_freeze.go index 80631b61a31..a3434d75b5e 100644 --- a/syft/pkg/cataloger/haskell/parse_cabal_freeze.go +++ b/syft/pkg/cataloger/haskell/parse_cabal_freeze.go @@ -46,6 +46,14 @@ func parseCabalFreeze(_ source.FileResolver, _ *generic.Environment, reader sour fields := strings.Split(line, " ==") pkgName, pkgVersion := fields[0], fields[1] - pkgs = append(pkgs, newPackage(pkgName, pkgVersion, nil, reader.Location)) + pkgs = append( + pkgs, + newPackage( + pkgName, + pkgVersion, + nil, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } } diff --git a/syft/pkg/cataloger/haskell/parse_stack_lock.go b/syft/pkg/cataloger/haskell/parse_stack_lock.go index 58ce52c30cb..53ec9b6c7f1 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_lock.go +++ b/syft/pkg/cataloger/haskell/parse_stack_lock.go @@ -62,10 +62,18 @@ func parseStackLock(_ source.FileResolver, _ *generic.Environment, reader source for _, pack := range lockFile.Packages { pkgName, pkgVersion, pkgHash := parseStackPackageEncoding(pack.Completed.Hackage) - pkgs = append(pkgs, newPackage(pkgName, pkgVersion, &pkg.HackageMetadata{ - PkgHash: pkgHash, - SnapshotURL: snapshotURL, - }, reader.Location)) + pkgs = append( + pkgs, + newPackage( + pkgName, + pkgVersion, + &pkg.HackageMetadata{ + PkgHash: pkgHash, + SnapshotURL: snapshotURL, + }, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } return pkgs, nil, nil diff --git a/syft/pkg/cataloger/haskell/parse_stack_yaml.go b/syft/pkg/cataloger/haskell/parse_stack_yaml.go index 7325c8b798f..338f4942093 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_yaml.go +++ b/syft/pkg/cataloger/haskell/parse_stack_yaml.go @@ -34,9 +34,17 @@ func parseStackYaml(_ source.FileResolver, _ *generic.Environment, reader source var pkgs []pkg.Package for _, dep := range stackFile.ExtraDeps { pkgName, pkgVersion, pkgHash := parseStackPackageEncoding(dep) - pkgs = append(pkgs, newPackage(pkgName, pkgVersion, &pkg.HackageMetadata{ - PkgHash: pkgHash, - }, reader.Location)) + pkgs = append( + pkgs, + newPackage( + pkgName, + pkgVersion, + &pkg.HackageMetadata{ + PkgHash: pkgHash, + }, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } return pkgs, nil, nil diff --git a/syft/pkg/cataloger/java/archive_parser.go b/syft/pkg/cataloger/java/archive_parser.go index a0e8b746556..bd19a5fa9bf 100644 --- a/syft/pkg/cataloger/java/archive_parser.go +++ b/syft/pkg/cataloger/java/archive_parser.go @@ -186,11 +186,13 @@ func (j *archiveParser) discoverMainPackage() (*pkg.Package, error) { } return &pkg.Package{ - Name: selectName(manifest, j.fileInfo), - Version: selectVersion(manifest, j.fileInfo), - Licenses: selectLicense(manifest), - Language: pkg.Java, - Locations: source.NewLocationSet(j.location), + Name: selectName(manifest, j.fileInfo), + Version: selectVersion(manifest, j.fileInfo), + Licenses: selectLicense(manifest), + Language: pkg.Java, + Locations: source.NewLocationSet( + j.location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), Type: j.fileInfo.pkgType(), MetadataType: pkg.JavaMetadataType, Metadata: pkg.JavaMetadata{ @@ -380,9 +382,11 @@ func newPackageFromMavenData(pomProperties pkg.PomProperties, pomProject *pkg.Po // discovered props = new package p := pkg.Package{ - Name: pomProperties.ArtifactID, - Version: pomProperties.Version, - Locations: source.NewLocationSet(location), + Name: pomProperties.ArtifactID, + Version: pomProperties.Version, + Locations: source.NewLocationSet( + location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), Language: pkg.Java, Type: pomProperties.PkgTypeIndicated(), MetadataType: pkg.JavaMetadataType, diff --git a/syft/pkg/cataloger/java/parse_gradle_lockfile.go b/syft/pkg/cataloger/java/parse_gradle_lockfile.go index 65ea51466f0..c1ed7dfa614 100644 --- a/syft/pkg/cataloger/java/parse_gradle_lockfile.go +++ b/syft/pkg/cataloger/java/parse_gradle_lockfile.go @@ -49,9 +49,11 @@ func parseGradleLockfile(_ source.FileResolver, _ *generic.Environment, reader s // map the dependencies for _, dep := range dependencies { mappedPkg := pkg.Package{ - Name: dep.Name, - Version: dep.Version, - Locations: source.NewLocationSet(reader.Location), + Name: dep.Name, + Version: dep.Version, + Locations: source.NewLocationSet( + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), Language: pkg.Java, Type: pkg.JavaPkg, MetadataType: pkg.JavaMetadataType, diff --git a/syft/pkg/cataloger/java/parse_pom_xml.go b/syft/pkg/cataloger/java/parse_pom_xml.go index 0f30e092999..314496a2b22 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml.go +++ b/syft/pkg/cataloger/java/parse_pom_xml.go @@ -29,7 +29,11 @@ func parserPomXML(_ source.FileResolver, _ *generic.Environment, reader source.L var pkgs []pkg.Package for _, dep := range pom.Dependencies { - p := newPackageFromPom(pom, dep, reader.Location) + p := newPackageFromPom( + pom, + dep, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ) if p.Name == "" { continue } diff --git a/syft/pkg/cataloger/javascript/package.go b/syft/pkg/cataloger/javascript/package.go index fb5241334b4..072c41ed293 100644 --- a/syft/pkg/cataloger/javascript/package.go +++ b/syft/pkg/cataloger/javascript/package.go @@ -66,7 +66,7 @@ func newPackageLockV1Package(resolver source.FileResolver, location source.Locat pkg.Package{ Name: name, Version: version, - Locations: source.NewLocationSet(location), + Locations: source.NewLocationSet(location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(name, version), Language: pkg.JavaScript, Type: pkg.NpmPkg, @@ -89,7 +89,7 @@ func newPackageLockV2Package(resolver source.FileResolver, location source.Locat pkg.Package{ Name: name, Version: u.Version, - Locations: source.NewLocationSet(location), + Locations: source.NewLocationSet(location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(name, u.Version), Language: pkg.JavaScript, Type: pkg.NpmPkg, @@ -107,7 +107,7 @@ func newPnpmPackage(resolver source.FileResolver, location source.Location, name pkg.Package{ Name: name, Version: version, - Locations: source.NewLocationSet(location), + Locations: source.NewLocationSet(location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(name, version), Language: pkg.JavaScript, Type: pkg.NpmPkg, @@ -122,7 +122,7 @@ func newYarnLockPackage(resolver source.FileResolver, location source.Location, pkg.Package{ Name: name, Version: version, - Locations: source.NewLocationSet(location), + Locations: source.NewLocationSet(location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(name, version), Language: pkg.JavaScript, Type: pkg.NpmPkg, diff --git a/syft/pkg/cataloger/javascript/parse_package_json.go b/syft/pkg/cataloger/javascript/parse_package_json.go index edf403c7ae1..c915f3ec1c7 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json.go +++ b/syft/pkg/cataloger/javascript/parse_package_json.go @@ -68,7 +68,11 @@ func parsePackageJSON(_ source.FileResolver, _ *generic.Environment, reader sour return nil, nil, nil } - pkgs = append(pkgs, newPackageJSONPackage(p, reader.Location)) + pkgs = append( + pkgs, + newPackageJSONPackage(p, reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } pkg.Sort(pkgs) diff --git a/syft/pkg/cataloger/javascript/parse_package_lock.go b/syft/pkg/cataloger/javascript/parse_package_lock.go index 85574153f84..d0a75f1acff 100644 --- a/syft/pkg/cataloger/javascript/parse_package_lock.go +++ b/syft/pkg/cataloger/javascript/parse_package_lock.go @@ -113,7 +113,10 @@ func parsePackageLock(resolver source.FileResolver, _ *generic.Environment, read name = pkgMeta.Name } - pkgs = append(pkgs, newPackageLockV2Package(resolver, reader.Location, getNameFromPath(name), pkgMeta)) + pkgs = append( + pkgs, + newPackageLockV2Package(resolver, reader.Location, getNameFromPath(name), pkgMeta), + ) } } diff --git a/syft/pkg/cataloger/nix/cataloger.go b/syft/pkg/cataloger/nix/cataloger.go index 4343844b150..a5625526ba5 100644 --- a/syft/pkg/cataloger/nix/cataloger.go +++ b/syft/pkg/cataloger/nix/cataloger.go @@ -56,7 +56,7 @@ func (c *StoreCataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, [ continue } - p := newNixStorePackage(*storePath, location) + p := newNixStorePackage(*storePath, location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)) pkgs = append(pkgs, p) } diff --git a/syft/pkg/cataloger/php/parse_composer_lock.go b/syft/pkg/cataloger/php/parse_composer_lock.go index e8d258c7207..a0f8d5c1078 100644 --- a/syft/pkg/cataloger/php/parse_composer_lock.go +++ b/syft/pkg/cataloger/php/parse_composer_lock.go @@ -32,7 +32,13 @@ func parseComposerLock(_ source.FileResolver, _ *generic.Environment, reader sou return nil, nil, fmt.Errorf("failed to parse composer.lock file: %w", err) } for _, m := range lock.Packages { - pkgs = append(pkgs, newComposerLockPackage(m, reader.Location)) + pkgs = append( + pkgs, + newComposerLockPackage( + m, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } } diff --git a/syft/pkg/cataloger/php/parse_installed_json.go b/syft/pkg/cataloger/php/parse_installed_json.go index b5cd1b86a88..46848b0b68c 100644 --- a/syft/pkg/cataloger/php/parse_installed_json.go +++ b/syft/pkg/cataloger/php/parse_installed_json.go @@ -53,7 +53,12 @@ func parseInstalledJSON(_ source.FileResolver, _ *generic.Environment, reader so return nil, nil, fmt.Errorf("failed to parse installed.json file: %w", err) } for _, pkgMeta := range lock.Packages { - pkgs = append(pkgs, newComposerLockPackage(pkgMeta, reader.Location)) + pkgs = append( + pkgs, + newComposerLockPackage(pkgMeta, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } } diff --git a/syft/pkg/cataloger/portage/parse_portage_contents.go b/syft/pkg/cataloger/portage/parse_portage_contents.go index dba65ace0dd..588258510da 100644 --- a/syft/pkg/cataloger/portage/parse_portage_contents.go +++ b/syft/pkg/cataloger/portage/parse_portage_contents.go @@ -37,10 +37,12 @@ func parsePortageContents(resolver source.FileResolver, _ *generic.Environment, } p := pkg.Package{ - Name: name, - Version: version, - PURL: packageURL(name, version), - Locations: source.NewLocationSet(), + Name: name, + Version: version, + PURL: packageURL(name, version), + Locations: source.NewLocationSet( + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), Type: pkg.PortagePkg, MetadataType: pkg.PortageMetadataType, Metadata: pkg.PortageMetadata{ @@ -117,7 +119,7 @@ func addLicenses(resolver source.FileResolver, dbLocation source.Location, p *pk licenses := findings.ToSlice() sort.Strings(licenses) p.Licenses = licenses - p.Locations.Add(*location) + p.Locations.Add(location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) } func addSize(resolver source.FileResolver, dbLocation source.Location, p *pkg.Package) { @@ -150,5 +152,5 @@ func addSize(resolver source.FileResolver, dbLocation source.Location, p *pkg.Pa } p.Metadata = entry - p.Locations.Add(*location) + p.Locations.Add(location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) } diff --git a/syft/pkg/cataloger/python/parse_poetry_lock.go b/syft/pkg/cataloger/python/parse_poetry_lock.go index 52e33e61889..7b8e8d94bc2 100644 --- a/syft/pkg/cataloger/python/parse_poetry_lock.go +++ b/syft/pkg/cataloger/python/parse_poetry_lock.go @@ -39,7 +39,14 @@ func parsePoetryLock(_ source.FileResolver, _ *generic.Environment, reader sourc var pkgs []pkg.Package for _, p := range metadata.Packages { - pkgs = append(pkgs, newPackageForIndex(p.Name, p.Version, reader.Location)) + pkgs = append( + pkgs, + newPackageForIndex( + p.Name, + p.Version, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } return pkgs, nil, nil diff --git a/syft/pkg/cataloger/python/parse_requirements.go b/syft/pkg/cataloger/python/parse_requirements.go index 599fe3db5eb..7a7a1eb7c4f 100644 --- a/syft/pkg/cataloger/python/parse_requirements.go +++ b/syft/pkg/cataloger/python/parse_requirements.go @@ -61,7 +61,14 @@ func parseRequirementsTxt(_ source.FileResolver, _ *generic.Environment, reader log.WithFields("path", reader.RealPath).Debugf("found empty package in requirements.txt line: %q", line) continue } - packages = append(packages, newPackageForIndex(name, version, reader.Location)) + packages = append( + packages, + newPackageForIndex( + name, + version, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } if err := scanner.Err(); err != nil { diff --git a/syft/pkg/cataloger/python/parse_setup.go b/syft/pkg/cataloger/python/parse_setup.go index 05a2224df84..cf565087757 100644 --- a/syft/pkg/cataloger/python/parse_setup.go +++ b/syft/pkg/cataloger/python/parse_setup.go @@ -53,7 +53,14 @@ func parseSetup(_ source.FileResolver, _ *generic.Environment, reader source.Loc continue } - packages = append(packages, newPackageForIndex(name, version, reader.Location)) + packages = append( + packages, + newPackageForIndex( + name, + version, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } } diff --git a/syft/pkg/cataloger/python/parse_wheel_egg.go b/syft/pkg/cataloger/python/parse_wheel_egg.go index 1ccf4664b16..5177b713198 100644 --- a/syft/pkg/cataloger/python/parse_wheel_egg.go +++ b/syft/pkg/cataloger/python/parse_wheel_egg.go @@ -47,7 +47,7 @@ func fetchInstalledFiles(resolver source.FileResolver, metadataLocation source.L installedFilesRef := resolver.RelativeFileByPath(metadataLocation, installedFilesPath) if installedFilesRef != nil { - sources = append(sources, *installedFilesRef) + sources = append(sources, installedFilesRef.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) installedFilesContents, err := resolver.FileContentsByLocation(*installedFilesRef) if err != nil { @@ -78,7 +78,7 @@ func fetchRecordFiles(resolver source.FileResolver, metadataLocation source.Loca recordRef := resolver.RelativeFileByPath(metadataLocation, recordPath) if recordRef != nil { - sources = append(sources, *recordRef) + sources = append(sources, recordRef.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) recordContents, err := resolver.FileContentsByLocation(*recordRef) if err != nil { @@ -105,7 +105,7 @@ func fetchTopLevelPackages(resolver source.FileResolver, metadataLocation source return nil, nil, nil } - sources = append(sources, *topLevelLocation) + sources = append(sources, topLevelLocation.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) topLevelContents, err := resolver.FileContentsByLocation(*topLevelLocation) if err != nil { @@ -134,7 +134,7 @@ func fetchDirectURLData(resolver source.FileResolver, metadataLocation source.Lo return nil, nil, nil } - sources = append(sources, *directURLLocation) + sources = append(sources, directURLLocation.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) directURLContents, err := resolver.FileContentsByLocation(*directURLLocation) if err != nil { @@ -161,7 +161,9 @@ func fetchDirectURLData(resolver source.FileResolver, metadataLocation source.Lo // assembleEggOrWheelMetadata discovers and accumulates python package metadata from multiple file sources and returns a single metadata object as well as a list of files where the metadata was derived from. func assembleEggOrWheelMetadata(resolver source.FileResolver, metadataLocation source.Location) (*pkg.PythonPackageMetadata, []source.Location, error) { - var sources = []source.Location{metadataLocation} + var sources = []source.Location{ + metadataLocation.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + } metadataContents, err := resolver.FileContentsByLocation(metadataLocation) if err != nil { diff --git a/syft/pkg/cataloger/rpm/package.go b/syft/pkg/cataloger/rpm/package.go index cf277e7804b..41486f0b5d7 100644 --- a/syft/pkg/cataloger/rpm/package.go +++ b/syft/pkg/cataloger/rpm/package.go @@ -13,12 +13,12 @@ import ( "github.com/anchore/syft/syft/source" ) -func newPackage(dbLocation source.Location, metadata pkg.RpmMetadata, distro *linux.Release) pkg.Package { +func newPackage(location source.Location, metadata pkg.RpmMetadata, distro *linux.Release) pkg.Package { p := pkg.Package{ Name: metadata.Name, Version: toELVersion(metadata), PURL: packageURL(metadata, distro), - Locations: source.NewLocationSet(dbLocation), + Locations: source.NewLocationSet(location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), Type: pkg.RpmPkg, MetadataType: pkg.RpmMetadataType, Metadata: metadata, diff --git a/syft/pkg/cataloger/ruby/parse_gemfile_lock.go b/syft/pkg/cataloger/ruby/parse_gemfile_lock.go index e48326ef3f7..7d8856100fe 100644 --- a/syft/pkg/cataloger/ruby/parse_gemfile_lock.go +++ b/syft/pkg/cataloger/ruby/parse_gemfile_lock.go @@ -44,7 +44,7 @@ func parseGemFileLockEntries(_ source.FileResolver, _ *generic.Environment, read newGemfileLockPackage( candidate[0], strings.Trim(candidate[1], "()"), - reader.Location, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/ruby/parse_gemspec.go b/syft/pkg/cataloger/ruby/parse_gemspec.go index 08bc9fe96de..8544ae70cb3 100644 --- a/syft/pkg/cataloger/ruby/parse_gemspec.go +++ b/syft/pkg/cataloger/ruby/parse_gemspec.go @@ -95,7 +95,10 @@ func parseGemSpecEntries(_ source.FileResolver, _ *generic.Environment, reader s return nil, nil, fmt.Errorf("unable to decode gem metadata: %w", err) } - pkgs = append(pkgs, newGemspecPackage(metadata, reader.Location)) + pkgs = append( + pkgs, + newGemspecPackage(metadata, reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + ) } return pkgs, nil, nil diff --git a/syft/pkg/cataloger/rust/package.go b/syft/pkg/cataloger/rust/package.go index 2a6b995a026..bf800c04116 100644 --- a/syft/pkg/cataloger/rust/package.go +++ b/syft/pkg/cataloger/rust/package.go @@ -31,7 +31,7 @@ func newPackagesFromAudit(location source.Location, versionInfo rustaudit.Versio for _, dep := range versionInfo.Packages { dep := dep - p := newPackageFromAudit(&dep, location) + p := newPackageFromAudit(&dep, location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)) if pkg.IsValid(&p) && dep.Kind == rustaudit.Runtime { pkgs = append(pkgs, p) } diff --git a/syft/pkg/cataloger/rust/parse_cargo_lock.go b/syft/pkg/cataloger/rust/parse_cargo_lock.go index 04bf4d20df2..db5e7104cc9 100644 --- a/syft/pkg/cataloger/rust/parse_cargo_lock.go +++ b/syft/pkg/cataloger/rust/parse_cargo_lock.go @@ -36,7 +36,13 @@ func parseCargoLock(_ source.FileResolver, _ *generic.Environment, reader source if p.Dependencies == nil { p.Dependencies = make([]string, 0) } - pkgs = append(pkgs, newPackageFromCargoMetadata(p, reader.Location)) + pkgs = append( + pkgs, + newPackageFromCargoMetadata( + p, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } return pkgs, nil, nil diff --git a/syft/pkg/cataloger/sbom/cataloger.go b/syft/pkg/cataloger/sbom/cataloger.go index 0c82f452ebd..a730e81e380 100644 --- a/syft/pkg/cataloger/sbom/cataloger.go +++ b/syft/pkg/cataloger/sbom/cataloger.go @@ -47,7 +47,9 @@ func parseSBOM(_ source.FileResolver, _ *generic.Environment, reader source.Loca // Why not keep the original list of locations? Since the "locations" field is meant to capture // where there is evidence of this file, and the catalogers have not run against any file other than, // the SBOM, this is the only location that is relevant for this cataloger. - p.Locations = source.NewLocationSet(reader.Location) + p.Locations = source.NewLocationSet( + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ) p.FoundBy = catalogerName pkgs = append(pkgs, p) diff --git a/syft/pkg/cataloger/swift/parse_podfile_lock.go b/syft/pkg/cataloger/swift/parse_podfile_lock.go index 4b6409bffbf..f8781fd83bc 100644 --- a/syft/pkg/cataloger/swift/parse_podfile_lock.go +++ b/syft/pkg/cataloger/swift/parse_podfile_lock.go @@ -59,7 +59,15 @@ func parsePodfileLock(_ source.FileResolver, _ *generic.Environment, reader sour return nil, nil, fmt.Errorf("malformed podfile.lock: incomplete checksums") } - pkgs = append(pkgs, newPackage(podName, podVersion, pkgHash, reader.Location)) + pkgs = append( + pkgs, + newPackage( + podName, + podVersion, + pkgHash, + reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ), + ) } return pkgs, nil, nil diff --git a/test/integration/catalog_packages_test.go b/test/integration/catalog_packages_test.go index ff7497942d2..336694ec97e 100644 --- a/test/integration/catalog_packages_test.go +++ b/test/integration/catalog_packages_test.go @@ -269,6 +269,7 @@ func TestPkgCoverageImage_HasEvidence(t *testing.T) { t.Run(c.name, func(t *testing.T) { for a := range sbom.Artifacts.PackageCatalog.Enumerate(c.pkgType) { + assert.NotEmpty(t, a.Locations.ToSlice(), "package %q has no locations (type=%q)", a.Name, a.Type) for _, l := range a.Locations.ToSlice() { if _, exists := l.Annotations[pkg.EvidenceAnnotationKey]; !exists { pkgTypesMissingEvidence.Add(string(a.Type)) @@ -281,7 +282,7 @@ func TestPkgCoverageImage_HasEvidence(t *testing.T) { } if pkgTypesMissingEvidence.Size() > 0 { - t.Log("Package types missing evidence (img resolver): ", pkgTypesMissingEvidence.List()) + t.Log("Package types missing evidence annotations (img resolver): ", pkgTypesMissingEvidence.List()) } } @@ -298,6 +299,7 @@ func TestPkgCoverageDirectory_HasEvidence(t *testing.T) { t.Run(c.name, func(t *testing.T) { for a := range sbom.Artifacts.PackageCatalog.Enumerate(c.pkgType) { + assert.NotEmpty(t, a.Locations.ToSlice(), "package %q has no locations (type=%q)", a.Name, a.Type) for _, l := range a.Locations.ToSlice() { if _, exists := l.Annotations[pkg.EvidenceAnnotationKey]; !exists { pkgTypesMissingEvidence.Add(string(a.Type)) @@ -310,6 +312,6 @@ func TestPkgCoverageDirectory_HasEvidence(t *testing.T) { } if pkgTypesMissingEvidence.Size() > 0 { - t.Log("Package types missing evidence (dir resolver): ", pkgTypesMissingEvidence.List()) + t.Log("Package types missing evidence annotations (dir resolver): ", pkgTypesMissingEvidence.List()) } } From 08b8b95ea5d3321aa07276e2de3c10266ff02357 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 12 Apr 2023 16:12:08 -0400 Subject: [PATCH 08/12] fix unit tests Signed-off-by: Alex Goodman --- .../common/cyclonedxhelpers/component_test.go | 2 +- syft/formats/github/encoder_test.go | 30 +-- syft/formats/syftjson/encoder_test.go | 16 +- syft/pkg/catalog_test.go | 32 +-- syft/pkg/cataloger/binary/cataloger_test.go | 8 +- .../cataloger/elixir/parse_mix_lock_test.go | 16 ++ .../cataloger/erlang/parse_rebar_lock_test.go | 16 ++ .../cataloger/golang/parse_go_binary_test.go | 60 ++--- syft/pkg/package_test.go | 42 ++-- syft/source/directory_resolver_test.go | 175 ++++--------- syft/source/excluding_file_resolver_test.go | 34 +-- syft/source/image_all_layers_resolver_test.go | 231 +++--------------- syft/source/image_squash_resolver_test.go | 204 ++++------------ syft/source/location_set_test.go | 86 ++++--- syft/source/location_test.go | 8 +- 15 files changed, 324 insertions(+), 636 deletions(-) diff --git a/syft/formats/common/cyclonedxhelpers/component_test.go b/syft/formats/common/cyclonedxhelpers/component_test.go index 01bbaf97aed..248d8ca46b6 100644 --- a/syft/formats/common/cyclonedxhelpers/component_test.go +++ b/syft/formats/common/cyclonedxhelpers/component_test.go @@ -29,7 +29,7 @@ func Test_encodeComponentProperties(t *testing.T) { input: pkg.Package{ FoundBy: "cataloger", Locations: source.NewLocationSet( - source.Location{Coordinates: source.Coordinates{RealPath: "test"}}, + source.NewLocationFromCoordinates(source.Coordinates{RealPath: "test"}), ), Metadata: pkg.ApkMetadata{ Package: "libc-utils", diff --git a/syft/formats/github/encoder_test.go b/syft/formats/github/encoder_test.go index 3eb58c75571..86c50132ad7 100644 --- a/syft/formats/github/encoder_test.go +++ b/syft/formats/github/encoder_test.go @@ -36,36 +36,30 @@ func Test_toGithubModel(t *testing.T) { Name: "pkg-1", Version: "1.0.1", Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ - RealPath: "/usr/lib", - FileSystemID: "fsid-1", - }, - }, + source.NewLocationFromCoordinates(source.Coordinates{ + RealPath: "/usr/lib", + FileSystemID: "fsid-1", + }), ), }, { Name: "pkg-2", Version: "2.0.2", Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ - RealPath: "/usr/lib", - FileSystemID: "fsid-1", - }, - }, + source.NewLocationFromCoordinates(source.Coordinates{ + RealPath: "/usr/lib", + FileSystemID: "fsid-1", + }), ), }, { Name: "pkg-3", Version: "3.0.3", Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ - RealPath: "/etc", - FileSystemID: "fsid-1", - }, - }, + source.NewLocationFromCoordinates(source.Coordinates{ + RealPath: "/etc", + FileSystemID: "fsid-1", + }), ), }, } { diff --git a/syft/formats/syftjson/encoder_test.go b/syft/formats/syftjson/encoder_test.go index 185658f7b77..39510fcb84f 100644 --- a/syft/formats/syftjson/encoder_test.go +++ b/syft/formats/syftjson/encoder_test.go @@ -53,11 +53,9 @@ func TestEncodeFullJSONDocument(t *testing.T) { Name: "package-1", Version: "1.0.1", Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ - RealPath: "/a/place/a", - }, - }, + source.NewLocationFromCoordinates(source.Coordinates{ + RealPath: "/a/place/a", + }), ), Type: pkg.PythonPkg, FoundBy: "the-cataloger-1", @@ -79,11 +77,9 @@ func TestEncodeFullJSONDocument(t *testing.T) { Name: "package-2", Version: "2.0.1", Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ - RealPath: "/b/place/b", - }, - }, + source.NewLocationFromCoordinates(source.Coordinates{ + RealPath: "/b/place/b", + }), ), Type: pkg.DebPkg, FoundBy: "the-cataloger-2", diff --git a/syft/pkg/catalog_test.go b/syft/pkg/catalog_test.go index 62513203988..371a093c19a 100644 --- a/syft/pkg/catalog_test.go +++ b/syft/pkg/catalog_test.go @@ -327,45 +327,45 @@ func TestCatalog_MergeRecords(t *testing.T) { { CPEs: []cpe.CPE{cpe.Must("cpe:2.3:a:package:1:1:*:*:*:*:*:*:*")}, Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ + source.NewVirtualLocationFromCoordinates( + source.Coordinates{ RealPath: "/b/path", FileSystemID: "a", }, - VirtualPath: "/another/path", - }, + "/another/path", + ), ), Type: RpmPkg, }, { CPEs: []cpe.CPE{cpe.Must("cpe:2.3:b:package:1:1:*:*:*:*:*:*:*")}, Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ + source.NewVirtualLocationFromCoordinates( + source.Coordinates{ RealPath: "/b/path", FileSystemID: "b", }, - VirtualPath: "/another/path", - }, + "/another/path", + ), ), Type: RpmPkg, }, }, expectedLocations: []source.Location{ - { - Coordinates: source.Coordinates{ + source.NewVirtualLocationFromCoordinates( + source.Coordinates{ RealPath: "/b/path", FileSystemID: "a", }, - VirtualPath: "/another/path", - }, - { - Coordinates: source.Coordinates{ + "/another/path", + ), + source.NewVirtualLocationFromCoordinates( + source.Coordinates{ RealPath: "/b/path", FileSystemID: "b", }, - VirtualPath: "/another/path", - }, + "/another/path", + ), }, expectedCPECount: 2, }, diff --git a/syft/pkg/cataloger/binary/cataloger_test.go b/syft/pkg/cataloger/binary/cataloger_test.go index a35d3cced6e..af31d4fa474 100644 --- a/syft/pkg/cataloger/binary/cataloger_test.go +++ b/syft/pkg/cataloger/binary/cataloger_test.go @@ -829,12 +829,12 @@ func match(classifier string, paths ...string) pkg.ClassifierMatch { } return pkg.ClassifierMatch{ Classifier: classifier, - Location: source.Location{ - Coordinates: source.Coordinates{ + Location: source.NewVirtualLocationFromCoordinates( + source.Coordinates{ RealPath: realPath, }, - VirtualPath: virtualPath, - }, + virtualPath, + ), } } diff --git a/syft/pkg/cataloger/elixir/parse_mix_lock_test.go b/syft/pkg/cataloger/elixir/parse_mix_lock_test.go index 11de894ac07..bc6aab5da9e 100644 --- a/syft/pkg/cataloger/elixir/parse_mix_lock_test.go +++ b/syft/pkg/cataloger/elixir/parse_mix_lock_test.go @@ -1,6 +1,7 @@ package elixir import ( + "github.com/anchore/syft/syft/source" "testing" "github.com/anchore/syft/syft/artifact" @@ -15,6 +16,7 @@ func TestParseMixLock(t *testing.T) { Version: "0.1.17", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/castore@0.1.17", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -29,6 +31,7 @@ func TestParseMixLock(t *testing.T) { Version: "1.1.0", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/connection@1.1.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -43,6 +46,7 @@ func TestParseMixLock(t *testing.T) { Version: "2.9.0", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/cowboy@2.9.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -57,6 +61,7 @@ func TestParseMixLock(t *testing.T) { Version: "0.4.0", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/cowboy_telemetry@0.4.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -71,6 +76,7 @@ func TestParseMixLock(t *testing.T) { Version: "2.11.0", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/cowlib@2.11.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -85,6 +91,7 @@ func TestParseMixLock(t *testing.T) { Version: "2.4.2", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/db_connection@2.4.2", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -99,6 +106,7 @@ func TestParseMixLock(t *testing.T) { Version: "2.0.0", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/decimal@2.0.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -113,6 +121,7 @@ func TestParseMixLock(t *testing.T) { Version: "1.4.25", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/earmark_parser@1.4.25", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -127,6 +136,7 @@ func TestParseMixLock(t *testing.T) { Version: "3.8.1", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/ecto@3.8.1", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -141,6 +151,7 @@ func TestParseMixLock(t *testing.T) { Version: "3.8.1", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/ecto_sql@3.8.1", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -155,6 +166,7 @@ func TestParseMixLock(t *testing.T) { Version: "0.5.0", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/esbuild@0.5.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -169,6 +181,7 @@ func TestParseMixLock(t *testing.T) { Version: "0.28.4", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/ex_doc@0.28.4", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -183,6 +196,7 @@ func TestParseMixLock(t *testing.T) { Version: "0.19.1", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/gettext@0.19.1", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -197,6 +211,7 @@ func TestParseMixLock(t *testing.T) { Version: "0.1.1", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/hpax@0.1.1", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -211,6 +226,7 @@ func TestParseMixLock(t *testing.T) { Version: "1.3.0", Language: pkg.Elixir, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), PURL: "pkg:hex/jason@1.3.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ diff --git a/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go b/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go index 7986f5b5f18..4169afd9c97 100644 --- a/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go +++ b/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go @@ -1,6 +1,7 @@ package erlang import ( + "github.com/anchore/syft/syft/source" "testing" "github.com/anchore/syft/syft/artifact" @@ -21,6 +22,7 @@ func TestParseRebarLock(t *testing.T) { Version: "2.9.0", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/certifi@2.9.0", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -35,6 +37,7 @@ func TestParseRebarLock(t *testing.T) { Version: "6.1.1", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/idna@6.1.1", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -49,6 +52,7 @@ func TestParseRebarLock(t *testing.T) { Version: "1.0.1", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/metrics@1.0.1", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -63,6 +67,7 @@ func TestParseRebarLock(t *testing.T) { Version: "1.2.0", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/mimerl@1.2.0", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -77,6 +82,7 @@ func TestParseRebarLock(t *testing.T) { Version: "3.3.1", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/parse_trans@3.3.1", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -91,6 +97,7 @@ func TestParseRebarLock(t *testing.T) { Version: "1.1.6", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/ssl_verify_fun@1.1.6", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -105,6 +112,7 @@ func TestParseRebarLock(t *testing.T) { Version: "0.7.0", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/unicode_util_compat@0.7.0", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -127,6 +135,7 @@ func TestParseRebarLock(t *testing.T) { Version: "1.1.5", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/bcrypt@1.1.5", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -145,6 +154,7 @@ func TestParseRebarLock(t *testing.T) { Version: "14308ab927cfa69324742c3de720578094e0bb19", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/bson@14308ab927cfa69324742c3de720578094e0bb19", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -160,6 +170,7 @@ func TestParseRebarLock(t *testing.T) { Version: "2.9.0", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/certifi@2.9.0", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -177,6 +188,7 @@ func TestParseRebarLock(t *testing.T) { Version: "0.2.3", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/stdout_formatter@0.2.3", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -195,6 +207,7 @@ func TestParseRebarLock(t *testing.T) { Version: "4835239dca5a5f4ac7202dd94d7effcaa617d575", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/swc@4835239dca5a5f4ac7202dd94d7effcaa617d575", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -210,6 +223,7 @@ func TestParseRebarLock(t *testing.T) { Version: "1.1.0", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/syslog@1.1.0", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -227,6 +241,7 @@ func TestParseRebarLock(t *testing.T) { Version: "0.7.0", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/unicode_util_compat@0.7.0", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -245,6 +260,7 @@ func TestParseRebarLock(t *testing.T) { Version: "6d622aa8c901ae7777433aef2bd049e380c474a6", Language: pkg.Erlang, Type: pkg.HexPkg, + Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/vernemq_dev@6d622aa8c901ae7777433aef2bd049e380c474a6", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ diff --git a/syft/pkg/cataloger/golang/parse_go_binary_test.go b/syft/pkg/cataloger/golang/parse_go_binary_test.go index 93b91ff2220..b13a46809c2 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary_test.go +++ b/syft/pkg/cataloger/golang/parse_go_binary_test.go @@ -136,12 +136,12 @@ func TestBuildGoPkgInfo(t *testing.T) { Version: "(devel)", PURL: "pkg:golang/github.com/anchore/syft@(devel)", Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ + source.NewLocationFromCoordinates( + source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, - }, + ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -183,12 +183,12 @@ func TestBuildGoPkgInfo(t *testing.T) { Language: pkg.Go, Type: pkg.GoModulePkg, Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ + source.NewLocationFromCoordinates( + source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, - }, + ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{}, @@ -226,12 +226,12 @@ func TestBuildGoPkgInfo(t *testing.T) { Language: pkg.Go, Type: pkg.GoModulePkg, Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ + source.NewLocationFromCoordinates( + source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, - }, + ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -262,12 +262,12 @@ func TestBuildGoPkgInfo(t *testing.T) { Language: pkg.Go, Type: pkg.GoModulePkg, Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ + source.NewLocationFromCoordinates( + source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, - }, + ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -320,12 +320,12 @@ func TestBuildGoPkgInfo(t *testing.T) { Version: "v0.0.0-20221014195457-41bc6bb41035", PURL: "pkg:golang/github.com/anchore/syft@v0.0.0-20221014195457-41bc6bb41035", Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ + source.NewLocationFromCoordinates( + source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, - }, + ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -375,12 +375,12 @@ func TestBuildGoPkgInfo(t *testing.T) { Language: pkg.Go, Type: pkg.GoModulePkg, Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ + source.NewLocationFromCoordinates( + source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, - }, + ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -397,12 +397,12 @@ func TestBuildGoPkgInfo(t *testing.T) { Language: pkg.Go, Type: pkg.GoModulePkg, Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ + source.NewLocationFromCoordinates( + source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, - }, + ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -452,12 +452,12 @@ func TestBuildGoPkgInfo(t *testing.T) { Language: pkg.Go, Type: pkg.GoModulePkg, Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ + source.NewLocationFromCoordinates( + source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, - }, + ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -473,12 +473,12 @@ func TestBuildGoPkgInfo(t *testing.T) { Language: pkg.Go, Type: pkg.GoModulePkg, Locations: source.NewLocationSet( - source.Location{ - Coordinates: source.Coordinates{ + source.NewLocationFromCoordinates( + source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, - }, + ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -502,12 +502,12 @@ func TestBuildGoPkgInfo(t *testing.T) { } p.SetID() } - location := source.Location{ - Coordinates: source.Coordinates{ + location := source.NewLocationFromCoordinates( + source.Coordinates{ RealPath: "/a-path", FileSystemID: "layer-id", }, - } + ) c := goBinaryCataloger{} pkgs := c.buildGoPkgInfo(source.NewMockResolverForPaths(), location, test.mod, test.arch) diff --git a/syft/pkg/package_test.go b/syft/pkg/package_test.go index 51854c061ed..69addce289f 100644 --- a/syft/pkg/package_test.go +++ b/syft/pkg/package_test.go @@ -7,19 +7,19 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/anchore/stereoscope/pkg/file" "github.com/anchore/syft/syft/cpe" "github.com/anchore/syft/syft/source" ) func TestIDUniqueness(t *testing.T) { - originalLocation := source.Location{ - Coordinates: source.Coordinates{ + originalLocation := source.NewVirtualLocationFromCoordinates( + source.Coordinates{ RealPath: "39.0742° N, 21.8243° E", FileSystemID: "Earth", }, - VirtualPath: "/Ancient-Greece", - } + "/Ancient-Greece", + ) + originalPkg := Package{ Name: "pi", Version: "3.14", @@ -238,13 +238,13 @@ func TestIDUniqueness(t *testing.T) { } func TestPackage_Merge(t *testing.T) { - originalLocation := source.Location{ - Coordinates: source.Coordinates{ + originalLocation := source.NewVirtualLocationFromCoordinates( + source.Coordinates{ RealPath: "39.0742° N, 21.8243° E", FileSystemID: "Earth", }, - VirtualPath: "/Ancient-Greece", - } + "/Ancient-Greece", + ) similarLocation := originalLocation similarLocation.FileSystemID = "Mars" @@ -423,13 +423,23 @@ func TestPackage_Merge(t *testing.T) { cmp.AllowUnexported(Package{}), cmp.Comparer( func(x, y source.LocationSet) bool { - return cmp.Equal( - x.ToSlice(), y.ToSlice(), - cmp.AllowUnexported(source.Location{}), - cmp.AllowUnexported(file.Reference{}), - ) + xs := x.ToSlice() + ys := y.ToSlice() + + if len(xs) != len(ys) { + return false + } + for i, xe := range xs { + ye := ys[i] + if !locationComparer(xe, ye) { + return false + } + } + + return true }, ), + cmp.Comparer(locationComparer), ); diff != "" { t.Errorf("unexpected result from parsing (-expected +actual)\n%s", diff) } @@ -437,6 +447,10 @@ func TestPackage_Merge(t *testing.T) { } } +func locationComparer(x, y source.Location) bool { + return cmp.Equal(x.Coordinates, y.Coordinates) && cmp.Equal(x.VirtualPath, y.VirtualPath) +} + func TestIsValid(t *testing.T) { cases := []struct { name string diff --git a/syft/source/directory_resolver_test.go b/syft/source/directory_resolver_test.go index 550488aaab9..c976fc3431b 100644 --- a/syft/source/directory_resolver_test.go +++ b/syft/source/directory_resolver_test.go @@ -765,30 +765,10 @@ func Test_directoryResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - { - Coordinates: Coordinates{ - RealPath: "file-1.txt", - }, - //VirtualPath: "file-1.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "file-3.txt", - }, - //VirtualPath: "file-3.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "file-2.txt", - }, - //VirtualPath: "file-2.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "parent/file-4.txt", - }, - //VirtualPath: "parent/file-4.txt", - }, + NewLocation("file-1.txt"), // note: missing virtual path "file-1.txt" + NewLocation("file-3.txt"), // note: missing virtual path "file-3.txt" + NewLocation("file-2.txt"), // note: missing virtual path "file-2.txt" + NewLocation("parent/file-4.txt"), // note: missing virtual path "file-4.txt" }, }, { @@ -801,31 +781,11 @@ func Test_directoryResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - { - Coordinates: Coordinates{ - RealPath: "file-1.txt", - }, - VirtualPath: "link-1", - }, - { - Coordinates: Coordinates{ - RealPath: "file-2.txt", - }, - VirtualPath: "link-2", - }, + NewVirtualLocation("file-1.txt", "link-1"), + NewVirtualLocation("file-2.txt", "link-2"), // we already have this real file path via another link, so only one is returned - //{ - // Coordinates: Coordinates{ - // RealPath: "file-2.txt", - // }, - // VirtualPath: "link-indirect", - //}, - { - Coordinates: Coordinates{ - RealPath: "file-3.txt", - }, - VirtualPath: "link-within", - }, + //NewVirtualLocation("file-2.txt", "link-indirect"), + NewVirtualLocation("file-3.txt", "link-within"), }, }, { @@ -838,12 +798,7 @@ func Test_directoryResolver_resolvesLinks(t *testing.T) { }, expected: []Location{ // this has two copies in the base image, which overwrites the same location - { - Coordinates: Coordinates{ - RealPath: "file-2.txt", - }, - //VirtualPath: "file-2.txt", - }, + NewLocation("file-2.txt"), // note: missing virtual path "file-2.txt", }, }, { @@ -855,30 +810,10 @@ func Test_directoryResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - { - Coordinates: Coordinates{ - RealPath: "file-1.txt", - }, - //VirtualPath: "file-1.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "file-2.txt", - }, - //VirtualPath: "file-2.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "file-3.txt", - }, - //VirtualPath: "file-3.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "parent/file-4.txt", - }, - //VirtualPath: "parent/file-4.txt", - }, + NewLocation("file-1.txt"), // note: missing virtual path "file-1.txt" + NewLocation("file-2.txt"), // note: missing virtual path "file-2.txt" + NewLocation("file-3.txt"), // note: missing virtual path "file-3.txt" + NewLocation("parent/file-4.txt"), // note: missing virtual path "parent/file-4.txt" }, }, { @@ -890,33 +825,41 @@ func Test_directoryResolver_resolvesLinks(t *testing.T) { }, expected: []Location{ { - Coordinates: Coordinates{ - RealPath: "file-1.txt", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "file-1.txt", + }, + VirtualPath: "link-1", + ref: file.Reference{RealPath: "file-1.txt"}, }, - VirtualPath: "link-1", - ref: file.Reference{RealPath: "file-1.txt"}, }, { - Coordinates: Coordinates{ - RealPath: "file-2.txt", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "file-2.txt", + }, + VirtualPath: "link-2", + ref: file.Reference{RealPath: "file-2.txt"}, }, - VirtualPath: "link-2", - ref: file.Reference{RealPath: "file-2.txt"}, }, // we already have this real file path via another link, so only one is returned //{ - // Coordinates: Coordinates{ - // RealPath: "file-2.txt", - // }, - // VirtualPath: "link-indirect", - // ref: file.Reference{RealPath: "file-2.txt"}, + // LocationData: LocationData{ + // Coordinates: Coordinates{ + // RealPath: "file-2.txt", + // }, + // VirtualPath: "link-indirect", + // ref: file.Reference{RealPath: "file-2.txt"}, + // }, //}, { - Coordinates: Coordinates{ - RealPath: "file-3.txt", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "file-3.txt", + }, + VirtualPath: "link-within", + ref: file.Reference{RealPath: "file-3.txt"}, }, - VirtualPath: "link-within", - ref: file.Reference{RealPath: "file-3.txt"}, }, }, }, @@ -929,30 +872,10 @@ func Test_directoryResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - { - Coordinates: Coordinates{ - RealPath: "file-1.txt", - }, - //VirtualPath: "file-1.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "file-2.txt", - }, - //VirtualPath: "file-2.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "file-3.txt", - }, - //VirtualPath: "file-3.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "parent/file-4.txt", - }, - //VirtualPath: "parent/file-4.txt", - }, + NewLocation("file-1.txt"), // note: missing virtual path "file-1.txt" + NewLocation("file-2.txt"), // note: missing virtual path "file-2.txt" + NewLocation("file-3.txt"), // note: missing virtual path "file-3.txt" + NewLocation("parent/file-4.txt"), // note: missing virtual path "parent/file-4.txt" }, }, { @@ -965,12 +888,7 @@ func Test_directoryResolver_resolvesLinks(t *testing.T) { }, expected: []Location{ // we have multiple copies across layers - { - Coordinates: Coordinates{ - RealPath: "file-2.txt", - }, - VirtualPath: "link-2", - }, + NewVirtualLocation("file-2.txt", "link-2"), }, }, { @@ -983,12 +901,7 @@ func Test_directoryResolver_resolvesLinks(t *testing.T) { }, expected: []Location{ // we have multiple copies across layers - { - Coordinates: Coordinates{ - RealPath: "file-2.txt", - }, - VirtualPath: "link-indirect", - }, + NewVirtualLocation("file-2.txt", "link-indirect"), }, }, } diff --git a/syft/source/excluding_file_resolver_test.go b/syft/source/excluding_file_resolver_test.go index 968d2b6a818..c448e39210e 100644 --- a/syft/source/excluding_file_resolver_test.go +++ b/syft/source/excluding_file_resolver_test.go @@ -6,8 +6,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - - "github.com/anchore/stereoscope/pkg/file" ) func TestExcludingResolver(t *testing.T) { @@ -79,25 +77,25 @@ func TestExcludingResolver(t *testing.T) { for _, path := range diff { assert.False(t, er.HasPath(path)) - c, err := er.FileContentsByLocation(makeLocation(path)) + c, err := er.FileContentsByLocation(NewLocation(path)) assert.Nil(t, c) assert.Error(t, err) - m, err := er.FileMetadataByLocation(makeLocation(path)) + m, err := er.FileMetadataByLocation(NewLocation(path)) assert.Empty(t, m.LinkDestination) assert.Error(t, err) - l := er.RelativeFileByPath(makeLocation(""), path) + l := er.RelativeFileByPath(NewLocation(""), path) assert.Nil(t, l) } for _, path := range test.expected { assert.True(t, er.HasPath(path)) - c, err := er.FileContentsByLocation(makeLocation(path)) + c, err := er.FileContentsByLocation(NewLocation(path)) assert.NotNil(t, c) assert.Nil(t, err) - m, err := er.FileMetadataByLocation(makeLocation(path)) + m, err := er.FileMetadataByLocation(NewLocation(path)) assert.NotEmpty(t, m.LinkDestination) assert.Nil(t, err) - l := er.RelativeFileByPath(makeLocation(""), path) + l := er.RelativeFileByPath(NewLocation(""), path) assert.NotNil(t, l) } }) @@ -119,17 +117,6 @@ func difference(a, b []string) []string { return diff } -func makeLocation(path string) Location { - return Location{ - Coordinates: Coordinates{ - RealPath: path, - FileSystemID: "", - }, - VirtualPath: "", - ref: file.Reference{}, - } -} - func locationPaths(locations []Location) []string { paths := []string{} for _, l := range locations { @@ -145,7 +132,7 @@ type mockResolver struct { func (r *mockResolver) getLocations() ([]Location, error) { out := []Location{} for _, path := range r.locations { - out = append(out, makeLocation(path)) + out = append(out, NewLocation(path)) } return out, nil } @@ -189,11 +176,8 @@ func (r *mockResolver) FilesByBasenameGlob(_ ...string) ([]Location, error) { } func (r *mockResolver) RelativeFileByPath(_ Location, path string) *Location { - return &Location{ - Coordinates: Coordinates{ - RealPath: path, - }, - } + l := NewLocation(path) + return &l } func (r *mockResolver) AllLocations() <-chan Location { diff --git a/syft/source/image_all_layers_resolver_test.go b/syft/source/image_all_layers_resolver_test.go index a94039e7389..86892b1884f 100644 --- a/syft/source/image_all_layers_resolver_test.go +++ b/syft/source/image_all_layers_resolver_test.go @@ -398,66 +398,17 @@ func Test_imageAllLayersResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - { - Coordinates: Coordinates{ - RealPath: "/etc/group", - }, - VirtualPath: "/etc/group", - }, - { - Coordinates: Coordinates{ - RealPath: "/etc/passwd", - }, - VirtualPath: "/etc/passwd", - }, - { - Coordinates: Coordinates{ - RealPath: "/etc/shadow", - }, - VirtualPath: "/etc/shadow", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-1.txt", - }, - VirtualPath: "/file-1.txt", - }, - // copy 1 - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/file-2.txt", - }, + NewVirtualLocation("/etc/group", "/etc/group"), + NewVirtualLocation("/etc/passwd", "/etc/passwd"), + NewVirtualLocation("/etc/shadow", "/etc/shadow"), + NewVirtualLocation("/file-1.txt", "/file-1.txt"), + NewVirtualLocation("/file-2.txt", "/file-2.txt"), // copy 1 // note: we're de-duping the redundant access to file-3.txt // ... (there would usually be two copies) - { - Coordinates: Coordinates{ - RealPath: "/file-3.txt", - }, - VirtualPath: "/file-3.txt", - }, - // copy 2 - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/file-2.txt", - }, - // copy 1 - { - Coordinates: Coordinates{ - RealPath: "/parent/file-4.txt", - }, - VirtualPath: "/parent/file-4.txt", - }, - // copy 2 - { - Coordinates: Coordinates{ - RealPath: "/parent/file-4.txt", - }, - VirtualPath: "/parent/file-4.txt", - }, + NewVirtualLocation("/file-3.txt", "/file-3.txt"), + NewVirtualLocation("/file-2.txt", "/file-2.txt"), // copy 2 + NewVirtualLocation("/parent/file-4.txt", "/parent/file-4.txt"), // copy 1 + NewVirtualLocation("/parent/file-4.txt", "/parent/file-4.txt"), // copy 2 }, }, { @@ -469,32 +420,10 @@ func Test_imageAllLayersResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - { - Coordinates: Coordinates{ - RealPath: "/file-1.txt", - }, - VirtualPath: "/link-1", - }, - // copy 1 - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/link-2", - }, - // copy 2 - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/link-2", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-3.txt", - }, - VirtualPath: "/link-within", - }, + NewVirtualLocation("/file-1.txt", "/link-1"), + NewVirtualLocation("/file-2.txt", "/link-2"), // copy 1 + NewVirtualLocation("/file-2.txt", "/link-2"), // copy 2 + NewVirtualLocation("/file-3.txt", "/link-within"), }, }, { @@ -506,20 +435,8 @@ func Test_imageAllLayersResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - // copy 1 - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/file-2.txt", - }, - // copy 2 - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/file-2.txt", - }, + NewVirtualLocation("/file-2.txt", "/file-2.txt"), // copy 1 + NewVirtualLocation("/file-2.txt", "/file-2.txt"), // copy 2 }, }, { @@ -531,45 +448,12 @@ func Test_imageAllLayersResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - { - Coordinates: Coordinates{ - RealPath: "/file-1.txt", - }, - VirtualPath: "/file-1.txt", - }, - // copy 1 - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/file-2.txt", - }, - // copy 2 - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/file-2.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-3.txt", - }, - VirtualPath: "/file-3.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/parent/file-4.txt", - }, - VirtualPath: "/parent/file-4.txt", - }, - // when we copy into the link path, the same file-4.txt is copied - { - Coordinates: Coordinates{ - RealPath: "/parent/file-4.txt", - }, - VirtualPath: "/parent/file-4.txt", - }, + NewVirtualLocation("/file-1.txt", "/file-1.txt"), + NewVirtualLocation("/file-2.txt", "/file-2.txt"), // copy 1 + NewVirtualLocation("/file-2.txt", "/file-2.txt"), // copy 2 + NewVirtualLocation("/file-3.txt", "/file-3.txt"), + NewVirtualLocation("/parent/file-4.txt", "/parent/file-4.txt"), + NewVirtualLocation("/parent/file-4.txt", "/parent/file-4.txt"), // when we copy into the link path, the same file-4.txt is copied }, }, { @@ -581,45 +465,12 @@ func Test_imageAllLayersResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - { - Coordinates: Coordinates{ - RealPath: "/file-1.txt", - }, - VirtualPath: "/file-1.txt", - }, - // copy 1 - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/file-2.txt", - }, - // copy 2 - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/file-2.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-3.txt", - }, - VirtualPath: "/file-3.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/parent/file-4.txt", - }, - VirtualPath: "/parent/file-4.txt", - }, - // when we copy into the link path, the same file-4.txt is copied - { - Coordinates: Coordinates{ - RealPath: "/parent/file-4.txt", - }, - VirtualPath: "/parent/file-4.txt", - }, + NewVirtualLocation("/file-1.txt", "/file-1.txt"), + NewVirtualLocation("/file-2.txt", "/file-2.txt"), // copy 1 + NewVirtualLocation("/file-2.txt", "/file-2.txt"), // copy 2 + NewVirtualLocation("/file-3.txt", "/file-3.txt"), + NewVirtualLocation("/parent/file-4.txt", "/parent/file-4.txt"), + NewVirtualLocation("/parent/file-4.txt", "/parent/file-4.txt"), // when we copy into the link path, the same file-4.txt is copied }, }, { @@ -632,18 +483,8 @@ func Test_imageAllLayersResolver_resolvesLinks(t *testing.T) { }, expected: []Location{ // we have multiple copies across layers - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/link-2", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/link-2", - }, + NewVirtualLocation("/file-2.txt", "/link-2"), + NewVirtualLocation("/file-2.txt", "/link-2"), }, }, { @@ -656,18 +497,8 @@ func Test_imageAllLayersResolver_resolvesLinks(t *testing.T) { }, expected: []Location{ // we have multiple copies across layers - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/link-indirect", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/link-indirect", - }, + NewVirtualLocation("/file-2.txt", "/link-indirect"), + NewVirtualLocation("/file-2.txt", "/link-indirect"), }, }, } diff --git a/syft/source/image_squash_resolver_test.go b/syft/source/image_squash_resolver_test.go index cfbeff1677f..106de9a5e22 100644 --- a/syft/source/image_squash_resolver_test.go +++ b/syft/source/image_squash_resolver_test.go @@ -382,48 +382,13 @@ func Test_imageSquashResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - { - Coordinates: Coordinates{ - RealPath: "/etc/group", - }, - VirtualPath: "/etc/group", - }, - { - Coordinates: Coordinates{ - RealPath: "/etc/passwd", - }, - VirtualPath: "/etc/passwd", - }, - { - Coordinates: Coordinates{ - RealPath: "/etc/shadow", - }, - VirtualPath: "/etc/shadow", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-1.txt", - }, - VirtualPath: "/file-1.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-3.txt", - }, - VirtualPath: "/file-3.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/file-2.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/parent/file-4.txt", - }, - VirtualPath: "/parent/file-4.txt", - }, + NewVirtualLocation("/etc/group", "/etc/group"), + NewVirtualLocation("/etc/passwd", "/etc/passwd"), + NewVirtualLocation("/etc/shadow", "/etc/shadow"), + NewVirtualLocation("/file-1.txt", "/file-1.txt"), + NewVirtualLocation("/file-3.txt", "/file-3.txt"), + NewVirtualLocation("/file-2.txt", "/file-2.txt"), + NewVirtualLocation("/parent/file-4.txt", "/parent/file-4.txt"), }, }, { @@ -435,32 +400,14 @@ func Test_imageSquashResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - { - Coordinates: Coordinates{ - RealPath: "/file-1.txt", - }, - VirtualPath: "/link-1", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/link-2", - }, + NewVirtualLocation("/file-1.txt", "/link-1"), + NewVirtualLocation("/file-2.txt", "/link-2"), + // though this is a link, and it matches to the file, the resolver de-duplicates files // by the real path, so it is not included in the results - //{ - // Coordinates: Coordinates{ - // RealPath: "/file-2.txt", - // }, - // VirtualPath: "/link-indirect", - //}, - { - Coordinates: Coordinates{ - RealPath: "/file-3.txt", - }, - VirtualPath: "/link-within", - }, + //NewVirtualLocation("/file-2.txt", "/link-indirect"), + + NewVirtualLocation("/file-3.txt", "/link-within"), }, }, { @@ -473,12 +420,7 @@ func Test_imageSquashResolver_resolvesLinks(t *testing.T) { }, expected: []Location{ // this has two copies in the base image, which overwrites the same location - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/file-2.txt", - }, + NewVirtualLocation("/file-2.txt", "/file-2.txt"), }, }, { @@ -490,30 +432,10 @@ func Test_imageSquashResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - { - Coordinates: Coordinates{ - RealPath: "/file-1.txt", - }, - VirtualPath: "/file-1.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/file-2.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-3.txt", - }, - VirtualPath: "/file-3.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/parent/file-4.txt", - }, - VirtualPath: "/parent/file-4.txt", - }, + NewVirtualLocation("/file-1.txt", "/file-1.txt"), + NewVirtualLocation("/file-2.txt", "/file-2.txt"), + NewVirtualLocation("/file-3.txt", "/file-3.txt"), + NewVirtualLocation("/parent/file-4.txt", "/parent/file-4.txt"), }, }, { @@ -524,34 +446,44 @@ func Test_imageSquashResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ + { - Coordinates: Coordinates{ - RealPath: "/file-1.txt", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "/file-1.txt", + }, + VirtualPath: "/link-1", + ref: file.Reference{RealPath: "/file-1.txt"}, }, - VirtualPath: "/link-1", - ref: file.Reference{RealPath: "/file-1.txt"}, }, { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", + LocationData: LocationData{ + + Coordinates: Coordinates{ + RealPath: "/file-2.txt", + }, + VirtualPath: "/link-2", + ref: file.Reference{RealPath: "/file-2.txt"}, }, - VirtualPath: "/link-2", - ref: file.Reference{RealPath: "/file-2.txt"}, }, // we already have this real file path via another link, so only one is returned //{ - // Coordinates: Coordinates{ - // RealPath: "/file-2.txt", - // }, - // VirtualPath: "/link-indirect", - // ref: file.Reference{RealPath: "/file-2.txt"}, + // LocationData: LocationData{ + // Coordinates: Coordinates{ + // RealPath: "/file-2.txt", + // }, + // VirtualPath: "/link-indirect", + // ref: file.Reference{RealPath: "/file-2.txt"}, + // }, //}, { - Coordinates: Coordinates{ - RealPath: "/file-3.txt", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "/file-3.txt", + }, + VirtualPath: "/link-within", + ref: file.Reference{RealPath: "/file-3.txt"}, }, - VirtualPath: "/link-within", - ref: file.Reference{RealPath: "/file-3.txt"}, }, }, }, @@ -564,30 +496,10 @@ func Test_imageSquashResolver_resolvesLinks(t *testing.T) { return actualLocations }, expected: []Location{ - { - Coordinates: Coordinates{ - RealPath: "/file-1.txt", - }, - VirtualPath: "/file-1.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/file-2.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/file-3.txt", - }, - VirtualPath: "/file-3.txt", - }, - { - Coordinates: Coordinates{ - RealPath: "/parent/file-4.txt", - }, - VirtualPath: "/parent/file-4.txt", - }, + NewVirtualLocation("/file-1.txt", "/file-1.txt"), + NewVirtualLocation("/file-2.txt", "/file-2.txt"), + NewVirtualLocation("/file-3.txt", "/file-3.txt"), + NewVirtualLocation("/parent/file-4.txt", "/parent/file-4.txt"), }, }, { @@ -600,12 +512,7 @@ func Test_imageSquashResolver_resolvesLinks(t *testing.T) { }, expected: []Location{ // we have multiple copies across layers - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/link-2", - }, + NewVirtualLocation("/file-2.txt", "/link-2"), }, }, { @@ -618,12 +525,7 @@ func Test_imageSquashResolver_resolvesLinks(t *testing.T) { }, expected: []Location{ // we have multiple copies across layers - { - Coordinates: Coordinates{ - RealPath: "/file-2.txt", - }, - VirtualPath: "/link-indirect", - }, + NewVirtualLocation("/file-2.txt", "/link-indirect"), }, }, } @@ -646,7 +548,8 @@ func Test_imageSquashResolver_resolvesLinks(t *testing.T) { func compareLocations(t *testing.T, expected, actual []Location) { t.Helper() - ignoreUnexported := cmpopts.IgnoreFields(Location{}, "ref") + ignoreUnexported := cmpopts.IgnoreFields(LocationData{}, "ref") + ignoreMetadata := cmpopts.IgnoreFields(LocationMetadata{}, "Annotations") ignoreFS := cmpopts.IgnoreFields(Coordinates{}, "FileSystemID") sort.Sort(Locations(expected)) @@ -655,6 +558,7 @@ func compareLocations(t *testing.T, expected, actual []Location) { if d := cmp.Diff(expected, actual, ignoreUnexported, ignoreFS, + ignoreMetadata, ); d != "" { t.Errorf("unexpected locations (-want +got):\n%s", d) diff --git a/syft/source/location_set_test.go b/syft/source/location_set_test.go index e9a98fe2bcb..b3d53ae5856 100644 --- a/syft/source/location_set_test.go +++ b/syft/source/location_set_test.go @@ -12,35 +12,43 @@ import ( func TestLocationSet(t *testing.T) { etcHostsLinkVar := Location{ - Coordinates: Coordinates{ - RealPath: "/etc/hosts", - FileSystemID: "a", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "/etc/hosts", + FileSystemID: "a", + }, + VirtualPath: "/var/etc/hosts", }, - VirtualPath: "/var/etc/hosts", } etcHostsLinkHome := Location{ - Coordinates: Coordinates{ - RealPath: "/etc/hosts", - FileSystemID: "a", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "/etc/hosts", + FileSystemID: "a", + }, + VirtualPath: "/home/wagoodman/hosts", }, - VirtualPath: "/home/wagoodman/hosts", } binA := Location{ - Coordinates: Coordinates{ - RealPath: "/bin", - FileSystemID: "a", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "/bin", + FileSystemID: "a", + }, + VirtualPath: "/usr/bin", }, - VirtualPath: "/usr/bin", } binB := Location{ - Coordinates: Coordinates{ - RealPath: "/bin", - FileSystemID: "b", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "/bin", + FileSystemID: "b", + }, + VirtualPath: "/usr/bin", }, - VirtualPath: "/usr/bin", } tests := []struct { @@ -87,41 +95,51 @@ func TestLocationSet(t *testing.T) { func TestLocationSet_Hash(t *testing.T) { etcAlink := Location{ - Coordinates: Coordinates{ - RealPath: "/etc/hosts", - FileSystemID: "a", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "/etc/hosts", + FileSystemID: "a", + }, + VirtualPath: "/var/etc/hosts", }, - VirtualPath: "/var/etc/hosts", } etcA := Location{ - Coordinates: Coordinates{ - RealPath: "/etc/hosts", - FileSystemID: "a", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "/etc/hosts", + FileSystemID: "a", + }, }, } etcB := Location{ - Coordinates: Coordinates{ - RealPath: "/etc/hosts", - FileSystemID: "b", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "/etc/hosts", + FileSystemID: "b", + }, }, } binA := Location{ - Coordinates: Coordinates{ - RealPath: "/bin", - FileSystemID: "a", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "/bin", + FileSystemID: "a", + }, + VirtualPath: "/usr/bin", }, - VirtualPath: "/usr/bin", } binB := Location{ - Coordinates: Coordinates{ - RealPath: "/bin", - FileSystemID: "b", + LocationData: LocationData{ + Coordinates: Coordinates{ + RealPath: "/bin", + FileSystemID: "b", + }, + VirtualPath: "/usr/bin", }, - VirtualPath: "/usr/bin", } tests := []struct { diff --git a/syft/source/location_test.go b/syft/source/location_test.go index 92b6ee45b9b..96f0e3fcd3d 100644 --- a/syft/source/location_test.go +++ b/syft/source/location_test.go @@ -37,9 +37,11 @@ func TestLocation_ID(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { l := Location{ - Coordinates: test.coordinates, - VirtualPath: test.virtualPath, - ref: test.ref, + LocationData: LocationData{ + Coordinates: test.coordinates, + VirtualPath: test.virtualPath, + ref: test.ref, + }, } assert.Equal(t, l.ID(), test.coordinates.ID()) }) From bf30d0850cb8951dbd384c1f341424f280e31c80 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 12 Apr 2023 16:20:43 -0400 Subject: [PATCH 09/12] fix linting Signed-off-by: Alex Goodman --- syft/pkg/cataloger/binary/package.go | 3 ++- syft/pkg/cataloger/deb/package.go | 3 ++- syft/pkg/cataloger/elixir/parse_mix_lock_test.go | 2 +- syft/pkg/cataloger/erlang/parse_rebar_lock_test.go | 2 +- syft/pkg/cataloger/javascript/parse_package_json.go | 3 +-- syft/source/location.go | 1 + syft/source/location_set.go | 3 ++- test/integration/catalog_packages_test.go | 2 +- 8 files changed, 11 insertions(+), 8 deletions(-) diff --git a/syft/pkg/cataloger/binary/package.go b/syft/pkg/cataloger/binary/package.go index 8ee04189b81..7c151321a25 100644 --- a/syft/pkg/cataloger/binary/package.go +++ b/syft/pkg/cataloger/binary/package.go @@ -1,10 +1,11 @@ package binary import ( + "reflect" + "github.com/anchore/syft/syft/cpe" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/source" - "reflect" ) func newPackage(classifier classifier, location source.Location, matchMetadata map[string]string) []pkg.Package { diff --git a/syft/pkg/cataloger/deb/package.go b/syft/pkg/cataloger/deb/package.go index 27395a73a67..be1279895be 100644 --- a/syft/pkg/cataloger/deb/package.go +++ b/syft/pkg/cataloger/deb/package.go @@ -22,7 +22,6 @@ const ( ) func newDpkgPackage(d pkg.DpkgMetadata, dbLocation source.Location, resolver source.FileResolver, release *linux.Release) pkg.Package { - p := pkg.Package{ Name: d.Package, Version: d.Version, @@ -163,6 +162,7 @@ func getAdditionalFileListing(resolver source.FileResolver, dbLocation source.Lo return files, locations } +//nolint:dupl func fetchMd5Contents(resolver source.FileResolver, dbLocation source.Location, m pkg.DpkgMetadata) (io.ReadCloser, *source.Location) { var md5Reader io.ReadCloser var err error @@ -198,6 +198,7 @@ func fetchMd5Contents(resolver source.FileResolver, dbLocation source.Location, return md5Reader, &l } +//nolint:dupl func fetchConffileContents(resolver source.FileResolver, dbLocation source.Location, m pkg.DpkgMetadata) (io.ReadCloser, *source.Location) { var reader io.ReadCloser var err error diff --git a/syft/pkg/cataloger/elixir/parse_mix_lock_test.go b/syft/pkg/cataloger/elixir/parse_mix_lock_test.go index bc6aab5da9e..f164a270ffa 100644 --- a/syft/pkg/cataloger/elixir/parse_mix_lock_test.go +++ b/syft/pkg/cataloger/elixir/parse_mix_lock_test.go @@ -1,12 +1,12 @@ package elixir import ( - "github.com/anchore/syft/syft/source" "testing" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" + "github.com/anchore/syft/syft/source" ) func TestParseMixLock(t *testing.T) { diff --git a/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go b/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go index 4169afd9c97..e2dad051999 100644 --- a/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go +++ b/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go @@ -1,12 +1,12 @@ package erlang import ( - "github.com/anchore/syft/syft/source" "testing" "github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest" + "github.com/anchore/syft/syft/source" ) func TestParseRebarLock(t *testing.T) { diff --git a/syft/pkg/cataloger/javascript/parse_package_json.go b/syft/pkg/cataloger/javascript/parse_package_json.go index c915f3ec1c7..fe75d8c58a9 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json.go +++ b/syft/pkg/cataloger/javascript/parse_package_json.go @@ -70,8 +70,7 @@ func parsePackageJSON(_ source.FileResolver, _ *generic.Environment, reader sour pkgs = append( pkgs, - newPackageJSONPackage(p, reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), - ), + newPackageJSONPackage(p, reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), ) } diff --git a/syft/source/location.go b/syft/source/location.go index e99b57640fd..cc6285e059f 100644 --- a/syft/source/location.go +++ b/syft/source/location.go @@ -2,6 +2,7 @@ package source import ( "fmt" + "github.com/hashicorp/go-multierror" "github.com/anchore/stereoscope/pkg/file" diff --git a/syft/source/location_set.go b/syft/source/location_set.go index 910e629773a..b174827334f 100644 --- a/syft/source/location_set.go +++ b/syft/source/location_set.go @@ -1,10 +1,11 @@ package source import ( - "github.com/anchore/syft/internal/log" "sort" "github.com/mitchellh/hashstructure/v2" + + "github.com/anchore/syft/internal/log" ) type LocationSet struct { diff --git a/test/integration/catalog_packages_test.go b/test/integration/catalog_packages_test.go index 336694ec97e..7ef25c7839b 100644 --- a/test/integration/catalog_packages_test.go +++ b/test/integration/catalog_packages_test.go @@ -1,11 +1,11 @@ package integration import ( - "github.com/scylladb/go-set/strset" "strings" "testing" "github.com/google/go-cmp/cmp" + "github.com/scylladb/go-set/strset" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" From f1ac26556049c1103e7e0244e5d5548abbec9241 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Wed, 12 Apr 2023 16:25:02 -0400 Subject: [PATCH 10/12] bump json schema Signed-off-by: Alex Goodman --- internal/constants.go | 2 +- schema/json/schema-7.1.2.json | 1668 +++++++++++++++++ .../snapshot/TestDirectoryEncoder.golden | 4 +- .../TestEncodeFullJSONDocument.golden | 4 +- .../snapshot/TestImageEncoder.golden | 4 +- 5 files changed, 1675 insertions(+), 7 deletions(-) create mode 100644 schema/json/schema-7.1.2.json diff --git a/internal/constants.go b/internal/constants.go index 1fda74223f2..127fb392489 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -6,5 +6,5 @@ const ( // 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. - JSONSchemaVersion = "7.1.1" + JSONSchemaVersion = "7.1.2" ) diff --git a/schema/json/schema-7.1.2.json b/schema/json/schema-7.1.2.json new file mode 100644 index 00000000000..0a51f5518d9 --- /dev/null +++ b/schema/json/schema-7.1.2.json @@ -0,0 +1,1668 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/anchore/syft/syft/formats/syftjson/model/document", + "$ref": "#/$defs/Document", + "$defs": { + "AlpmFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "type": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "gid": { + "type": "string" + }, + "time": { + "type": "string", + "format": "date-time" + }, + "size": { + "type": "string" + }, + "link": { + "type": "string" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object" + }, + "AlpmMetadata": { + "properties": { + "basepackage": { + "type": "string" + }, + "package": { + "type": "string" + }, + "version": { + "type": "string" + }, + "description": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "packager": { + "type": "string" + }, + "license": { + "type": "string" + }, + "url": { + "type": "string" + }, + "validation": { + "type": "string" + }, + "reason": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + }, + "backup": { + "items": { + "$ref": "#/$defs/AlpmFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "basepackage", + "package", + "version", + "description", + "architecture", + "size", + "packager", + "license", + "url", + "validation", + "reason", + "files", + "backup" + ] + }, + "ApkFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "ownerUid": { + "type": "string" + }, + "ownerGid": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "ApkMetadata": { + "properties": { + "package": { + "type": "string" + }, + "originPackage": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "url": { + "type": "string" + }, + "description": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "installedSize": { + "type": "integer" + }, + "pullDependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "provides": { + "items": { + "type": "string" + }, + "type": "array" + }, + "pullChecksum": { + "type": "string" + }, + "gitCommitOfApkPort": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/ApkFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "originPackage", + "maintainer", + "version", + "license", + "architecture", + "url", + "description", + "size", + "installedSize", + "pullDependencies", + "provides", + "pullChecksum", + "gitCommitOfApkPort", + "files" + ] + }, + "BinaryMetadata": { + "properties": { + "matches": { + "items": { + "$ref": "#/$defs/ClassifierMatch" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "matches" + ] + }, + "CargoPackageMetadata": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "type": "string" + }, + "checksum": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "checksum", + "dependencies" + ] + }, + "ClassifierMatch": { + "properties": { + "classifier": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Location" + } + }, + "type": "object", + "required": [ + "classifier", + "location" + ] + }, + "CocoapodsMetadata": { + "properties": { + "checksum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "checksum" + ] + }, + "ConanLockMetadata": { + "properties": { + "ref": { + "type": "string" + }, + "package_id": { + "type": "string" + }, + "prev": { + "type": "string" + }, + "requires": { + "type": "string" + }, + "build_requires": { + "type": "string" + }, + "py_requires": { + "type": "string" + }, + "options": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "path": { + "type": "string" + }, + "context": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "ConanMetadata": { + "properties": { + "ref": { + "type": "string" + } + }, + "type": "object", + "required": [ + "ref" + ] + }, + "Coordinates": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "DartPubMetadata": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "hosted_url": { + "type": "string" + }, + "vcs_url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Descriptor": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "configuration": true + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "Digest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "Document": { + "properties": { + "artifacts": { + "items": { + "$ref": "#/$defs/Package" + }, + "type": "array" + }, + "artifactRelationships": { + "items": { + "$ref": "#/$defs/Relationship" + }, + "type": "array" + }, + "files": { + "items": { + "$ref": "#/$defs/File" + }, + "type": "array" + }, + "secrets": { + "items": { + "$ref": "#/$defs/Secrets" + }, + "type": "array" + }, + "source": { + "$ref": "#/$defs/Source" + }, + "distro": { + "$ref": "#/$defs/LinuxRelease" + }, + "descriptor": { + "$ref": "#/$defs/Descriptor" + }, + "schema": { + "$ref": "#/$defs/Schema" + } + }, + "type": "object", + "required": [ + "artifacts", + "artifactRelationships", + "source", + "distro", + "descriptor", + "schema" + ] + }, + "DotnetDepsMetadata": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "path": { + "type": "string" + }, + "sha512": { + "type": "string" + }, + "hashPath": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "path", + "sha512", + "hashPath" + ] + }, + "DpkgFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "isConfigFile": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "path", + "isConfigFile" + ] + }, + "DpkgMetadata": { + "properties": { + "package": { + "type": "string" + }, + "source": { + "type": "string" + }, + "version": { + "type": "string" + }, + "sourceVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "maintainer": { + "type": "string" + }, + "installedSize": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/DpkgFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "package", + "source", + "version", + "sourceVersion", + "architecture", + "maintainer", + "installedSize", + "files" + ] + }, + "File": { + "properties": { + "id": { + "type": "string" + }, + "location": { + "$ref": "#/$defs/Coordinates" + }, + "metadata": { + "$ref": "#/$defs/FileMetadataEntry" + }, + "contents": { + "type": "string" + }, + "digests": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "id", + "location" + ] + }, + "FileMetadataEntry": { + "properties": { + "mode": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "linkDestination": { + "type": "string" + }, + "userID": { + "type": "integer" + }, + "groupID": { + "type": "integer" + }, + "mimeType": { + "type": "string" + } + }, + "type": "object", + "required": [ + "mode", + "type", + "userID", + "groupID", + "mimeType" + ] + }, + "GemMetadata": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "type": "string" + }, + "type": "array" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "GolangBinMetadata": { + "properties": { + "goBuildSettings": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "goCompiledVersion": { + "type": "string" + }, + "architecture": { + "type": "string" + }, + "h1Digest": { + "type": "string" + }, + "mainModule": { + "type": "string" + } + }, + "type": "object", + "required": [ + "goCompiledVersion", + "architecture" + ] + }, + "GolangModMetadata": { + "properties": { + "h1Digest": { + "type": "string" + } + }, + "type": "object" + }, + "HackageMetadata": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "snapshotURL": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version" + ] + }, + "IDLikes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "JavaManifest": { + "properties": { + "main": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "namedSections": { + "patternProperties": { + ".*": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "JavaMetadata": { + "properties": { + "virtualPath": { + "type": "string" + }, + "manifest": { + "$ref": "#/$defs/JavaManifest" + }, + "pomProperties": { + "$ref": "#/$defs/PomProperties" + }, + "pomProject": { + "$ref": "#/$defs/PomProject" + }, + "digest": { + "items": { + "$ref": "#/$defs/Digest" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "virtualPath" + ] + }, + "KbPackageMetadata": { + "properties": { + "product_id": { + "type": "string" + }, + "kb": { + "type": "string" + } + }, + "type": "object", + "required": [ + "product_id", + "kb" + ] + }, + "LinuxRelease": { + "properties": { + "prettyName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "id": { + "type": "string" + }, + "idLike": { + "$ref": "#/$defs/IDLikes" + }, + "version": { + "type": "string" + }, + "versionID": { + "type": "string" + }, + "versionCodename": { + "type": "string" + }, + "buildID": { + "type": "string" + }, + "imageID": { + "type": "string" + }, + "imageVersion": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "variantID": { + "type": "string" + }, + "homeURL": { + "type": "string" + }, + "supportURL": { + "type": "string" + }, + "bugReportURL": { + "type": "string" + }, + "privacyPolicyURL": { + "type": "string" + }, + "cpeName": { + "type": "string" + }, + "supportEnd": { + "type": "string" + } + }, + "type": "object" + }, + "Location": { + "properties": { + "path": { + "type": "string" + }, + "layerID": { + "type": "string" + }, + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "MixLockMetadata": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "NixStoreMetadata": { + "properties": { + "outputHash": { + "type": "string" + }, + "output": { + "type": "string" + }, + "files": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "outputHash", + "files" + ] + }, + "NpmPackageJSONMetadata": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "author": { + "type": "string" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "homepage": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "private": { + "type": "boolean" + } + }, + "type": "object", + "required": [ + "name", + "version", + "author", + "licenses", + "homepage", + "description", + "url", + "private" + ] + }, + "NpmPackageLockJSONMetadata": { + "properties": { + "resolved": { + "type": "string" + }, + "integrity": { + "type": "string" + } + }, + "type": "object", + "required": [ + "resolved", + "integrity" + ] + }, + "Package": { + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "type": { + "type": "string" + }, + "foundBy": { + "type": "string" + }, + "locations": { + "items": { + "$ref": "#/$defs/Location" + }, + "type": "array" + }, + "licenses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "language": { + "type": "string" + }, + "cpes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "purl": { + "type": "string" + }, + "metadataType": { + "type": "string" + }, + "metadata": { + "anyOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/AlpmMetadata" + }, + { + "$ref": "#/$defs/ApkMetadata" + }, + { + "$ref": "#/$defs/BinaryMetadata" + }, + { + "$ref": "#/$defs/CargoPackageMetadata" + }, + { + "$ref": "#/$defs/CocoapodsMetadata" + }, + { + "$ref": "#/$defs/ConanLockMetadata" + }, + { + "$ref": "#/$defs/ConanMetadata" + }, + { + "$ref": "#/$defs/DartPubMetadata" + }, + { + "$ref": "#/$defs/DotnetDepsMetadata" + }, + { + "$ref": "#/$defs/DpkgMetadata" + }, + { + "$ref": "#/$defs/GemMetadata" + }, + { + "$ref": "#/$defs/GolangBinMetadata" + }, + { + "$ref": "#/$defs/GolangModMetadata" + }, + { + "$ref": "#/$defs/HackageMetadata" + }, + { + "$ref": "#/$defs/JavaMetadata" + }, + { + "$ref": "#/$defs/KbPackageMetadata" + }, + { + "$ref": "#/$defs/MixLockMetadata" + }, + { + "$ref": "#/$defs/NixStoreMetadata" + }, + { + "$ref": "#/$defs/NpmPackageJSONMetadata" + }, + { + "$ref": "#/$defs/NpmPackageLockJSONMetadata" + }, + { + "$ref": "#/$defs/PhpComposerJSONMetadata" + }, + { + "$ref": "#/$defs/PortageMetadata" + }, + { + "$ref": "#/$defs/PythonPackageMetadata" + }, + { + "$ref": "#/$defs/PythonPipfileLockMetadata" + }, + { + "$ref": "#/$defs/RebarLockMetadata" + }, + { + "$ref": "#/$defs/RpmMetadata" + } + ] + } + }, + "type": "object", + "required": [ + "id", + "name", + "version", + "type", + "foundBy", + "locations", + "licenses", + "language", + "cpes", + "purl" + ] + }, + "PhpComposerAuthors": { + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + }, + "homepage": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name" + ] + }, + "PhpComposerExternalReference": { + "properties": { + "type": { + "type": "string" + }, + "url": { + "type": "string" + }, + "reference": { + "type": "string" + }, + "shasum": { + "type": "string" + } + }, + "type": "object", + "required": [ + "type", + "url", + "reference" + ] + }, + "PhpComposerJSONMetadata": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "source": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "dist": { + "$ref": "#/$defs/PhpComposerExternalReference" + }, + "require": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "provide": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "require-dev": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "suggest": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "type": { + "type": "string" + }, + "notification-url": { + "type": "string" + }, + "bin": { + "items": { + "type": "string" + }, + "type": "array" + }, + "license": { + "items": { + "type": "string" + }, + "type": "array" + }, + "authors": { + "items": { + "$ref": "#/$defs/PhpComposerAuthors" + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "homepage": { + "type": "string" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "time": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "source", + "dist" + ] + }, + "PomParent": { + "properties": { + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "required": [ + "groupId", + "artifactId", + "version" + ] + }, + "PomProject": { + "properties": { + "path": { + "type": "string" + }, + "parent": { + "$ref": "#/$defs/PomParent" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "groupId", + "artifactId", + "version", + "name" + ] + }, + "PomProperties": { + "properties": { + "path": { + "type": "string" + }, + "name": { + "type": "string" + }, + "groupId": { + "type": "string" + }, + "artifactId": { + "type": "string" + }, + "version": { + "type": "string" + }, + "extraFields": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object", + "required": [ + "path", + "name", + "groupId", + "artifactId", + "version" + ] + }, + "PortageFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/Digest" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PortageMetadata": { + "properties": { + "installedSize": { + "type": "integer" + }, + "files": { + "items": { + "$ref": "#/$defs/PortageFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "installedSize", + "files" + ] + }, + "PythonDirectURLOriginInfo": { + "properties": { + "url": { + "type": "string" + }, + "commitId": { + "type": "string" + }, + "vcs": { + "type": "string" + } + }, + "type": "object", + "required": [ + "url" + ] + }, + "PythonFileDigest": { + "properties": { + "algorithm": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "algorithm", + "value" + ] + }, + "PythonFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "digest": { + "$ref": "#/$defs/PythonFileDigest" + }, + "size": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path" + ] + }, + "PythonPackageMetadata": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "license": { + "type": "string" + }, + "author": { + "type": "string" + }, + "authorEmail": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/PythonFileRecord" + }, + "type": "array" + }, + "sitePackagesRootPath": { + "type": "string" + }, + "topLevelPackages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "directUrlOrigin": { + "$ref": "#/$defs/PythonDirectURLOriginInfo" + } + }, + "type": "object", + "required": [ + "name", + "version", + "license", + "author", + "authorEmail", + "platform", + "sitePackagesRootPath" + ] + }, + "PythonPipfileLockMetadata": { + "properties": { + "hashes": { + "items": { + "type": "string" + }, + "type": "array" + }, + "index": { + "type": "string" + } + }, + "type": "object", + "required": [ + "hashes", + "index" + ] + }, + "RebarLockMetadata": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "pkgHash": { + "type": "string" + }, + "pkgHashExt": { + "type": "string" + } + }, + "type": "object", + "required": [ + "name", + "version", + "pkgHash", + "pkgHashExt" + ] + }, + "Relationship": { + "properties": { + "parent": { + "type": "string" + }, + "child": { + "type": "string" + }, + "type": { + "type": "string" + }, + "metadata": true + }, + "type": "object", + "required": [ + "parent", + "child", + "type" + ] + }, + "RpmMetadata": { + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + }, + "epoch": { + "oneOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "architecture": { + "type": "string" + }, + "release": { + "type": "string" + }, + "sourceRpm": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "license": { + "type": "string" + }, + "vendor": { + "type": "string" + }, + "modularityLabel": { + "type": "string" + }, + "files": { + "items": { + "$ref": "#/$defs/RpmdbFileRecord" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "name", + "version", + "epoch", + "architecture", + "release", + "sourceRpm", + "size", + "license", + "vendor", + "modularityLabel", + "files" + ] + }, + "RpmdbFileRecord": { + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "digest": { + "$ref": "#/$defs/Digest" + }, + "userName": { + "type": "string" + }, + "groupName": { + "type": "string" + }, + "flags": { + "type": "string" + } + }, + "type": "object", + "required": [ + "path", + "mode", + "size", + "digest", + "userName", + "groupName", + "flags" + ] + }, + "Schema": { + "properties": { + "version": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "required": [ + "version", + "url" + ] + }, + "SearchResult": { + "properties": { + "classification": { + "type": "string" + }, + "lineNumber": { + "type": "integer" + }, + "lineOffset": { + "type": "integer" + }, + "seekPosition": { + "type": "integer" + }, + "length": { + "type": "integer" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "required": [ + "classification", + "lineNumber", + "lineOffset", + "seekPosition", + "length" + ] + }, + "Secrets": { + "properties": { + "location": { + "$ref": "#/$defs/Coordinates" + }, + "secrets": { + "items": { + "$ref": "#/$defs/SearchResult" + }, + "type": "array" + } + }, + "type": "object", + "required": [ + "location", + "secrets" + ] + }, + "Source": { + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + }, + "target": true + }, + "type": "object", + "required": [ + "id", + "type", + "target" + ] + } + } +} diff --git a/syft/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden b/syft/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden index 8d30145dd04..f0ad7b3ae53 100644 --- a/syft/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden +++ b/syft/formats/syftjson/test-fixtures/snapshot/TestDirectoryEncoder.golden @@ -89,7 +89,7 @@ } }, "schema": { - "version": "7.1.1", - "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.1.json" + "version": "7.1.2", + "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.2.json" } } diff --git a/syft/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden b/syft/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden index 7b4ccd02b36..cccc7ae4ef1 100644 --- a/syft/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden +++ b/syft/formats/syftjson/test-fixtures/snapshot/TestEncodeFullJSONDocument.golden @@ -185,7 +185,7 @@ } }, "schema": { - "version": "7.1.1", - "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.1.json" + "version": "7.1.2", + "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.2.json" } } diff --git a/syft/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden b/syft/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden index 7e922e6ac58..a5b6a2d839a 100644 --- a/syft/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden +++ b/syft/formats/syftjson/test-fixtures/snapshot/TestImageEncoder.golden @@ -112,7 +112,7 @@ } }, "schema": { - "version": "7.1.1", - "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.1.json" + "version": "7.1.2", + "url": "https://raw.githubusercontent.com/anchore/syft/main/schema/json/schema-7.1.2.json" } } From 990eb13423dba4fa8b8c22de7328943606e4c5a1 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Thu, 13 Apr 2023 11:08:33 -0400 Subject: [PATCH 11/12] partial addressing of review comments Signed-off-by: Alex Goodman --- syft/pkg/cataloger/binary/classifier.go | 16 ++++++++-- syft/pkg/cataloger/binary/package.go | 4 +-- .../cataloger/elixir/parse_mix_lock_test.go | 31 ++++++++++--------- .../cataloger/erlang/parse_rebar_lock_test.go | 19 +++--------- 4 files changed, 36 insertions(+), 34 deletions(-) diff --git a/syft/pkg/cataloger/binary/classifier.go b/syft/pkg/cataloger/binary/classifier.go index e5a2509e299..6ab18985c52 100644 --- a/syft/pkg/cataloger/binary/classifier.go +++ b/syft/pkg/cataloger/binary/classifier.go @@ -106,7 +106,13 @@ func fileNameTemplateVersionMatcher(fileNamePattern string, contentTemplate stri } matchMetadata := internal.MatchNamedCaptureGroups(tmplPattern, string(contents)) - return newPackage(classifier, location, matchMetadata), nil + + p := newPackage(classifier, location, matchMetadata) + if p == nil { + return nil, nil + } + + return []pkg.Package{*p}, nil } } @@ -119,7 +125,13 @@ func fileContentsVersionMatcher(pattern string) evidenceMatcher { } matchMetadata := internal.MatchNamedCaptureGroups(pat, string(contents)) - return newPackage(classifier, location, matchMetadata), nil + + p := newPackage(classifier, location, matchMetadata) + if p == nil { + return nil, nil + } + + return []pkg.Package{*p}, nil } } diff --git a/syft/pkg/cataloger/binary/package.go b/syft/pkg/cataloger/binary/package.go index 7c151321a25..eb331e2cfbe 100644 --- a/syft/pkg/cataloger/binary/package.go +++ b/syft/pkg/cataloger/binary/package.go @@ -8,7 +8,7 @@ import ( "github.com/anchore/syft/syft/source" ) -func newPackage(classifier classifier, location source.Location, matchMetadata map[string]string) []pkg.Package { +func newPackage(classifier classifier, location source.Location, matchMetadata map[string]string) *pkg.Package { version, ok := matchMetadata["version"] if !ok { return nil @@ -59,5 +59,5 @@ func newPackage(classifier classifier, location source.Location, matchMetadata m p.SetID() - return []pkg.Package{p} + return &p } diff --git a/syft/pkg/cataloger/elixir/parse_mix_lock_test.go b/syft/pkg/cataloger/elixir/parse_mix_lock_test.go index f164a270ffa..2f5de43d4e1 100644 --- a/syft/pkg/cataloger/elixir/parse_mix_lock_test.go +++ b/syft/pkg/cataloger/elixir/parse_mix_lock_test.go @@ -10,13 +10,14 @@ import ( ) func TestParseMixLock(t *testing.T) { + locations := source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")) expected := []pkg.Package{ { Name: "castore", Version: "0.1.17", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/castore@0.1.17", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -31,7 +32,7 @@ func TestParseMixLock(t *testing.T) { Version: "1.1.0", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/connection@1.1.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -46,7 +47,7 @@ func TestParseMixLock(t *testing.T) { Version: "2.9.0", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/cowboy@2.9.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -61,7 +62,7 @@ func TestParseMixLock(t *testing.T) { Version: "0.4.0", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/cowboy_telemetry@0.4.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -76,7 +77,7 @@ func TestParseMixLock(t *testing.T) { Version: "2.11.0", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/cowlib@2.11.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -91,7 +92,7 @@ func TestParseMixLock(t *testing.T) { Version: "2.4.2", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/db_connection@2.4.2", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -106,7 +107,7 @@ func TestParseMixLock(t *testing.T) { Version: "2.0.0", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/decimal@2.0.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -121,7 +122,7 @@ func TestParseMixLock(t *testing.T) { Version: "1.4.25", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/earmark_parser@1.4.25", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -136,7 +137,7 @@ func TestParseMixLock(t *testing.T) { Version: "3.8.1", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/ecto@3.8.1", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -151,7 +152,7 @@ func TestParseMixLock(t *testing.T) { Version: "3.8.1", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/ecto_sql@3.8.1", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -166,7 +167,7 @@ func TestParseMixLock(t *testing.T) { Version: "0.5.0", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/esbuild@0.5.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -181,7 +182,7 @@ func TestParseMixLock(t *testing.T) { Version: "0.28.4", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/ex_doc@0.28.4", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -196,7 +197,7 @@ func TestParseMixLock(t *testing.T) { Version: "0.19.1", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/gettext@0.19.1", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -211,7 +212,7 @@ func TestParseMixLock(t *testing.T) { Version: "0.1.1", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/hpax@0.1.1", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ @@ -226,7 +227,7 @@ func TestParseMixLock(t *testing.T) { Version: "1.3.0", Language: pkg.Elixir, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/mix.lock")), + Locations: locations, PURL: "pkg:hex/jason@1.3.0", MetadataType: pkg.MixLockMetadataType, Metadata: pkg.MixLockMetadata{ diff --git a/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go b/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go index e2dad051999..b1293143277 100644 --- a/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go +++ b/syft/pkg/cataloger/erlang/parse_rebar_lock_test.go @@ -22,7 +22,6 @@ func TestParseRebarLock(t *testing.T) { Version: "2.9.0", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/certifi@2.9.0", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -37,7 +36,6 @@ func TestParseRebarLock(t *testing.T) { Version: "6.1.1", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/idna@6.1.1", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -52,7 +50,6 @@ func TestParseRebarLock(t *testing.T) { Version: "1.0.1", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/metrics@1.0.1", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -67,7 +64,6 @@ func TestParseRebarLock(t *testing.T) { Version: "1.2.0", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/mimerl@1.2.0", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -82,7 +78,6 @@ func TestParseRebarLock(t *testing.T) { Version: "3.3.1", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/parse_trans@3.3.1", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -97,7 +92,6 @@ func TestParseRebarLock(t *testing.T) { Version: "1.1.6", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/ssl_verify_fun@1.1.6", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -112,7 +106,6 @@ func TestParseRebarLock(t *testing.T) { Version: "0.7.0", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar.lock")), PURL: "pkg:hex/unicode_util_compat@0.7.0", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -135,7 +128,6 @@ func TestParseRebarLock(t *testing.T) { Version: "1.1.5", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/bcrypt@1.1.5", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -154,7 +146,6 @@ func TestParseRebarLock(t *testing.T) { Version: "14308ab927cfa69324742c3de720578094e0bb19", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/bson@14308ab927cfa69324742c3de720578094e0bb19", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -170,7 +161,6 @@ func TestParseRebarLock(t *testing.T) { Version: "2.9.0", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/certifi@2.9.0", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -188,7 +178,6 @@ func TestParseRebarLock(t *testing.T) { Version: "0.2.3", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/stdout_formatter@0.2.3", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -207,7 +196,6 @@ func TestParseRebarLock(t *testing.T) { Version: "4835239dca5a5f4ac7202dd94d7effcaa617d575", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/swc@4835239dca5a5f4ac7202dd94d7effcaa617d575", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -223,7 +211,6 @@ func TestParseRebarLock(t *testing.T) { Version: "1.1.0", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/syslog@1.1.0", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -241,7 +228,6 @@ func TestParseRebarLock(t *testing.T) { Version: "0.7.0", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/unicode_util_compat@0.7.0", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -260,7 +246,6 @@ func TestParseRebarLock(t *testing.T) { Version: "6d622aa8c901ae7777433aef2bd049e380c474a6", Language: pkg.Erlang, Type: pkg.HexPkg, - Locations: source.NewLocationSet(source.NewLocation("test-fixtures/rebar-2.lock")), PURL: "pkg:hex/vernemq_dev@6d622aa8c901ae7777433aef2bd049e380c474a6", MetadataType: pkg.RebarLockMetadataType, Metadata: pkg.RebarLockMetadata{ @@ -277,6 +262,10 @@ func TestParseRebarLock(t *testing.T) { // TODO: relationships are not under test var expectedRelationships []artifact.Relationship + for idx := range test.expected { + test.expected[idx].Locations = source.NewLocationSet(source.NewLocation(test.fixture)) + } + pkgtest.TestFileParser(t, test.fixture, parseRebarLock, test.expected, expectedRelationships) }) } From 9cbae1be771971ec67524a9dbd73c289c9af95d7 Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Thu, 13 Apr 2023 15:00:31 -0400 Subject: [PATCH 12/12] rename location.WithAnnotation Signed-off-by: Alex Goodman --- syft/pkg/cataloger/alpm/parse_alpm_db.go | 2 +- syft/pkg/cataloger/apkdb/parse_apk_db.go | 2 +- syft/pkg/cataloger/binary/package.go | 2 +- syft/pkg/cataloger/cpp/parse_conanfile.go | 2 +- syft/pkg/cataloger/cpp/parse_conanlock.go | 2 +- syft/pkg/cataloger/dart/parse_pubspec_lock.go | 2 +- syft/pkg/cataloger/deb/package.go | 8 ++++---- syft/pkg/cataloger/dotnet/parse_dotnet_deps.go | 2 +- syft/pkg/cataloger/elixir/parse_mix_lock.go | 2 +- syft/pkg/cataloger/erlang/parse_rebar_lock.go | 2 +- syft/pkg/cataloger/golang/parse_go_binary.go | 4 ++-- .../cataloger/golang/parse_go_binary_test.go | 18 +++++++++--------- syft/pkg/cataloger/golang/parse_go_mod.go | 4 ++-- .../cataloger/haskell/parse_cabal_freeze.go | 2 +- syft/pkg/cataloger/haskell/parse_stack_lock.go | 2 +- syft/pkg/cataloger/haskell/parse_stack_yaml.go | 2 +- syft/pkg/cataloger/java/archive_parser.go | 4 ++-- .../cataloger/java/parse_gradle_lockfile.go | 2 +- syft/pkg/cataloger/java/parse_pom_xml.go | 2 +- syft/pkg/cataloger/javascript/package.go | 8 ++++---- .../cataloger/javascript/parse_package_json.go | 2 +- syft/pkg/cataloger/nix/cataloger.go | 2 +- syft/pkg/cataloger/php/parse_composer_lock.go | 2 +- syft/pkg/cataloger/php/parse_installed_json.go | 2 +- .../portage/parse_portage_contents.go | 6 +++--- syft/pkg/cataloger/python/parse_poetry_lock.go | 2 +- .../pkg/cataloger/python/parse_requirements.go | 2 +- syft/pkg/cataloger/python/parse_setup.go | 2 +- syft/pkg/cataloger/python/parse_wheel_egg.go | 10 +++++----- syft/pkg/cataloger/rpm/package.go | 2 +- syft/pkg/cataloger/ruby/parse_gemfile_lock.go | 2 +- syft/pkg/cataloger/ruby/parse_gemspec.go | 2 +- syft/pkg/cataloger/rust/package.go | 2 +- syft/pkg/cataloger/rust/parse_cargo_lock.go | 2 +- syft/pkg/cataloger/sbom/cataloger.go | 2 +- syft/pkg/cataloger/swift/parse_podfile_lock.go | 2 +- syft/source/location.go | 2 +- syft/source/location_set.go | 18 +++++++----------- 38 files changed, 67 insertions(+), 71 deletions(-) diff --git a/syft/pkg/cataloger/alpm/parse_alpm_db.go b/syft/pkg/cataloger/alpm/parse_alpm_db.go index 301d6a09d8f..7c57ace4579 100644 --- a/syft/pkg/cataloger/alpm/parse_alpm_db.go +++ b/syft/pkg/cataloger/alpm/parse_alpm_db.go @@ -73,7 +73,7 @@ func parseAlpmDB(resolver source.FileResolver, env *generic.Environment, reader newPackage( *metadata, env.LinuxRelease, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), }, nil, nil } diff --git a/syft/pkg/cataloger/apkdb/parse_apk_db.go b/syft/pkg/cataloger/apkdb/parse_apk_db.go index 9e6c3a8a415..3409524f4c3 100644 --- a/syft/pkg/cataloger/apkdb/parse_apk_db.go +++ b/syft/pkg/cataloger/apkdb/parse_apk_db.go @@ -123,7 +123,7 @@ func parseApkDB(resolver source.FileResolver, env *generic.Environment, reader s pkgs := make([]pkg.Package, 0, len(apks)) for _, apk := range apks { - pkgs = append(pkgs, newPackage(apk, r, reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))) + pkgs = append(pkgs, newPackage(apk, r, reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation))) } return pkgs, discoverPackageDependencies(pkgs), nil diff --git a/syft/pkg/cataloger/binary/package.go b/syft/pkg/cataloger/binary/package.go index eb331e2cfbe..7c1fb7abc60 100644 --- a/syft/pkg/cataloger/binary/package.go +++ b/syft/pkg/cataloger/binary/package.go @@ -27,7 +27,7 @@ func newPackage(classifier classifier, location source.Location, matchMetadata m Name: classifier.Package, Version: version, Locations: source.NewLocationSet( - location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), Type: pkg.BinaryPkg, CPEs: cpes, diff --git a/syft/pkg/cataloger/cpp/parse_conanfile.go b/syft/pkg/cataloger/cpp/parse_conanfile.go index bdcca82d049..fdaf08026be 100644 --- a/syft/pkg/cataloger/cpp/parse_conanfile.go +++ b/syft/pkg/cataloger/cpp/parse_conanfile.go @@ -50,7 +50,7 @@ func parseConanfile(_ source.FileResolver, _ *generic.Environment, reader source p := newConanfilePackage( m, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) if p == nil { continue diff --git a/syft/pkg/cataloger/cpp/parse_conanlock.go b/syft/pkg/cataloger/cpp/parse_conanlock.go index c8adaf02eaa..b3bcf31d53e 100644 --- a/syft/pkg/cataloger/cpp/parse_conanlock.go +++ b/syft/pkg/cataloger/cpp/parse_conanlock.go @@ -46,7 +46,7 @@ func parseConanlock(_ source.FileResolver, _ *generic.Environment, reader source p := newConanlockPackage( metadata, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) if p != nil { diff --git a/syft/pkg/cataloger/dart/parse_pubspec_lock.go b/syft/pkg/cataloger/dart/parse_pubspec_lock.go index d2acc338863..bde8caf663d 100644 --- a/syft/pkg/cataloger/dart/parse_pubspec_lock.go +++ b/syft/pkg/cataloger/dart/parse_pubspec_lock.go @@ -62,7 +62,7 @@ func parsePubspecLock(_ source.FileResolver, _ *generic.Environment, reader sour newPubspecLockPackage( name, pubPkg, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/deb/package.go b/syft/pkg/cataloger/deb/package.go index be1279895be..2113c847222 100644 --- a/syft/pkg/cataloger/deb/package.go +++ b/syft/pkg/cataloger/deb/package.go @@ -25,7 +25,7 @@ func newDpkgPackage(d pkg.DpkgMetadata, dbLocation source.Location, resolver sou p := pkg.Package{ Name: d.Package, Version: d.Version, - Locations: source.NewLocationSet(dbLocation.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Locations: source.NewLocationSet(dbLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(d, release), Type: pkg.DebPkg, MetadataType: pkg.DpkgMetadataType, @@ -193,7 +193,7 @@ func fetchMd5Contents(resolver source.FileResolver, dbLocation source.Location, log.Warnf("failed to fetch deb md5 contents (package=%s): %+v", m.Package, err) } - l := location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) + l := location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) return md5Reader, &l } @@ -229,7 +229,7 @@ func fetchConffileContents(resolver source.FileResolver, dbLocation source.Locat log.Warnf("failed to fetch deb conffiles contents (package=%s): %+v", m.Package, err) } - l := location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) + l := location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) return reader, &l } @@ -253,7 +253,7 @@ func fetchCopyrightContents(resolver source.FileResolver, dbLocation source.Loca log.Warnf("failed to fetch deb copyright contents (package=%s): %w", m.Package, err) } - l := location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) + l := location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation) return reader, &l } diff --git a/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go b/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go index 13c617ffa7a..0e322d3db25 100644 --- a/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go +++ b/syft/pkg/cataloger/dotnet/parse_dotnet_deps.go @@ -48,7 +48,7 @@ func parseDotnetDeps(_ source.FileResolver, _ *generic.Environment, reader sourc dotnetPkg := newDotnetDepsPackage( nameVersion, lib, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) if dotnetPkg != nil { diff --git a/syft/pkg/cataloger/elixir/parse_mix_lock.go b/syft/pkg/cataloger/elixir/parse_mix_lock.go index be4daff0e89..6de1fc8f703 100644 --- a/syft/pkg/cataloger/elixir/parse_mix_lock.go +++ b/syft/pkg/cataloger/elixir/parse_mix_lock.go @@ -51,7 +51,7 @@ func parseMixLock(_ source.FileResolver, _ *generic.Environment, reader source.L PkgHash: hash, PkgHashExt: hashExt, }, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/erlang/parse_rebar_lock.go b/syft/pkg/cataloger/erlang/parse_rebar_lock.go index 407ea716221..547a4d3ec4f 100644 --- a/syft/pkg/cataloger/erlang/parse_rebar_lock.go +++ b/syft/pkg/cataloger/erlang/parse_rebar_lock.go @@ -53,7 +53,7 @@ func parseRebarLock(_ source.FileResolver, _ *generic.Environment, reader source Name: name, Version: version, }, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) pkgMap[name] = &p diff --git a/syft/pkg/cataloger/golang/parse_go_binary.go b/syft/pkg/cataloger/golang/parse_go_binary.go index 15bb45f3f09..c7b99fd2501 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary.go +++ b/syft/pkg/cataloger/golang/parse_go_binary.go @@ -69,7 +69,7 @@ func (c *goBinaryCataloger) makeGoMainPackage(resolver source.FileResolver, mod mod.GoVersion, arch, gbs, - location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) if main.Version == devel { if version, ok := gbs["vcs.revision"]; ok { @@ -219,7 +219,7 @@ func (c *goBinaryCataloger) buildGoPkgInfo(resolver source.FileResolver, locatio mod.GoVersion, arch, nil, - location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) if pkg.IsValid(&p) { pkgs = append(pkgs, p) diff --git a/syft/pkg/cataloger/golang/parse_go_binary_test.go b/syft/pkg/cataloger/golang/parse_go_binary_test.go index b13a46809c2..c9d78a2eab1 100644 --- a/syft/pkg/cataloger/golang/parse_go_binary_test.go +++ b/syft/pkg/cataloger/golang/parse_go_binary_test.go @@ -141,7 +141,7 @@ func TestBuildGoPkgInfo(t *testing.T) { RealPath: "/a-path", FileSystemID: "layer-id", }, - ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -188,7 +188,7 @@ func TestBuildGoPkgInfo(t *testing.T) { RealPath: "/a-path", FileSystemID: "layer-id", }, - ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{}, @@ -231,7 +231,7 @@ func TestBuildGoPkgInfo(t *testing.T) { RealPath: "/a-path", FileSystemID: "layer-id", }, - ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -267,7 +267,7 @@ func TestBuildGoPkgInfo(t *testing.T) { RealPath: "/a-path", FileSystemID: "layer-id", }, - ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -325,7 +325,7 @@ func TestBuildGoPkgInfo(t *testing.T) { RealPath: "/a-path", FileSystemID: "layer-id", }, - ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -380,7 +380,7 @@ func TestBuildGoPkgInfo(t *testing.T) { RealPath: "/a-path", FileSystemID: "layer-id", }, - ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -402,7 +402,7 @@ func TestBuildGoPkgInfo(t *testing.T) { RealPath: "/a-path", FileSystemID: "layer-id", }, - ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -457,7 +457,7 @@ func TestBuildGoPkgInfo(t *testing.T) { RealPath: "/a-path", FileSystemID: "layer-id", }, - ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ @@ -478,7 +478,7 @@ func TestBuildGoPkgInfo(t *testing.T) { RealPath: "/a-path", FileSystemID: "layer-id", }, - ).Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + ).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), MetadataType: pkg.GolangBinMetadataType, Metadata: pkg.GolangBinMetadata{ diff --git a/syft/pkg/cataloger/golang/parse_go_mod.go b/syft/pkg/cataloger/golang/parse_go_mod.go index 92b417dc3fe..203ba318919 100644 --- a/syft/pkg/cataloger/golang/parse_go_mod.go +++ b/syft/pkg/cataloger/golang/parse_go_mod.go @@ -51,7 +51,7 @@ func (c *goModCataloger) parseGoModFile(resolver source.FileResolver, _ *generic Name: m.Mod.Path, Version: m.Mod.Version, Licenses: licenses, - Locations: source.NewLocationSet(reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Locations: source.NewLocationSet(reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(m.Mod.Path, m.Mod.Version), Language: pkg.Go, Type: pkg.GoModulePkg, @@ -73,7 +73,7 @@ func (c *goModCataloger) parseGoModFile(resolver source.FileResolver, _ *generic Name: m.New.Path, Version: m.New.Version, Licenses: licenses, - Locations: source.NewLocationSet(reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Locations: source.NewLocationSet(reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(m.New.Path, m.New.Version), Language: pkg.Go, Type: pkg.GoModulePkg, diff --git a/syft/pkg/cataloger/haskell/parse_cabal_freeze.go b/syft/pkg/cataloger/haskell/parse_cabal_freeze.go index a3434d75b5e..d95446984cc 100644 --- a/syft/pkg/cataloger/haskell/parse_cabal_freeze.go +++ b/syft/pkg/cataloger/haskell/parse_cabal_freeze.go @@ -52,7 +52,7 @@ func parseCabalFreeze(_ source.FileResolver, _ *generic.Environment, reader sour pkgName, pkgVersion, nil, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/haskell/parse_stack_lock.go b/syft/pkg/cataloger/haskell/parse_stack_lock.go index 53ec9b6c7f1..de41a57672d 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_lock.go +++ b/syft/pkg/cataloger/haskell/parse_stack_lock.go @@ -71,7 +71,7 @@ func parseStackLock(_ source.FileResolver, _ *generic.Environment, reader source PkgHash: pkgHash, SnapshotURL: snapshotURL, }, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/haskell/parse_stack_yaml.go b/syft/pkg/cataloger/haskell/parse_stack_yaml.go index 338f4942093..8404f4bf47c 100644 --- a/syft/pkg/cataloger/haskell/parse_stack_yaml.go +++ b/syft/pkg/cataloger/haskell/parse_stack_yaml.go @@ -42,7 +42,7 @@ func parseStackYaml(_ source.FileResolver, _ *generic.Environment, reader source &pkg.HackageMetadata{ PkgHash: pkgHash, }, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/java/archive_parser.go b/syft/pkg/cataloger/java/archive_parser.go index bd19a5fa9bf..0128709d539 100644 --- a/syft/pkg/cataloger/java/archive_parser.go +++ b/syft/pkg/cataloger/java/archive_parser.go @@ -191,7 +191,7 @@ func (j *archiveParser) discoverMainPackage() (*pkg.Package, error) { Licenses: selectLicense(manifest), Language: pkg.Java, Locations: source.NewLocationSet( - j.location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + j.location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), Type: j.fileInfo.pkgType(), MetadataType: pkg.JavaMetadataType, @@ -385,7 +385,7 @@ func newPackageFromMavenData(pomProperties pkg.PomProperties, pomProject *pkg.Po Name: pomProperties.ArtifactID, Version: pomProperties.Version, Locations: source.NewLocationSet( - location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), Language: pkg.Java, Type: pomProperties.PkgTypeIndicated(), diff --git a/syft/pkg/cataloger/java/parse_gradle_lockfile.go b/syft/pkg/cataloger/java/parse_gradle_lockfile.go index c1ed7dfa614..803639ab43a 100644 --- a/syft/pkg/cataloger/java/parse_gradle_lockfile.go +++ b/syft/pkg/cataloger/java/parse_gradle_lockfile.go @@ -52,7 +52,7 @@ func parseGradleLockfile(_ source.FileResolver, _ *generic.Environment, reader s Name: dep.Name, Version: dep.Version, Locations: source.NewLocationSet( - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), Language: pkg.Java, Type: pkg.JavaPkg, diff --git a/syft/pkg/cataloger/java/parse_pom_xml.go b/syft/pkg/cataloger/java/parse_pom_xml.go index 314496a2b22..8df940869ed 100644 --- a/syft/pkg/cataloger/java/parse_pom_xml.go +++ b/syft/pkg/cataloger/java/parse_pom_xml.go @@ -32,7 +32,7 @@ func parserPomXML(_ source.FileResolver, _ *generic.Environment, reader source.L p := newPackageFromPom( pom, dep, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) if p.Name == "" { continue diff --git a/syft/pkg/cataloger/javascript/package.go b/syft/pkg/cataloger/javascript/package.go index 072c41ed293..314ce64e5fb 100644 --- a/syft/pkg/cataloger/javascript/package.go +++ b/syft/pkg/cataloger/javascript/package.go @@ -66,7 +66,7 @@ func newPackageLockV1Package(resolver source.FileResolver, location source.Locat pkg.Package{ Name: name, Version: version, - Locations: source.NewLocationSet(location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Locations: source.NewLocationSet(location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(name, version), Language: pkg.JavaScript, Type: pkg.NpmPkg, @@ -89,7 +89,7 @@ func newPackageLockV2Package(resolver source.FileResolver, location source.Locat pkg.Package{ Name: name, Version: u.Version, - Locations: source.NewLocationSet(location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Locations: source.NewLocationSet(location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(name, u.Version), Language: pkg.JavaScript, Type: pkg.NpmPkg, @@ -107,7 +107,7 @@ func newPnpmPackage(resolver source.FileResolver, location source.Location, name pkg.Package{ Name: name, Version: version, - Locations: source.NewLocationSet(location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Locations: source.NewLocationSet(location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(name, version), Language: pkg.JavaScript, Type: pkg.NpmPkg, @@ -122,7 +122,7 @@ func newYarnLockPackage(resolver source.FileResolver, location source.Location, pkg.Package{ Name: name, Version: version, - Locations: source.NewLocationSet(location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Locations: source.NewLocationSet(location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), PURL: packageURL(name, version), Language: pkg.JavaScript, Type: pkg.NpmPkg, diff --git a/syft/pkg/cataloger/javascript/parse_package_json.go b/syft/pkg/cataloger/javascript/parse_package_json.go index fe75d8c58a9..2d943e7108a 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json.go +++ b/syft/pkg/cataloger/javascript/parse_package_json.go @@ -70,7 +70,7 @@ func parsePackageJSON(_ source.FileResolver, _ *generic.Environment, reader sour pkgs = append( pkgs, - newPackageJSONPackage(p, reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + newPackageJSONPackage(p, reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), ) } diff --git a/syft/pkg/cataloger/nix/cataloger.go b/syft/pkg/cataloger/nix/cataloger.go index a5625526ba5..b4b440c2687 100644 --- a/syft/pkg/cataloger/nix/cataloger.go +++ b/syft/pkg/cataloger/nix/cataloger.go @@ -56,7 +56,7 @@ func (c *StoreCataloger) Catalog(resolver source.FileResolver) ([]pkg.Package, [ continue } - p := newNixStorePackage(*storePath, location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)) + p := newNixStorePackage(*storePath, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)) pkgs = append(pkgs, p) } diff --git a/syft/pkg/cataloger/php/parse_composer_lock.go b/syft/pkg/cataloger/php/parse_composer_lock.go index a0f8d5c1078..51614635096 100644 --- a/syft/pkg/cataloger/php/parse_composer_lock.go +++ b/syft/pkg/cataloger/php/parse_composer_lock.go @@ -36,7 +36,7 @@ func parseComposerLock(_ source.FileResolver, _ *generic.Environment, reader sou pkgs, newComposerLockPackage( m, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/php/parse_installed_json.go b/syft/pkg/cataloger/php/parse_installed_json.go index 46848b0b68c..e5309c5f3e3 100644 --- a/syft/pkg/cataloger/php/parse_installed_json.go +++ b/syft/pkg/cataloger/php/parse_installed_json.go @@ -56,7 +56,7 @@ func parseInstalledJSON(_ source.FileResolver, _ *generic.Environment, reader so pkgs = append( pkgs, newComposerLockPackage(pkgMeta, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/portage/parse_portage_contents.go b/syft/pkg/cataloger/portage/parse_portage_contents.go index 588258510da..799cb8b2a40 100644 --- a/syft/pkg/cataloger/portage/parse_portage_contents.go +++ b/syft/pkg/cataloger/portage/parse_portage_contents.go @@ -41,7 +41,7 @@ func parsePortageContents(resolver source.FileResolver, _ *generic.Environment, Version: version, PURL: packageURL(name, version), Locations: source.NewLocationSet( - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), Type: pkg.PortagePkg, MetadataType: pkg.PortageMetadataType, @@ -119,7 +119,7 @@ func addLicenses(resolver source.FileResolver, dbLocation source.Location, p *pk licenses := findings.ToSlice() sort.Strings(licenses) p.Licenses = licenses - p.Locations.Add(location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) + p.Locations.Add(location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) } func addSize(resolver source.FileResolver, dbLocation source.Location, p *pkg.Package) { @@ -152,5 +152,5 @@ func addSize(resolver source.FileResolver, dbLocation source.Location, p *pkg.Pa } p.Metadata = entry - p.Locations.Add(location.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) + p.Locations.Add(location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) } diff --git a/syft/pkg/cataloger/python/parse_poetry_lock.go b/syft/pkg/cataloger/python/parse_poetry_lock.go index 7b8e8d94bc2..0e29de0178c 100644 --- a/syft/pkg/cataloger/python/parse_poetry_lock.go +++ b/syft/pkg/cataloger/python/parse_poetry_lock.go @@ -44,7 +44,7 @@ func parsePoetryLock(_ source.FileResolver, _ *generic.Environment, reader sourc newPackageForIndex( p.Name, p.Version, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/python/parse_requirements.go b/syft/pkg/cataloger/python/parse_requirements.go index 7a7a1eb7c4f..9b6e5db5835 100644 --- a/syft/pkg/cataloger/python/parse_requirements.go +++ b/syft/pkg/cataloger/python/parse_requirements.go @@ -66,7 +66,7 @@ func parseRequirementsTxt(_ source.FileResolver, _ *generic.Environment, reader newPackageForIndex( name, version, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/python/parse_setup.go b/syft/pkg/cataloger/python/parse_setup.go index cf565087757..ee91f6ada2a 100644 --- a/syft/pkg/cataloger/python/parse_setup.go +++ b/syft/pkg/cataloger/python/parse_setup.go @@ -58,7 +58,7 @@ func parseSetup(_ source.FileResolver, _ *generic.Environment, reader source.Loc newPackageForIndex( name, version, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/python/parse_wheel_egg.go b/syft/pkg/cataloger/python/parse_wheel_egg.go index 5177b713198..7299e150c22 100644 --- a/syft/pkg/cataloger/python/parse_wheel_egg.go +++ b/syft/pkg/cataloger/python/parse_wheel_egg.go @@ -47,7 +47,7 @@ func fetchInstalledFiles(resolver source.FileResolver, metadataLocation source.L installedFilesRef := resolver.RelativeFileByPath(metadataLocation, installedFilesPath) if installedFilesRef != nil { - sources = append(sources, installedFilesRef.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) + sources = append(sources, installedFilesRef.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) installedFilesContents, err := resolver.FileContentsByLocation(*installedFilesRef) if err != nil { @@ -78,7 +78,7 @@ func fetchRecordFiles(resolver source.FileResolver, metadataLocation source.Loca recordRef := resolver.RelativeFileByPath(metadataLocation, recordPath) if recordRef != nil { - sources = append(sources, recordRef.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) + sources = append(sources, recordRef.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) recordContents, err := resolver.FileContentsByLocation(*recordRef) if err != nil { @@ -105,7 +105,7 @@ func fetchTopLevelPackages(resolver source.FileResolver, metadataLocation source return nil, nil, nil } - sources = append(sources, topLevelLocation.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) + sources = append(sources, topLevelLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) topLevelContents, err := resolver.FileContentsByLocation(*topLevelLocation) if err != nil { @@ -134,7 +134,7 @@ func fetchDirectURLData(resolver source.FileResolver, metadataLocation source.Lo return nil, nil, nil } - sources = append(sources, directURLLocation.Annotate(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) + sources = append(sources, directURLLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.SupportingEvidenceAnnotation)) directURLContents, err := resolver.FileContentsByLocation(*directURLLocation) if err != nil { @@ -162,7 +162,7 @@ func fetchDirectURLData(resolver source.FileResolver, metadataLocation source.Lo // assembleEggOrWheelMetadata discovers and accumulates python package metadata from multiple file sources and returns a single metadata object as well as a list of files where the metadata was derived from. func assembleEggOrWheelMetadata(resolver source.FileResolver, metadataLocation source.Location) (*pkg.PythonPackageMetadata, []source.Location, error) { var sources = []source.Location{ - metadataLocation.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + metadataLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), } metadataContents, err := resolver.FileContentsByLocation(metadataLocation) diff --git a/syft/pkg/cataloger/rpm/package.go b/syft/pkg/cataloger/rpm/package.go index 41486f0b5d7..77e5e14be5b 100644 --- a/syft/pkg/cataloger/rpm/package.go +++ b/syft/pkg/cataloger/rpm/package.go @@ -18,7 +18,7 @@ func newPackage(location source.Location, metadata pkg.RpmMetadata, distro *linu Name: metadata.Name, Version: toELVersion(metadata), PURL: packageURL(metadata, distro), - Locations: source.NewLocationSet(location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + Locations: source.NewLocationSet(location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), Type: pkg.RpmPkg, MetadataType: pkg.RpmMetadataType, Metadata: metadata, diff --git a/syft/pkg/cataloger/ruby/parse_gemfile_lock.go b/syft/pkg/cataloger/ruby/parse_gemfile_lock.go index 7d8856100fe..8667102f27a 100644 --- a/syft/pkg/cataloger/ruby/parse_gemfile_lock.go +++ b/syft/pkg/cataloger/ruby/parse_gemfile_lock.go @@ -44,7 +44,7 @@ func parseGemFileLockEntries(_ source.FileResolver, _ *generic.Environment, read newGemfileLockPackage( candidate[0], strings.Trim(candidate[1], "()"), - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/ruby/parse_gemspec.go b/syft/pkg/cataloger/ruby/parse_gemspec.go index 8544ae70cb3..6bb11a80914 100644 --- a/syft/pkg/cataloger/ruby/parse_gemspec.go +++ b/syft/pkg/cataloger/ruby/parse_gemspec.go @@ -97,7 +97,7 @@ func parseGemSpecEntries(_ source.FileResolver, _ *generic.Environment, reader s pkgs = append( pkgs, - newGemspecPackage(metadata, reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), + newGemspecPackage(metadata, reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)), ) } diff --git a/syft/pkg/cataloger/rust/package.go b/syft/pkg/cataloger/rust/package.go index bf800c04116..1d661bce3b5 100644 --- a/syft/pkg/cataloger/rust/package.go +++ b/syft/pkg/cataloger/rust/package.go @@ -31,7 +31,7 @@ func newPackagesFromAudit(location source.Location, versionInfo rustaudit.Versio for _, dep := range versionInfo.Packages { dep := dep - p := newPackageFromAudit(&dep, location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)) + p := newPackageFromAudit(&dep, location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)) if pkg.IsValid(&p) && dep.Kind == rustaudit.Runtime { pkgs = append(pkgs, p) } diff --git a/syft/pkg/cataloger/rust/parse_cargo_lock.go b/syft/pkg/cataloger/rust/parse_cargo_lock.go index db5e7104cc9..0e9d582a7ed 100644 --- a/syft/pkg/cataloger/rust/parse_cargo_lock.go +++ b/syft/pkg/cataloger/rust/parse_cargo_lock.go @@ -40,7 +40,7 @@ func parseCargoLock(_ source.FileResolver, _ *generic.Environment, reader source pkgs, newPackageFromCargoMetadata( p, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/pkg/cataloger/sbom/cataloger.go b/syft/pkg/cataloger/sbom/cataloger.go index a730e81e380..17e6618e6cd 100644 --- a/syft/pkg/cataloger/sbom/cataloger.go +++ b/syft/pkg/cataloger/sbom/cataloger.go @@ -48,7 +48,7 @@ func parseSBOM(_ source.FileResolver, _ *generic.Environment, reader source.Loca // where there is evidence of this file, and the catalogers have not run against any file other than, // the SBOM, this is the only location that is relevant for this cataloger. p.Locations = source.NewLocationSet( - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ) p.FoundBy = catalogerName diff --git a/syft/pkg/cataloger/swift/parse_podfile_lock.go b/syft/pkg/cataloger/swift/parse_podfile_lock.go index f8781fd83bc..afff41ae9b3 100644 --- a/syft/pkg/cataloger/swift/parse_podfile_lock.go +++ b/syft/pkg/cataloger/swift/parse_podfile_lock.go @@ -65,7 +65,7 @@ func parsePodfileLock(_ source.FileResolver, _ *generic.Environment, reader sour podName, podVersion, pkgHash, - reader.Location.Annotate(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), + reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation), ), ) } diff --git a/syft/source/location.go b/syft/source/location.go index cc6285e059f..70e140a1047 100644 --- a/syft/source/location.go +++ b/syft/source/location.go @@ -43,7 +43,7 @@ func (m *LocationMetadata) merge(other LocationMetadata) error { return errs } -func (l Location) Annotate(key, value string) Location { +func (l Location) WithAnnotation(key, value string) Location { if l.LocationMetadata.Annotations == nil { l.LocationMetadata.Annotations = map[string]string{} } diff --git a/syft/source/location_set.go b/syft/source/location_set.go index b174827334f..86d184c769d 100644 --- a/syft/source/location_set.go +++ b/syft/source/location_set.go @@ -9,8 +9,7 @@ import ( ) type LocationSet struct { - set map[LocationData]struct{} - metadata map[LocationData]LocationMetadata + set map[LocationData]LocationMetadata } func NewLocationSet(locations ...Location) (s LocationSet) { @@ -23,19 +22,17 @@ func NewLocationSet(locations ...Location) (s LocationSet) { func (s *LocationSet) Add(locations ...Location) { if s.set == nil { - s.set = make(map[LocationData]struct{}) - s.metadata = make(map[LocationData]LocationMetadata) + s.set = make(map[LocationData]LocationMetadata) } for _, l := range locations { - s.set[l.LocationData] = struct{}{} - if m, ok := s.metadata[l.LocationData]; ok { + if m, ok := s.set[l.LocationData]; ok { err := m.merge(l.LocationMetadata) if err != nil { - log.Warnf("partial merge of location metadata: %+v", err) + log.Debugf("partial merge of location metadata: %+v", err) } - s.metadata[l.LocationData] = m + s.set[l.LocationData] = m } else { - s.metadata[l.LocationData] = l.LocationMetadata + s.set[l.LocationData] = l.LocationMetadata } } } @@ -46,7 +43,6 @@ func (s LocationSet) Remove(locations ...Location) { } for _, l := range locations { delete(s.set, l.LocationData) - delete(s.metadata, l.LocationData) } } @@ -67,7 +63,7 @@ func (s LocationSet) ToSlice() []Location { for dir := range s.set { locations[idx] = Location{ LocationData: dir, - LocationMetadata: s.metadata[dir], + LocationMetadata: s.set[dir], } idx++ }