mirror of
https://github.com/anchore/syft.git
synced 2026-11-05 00:46:38 +01:00
* [wip] Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * distinct the package metadata functions Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * remove metadata type from package core model Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * incorporate review feedback for names Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * add RPM archive metadata and split parser helpers Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * clarify the python package metadata type Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * rename the KB metadata type Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * break hackage and composer types by use case Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * linting fix Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix encoding and decoding for syft-json and cyclonedx Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * bump json schema to 11 Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * update cyclonedx-json snapshots Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * update cyclonedx-xml snapshots Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * update spdx-json snapshots Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * update spdx-tv snapshots Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * update syft-json snapshots Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * correct metadata type in stack yaml parser test Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix bom-ref redactor for cyclonedx-xml Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * add tests for legacy package metadata names Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * regenerate json schema v11 Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix legacy HackageMetadataType reflect type value check Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix linting Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * packagemetadata discovery should account for type shadowing Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix linting Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * fix cli tests Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * bump json schema version to v12 Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * update json schema to incorporate changes from main Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * add syft-json legacy config option Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * add tests around v11-v12 json decoding Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * add docs for SYFT_JSON_LEGACY Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * rename structs to be compliant with new naming scheme Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
441 lines
9.6 KiB
Go
441 lines
9.6 KiB
Go
package cpe
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/anchore/syft/syft/pkg"
|
|
)
|
|
|
|
func Test_candidateVendorsForAPK(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
pkg pkg.Package
|
|
expected []string
|
|
}{
|
|
{
|
|
name: "py3-cryptography Package",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "py3-cryptography",
|
|
},
|
|
},
|
|
expected: []string{"python-cryptography_project", "cryptography", "cryptographyproject", "cryptography_project"},
|
|
},
|
|
{
|
|
name: "py2-pypdf with explicit different origin",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "py2-pypdf",
|
|
OriginPackage: "abcdefg",
|
|
},
|
|
},
|
|
expected: []string{"pypdf", "pypdfproject", "pypdf_project"},
|
|
},
|
|
{
|
|
name: "ruby-armadillo Package",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "ruby-armadillo",
|
|
},
|
|
},
|
|
expected: []string{"armadillo"},
|
|
},
|
|
{
|
|
name: "python-3.6",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "python-3.6",
|
|
},
|
|
},
|
|
expected: []string{"python", "python_software_foundation"},
|
|
},
|
|
{
|
|
name: "ruby-3.6",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "ruby-3.6",
|
|
URL: "https://www.ruby-lang.org/",
|
|
},
|
|
},
|
|
expected: []string{"ruby", "ruby-lang"},
|
|
},
|
|
{
|
|
name: "make",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "make",
|
|
URL: "https://www.gnu.org/software/make",
|
|
},
|
|
},
|
|
expected: []string{"gnu", "make"},
|
|
},
|
|
{
|
|
name: "ruby-rake with matching origin",
|
|
pkg: pkg.Package{
|
|
Name: "ruby-rake",
|
|
Type: pkg.ApkPkg,
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "ruby-rake",
|
|
URL: "https://github.com/ruby/rake",
|
|
OriginPackage: "ruby-rake",
|
|
},
|
|
},
|
|
expected: []string{"rake", "ruby-lang", "ruby"},
|
|
},
|
|
{
|
|
name: "ruby-rake with non-matching origin",
|
|
pkg: pkg.Package{
|
|
Name: "ruby-rake",
|
|
Type: pkg.ApkPkg,
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "ruby-rake",
|
|
URL: "https://www.ruby-lang.org/",
|
|
OriginPackage: "ruby",
|
|
},
|
|
},
|
|
expected: []string{"rake", "ruby-lang"},
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
assert.ElementsMatch(t, test.expected, candidateVendorsForAPK(test.pkg).uniqueValues(), "different vendors")
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_candidateProductsForAPK(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
pkg pkg.Package
|
|
expected []string
|
|
}{
|
|
{
|
|
name: "py3-cryptography Package",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "py3-cryptography",
|
|
},
|
|
},
|
|
expected: []string{"cryptography", "python-cryptography"},
|
|
},
|
|
{
|
|
name: "py2-pypdf with explicit different origin",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "py2-pypdf",
|
|
OriginPackage: "abcdefg",
|
|
},
|
|
},
|
|
expected: []string{"pypdf"},
|
|
},
|
|
{
|
|
name: "ruby-armadillo Package",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "ruby-armadillo",
|
|
},
|
|
},
|
|
expected: []string{"armadillo"},
|
|
},
|
|
{
|
|
name: "python-3.6",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "python-3.6",
|
|
},
|
|
},
|
|
expected: []string{"python"},
|
|
},
|
|
{
|
|
name: "ruby-3.6",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "ruby-3.6",
|
|
URL: "https://www.ruby-lang.org/",
|
|
},
|
|
},
|
|
expected: []string{"ruby"},
|
|
},
|
|
{
|
|
name: "make",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "make",
|
|
URL: "https://www.gnu.org/software/make",
|
|
},
|
|
},
|
|
expected: []string{"make"},
|
|
},
|
|
{
|
|
name: "ruby-rake with matching origin",
|
|
pkg: pkg.Package{
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "ruby-rake",
|
|
URL: "https://github.com/ruby/rake",
|
|
OriginPackage: "ruby-rake",
|
|
},
|
|
},
|
|
expected: []string{"rake"},
|
|
},
|
|
{
|
|
name: "ruby-rake with non-matching origin",
|
|
pkg: pkg.Package{
|
|
Name: "ruby-rake",
|
|
Type: pkg.ApkPkg,
|
|
Metadata: pkg.ApkDBEntry{
|
|
Package: "ruby-rake",
|
|
URL: "https://www.ruby-lang.org/",
|
|
OriginPackage: "ruby",
|
|
},
|
|
},
|
|
expected: []string{"rake"},
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
assert.ElementsMatch(t, test.expected, candidateProductsForAPK(test.pkg).uniqueValues(), "different products")
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_upstreamCandidates(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
metadata pkg.ApkDBEntry
|
|
expected []upstreamCandidate
|
|
}{
|
|
{
|
|
name: "gocase",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "p",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "p", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "same package and origin simple case",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "p",
|
|
OriginPackage: "p",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "p", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "different package and origin",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "p",
|
|
OriginPackage: "origin",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "p", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "upstream python package information as qualifier py- prefix",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "py-potatoes",
|
|
OriginPackage: "py-potatoes",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "potatoes", Type: pkg.PythonPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "upstream python package information as qualifier py3- prefix",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "py3-potatoes",
|
|
OriginPackage: "py3-potatoes",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "potatoes", Type: pkg.PythonPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "python package with distinct origin package",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "py3-non-existant",
|
|
OriginPackage: "abcdefg",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "non-existant", Type: pkg.PythonPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "upstream ruby package information as qualifier",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "ruby-something",
|
|
OriginPackage: "ruby-something",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "something", Type: pkg.GemPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "ruby package with distinct origin package",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "ruby-something",
|
|
OriginPackage: "1234567",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "something", Type: pkg.GemPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "postgesql-15 upstream postgresql",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "postgresql-15",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "postgresql", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "postgesql15 upstream postgresql",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "postgresql15",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "postgresql", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "go-1.19 upstream go",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "go-1.19",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "go", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "go1.143 upstream go",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "go1.143",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "go", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "abc-101.191.23456 upstream abc",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "abc-101.191.23456",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "abc", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "abc101.191.23456 upstream abc",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "abc101.191.23456",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "abc", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "abc101-12345-1045 upstream abc101-12345",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "abc101-12345-1045",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "abc101-12345", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "abc101-a12345-1045 upstream abc101-a12345",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "abc101-a12345-1045",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "abc-a12345-1045", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "package starting with single digit",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "3proxy",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "3proxy", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "package starting with multiple digits",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "356proxy",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "356proxy", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "package composed of only digits",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "123456",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "123456", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "ruby-3.6 upstream ruby",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "ruby-3.6",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "ruby", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "ruby3.6 upstream ruby",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "ruby3.6",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "ruby", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "ruby3.6-tacos upstream tacos",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "ruby3.6-tacos",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "tacos", Type: pkg.GemPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "ruby-3.6-tacos upstream tacos",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "ruby-3.6-tacos",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "tacos", Type: pkg.GemPkg},
|
|
},
|
|
},
|
|
{
|
|
name: "abc1234jksajflksa",
|
|
metadata: pkg.ApkDBEntry{
|
|
Package: "abc1234jksajflksa",
|
|
},
|
|
expected: []upstreamCandidate{
|
|
{Name: "abc1234jksajflksa", Type: pkg.UnknownPkg},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
actual := upstreamCandidates(test.metadata)
|
|
assert.Equal(t, test.expected, actual)
|
|
})
|
|
}
|
|
}
|