Documentation
¶
Overview ¶
Package webhooks loads a YAML config of outbound HTTP subscribers and dispatches matching findings to each one after every scan. Acts as the generic version of the Slack notifier: same dedup window, same "no notification failure ever breaks a scan" stance, but configurable to fit any system that takes an HTTP POST.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidConfig = errors.New("invalid webhook config")
ErrInvalidConfig is returned by LoadConfig when the YAML is unparseable.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Webhooks lists outbound subscribers.
Webhooks []Subscriber `json:"webhooks"`
}
Config is the YAML shape an operator supplies via --webhook-config.
func LoadConfig ¶
LoadConfig reads and validates a webhook config from path. Returns a zero-valued (no subscribers) config when path is empty so callers can pass through unset flags without an explicit nil check.
type Dispatcher ¶
type Dispatcher struct {
// contains filtered or unexported fields
}
Dispatcher is the per-server runtime that holds a Config plus a dedupe map keyed by subscriber + finding fingerprint, so the same critical does not get fired at every subscriber on every scan.
func NewDispatcher ¶
func NewDispatcher(cfg *Config, log Logger) *Dispatcher
NewDispatcher returns a Dispatcher for cfg. cfg may be nil, in which case Dispatch is a no-op.
func (*Dispatcher) Dispatch ¶
func (d *Dispatcher) Dispatch(ctx context.Context, findings []report.Finding)
Dispatch sends every matching, non-deduped finding to each subscriber. Subscribers run sequentially within one call so the order in the config file is the order operators see things hit the wire.
func (*Dispatcher) SetClient ¶
func (d *Dispatcher) SetClient(c *http.Client)
SetClient lets tests inject an httptest.Server's client.
type Logger ¶
type Logger interface {
// Warnw logs a warning with the given message and key/value pairs.
Warnw(msg string, keysAndValues ...any)
// Infow logs an info message with the given key/value pairs.
Infow(msg string, keysAndValues ...any)
}
Logger is the minimal logging surface the dispatcher needs. Compatible with zap.SugaredLogger and the standard log package via small wrappers.
type NoopLogger ¶
type NoopLogger struct{}
NoopLogger satisfies Logger and discards every message.
func (NoopLogger) Infow ¶
func (NoopLogger) Infow(string, ...any)
Infow implements Logger.Infow and discards the message.
func (NoopLogger) Warnw ¶
func (NoopLogger) Warnw(string, ...any)
Warnw implements Logger.Warnw and discards the message.
type Subscriber ¶
type Subscriber struct {
// Name labels the subscriber in logs.
Name string `json:"name"`
// URL is the POST target.
URL string `json:"url"`
// MinSeverity is critical, warning, or info. Findings below this are
// dropped before any other matching takes place.
MinSeverity string `json:"min_severity"`
// ScannerRegex, when set, restricts to findings whose Scanner matches.
ScannerRegex string `json:"scanner_regex,omitempty"`
// ClusterRegex, when set, restricts to findings whose Cluster matches.
ClusterRegex string `json:"cluster_regex,omitempty"`
// Headers are added to every outbound request. Values are passed
// through os.ExpandEnv so "$PAGERDUTY_TOKEN" is substituted from env.
Headers map[string]string `json:"headers,omitempty"`
// BodyTemplate is a Go text/template string evaluated per finding with
// the Finding object plus a few helpers. Empty means a default JSON
// envelope is sent.
BodyTemplate string `json:"body_template,omitempty"`
// ContentType is the value of the Content-Type header. Defaults to
// application/json.
ContentType string `json:"content_type,omitempty"`
// contains filtered or unexported fields
}
Subscriber is one outbound webhook target. Filters compose with AND.