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)
|
// 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 {
|
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(
|
return packageurl.NewPackageURL(
|
||||||
// note: this is currently a candidate and not technically within spec
|
// note: this is currently a candidate and not technically within spec
|
||||||
// see https://github.com/package-url/purl-spec#other-candidate-types-to-define
|
// 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.Package,
|
||||||
m.Version,
|
m.Version,
|
||||||
purlQualifiers(
|
purlQualifiers(
|
||||||
map[string]string{
|
qualifiers,
|
||||||
purlArchQualifier: m.Architecture,
|
|
||||||
},
|
|
||||||
distro,
|
distro,
|
||||||
),
|
),
|
||||||
"",
|
"",
|
||||||
|
|||||||
@ -31,7 +31,7 @@ func TestApkMetadata_pURL(t *testing.T) {
|
|||||||
expected: "pkg:alpine/p@v?arch=a&distro=alpine-3.4.6",
|
expected: "pkg:alpine/p@v?arch=a&distro=alpine-3.4.6",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "missing architecure",
|
name: "missing architecture",
|
||||||
metadata: ApkMetadata{
|
metadata: ApkMetadata{
|
||||||
Package: "p",
|
Package: "p",
|
||||||
Version: "v",
|
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",
|
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 {
|
for _, test := range tests {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
@ -43,6 +44,19 @@ func (m DpkgMetadata) PackageURL(distro *linux.Release) string {
|
|||||||
if distro != nil {
|
if distro != nil {
|
||||||
namespace = distro.ID
|
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(
|
return packageurl.NewPackageURL(
|
||||||
// TODO: replace with `packageurl.TypeDebian` upon merge of https://github.com/package-url/packageurl-go/pull/21
|
// 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.
|
// 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.Package,
|
||||||
m.Version,
|
m.Version,
|
||||||
purlQualifiers(
|
purlQualifiers(
|
||||||
map[string]string{
|
qualifiers,
|
||||||
purlArchQualifier: m.Architecture,
|
|
||||||
},
|
|
||||||
distro,
|
distro,
|
||||||
),
|
),
|
||||||
"",
|
"",
|
||||||
|
|||||||
@ -25,7 +25,6 @@ func TestDpkgMetadata_pURL(t *testing.T) {
|
|||||||
},
|
},
|
||||||
metadata: DpkgMetadata{
|
metadata: DpkgMetadata{
|
||||||
Package: "p",
|
Package: "p",
|
||||||
Source: "s",
|
|
||||||
Version: "v",
|
Version: "v",
|
||||||
},
|
},
|
||||||
expected: "pkg:deb/debian/p@v?distro=debian-11",
|
expected: "pkg:deb/debian/p@v?distro=debian-11",
|
||||||
@ -38,7 +37,6 @@ func TestDpkgMetadata_pURL(t *testing.T) {
|
|||||||
},
|
},
|
||||||
metadata: DpkgMetadata{
|
metadata: DpkgMetadata{
|
||||||
Package: "p",
|
Package: "p",
|
||||||
Source: "s",
|
|
||||||
Version: "v",
|
Version: "v",
|
||||||
Architecture: "a",
|
Architecture: "a",
|
||||||
},
|
},
|
||||||
@ -48,11 +46,37 @@ func TestDpkgMetadata_pURL(t *testing.T) {
|
|||||||
name: "missing distro",
|
name: "missing distro",
|
||||||
metadata: DpkgMetadata{
|
metadata: DpkgMetadata{
|
||||||
Package: "p",
|
Package: "p",
|
||||||
Source: "s",
|
|
||||||
Version: "v",
|
Version: "v",
|
||||||
},
|
},
|
||||||
expected: "pkg:deb/p@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 {
|
for _, test := range tests {
|
||||||
|
|||||||
@ -106,7 +106,7 @@ func (p PythonDirectURLOriginInfo) vcsURLQualifier() packageurl.Qualifiers {
|
|||||||
if p.VCS != "" {
|
if p.VCS != "" {
|
||||||
// Taken from https://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rst#known-qualifiers-keyvalue-pairs
|
// 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
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,6 +63,10 @@ func (m RpmdbMetadata) PackageURL(distro *linux.Release) string {
|
|||||||
qualifiers[purlEpochQualifier] = strconv.Itoa(*m.Epoch)
|
qualifiers[purlEpochQualifier] = strconv.Itoa(*m.Epoch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.SourceRpm != "" {
|
||||||
|
qualifiers[purlUpstreamQualifier] = m.SourceRpm
|
||||||
|
}
|
||||||
|
|
||||||
return packageurl.NewPackageURL(
|
return packageurl.NewPackageURL(
|
||||||
packageurl.TypeRPM,
|
packageurl.TypeRPM,
|
||||||
namespace,
|
namespace,
|
||||||
|
|||||||
@ -17,6 +17,20 @@ func TestRpmMetadata_pURL(t *testing.T) {
|
|||||||
metadata RpmdbMetadata
|
metadata RpmdbMetadata
|
||||||
expected string
|
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",
|
name: "with arch and epoch",
|
||||||
distro: &linux.Release{
|
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",
|
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",
|
name: "missing distro",
|
||||||
metadata: RpmdbMetadata{
|
metadata: RpmdbMetadata{
|
||||||
@ -56,6 +56,20 @@ func TestRpmMetadata_pURL(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: "pkg:rpm/p@v-r",
|
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 {
|
for _, test := range tests {
|
||||||
|
|||||||
@ -14,7 +14,10 @@ const (
|
|||||||
purlArchQualifier = "arch"
|
purlArchQualifier = "arch"
|
||||||
purlDistroQualifier = "distro"
|
purlDistroQualifier = "distro"
|
||||||
purlEpochQualifier = "epoch"
|
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 {
|
type urlIdentifier interface {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user