diff --git a/pkg/analyzer/cel_filter.go b/pkg/analyzer/cel_filter.go index 42db95e..6126016 100644 --- a/pkg/analyzer/cel_filter.go +++ b/pkg/analyzer/cel_filter.go @@ -9,6 +9,7 @@ import ( "github.com/safedep/vet/pkg/analyzer/filter" "github.com/safedep/vet/pkg/common/logger" "github.com/safedep/vet/pkg/models" + "github.com/safedep/vet/pkg/readers" ) type celFilterAnalyzer struct { @@ -48,7 +49,7 @@ func (f *celFilterAnalyzer) Analyze(manifest *models.PackageManifest, logger.Infof("CEL filtering manifest: %s", manifest.Path) f.stat.IncScannedManifest() - for _, pkg := range manifest.Packages { + readers.NewManifestModelReader(manifest).EnumPackages(func(pkg *models.Package) error { f.stat.IncEvaluatedPackage() res, err := f.evaluator.EvalPackage(pkg) @@ -59,19 +60,21 @@ func (f *celFilterAnalyzer) Analyze(manifest *models.PackageManifest, pkg.PackageDetails.Name, pkg.PackageDetails.Version, err) - continue + return nil } if res.Matched() { // Avoid duplicates added to the table if _, ok := f.packages[pkg.Id()]; ok { - continue + return nil } f.stat.IncMatchedPackage() f.packages[pkg.Id()] = pkg } - } + + return nil + }) return f.notifyCaller(manifest, handler) } diff --git a/pkg/analyzer/cel_filter_suite.go b/pkg/analyzer/cel_filter_suite.go index 13153c8..158347b 100644 --- a/pkg/analyzer/cel_filter_suite.go +++ b/pkg/analyzer/cel_filter_suite.go @@ -10,6 +10,7 @@ import ( "github.com/safedep/vet/pkg/analyzer/filter" "github.com/safedep/vet/pkg/common/logger" "github.com/safedep/vet/pkg/models" + "github.com/safedep/vet/pkg/readers" ) type celFilterMatchedPackage struct { @@ -62,7 +63,7 @@ func (f *celFilterSuiteAnalyzer) Analyze(manifest *models.PackageManifest, logger.Infof("CEL Filter Suite: Analyzing manifest: %s", manifest.Path) f.stat.IncScannedManifest() - for _, pkg := range manifest.Packages { + readers.NewManifestModelReader(manifest).EnumPackages(func(pkg *models.Package) error { f.stat.IncEvaluatedPackage() res, err := f.evaluator.EvalPackage(pkg) @@ -73,13 +74,15 @@ func (f *celFilterSuiteAnalyzer) Analyze(manifest *models.PackageManifest, pkg.PackageDetails.Name, pkg.PackageDetails.Version, err) - continue + return nil } if res.Matched() { f.queueMatchedPkg(pkg, res.GetMatchedFilter().Name()) } - } + + return nil + }) if f.failOnMatch && (len(f.matchedPackages) > 0) { handler(&AnalyzerEvent{ diff --git a/pkg/exceptions/utils.go b/pkg/exceptions/utils.go new file mode 100644 index 0000000..903ed88 --- /dev/null +++ b/pkg/exceptions/utils.go @@ -0,0 +1,31 @@ +package exceptions + +import ( + "github.com/safedep/vet/pkg/common/logger" + "github.com/safedep/vet/pkg/models" +) + +// AllowedPackages iterates over packages in the manifest and call handler +// only for packages not in the exempted by exception rules +func AllowedPackages(manifest *models.PackageManifest, + handler func(pkg *models.Package) error) error { + for _, pkg := range manifest.Packages { + res, err := Apply(pkg) + if err != nil { + logger.Errorf("Failed to evaluate exception for %s: %v", + pkg.ShortName(), err) + continue + } + + if res.Matched() { + continue + } + + err = handler(pkg) + if err != nil { + return err + } + } + + return nil +} diff --git a/pkg/models/models.go b/pkg/models/models.go index 83a171a..17dbddf 100644 --- a/pkg/models/models.go +++ b/pkg/models/models.go @@ -75,6 +75,12 @@ func (p *Package) Id() string { return strconv.FormatUint(h.Sum64(), 16) } +func (p *Package) ShortName() string { + return fmt.Sprintf("pkg:%s/%s@%s", + strings.ToLower(string(p.Ecosystem)), + strings.ToLower(p.Name), p.Version) +} + func NewPackageDetail(e, n, v string) lockfile.PackageDetails { return lockfile.PackageDetails{ Ecosystem: lockfile.Ecosystem(e), diff --git a/pkg/readers/pm.go b/pkg/readers/pm.go new file mode 100644 index 0000000..3737b3e --- /dev/null +++ b/pkg/readers/pm.go @@ -0,0 +1,18 @@ +package readers + +import ( + "github.com/safedep/vet/pkg/exceptions" + "github.com/safedep/vet/pkg/models" +) + +type packageManifestReader struct { + manifest *models.PackageManifest +} + +func NewManifestModelReader(manifest *models.PackageManifest) PackageReader { + return &packageManifestReader{manifest: manifest} +} + +func (r *packageManifestReader) EnumPackages(handler func(pkg *models.Package) error) error { + return exceptions.AllowedPackages(r.manifest, handler) +} diff --git a/pkg/readers/reader.go b/pkg/readers/reader.go new file mode 100644 index 0000000..925c200 --- /dev/null +++ b/pkg/readers/reader.go @@ -0,0 +1,16 @@ +package readers + +import "github.com/safedep/vet/pkg/models" + +// Contract for implementing package manifest readers such as lockfile parser, +// SBOM parser etc. Reader should stop enumeration and return error if handler +// returns an error +type PackageManifestReader interface { + EnumManifests(func(*models.PackageManifest) error) error +} + +// Contract for implementing a package reader. Enumerator should fail and return +// error if handler fails +type PackageReader interface { + EnumPackages(func(*models.Package) error) error +} diff --git a/pkg/reporter/console.go b/pkg/reporter/console.go index 9793704..e67466d 100644 --- a/pkg/reporter/console.go +++ b/pkg/reporter/console.go @@ -11,6 +11,7 @@ import ( "github.com/safedep/vet/pkg/analyzer" "github.com/safedep/vet/pkg/models" "github.com/safedep/vet/pkg/policy" + "github.com/safedep/vet/pkg/readers" ) type consoleReporter struct{} @@ -29,9 +30,10 @@ func (r *consoleReporter) AddManifest(manifest *models.PackageManifest) { tbl.SetStyle(table.StyleLight) tbl.AppendHeader(table.Row{"Package", "Attribute", "Summary"}) - for _, pkg := range manifest.Packages { + readers.NewManifestModelReader(manifest).EnumPackages(func(pkg *models.Package) error { r.report(tbl, pkg) - } + return nil + }) fmt.Print(text.Bold.Sprint("Manifest: ", text.FgBlue.Sprint(manifest.Path))) fmt.Print("\n") diff --git a/pkg/reporter/summary.go b/pkg/reporter/summary.go index e24487b..09b3933 100644 --- a/pkg/reporter/summary.go +++ b/pkg/reporter/summary.go @@ -14,6 +14,7 @@ import ( "github.com/safedep/vet/pkg/analyzer" "github.com/safedep/vet/pkg/models" "github.com/safedep/vet/pkg/policy" + "github.com/safedep/vet/pkg/readers" ) const ( @@ -72,13 +73,14 @@ func (r *summaryReporter) Name() string { } func (r *summaryReporter) AddManifest(manifest *models.PackageManifest) { - for _, pkg := range manifest.Packages { + readers.NewManifestModelReader(manifest).EnumPackages(func(pkg *models.Package) error { r.processForVulns(pkg) r.processForPopularity(pkg) r.processForVersionDrift(pkg) r.summary.packages += 1 - } + return nil + }) r.summary.manifests += 1 } diff --git a/pkg/scanner/scanner.go b/pkg/scanner/scanner.go index b86e7c8..5751060 100644 --- a/pkg/scanner/scanner.go +++ b/pkg/scanner/scanner.go @@ -7,6 +7,7 @@ import ( "github.com/safedep/vet/pkg/common/logger" "github.com/safedep/vet/pkg/common/utils" "github.com/safedep/vet/pkg/models" + "github.com/safedep/vet/pkg/readers" "github.com/safedep/vet/pkg/reporter" ) @@ -217,9 +218,10 @@ func (s *packageManifestScanner) enrichManifest(manifest *models.PackageManifest q.Start() - for _, pkg := range manifest.Packages { + readers.NewManifestModelReader(manifest).EnumPackages(func(pkg *models.Package) error { q.Add(pkg) - } + return nil + }) q.Wait() q.Stop()