mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
encode upstream qualifier on os package pURLs (#769)
Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
parent
d2e815a2c5
commit
6f0fad7ffd
@ -49,6 +49,14 @@ type ApkFileRecord struct {
|
||||
|
||||
// PackageURL returns the PURL for the specific Alpine package (see https://github.com/package-url/purl-spec)
|
||||
func (m ApkMetadata) PackageURL(distro *linux.Release) string {
|
||||
qualifiers := map[string]string{
|
||||
purlArchQualifier: m.Architecture,
|
||||
}
|
||||
|
||||
if m.OriginPackage != "" {
|
||||
qualifiers[purlUpstreamQualifier] = m.OriginPackage
|
||||
}
|
||||
|
||||
return packageurl.NewPackageURL(
|
||||
// note: this is currently a candidate and not technically within spec
|
||||
// see https://github.com/package-url/purl-spec#other-candidate-types-to-define
|
||||
@ -57,9 +65,7 @@ func (m ApkMetadata) PackageURL(distro *linux.Release) string {
|
||||
m.Package,
|
||||
m.Version,
|
||||
purlQualifiers(
|
||||
map[string]string{
|
||||
purlArchQualifier: m.Architecture,
|
||||
},
|
||||
qualifiers,
|
||||
distro,
|
||||
),
|
||||
"",
|
||||
|
||||
@ -31,7 +31,7 @@ func TestApkMetadata_pURL(t *testing.T) {
|
||||
expected: "pkg:alpine/p@v?arch=a&distro=alpine-3.4.6",
|
||||
},
|
||||
{
|
||||
name: "missing architecure",
|
||||
name: "missing architecture",
|
||||
metadata: ApkMetadata{
|
||||
Package: "p",
|
||||
Version: "v",
|
||||
@ -67,6 +67,20 @@ func TestApkMetadata_pURL(t *testing.T) {
|
||||
},
|
||||
expected: "pkg:alpine/g%20plus%20plus@v84?arch=am86&distro=alpine-3.15.0",
|
||||
},
|
||||
{
|
||||
name: "add source information as qualifier",
|
||||
metadata: ApkMetadata{
|
||||
Package: "p",
|
||||
Version: "v",
|
||||
Architecture: "a",
|
||||
OriginPackage: "origin",
|
||||
},
|
||||
distro: linux.Release{
|
||||
ID: "alpine",
|
||||
VersionID: "3.4.6",
|
||||
},
|
||||
expected: "pkg:alpine/p@v?arch=a&upstream=origin&distro=alpine-3.4.6",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/anchore/syft/syft/file"
|
||||
@ -43,6 +44,19 @@ func (m DpkgMetadata) PackageURL(distro *linux.Release) string {
|
||||
if distro != nil {
|
||||
namespace = distro.ID
|
||||
}
|
||||
|
||||
qualifiers := map[string]string{
|
||||
purlArchQualifier: m.Architecture,
|
||||
}
|
||||
|
||||
if m.Source != "" {
|
||||
if m.SourceVersion != "" {
|
||||
qualifiers[purlUpstreamQualifier] = fmt.Sprintf("%s@%s", m.Source, m.SourceVersion)
|
||||
} else {
|
||||
qualifiers[purlUpstreamQualifier] = m.Source
|
||||
}
|
||||
}
|
||||
|
||||
return packageurl.NewPackageURL(
|
||||
// TODO: replace with `packageurl.TypeDebian` upon merge of https://github.com/package-url/packageurl-go/pull/21
|
||||
// TODO: or, since we're now using an Anchore fork of this module, we could do this sooner.
|
||||
@ -51,9 +65,7 @@ func (m DpkgMetadata) PackageURL(distro *linux.Release) string {
|
||||
m.Package,
|
||||
m.Version,
|
||||
purlQualifiers(
|
||||
map[string]string{
|
||||
purlArchQualifier: m.Architecture,
|
||||
},
|
||||
qualifiers,
|
||||
distro,
|
||||
),
|
||||
"",
|
||||
|
||||
@ -25,7 +25,6 @@ func TestDpkgMetadata_pURL(t *testing.T) {
|
||||
},
|
||||
metadata: DpkgMetadata{
|
||||
Package: "p",
|
||||
Source: "s",
|
||||
Version: "v",
|
||||
},
|
||||
expected: "pkg:deb/debian/p@v?distro=debian-11",
|
||||
@ -38,7 +37,6 @@ func TestDpkgMetadata_pURL(t *testing.T) {
|
||||
},
|
||||
metadata: DpkgMetadata{
|
||||
Package: "p",
|
||||
Source: "s",
|
||||
Version: "v",
|
||||
Architecture: "a",
|
||||
},
|
||||
@ -48,11 +46,37 @@ func TestDpkgMetadata_pURL(t *testing.T) {
|
||||
name: "missing distro",
|
||||
metadata: DpkgMetadata{
|
||||
Package: "p",
|
||||
Source: "s",
|
||||
Version: "v",
|
||||
},
|
||||
expected: "pkg:deb/p@v",
|
||||
},
|
||||
{
|
||||
name: "with upstream qualifier with source pkg name info",
|
||||
distro: &linux.Release{
|
||||
ID: "debian",
|
||||
VersionID: "11",
|
||||
},
|
||||
metadata: DpkgMetadata{
|
||||
Package: "p",
|
||||
Source: "s",
|
||||
Version: "v",
|
||||
},
|
||||
expected: "pkg:deb/debian/p@v?upstream=s&distro=debian-11",
|
||||
},
|
||||
{
|
||||
name: "with upstream qualifier with source pkg name and version info",
|
||||
distro: &linux.Release{
|
||||
ID: "debian",
|
||||
VersionID: "11",
|
||||
},
|
||||
metadata: DpkgMetadata{
|
||||
Package: "p",
|
||||
Source: "s",
|
||||
Version: "v",
|
||||
SourceVersion: "2.3",
|
||||
},
|
||||
expected: "pkg:deb/debian/p@v?upstream=s@2.3&distro=debian-11",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
@ -106,7 +106,7 @@ func (p PythonDirectURLOriginInfo) vcsURLQualifier() packageurl.Qualifiers {
|
||||
if p.VCS != "" {
|
||||
// Taken from https://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rst#known-qualifiers-keyvalue-pairs
|
||||
// packageurl-go still doesn't support all qualifier names
|
||||
return packageurl.Qualifiers{{Key: purlVCSURL, Value: fmt.Sprintf("%s+%s@%s", p.VCS, p.URL, p.CommitID)}}
|
||||
return packageurl.Qualifiers{{Key: purlVCSURLQualifier, Value: fmt.Sprintf("%s+%s@%s", p.VCS, p.URL, p.CommitID)}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -63,6 +63,10 @@ func (m RpmdbMetadata) PackageURL(distro *linux.Release) string {
|
||||
qualifiers[purlEpochQualifier] = strconv.Itoa(*m.Epoch)
|
||||
}
|
||||
|
||||
if m.SourceRpm != "" {
|
||||
qualifiers[purlUpstreamQualifier] = m.SourceRpm
|
||||
}
|
||||
|
||||
return packageurl.NewPackageURL(
|
||||
packageurl.TypeRPM,
|
||||
namespace,
|
||||
|
||||
@ -17,6 +17,20 @@ func TestRpmMetadata_pURL(t *testing.T) {
|
||||
metadata RpmdbMetadata
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "go case",
|
||||
distro: &linux.Release{
|
||||
ID: "rhel",
|
||||
VersionID: "8.4",
|
||||
},
|
||||
metadata: RpmdbMetadata{
|
||||
Name: "p",
|
||||
Version: "v",
|
||||
Release: "r",
|
||||
Epoch: nil,
|
||||
},
|
||||
expected: "pkg:rpm/rhel/p@v-r?distro=rhel-8.4",
|
||||
},
|
||||
{
|
||||
name: "with arch and epoch",
|
||||
distro: &linux.Release{
|
||||
@ -32,20 +46,6 @@ func TestRpmMetadata_pURL(t *testing.T) {
|
||||
},
|
||||
expected: "pkg:rpm/centos/p@v-r?arch=a&epoch=1&distro=centos-7",
|
||||
},
|
||||
{
|
||||
name: "go case",
|
||||
distro: &linux.Release{
|
||||
ID: "rhel",
|
||||
VersionID: "8.4",
|
||||
},
|
||||
metadata: RpmdbMetadata{
|
||||
Name: "p",
|
||||
Version: "v",
|
||||
Release: "r",
|
||||
Epoch: nil,
|
||||
},
|
||||
expected: "pkg:rpm/rhel/p@v-r?distro=rhel-8.4",
|
||||
},
|
||||
{
|
||||
name: "missing distro",
|
||||
metadata: RpmdbMetadata{
|
||||
@ -56,6 +56,20 @@ func TestRpmMetadata_pURL(t *testing.T) {
|
||||
},
|
||||
expected: "pkg:rpm/p@v-r",
|
||||
},
|
||||
{
|
||||
name: "with upstream source rpm info",
|
||||
distro: &linux.Release{
|
||||
ID: "rhel",
|
||||
VersionID: "8.4",
|
||||
},
|
||||
metadata: RpmdbMetadata{
|
||||
Name: "p",
|
||||
Version: "v",
|
||||
Release: "r",
|
||||
SourceRpm: "sourcerpm",
|
||||
},
|
||||
expected: "pkg:rpm/rhel/p@v-r?upstream=sourcerpm&distro=rhel-8.4",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
@ -14,7 +14,10 @@ const (
|
||||
purlArchQualifier = "arch"
|
||||
purlDistroQualifier = "distro"
|
||||
purlEpochQualifier = "epoch"
|
||||
purlVCSURL = "vcs_url"
|
||||
purlVCSURLQualifier = "vcs_url"
|
||||
|
||||
// this qualifier is not in the pURL spec, but is used by grype to perform indirect matching based on source information
|
||||
purlUpstreamQualifier = "upstream"
|
||||
)
|
||||
|
||||
type urlIdentifier interface {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user