add nomatch_inclusion engine mechanism in cpe generation logic (#394)

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
Alex Goodman 2021-04-20 15:57:04 -04:00 committed by GitHub
parent 676bdf9816
commit b301b56db1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 92 additions and 9 deletions

View File

@ -13,6 +13,47 @@ import (
// this is functionally equivalent to "*" and consistent with no input given (thus easier to test)
const any = ""
// this is a static mapping of known package names (keys) to official cpe names for each package
type candidateStore map[pkg.Type]map[string][]string
var productCandidatesByPkgType = candidateStore{
pkg.JavaPkg: {
"springframework": []string{"spring_framework", "springsource_spring_framework"},
"spring-core": []string{"spring_framework", "springsource_spring_framework"},
},
pkg.NpmPkg: {
"hapi": []string{"hapi_server_framework"},
"handlebars.js": []string{"handlebars"},
"is-my-json-valid": []string{"is_my_json_valid"},
"mustache": []string{"mustache.js"},
},
pkg.GemPkg: {
"Arabic-Prawn": []string{"arabic_prawn"},
"bio-basespace-sdk": []string{"basespace_ruby_sdk"},
"cremefraiche": []string{"creme_fraiche"},
"html-sanitizer": []string{"html_sanitizer"},
"sentry-raven": []string{"raven-ruby"},
"RedCloth": []string{"redcloth_library"},
"VladTheEnterprising": []string{"vladtheenterprising"},
"yajl-ruby": []string{"yajl-ruby_gem"},
},
pkg.PythonPkg: {
"python-rrdtool": []string{"rrdtool"},
},
}
func (s candidateStore) getCandidates(t pkg.Type, key string) []string {
if _, ok := s[t]; !ok {
return nil
}
value, ok := s[t][key]
if !ok {
return nil
}
return value
}
func newCPE(product, vendor, version, targetSW string) wfn.Attributes {
cpe := *(wfn.NewAttributesWithAny())
cpe.Part = "a"
@ -98,8 +139,8 @@ func candidateVendors(p pkg.Package) []string {
func candidateProducts(p pkg.Package) []string {
var products = []string{p.Name}
switch p.Language {
case pkg.Java:
if p.Language == pkg.Java {
if p.MetadataType == pkg.JavaMetadataType {
if metadata, ok := p.Metadata.(pkg.JavaMetadata); ok && metadata.PomProperties != nil {
// derive the product from the groupID (e.g. org.sonatype.nexus --> nexus)
@ -111,8 +152,8 @@ func candidateProducts(p pkg.Package) []string {
}
}
}
default:
return products
}
return products
// return any known product name swaps prepended to the results
return append(productCandidatesByPkgType.getCandidates(p.Type, p.Name), products...)
}

View File

@ -1,14 +1,14 @@
package cataloger
import (
"fmt"
"sort"
"testing"
"github.com/scylladb/go-set/strset"
"github.com/scylladb/go-set"
"github.com/anchore/syft/syft/pkg"
"github.com/scylladb/go-set"
"github.com/scylladb/go-set/strset"
"github.com/stretchr/testify/assert"
)
func TestGenerate(t *testing.T) {
@ -180,3 +180,45 @@ func TestGenerate(t *testing.T) {
})
}
}
func TestCandidateProducts(t *testing.T) {
tests := []struct {
p pkg.Package
expected []string
}{
{
p: pkg.Package{
Name: "springframework",
Type: pkg.JavaPkg,
},
expected: []string{"spring_framework", "springsource_spring_framework" /* <-- known good names | default guess --> */, "springframework"},
},
{
p: pkg.Package{
Name: "handlebars.js",
Type: pkg.NpmPkg,
},
expected: []string{"handlebars" /* <-- known good names | default guess --> */, "handlebars.js"},
},
{
p: pkg.Package{
Name: "RedCloth",
Type: pkg.GemPkg,
},
expected: []string{"redcloth_library" /* <-- known good names | default guess --> */, "RedCloth"},
},
{
p: pkg.Package{
Name: "python-rrdtool",
Type: pkg.PythonPkg,
},
expected: []string{"rrdtool" /* <-- known good names | default guess --> */, "python-rrdtool"},
},
}
for _, test := range tests {
t.Run(fmt.Sprintf("%+v %+v", test.p, test.expected), func(t *testing.T) {
assert.Equal(t, test.expected, candidateProducts(test.p))
})
}
}