mirror of
https://github.com/safedep/vet.git
synced 2025-12-10 00:22:08 -06:00
Add reporting interface
This commit is contained in:
parent
33fadddf2f
commit
73624a8a6e
6
pkg/policy/policy.go
Normal file
6
pkg/policy/policy.go
Normal file
@ -0,0 +1,6 @@
|
||||
package policy
|
||||
|
||||
type PolicyEvent struct {
|
||||
}
|
||||
|
||||
type PolicyEventHandler func(event *PolicyEvent) error
|
||||
83
pkg/reporter/markdown.go
Normal file
83
pkg/reporter/markdown.go
Normal file
@ -0,0 +1,83 @@
|
||||
package reporter
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
"text/template"
|
||||
|
||||
"github.com/safedep/vet/pkg/analyzer"
|
||||
"github.com/safedep/vet/pkg/common/logger"
|
||||
"github.com/safedep/vet/pkg/models"
|
||||
"github.com/safedep/vet/pkg/policy"
|
||||
|
||||
_ "embed"
|
||||
)
|
||||
|
||||
//go:embed markdown.template.md
|
||||
var markdownTemplate string
|
||||
|
||||
type MarkdownReportingConfig struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
type markdownTemplateInput struct {
|
||||
Manifests []*models.PackageManifest
|
||||
AnalyzerEvents []*analyzer.AnalyzerEvent
|
||||
PolicyEvents []*policy.PolicyEvent
|
||||
}
|
||||
|
||||
type markdownReportGenerator struct {
|
||||
m sync.Mutex
|
||||
config MarkdownReportingConfig
|
||||
templateInput markdownTemplateInput
|
||||
}
|
||||
|
||||
func NewMarkdownReportGenerator(config MarkdownReportingConfig) (Reporter, error) {
|
||||
return &markdownReportGenerator{
|
||||
config: config,
|
||||
templateInput: markdownTemplateInput{
|
||||
Manifests: make([]*models.PackageManifest, 0),
|
||||
AnalyzerEvents: make([]*analyzer.AnalyzerEvent, 0),
|
||||
PolicyEvents: make([]*policy.PolicyEvent, 0),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *markdownReportGenerator) Name() string {
|
||||
return "Markdown Report Generator"
|
||||
}
|
||||
|
||||
func (r *markdownReportGenerator) AddManifest(manifest *models.PackageManifest) {
|
||||
r.m.Lock()
|
||||
defer r.m.Unlock()
|
||||
r.templateInput.Manifests = append(r.templateInput.Manifests, manifest)
|
||||
}
|
||||
|
||||
func (r *markdownReportGenerator) AddAnalyzerEvent(event *analyzer.AnalyzerEvent) {
|
||||
r.m.Lock()
|
||||
defer r.m.Unlock()
|
||||
r.templateInput.AnalyzerEvents = append(r.templateInput.AnalyzerEvents, event)
|
||||
}
|
||||
|
||||
func (r *markdownReportGenerator) AddPolicyEvent(event *policy.PolicyEvent) {
|
||||
r.m.Lock()
|
||||
defer r.m.Unlock()
|
||||
r.templateInput.PolicyEvents = append(r.templateInput.PolicyEvents, event)
|
||||
}
|
||||
|
||||
func (r *markdownReportGenerator) Finish() error {
|
||||
logger.Infof("Generating consolidated markdown report: %s", r.config.Path)
|
||||
|
||||
tmpl, err := template.New("markdown").Parse(markdownTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file, err := os.Create(r.config.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
return tmpl.Execute(file, r.templateInput)
|
||||
}
|
||||
17
pkg/reporter/markdown.template.md
Normal file
17
pkg/reporter/markdown.template.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Vet Report
|
||||
|
||||
## Summary
|
||||
|
||||
* {{ len .Manifests }} manifest(s) were scanned
|
||||
* {{ len .AnalyzerEvents }} analyzer event(s) were generated
|
||||
* {{ len .PolicyEvents }} policy violation(s) were observed
|
||||
|
||||
## Details
|
||||
|
||||
The scan was performed on following manifests:
|
||||
{{ range $m := .Manifests }}
|
||||
* [{{ $m.Ecosystem }}] {{ $m.Path }}
|
||||
{{ end }}
|
||||
|
||||
|
||||
|
||||
19
pkg/reporter/reporter.go
Normal file
19
pkg/reporter/reporter.go
Normal file
@ -0,0 +1,19 @@
|
||||
package reporter
|
||||
|
||||
import (
|
||||
"github.com/safedep/vet/pkg/analyzer"
|
||||
"github.com/safedep/vet/pkg/models"
|
||||
"github.com/safedep/vet/pkg/policy"
|
||||
)
|
||||
|
||||
type Reporter interface {
|
||||
Name() string
|
||||
|
||||
// Feed collected data to reporting module
|
||||
AddManifest(manifest *models.PackageManifest)
|
||||
AddAnalyzerEvent(event *analyzer.AnalyzerEvent)
|
||||
AddPolicyEvent(event *policy.PolicyEvent)
|
||||
|
||||
// Inform reporting module to finalise (e.g. write report to file)
|
||||
Finish() error
|
||||
}
|
||||
@ -5,6 +5,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/reporter"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@ -17,15 +18,18 @@ type packageManifestScanner struct {
|
||||
config Config
|
||||
enrichers []PackageMetaEnricher
|
||||
analyzers []analyzer.Analyzer
|
||||
reporters []reporter.Reporter
|
||||
}
|
||||
|
||||
func NewPackageManifestScanner(config Config,
|
||||
enrichers []PackageMetaEnricher,
|
||||
analyzers []analyzer.Analyzer) *packageManifestScanner {
|
||||
analyzers []analyzer.Analyzer,
|
||||
reporters []reporter.Reporter) *packageManifestScanner {
|
||||
return &packageManifestScanner{
|
||||
config: config,
|
||||
enrichers: enrichers,
|
||||
analyzers: analyzers,
|
||||
reporters: reporters,
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,18 +76,28 @@ func (s *packageManifestScanner) analyzeManifests(manifests []*models.PackageMan
|
||||
|
||||
err = s.analyzeManifest(manifest)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to analyze %s manifest %v : %v",
|
||||
logger.Errorf("Failed to analyze %s manifest %s : %v",
|
||||
manifest.Ecosystem, manifest.Path, err)
|
||||
}
|
||||
|
||||
err = s.reportManifest(manifest)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to report %s manifest %s : %v",
|
||||
manifest.Ecosystem, manifest.Path, err)
|
||||
}
|
||||
}
|
||||
|
||||
s.finishReporting()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *packageManifestScanner) analyzeManifest(manifest *models.PackageManifest) error {
|
||||
for _, task := range s.analyzers {
|
||||
err := task.Analyze(manifest, func(event *analyzer.AnalyzerEvent) error {
|
||||
// Handle analyzer event
|
||||
for _, r := range s.reporters {
|
||||
r.AddAnalyzerEvent(event)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@ -94,6 +108,23 @@ func (s *packageManifestScanner) analyzeManifest(manifest *models.PackageManifes
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *packageManifestScanner) reportManifest(manifest *models.PackageManifest) error {
|
||||
for _, r := range s.reporters {
|
||||
r.AddManifest(manifest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *packageManifestScanner) finishReporting() {
|
||||
for _, r := range s.reporters {
|
||||
err := r.Finish()
|
||||
if err != nil {
|
||||
logger.Errorf("Reporter: %s failed with %v", r.Name(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *packageManifestScanner) enrichManifest(manifest *models.PackageManifest) error {
|
||||
// FIXME: Potential deadlock situation in case of channel buffer is full
|
||||
// because the goroutines perform both read and write to channel. Write occurs
|
||||
|
||||
21
scan.go
21
scan.go
@ -4,9 +4,11 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/safedep/dry/utils"
|
||||
"github.com/safedep/vet/pkg/analyzer"
|
||||
"github.com/safedep/vet/pkg/common/logger"
|
||||
"github.com/safedep/vet/pkg/parser"
|
||||
"github.com/safedep/vet/pkg/reporter"
|
||||
"github.com/safedep/vet/pkg/scanner"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -21,6 +23,7 @@ var (
|
||||
dumpJsonManifest bool
|
||||
dumpJsonManifestDir string
|
||||
celFilterExpression string
|
||||
markdownReportPath string
|
||||
)
|
||||
|
||||
func newScanCommand() *cobra.Command {
|
||||
@ -56,6 +59,8 @@ func newScanCommand() *cobra.Command {
|
||||
"Dump dir for enriched JSON docs")
|
||||
cmd.Flags().StringVarP(&celFilterExpression, "filter-cel", "", "",
|
||||
"Filter and print packages using CEL")
|
||||
cmd.Flags().StringVarP(&markdownReportPath, "report-markdown", "", "",
|
||||
"Generate consolidated markdown report to file")
|
||||
|
||||
cmd.AddCommand(listParsersCommand())
|
||||
return cmd
|
||||
@ -96,7 +101,7 @@ func internalStartScan() error {
|
||||
analyzers = append(analyzers, task)
|
||||
}
|
||||
|
||||
if len(celFilterExpression) > 0 {
|
||||
if !utils.IsEmptyString(celFilterExpression) {
|
||||
task, err := analyzer.NewCelFilterAnalyzer(celFilterExpression)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -105,6 +110,18 @@ func internalStartScan() error {
|
||||
analyzers = append(analyzers, task)
|
||||
}
|
||||
|
||||
reporters := []reporter.Reporter{}
|
||||
if !utils.IsEmptyString(markdownReportPath) {
|
||||
rp, err := reporter.NewMarkdownReportGenerator(reporter.MarkdownReportingConfig{
|
||||
Path: markdownReportPath,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reporters = append(reporters, rp)
|
||||
}
|
||||
|
||||
enrichers := []scanner.PackageMetaEnricher{
|
||||
scanner.NewInsightBasedPackageEnricher(),
|
||||
}
|
||||
@ -113,7 +130,7 @@ func internalStartScan() error {
|
||||
TransitiveAnalysis: transitiveAnalysis,
|
||||
TransitiveDepth: transitiveDepth,
|
||||
ConcurrentAnalyzer: concurrency,
|
||||
}, enrichers, analyzers)
|
||||
}, enrichers, analyzers, reporters)
|
||||
|
||||
var err error
|
||||
if len(lockfiles) > 0 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user