mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-05 20:40:16 -08:00
163 lines
4.2 KiB
Go
163 lines
4.2 KiB
Go
package extension
|
|
|
|
import (
|
|
"context"
|
|
"sort"
|
|
|
|
"github.com/samber/lo"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/aquasecurity/trivy/pkg/flag"
|
|
"github.com/aquasecurity/trivy/pkg/types"
|
|
)
|
|
|
|
var hooks = make(map[string]Hook)
|
|
|
|
func RegisterHook(s Hook) {
|
|
// Avoid duplication
|
|
hooks[s.Name()] = s
|
|
}
|
|
|
|
func DeregisterHook(name string) {
|
|
delete(hooks, name)
|
|
}
|
|
|
|
// Hook is an interface that defines the methods for a hook.
|
|
type Hook interface {
|
|
// Name returns the name of the extension.
|
|
Name() string
|
|
}
|
|
|
|
// RunHook is a extension that is called before and after all the processes.
|
|
type RunHook interface {
|
|
Hook
|
|
|
|
// PreRun is called before all the processes.
|
|
PreRun(ctx context.Context, opts flag.Options) error
|
|
|
|
// PostRun is called after all the processes.
|
|
PostRun(ctx context.Context, opts flag.Options) error
|
|
}
|
|
|
|
// ScanHook is a extension that is called before and after the scan.
|
|
type ScanHook interface {
|
|
Hook
|
|
|
|
// PreScan is called before the scan. It can modify the scan target.
|
|
// It may be called on the server side in client/server mode.
|
|
PreScan(ctx context.Context, target *types.ScanTarget, opts types.ScanOptions) error
|
|
|
|
// PostScan is called after the scan. It can modify the results.
|
|
// It may be called on the server side in client/server mode.
|
|
// NOTE: Wasm modules cannot directly modify the passed results,
|
|
// so it returns a copy of the results.
|
|
PostScan(ctx context.Context, results types.Results) (types.Results, error)
|
|
}
|
|
|
|
// ReportHook is a extension that is called before and after the report is written.
|
|
type ReportHook interface {
|
|
Hook
|
|
|
|
// PreReport is called before the report is written.
|
|
// It can modify the report. It is called on the client side.
|
|
PreReport(ctx context.Context, report *types.Report, opts flag.Options) error
|
|
|
|
// PostReport is called after the report is written.
|
|
// It can modify the report. It is called on the client side.
|
|
PostReport(ctx context.Context, report *types.Report, opts flag.Options) error
|
|
}
|
|
|
|
func PreRun(ctx context.Context, opts flag.Options) error {
|
|
for _, e := range Hooks() {
|
|
h, ok := e.(RunHook)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if err := h.PreRun(ctx, opts); err != nil {
|
|
return xerrors.Errorf("%s pre run error: %w", e.Name(), err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// PostRun is a hook that is called after all the processes.
|
|
func PostRun(ctx context.Context, opts flag.Options) error {
|
|
for _, e := range Hooks() {
|
|
h, ok := e.(RunHook)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if err := h.PostRun(ctx, opts); err != nil {
|
|
return xerrors.Errorf("%s post run error: %w", e.Name(), err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// PreScan is a hook that is called before the scan.
|
|
func PreScan(ctx context.Context, target *types.ScanTarget, options types.ScanOptions) error {
|
|
for _, e := range Hooks() {
|
|
h, ok := e.(ScanHook)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if err := h.PreScan(ctx, target, options); err != nil {
|
|
return xerrors.Errorf("%s pre scan error: %w", e.Name(), err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// PostScan is a hook that is called after the scan.
|
|
func PostScan(ctx context.Context, results types.Results) (types.Results, error) {
|
|
var err error
|
|
for _, e := range Hooks() {
|
|
h, ok := e.(ScanHook)
|
|
if !ok {
|
|
continue
|
|
}
|
|
results, err = h.PostScan(ctx, results)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("%s post scan error: %w", e.Name(), err)
|
|
}
|
|
}
|
|
return results, nil
|
|
}
|
|
|
|
// PreReport is a hook that is called before the report is written.
|
|
func PreReport(ctx context.Context, report *types.Report, opts flag.Options) error {
|
|
for _, e := range Hooks() {
|
|
h, ok := e.(ReportHook)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if err := h.PreReport(ctx, report, opts); err != nil {
|
|
return xerrors.Errorf("%s pre report error: %w", e.Name(), err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// PostReport is a hook that is called after the report is written.
|
|
func PostReport(ctx context.Context, report *types.Report, opts flag.Options) error {
|
|
for _, e := range Hooks() {
|
|
h, ok := e.(ReportHook)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if err := h.PostReport(ctx, report, opts); err != nil {
|
|
return xerrors.Errorf("%s post report error: %w", e.Name(), err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Hooks returns the list of hooks.
|
|
func Hooks() []Hook {
|
|
hooks := lo.Values(hooks)
|
|
sort.Slice(hooks, func(i, j int) bool {
|
|
return hooks[i].Name() < hooks[j].Name()
|
|
})
|
|
return hooks
|
|
}
|