8000 Refactor matcher ignore result by kzantow · Pull Request #2658 · anchore/grype · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Refactor matcher ignore result #2658

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
17 changes: 14 additions & 3 deletions grype/match/ignore.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type IgnoredMatch struct {
// rule to apply.
type IgnoreRule struct {
Vulnerability string `yaml:"vulnerability" json:"vulnerability" mapstructure:"vulnerability"`
IncludeAliases bool `yaml:"include-aliases" json:"include-aliases" mapstructure:"include-aliases"`
Reason string `yaml:"reason" json:"reason" mapstructure:"reason"`
Namespace string `yaml:"namespace" json:"namespace" mapstructure:"namespace"`
FixState string `yaml:"fix-state" json:"fix-state" mapstructure:"fix-state"`
Expand Down Expand Up @@ -139,7 +140,7 @@ func getIgnoreConditionsForRule(rule IgnoreRule) []ignoreCondition {
var ignoreConditions []ignoreCondition

if v := rule.Vulnerability; v != "" {
ignoreConditions = append(ignoreConditions, ifVulnerabilityApplies(v))
ignoreConditions = append(ignoreConditions, ifVulnerabilityApplies(v, rule.IncludeAliases))
}

if ns := rule.Namespace; ns != "" {
Expand Down Expand Up @@ -190,9 +191,19 @@ func ifFixStateApplies(fs string) ignoreCondition {
}
}

func ifVulnerabilityApplies(vulnerability string) ignoreCondition {
func ifVulnerabilityApplies(vulnerability string, includeAliases bool) ignoreCondition {
return func(match Match) bool {
return vulnerability == match.Vulnerability.ID
if vulnerability == match.Vulnerability.ID {
return true
}
if includeAliases {
for _, related := range match.Vulnerability.RelatedVulnerabilities {
if vulnerability == related.ID {
return true
}
}
}
return false
}
}

Expand Down
39 changes: 39 additions & 0 deletions grype/match/ignore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ var (
Fix: vulnerability.Fix{
State: vulnerability.FixStateNotFixed,
},
RelatedVulnerabilities: []vulnerability.Reference{
{
ID: "CVE-123",
},
},
},
Package: pkg.Package{
ID: pkg.ID(uuid.NewString()),
Expand Down Expand Up @@ -369,6 +374,40 @@ func TestApplyIgnoreRules(t *testing.T) {
},
},
},
{
name: "ignore related matches",
allMatches: allMatches,
ignoreRules: []IgnoreRule{
{
Vulnerability: "CVE-123",
IncludeAliases: true,
},
},
expectedRemainingMatches: []Match{
allMatches[2],
allMatches[3],
},
expectedIgnoredMatches: []IgnoredMatch{
{
Match: allMatches[0],
AppliedIgnoreRules: []IgnoreRule{
{
Vulnerability: "CVE-123",
IncludeAliases: true,
},
},
},
{
Match: allMatches[1],
AppliedIgnoreRules: []IgnoreRule{
{
Vulnerability: "CVE-123",
IncludeAliases: true,
},
},
},
},
},
{
name: "ignore subset of matches",
allMatches: allMatches,
Expand Down
2 changes: 1 addition & 1 deletion grype/match/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type Matcher interface {

// Match is called for every package found, returning any matches and an optional Ignorer which will be applied
// after all matches are found
Match(vp vulnerability.Provider, p pkg.Package) ([]Match, []IgnoredMatch, error)
Match(vp vulnerability.Provider, p pkg.Package) ([]Match, []IgnoreFilter, error)
}

// fatalError can be returned from a Matcher to indicate the matching process should stop.
Expand Down
39 changes: 20 additions & 19 deletions grype/matcher/apk/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"errors"
"fmt"

"github.com/anchore/grype/grype/distro"
"github.com/anchore/grype/grype/match"
"github.com/anchore/grype/grype/matcher/internal"
"github.com/anchore/grype/grype/pkg"
Expand All @@ -26,7 +25,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.ApkMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
var matches []match.Match

// direct matches with package itself
Expand Down Expand Up @@ -218,9 +217,8 @@ func (m *Matcher) findMatchesForOriginPackage(store vulnerability.Provider, p pk
// we want to report these NAK entries as match.IgnoredMatch, to allow for later processing to create ignore rules
// based on packages which overlap by location, such as a python binary found in addition to the python APK entry --
// we want to NAK this vulnerability for BOTH packages
func (m *Matcher) findNaksForPackage(provider vulnerability.Provider, p pkg.Package) ([]match.IgnoredMatch, error) {
// TODO: this was only applying to specific distros as originally implemented; this should probably be removed:
if d := p.Distro; d == nil || d.Type != distro.Wolfi && d.Type != distro.Chainguard && d.Type != distro.Alpine && d.Type != distro.MinimOS {
func (m *Matcher) findNaksForPackage(provider vulnerability.Provider, p pkg.Package) ([]match.IgnoreFilter, error) {
if p.Distro == nil {
return nil, nil
}

Expand Down Expand Up @@ -248,21 +246,24 @@ func (m *Matcher) findNaksForPackage(provider vulnerability.Provider, p pkg.Pack
naks = append(naks, upstreamNaks...)
}

var ignores []match.IgnoredMatch
meta, ok := p.Metadata.(pkg.ApkMetadata)
if !ok {
return nil, nil
}

var ignores []match.IgnoreFilter
for _, nak := range naks {
ignores = append(ignores, match.IgnoredMatch{
Match: match.Match{
Vulnerability: nak,
Package: p,
Details: nil, // Probably don't need details here
},
AppliedIgnoreRules: []match.IgnoreRule{
{
Vulnerability: nak.ID,
Reason: "NAK",
},
},
})
for _, f := range meta.Files {
ignores = append(ignores,
match.IgnoreRule{
Vulnerability: nak.ID,
IncludeAliases: true,
Reason: "Explicit APK NAK",
Package: match.IgnoreRulePackage{
Location: f.Path,
},
})
}
}

return ignores, nil
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/bitnami/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.BitnamiMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
// Bitnami packages' metadata are built from the package URL which contains
// info such as the package name, version, revision, distro or architecture.
// ref: https://github.com/anchore/syft/blob/main/syft/pkg/bitnami.go#L3-L13
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/dotnet/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.DotnetMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByEcosystemAndCPEs(store, p, m.Type(), m.cfg.UseCPEs)
}
2 changes: 1 addition & 1 deletion grype/matcher/dpkg/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.DpkgMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
matches := make([]match.Match, 0)

sourceMatches, err := m.matchUpstreamPackages(store, p)
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/golang/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.GoModuleMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
matches := make([]match.Match, 0)

mainModule := ""
Expand Down
6 changes: 3 additions & 3 deletions grype/matcher/internal/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"github.com/anchore/grype/internal/log"
)

func MatchPackageByEcosystemAndCPEs(store vulnerability.Provider, p pkg.Package, matcher match.MatcherType, includeCPEs bool) ([]match.Match, []match.IgnoredMatch, error) {
func MatchPackageByEcosystemAndCPEs(store vulnerability.Provider, p pkg.Package, matcher match.MatcherType, includeCPEs bool) ([]match.Match, []match.IgnoreFilter, error) {
var matches []match.Match
var ignored []match.IgnoredMatch
var ignored []match.IgnoreFilter

for _, name := range store.PackageSearchNames(p) {
nameMatches, nameIgnores, err := MatchPackageByEcosystemPackageNameAndCPEs(store, p, name, matcher, includeCPEs)
Expand All @@ -25,7 +25,7 @@ func MatchPackageByEcosystemAndCPEs(store vulnerability.Provider, p pkg.Package,
return matches, ignored, nil
}

func MatchPackageByEcosystemPackageNameAndCPEs(store vulnerability.Provider, p pkg.Package, packageName string, matcher match.MatcherType, includeCPEs bool) ([]match.Match, []match.IgnoredMatch, error) {
func MatchPackageByEcosystemPackageNameAndCPEs(store vulnerability.Provider, p pkg.Package, packageName string, matcher match.MatcherType, includeCPEs bool) ([]match.Match, []match.IgnoreFilter, error) {
matches, ignored, err := MatchPackageByEcosystemPackageName(store, p, packageName, matcher)
if err != nil {
log.Debugf("could not match by package ecosystem (package=%+v): %v", p, err)
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/internal/distro.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/anchore/grype/internal/log"
)

func MatchPackageByDistro(provider vulnerability.Provider, p pkg.Package, upstreamMatcher match.MatcherType) ([]match.Match, []match.IgnoredMatch, error) {
func MatchPackageByDistro(provider vulnerability.Provider, p pkg.Package, upstreamMatcher match.MatcherType) ([]match.Match, []match.IgnoreFilter, error) {
if p.Distro == nil {
return nil, nil, nil
}
Expand Down
6 changes: 3 additions & 3 deletions grype/matcher/internal/language.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
"github.com/anchore/grype/internal/log"
)

func MatchPackageByLanguage(store vulnerability.Provider, p pkg.Package, matcherType match.MatcherType) ([]match.Match, []match.IgnoredMatch, error) {
func MatchPackageByLanguage(store vulnerability.Provider, p pkg.Package, matcherType match.MatcherType) ([]match.Match, []match.IgnoreFilter, error) {
var matches []match.Match
var ignored []match.IgnoredMatch
var ignored []match.IgnoreFilter

for _, name := range store.PackageSearchNames(p) {
nameMatches, nameIgnores, err := MatchPackageByEcosystemPackageName(store, p, name, matcherType)
Expand All @@ -28,7 +28,7 @@ func MatchPackageByLanguage(store vulnerability.Provider, p pkg.Package, matcher
return matches, ignored, nil
}

func MatchPackageByEcosystemPackageName(provider vulnerability.Provider, p pkg.Package, packageName string, matcherType match.MatcherType) ([]match.Match, []match.IgnoredMatch, error) {
func MatchPackageByEcosystemPackageName(provider vulnerability.Provider, p pkg.Package, packageName string, matcherType match.MatcherType) ([]match.Match, []match.IgnoreFilter, error) {
if isUnknownVersion(p.Version) {
log.WithFields("package", p.Name).Trace("skipping package with unknown version")
return nil, nil, nil
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/java/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.JavaMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
var matches []match.Match

if m.cfg.SearchMavenUpstream {
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/javascript/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.JavascriptMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByEcosystemAndCPEs(store, p, m.Type(), m.cfg.UseCPEs)
}
4 changes: 2 additions & 2 deletions grype/matcher/mock/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

// MatchFunc is a function that takes a vulnerability provider and a package,
// and returns matches, ignored matches, and an error.
type MatchFunc func(vp vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error)
type MatchFunc func(vp vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error)

// Matcher is a mock implementation of the match.Matcher interface. This is
// intended for testing purposes only.
Expand All @@ -36,7 +36,7 @@ func (m Matcher) Type() match.MatcherType {
return "MOCK"
}

func (m Matcher) Match(vp vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m Matcher) Match(vp vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
if m.matchFunc != nil {
return m.matchFunc(vp, p)
}
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/msrc/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.MsrcMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(s 10000 tore vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
// find KB matches for the MSFT version given in the package and version.
// The "distro" holds the information about the Windows version, and its
// patch (KB)
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/portage/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.PortageMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByDistro(store, p, m.Type())
}
2 changes: 1 addition & 1 deletion grype/matcher/python/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.PythonMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByEcosystemAndCPEs(store, p, m.Type(), m.cfg.UseCPEs)
}
2 changes: 1 addition & 1 deletion grype/matcher/rpm/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (m *Matcher) Type() match.MatcherType {
}

//nolint:funlen
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
matches := make([]match.Match, 0)

// let's match with a synthetic package that doesn't exist. We will create a new
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/ruby/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.RubyGemMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByEcosystemAndCPEs(store, p, m.Type(), m.cfg.UseCPEs)
}
2 changes: 1 addition & 1 deletion grype/matcher/rust/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.RustMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByEcosystemAndCPEs(store, p, m.Type(), m.cfg.UseCPEs)
}
2 changes: 1 addition & 1 deletion grype/matcher/stock/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.StockMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByEcosystemAndCPEs(store, p, m.Type(), m.cfg.UseCPEs)
}
Loading
Loading
0