replace dummy matcher with os matcher

This commit is contained in:
Alex Goodman 2020-06-01 07:18:17 -04:00
parent 16c478536e
commit 386a13a4f6
No known key found for this signature in database
GPG key ID: 86E2870463D5E890
3 changed files with 81 additions and 40 deletions

View file

@ -1,11 +1,12 @@
package matcher package matcher
import ( import (
imgbomOS "github.com/anchore/imgbom/imgbom/os"
"github.com/anchore/imgbom/imgbom/pkg" "github.com/anchore/imgbom/imgbom/pkg"
"github.com/anchore/vulnscan/internal/log" "github.com/anchore/vulnscan/internal/log"
"github.com/anchore/vulnscan/vulnscan/match" "github.com/anchore/vulnscan/vulnscan/matcher/os"
"github.com/anchore/vulnscan/vulnscan/matcher/dummy"
"github.com/anchore/vulnscan/vulnscan/result" "github.com/anchore/vulnscan/vulnscan/result"
"github.com/anchore/vulnscan/vulnscan/vulnerability"
) )
var controllerInstance controller var controllerInstance controller
@ -14,7 +15,7 @@ func init() {
controllerInstance = controller{ controllerInstance = controller{
matchers: make(map[pkg.Type][]Matcher), matchers: make(map[pkg.Type][]Matcher),
} }
controllerInstance.add(&dummy.Matcher{}) controllerInstance.add(&os.Matcher{})
} }
type controller struct { type controller struct {
@ -23,28 +24,34 @@ type controller struct {
func (c *controller) add(matchers ...Matcher) { func (c *controller) add(matchers ...Matcher) {
for _, m := range matchers { for _, m := range matchers {
if _, ok := c.matchers[m.Type()]; ok { for _, t := range m.Types() {
c.matchers[m.Type()] = make([]Matcher, 0) if _, ok := c.matchers[t]; ok {
} c.matchers[t] = make([]Matcher, 0)
}
c.matchers[m.Type()] = append(c.matchers[m.Type()], m) c.matchers[t] = append(c.matchers[t], m)
log.Debugf("adding matcher: %+v", m.Type()) log.Debugf("adding matcher: %+v", t)
}
} }
} }
// TODO: do we need to pass the entire store? or just a reader interface subset? func (c *controller) findMatches(s vulnerability.Provider, o imgbomOS.OS, packages ...*pkg.Package) result.Result {
func (c *controller) findMatches(s match.Store, packages ...pkg.Package) result.Result {
res := result.NewResult() res := result.NewResult()
for _, p := range packages { for _, p := range packages {
for _, matchers := range c.matchers { for _, matchers := range c.matchers {
for _, m := range matchers { for _, m := range matchers {
res.Add(p, m.Match(s, p)...) matches, err := m.Match(s, o, p)
if err != nil {
log.Errorf("matcher failed for pkg=%s: %w", p, err)
} else {
res.Add(p, matches...)
}
} }
} }
} }
return res return res
} }
func FindMatches(s match.Store, packages ...pkg.Package) result.Result { func FindMatches(s vulnerability.Provider, o imgbomOS.OS, packages ...*pkg.Package) result.Result {
return controllerInstance.findMatches(s, packages...) return controllerInstance.findMatches(s, o, packages...)
} }

View file

@ -1,27 +0,0 @@
package dummy
import (
"github.com/anchore/imgbom/imgbom/pkg"
"github.com/anchore/vulnscan-db/pkg/vulnerability"
"github.com/anchore/vulnscan/vulnscan/match"
)
// TODO: delete me...
type Matcher struct {
}
func (m *Matcher) Type() pkg.Type {
return pkg.DebPkg
}
func (m *Matcher) Match(match.Store, pkg.Package) []match.Match {
return []match.Match{
{
Confidence: 42,
Vulnerability: vulnerability.Vulnerability{},
Package: pkg.Package{},
SearchKey: "the key",
},
}
}

View file

@ -0,0 +1,61 @@
package os
import (
"fmt"
"github.com/anchore/imgbom/imgbom/os"
"github.com/anchore/imgbom/imgbom/pkg"
"github.com/anchore/vulnscan/vulnscan/match"
"github.com/anchore/vulnscan/vulnscan/version"
"github.com/anchore/vulnscan/vulnscan/vulnerability"
)
// TODO: consider renaming this package to DISTRO for easier importing...
type Matcher struct {
}
func (m *Matcher) Types() []pkg.Type {
return []pkg.Type{pkg.DebPkg}
}
func (m *Matcher) Match(store vulnerability.Provider, o os.OS, p *pkg.Package) ([]match.Match, error) {
// TODO: add other kinds of matches? fuzzy matches, etc...
return m.exactPackageNameMatch(store, o, p)
}
func (m *Matcher) exactPackageNameMatch(store vulnerability.Provider, o os.OS, p *pkg.Package) ([]match.Match, error) {
matches := make([]match.Match, 0)
// TODO: there should be a vulnerability object in the vulnscan-db/db/vulnerability for mondel serialization and one here in vulnerability for rich objects
allPkgVulns, err := store.GetByOs(o, p)
if err != nil {
return nil, fmt.Errorf("matcher failed to fetch os=%s pkg=%s: %w", o, p.Name, err)
}
verObj, err := version.NewVersionFromPkg(p)
if err != nil {
return nil, fmt.Errorf("matcher failed to parse version pkg=%s ver=%s: %w", p.Name, p.Version, err)
}
for _, vuln := range allPkgVulns {
// if the constraint it met, then the given package has the vulnerability
satisfied, err := vuln.Constraint.Satisfied(verObj)
if err != nil {
// TODO: not enough information (cannot back track constraint object)
return nil, fmt.Errorf("matcher failed to check constraint=%s version=%s: %w", vuln.Constraint, verObj, err)
}
if satisfied {
matches = append(matches, match.Match{
Confidence: 1.0, // TODO: this is hard coded for now
Vulnerability: *vuln,
Package: p,
SearchKey: fmt.Sprintf("%s:%s", p.Name, p.Version), // TODO: better way to signify exact match?
})
}
}
return matches, nil
}