mirror of
https://github.com/anchore/syft
synced 2024-11-10 06:14:16 +00:00
Internalize CPE generation logic (#2541)
* migrate CPE generation logic to internal Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * remove create function Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
7f90b8f1eb
commit
b6cbf82389
36 changed files with 63 additions and 49 deletions
|
@ -8,6 +8,8 @@ import (
|
|||
"github.com/facebookincubator/nvdtools/wfn"
|
||||
)
|
||||
|
||||
const Any = ""
|
||||
|
||||
type CPE struct {
|
||||
Part string
|
||||
Vendor string
|
||||
|
@ -123,7 +125,7 @@ func normalizeField(field string) string {
|
|||
|
||||
// keep dashes and forward slashes unescaped
|
||||
if field == "*" {
|
||||
return wfn.Any
|
||||
return Any
|
||||
}
|
||||
return stripSlashes(field)
|
||||
}
|
||||
|
|
15
syft/pkg/cataloger/common/cpe/create.go
Normal file
15
syft/pkg/cataloger/common/cpe/create.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package cpe
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/cpegenerate"
|
||||
)
|
||||
|
||||
func Generate(p pkg.Package) []cpe.CPE {
|
||||
return cpegenerate.FromPackageAttributes(p)
|
||||
}
|
||||
|
||||
func DictionaryFind(p pkg.Package) (cpe.CPE, bool) {
|
||||
return cpegenerate.FromDictionaryFind(p)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"fmt"
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft/pkg"
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
"github.com/facebookincubator/nvdtools/wfn"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/common/cpe/dictionary"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/cpegenerate/dictionary"
|
||||
)
|
||||
|
||||
func generateIndexedDictionaryJSON(rawGzipData io.Reader) ([]byte, error) {
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/common/cpe/dictionary"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/cpegenerate/dictionary"
|
||||
)
|
||||
|
||||
func Test_generateIndexedDictionaryJSON(t *testing.T) {
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"strconv"
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
// A fieldCandidateCondition returns true if the condition is true for a given fieldCandidate.
|
||||
type fieldCandidateCondition func(fieldCandidate) bool
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"strings"
|
|
@ -1,10 +1,8 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/facebookincubator/nvdtools/wfn"
|
||||
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
@ -45,18 +43,18 @@ func disallowNonParseableCPEs(c cpe.CPE, _ pkg.Package) bool {
|
|||
}
|
||||
|
||||
// jenkins plugins should not match against jenkins
|
||||
func disallowJenkinsServerCPEForPluginPackage(cpe cpe.CPE, p pkg.Package) bool {
|
||||
if p.Type == pkg.JenkinsPluginPkg && cpe.Product == jenkinsName {
|
||||
func disallowJenkinsServerCPEForPluginPackage(c cpe.CPE, p pkg.Package) bool {
|
||||
if p.Type == pkg.JenkinsPluginPkg && c.Product == jenkinsName {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// filter to account that packages that are not for jenkins but have a CPE generated that will match against jenkins
|
||||
func disallowJenkinsCPEsNotAssociatedWithJenkins(cpe cpe.CPE, p pkg.Package) bool {
|
||||
func disallowJenkinsCPEsNotAssociatedWithJenkins(c cpe.CPE, p pkg.Package) bool {
|
||||
// jenkins server should only match against a product with the name jenkins
|
||||
if cpe.Product == jenkinsName && !strings.Contains(strings.ToLower(p.Name), jenkinsName) {
|
||||
if cpe.Vendor == wfn.Any || cpe.Vendor == jenkinsName || cpe.Vendor == "cloudbees" {
|
||||
if c.Product == jenkinsName && !strings.Contains(strings.ToLower(p.Name), jenkinsName) {
|
||||
if c.Vendor == cpe.Any || c.Vendor == jenkinsName || c.Vendor == "cloudbees" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -64,10 +62,10 @@ func disallowJenkinsCPEsNotAssociatedWithJenkins(cpe cpe.CPE, p pkg.Package) boo
|
|||
}
|
||||
|
||||
// filter to account for packages which are jira client packages but have a CPE that will match against jira
|
||||
func disallowJiraClientServerMismatch(cpe cpe.CPE, p pkg.Package) bool {
|
||||
func disallowJiraClientServerMismatch(c cpe.CPE, p pkg.Package) bool {
|
||||
// jira / atlassian should not apply to clients
|
||||
if cpe.Product == "jira" && strings.Contains(strings.ToLower(p.Name), "client") {
|
||||
if cpe.Vendor == wfn.Any || cpe.Vendor == "jira" || cpe.Vendor == "atlassian" {
|
||||
if c.Product == "jira" && strings.Contains(strings.ToLower(p.Name), "client") {
|
||||
if c.Vendor == cpe.Any || c.Vendor == "jira" || c.Vendor == "atlassian" {
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
@ -10,13 +10,12 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/facebookincubator/nvdtools/wfn"
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/common/cpe/dictionary"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/cpegenerate/dictionary"
|
||||
)
|
||||
|
||||
// knownVendors contains vendor strings that are known to exist in
|
||||
|
@ -59,7 +58,7 @@ func GetIndexedDictionary() (_ *dictionary.Indexed, err error) {
|
|||
return indexedCPEDictionary, err
|
||||
}
|
||||
|
||||
func DictionaryFind(p pkg.Package) (cpe.CPE, bool) {
|
||||
func FromDictionaryFind(p pkg.Package) (cpe.CPE, bool) {
|
||||
dict, err := GetIndexedDictionary()
|
||||
if err != nil {
|
||||
log.Debugf("dictionary CPE lookup not available: %+v", err)
|
||||
|
@ -107,10 +106,10 @@ func DictionaryFind(p pkg.Package) (cpe.CPE, bool) {
|
|||
return parsedCPE, true
|
||||
}
|
||||
|
||||
// Generate Create a list of CPEs for a given package, trying to guess the vendor, product tuple. We should be trying to
|
||||
// FromPackageAttributes Create a list of CPEs for a given package, trying to guess the vendor, product tuple. We should be trying to
|
||||
// generate the minimal set of representative CPEs, which implies that optional fields should not be included
|
||||
// (such as target SW).
|
||||
func Generate(p pkg.Package) []cpe.CPE {
|
||||
func FromPackageAttributes(p pkg.Package) []cpe.CPE {
|
||||
vendors := candidateVendors(p)
|
||||
products := candidateProducts(p)
|
||||
if len(products) == 0 {
|
||||
|
@ -128,7 +127,7 @@ func Generate(p pkg.Package) []cpe.CPE {
|
|||
}
|
||||
keys.Add(key)
|
||||
// add a new entry...
|
||||
if c := newCPE(product, vendor, p.Version, wfn.Any); c != nil {
|
||||
if c := newCPE(product, vendor, p.Version, cpe.Any); c != nil {
|
||||
cpes = append(cpes, *c)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -711,7 +711,7 @@ func TestGeneratePackageCPEs(t *testing.T) {
|
|||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
actual := Generate(test.p)
|
||||
actual := FromPackageAttributes(test.p)
|
||||
|
||||
expectedCpeSet := set.NewStringSet(test.expected...)
|
||||
actualCpeSet := set.NewStringSet()
|
||||
|
@ -994,7 +994,7 @@ func TestDictionaryFindIsWired(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, gotExists := DictionaryFind(tt.pkg)
|
||||
got, gotExists := FromDictionaryFind(tt.pkg)
|
||||
|
||||
assert.Equal(t, tt.want, got.BindToFmtString())
|
||||
assert.Equal(t, tt.wantExists, gotExists)
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"net/url"
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"sort"
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
var DefaultArtifactIDToGroupID = map[string]string{
|
||||
"ant": "org.apache.ant",
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"strings"
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import "github.com/anchore/syft/syft/pkg"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"fmt"
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import "github.com/anchore/syft/syft/pkg"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import "github.com/anchore/syft/syft/pkg"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import "strings"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"regexp"
|
|
@ -1,4 +1,4 @@
|
|||
package cpe
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
"github.com/anchore/packageurl-go"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/common/cpe"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/internal/cpegenerate"
|
||||
)
|
||||
|
||||
// PackageURL returns the PURL for the specific java package (see https://github.com/package-url/purl-spec)
|
||||
|
@ -53,7 +53,7 @@ func groupIDFromJavaMetadata(pkgName string, metadata pkg.JavaArchive) (groupID
|
|||
}
|
||||
|
||||
func groupIDFromKnownPackageList(pkgName string) (groupID string) {
|
||||
if groupID, ok := cpe.DefaultArtifactIDToGroupID[pkgName]; ok {
|
||||
if groupID, ok := cpegenerate.DefaultArtifactIDToGroupID[pkgName]; ok {
|
||||
return groupID
|
||||
}
|
||||
return groupID
|
||||
|
@ -64,13 +64,13 @@ func groupIDFromJavaManifest(manifest *pkg.JavaManifest) (groupID string) {
|
|||
return groupID
|
||||
}
|
||||
|
||||
groupIDS := cpe.GetManifestFieldGroupIDs(manifest, cpe.PrimaryJavaManifestGroupIDFields)
|
||||
groupIDS := cpegenerate.GetManifestFieldGroupIDs(manifest, cpegenerate.PrimaryJavaManifestGroupIDFields)
|
||||
// assumes that primaryJavaManifestNameFields are ordered by priority
|
||||
if len(groupIDS) != 0 {
|
||||
return groupIDS[0]
|
||||
}
|
||||
|
||||
groupIDS = cpe.GetManifestFieldGroupIDs(manifest, cpe.SecondaryJavaManifestGroupIDFields)
|
||||
groupIDS = cpegenerate.GetManifestFieldGroupIDs(manifest, cpegenerate.SecondaryJavaManifestGroupIDFields)
|
||||
|
||||
if len(groupIDS) != 0 {
|
||||
return groupIDS[0]
|
||||
|
|
Loading…
Reference in a new issue