Documentation
¶
Overview ¶
Package webhook delivers lifecycle events (host enrolled/blocked/deleted, cert rotated, cert expiring, …) to operator-configured HTTP endpoints. It is the unified outbound-event bus: handlers and background scanners publish typed events via Emit; the Dispatcher signs and delivers them asynchronously, off the request path, with bounded retry (#256).
Targets come from two places: an optional static target from server config (phase 1) and managed subscriptions loaded from a SubscriptionSource (phase 2). Deliveries are SSRF-guarded at request time and signed with HMAC-SHA256. The signing/guard logic mirrors internal/alerts and internal/config.hostIsPrivate and must stay in sync with them.
Index ¶
Constants ¶
const ( EventHeader = "X-Nebula-Event" DeliveryHeader = "X-Nebula-Delivery" SignatureHeader = "X-Nebula-Signature" )
HTTP headers attached to every delivery. Receivers authenticate the body via SignatureHeader and deduplicate on DeliveryHeader.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Static config target (optional).
URL string
HMACSecret string
AllowPrivate bool
Events []string // static target's event filter; empty = all
// Managed subscriptions (optional).
Source SubscriptionSource
// Tunables — zero values fall back to the defaults below.
QueueSize int
MaxRetries int
RetryBackoff time.Duration
DeliveryTO time.Duration
// Test seams.
HTTPClient *http.Client // overrides both guarded/unguarded clients
Now func() time.Time // nil => time.Now
NewID func() string // nil => "evt_"+uuid
}
Config configures a Dispatcher. A static target is delivered when URL is set (phase-1 config webhook); managed targets come from Source.
type Dispatcher ¶
type Dispatcher struct {
// contains filtered or unexported fields
}
Dispatcher signs and delivers events asynchronously. Construct with New, publish with Emit, and Close on shutdown to drain in-flight deliveries.
func New ¶
func New(cfg Config, logger *slog.Logger) *Dispatcher
New starts a Dispatcher and its delivery worker. The worker runs until Close.
func (*Dispatcher) Close ¶
func (d *Dispatcher) Close()
Close stops accepting events and drains what is already queued. Idempotent.
func (*Dispatcher) Emit ¶
func (d *Dispatcher) Emit(eventType string, data map[string]any)
Emit enqueues an event. It never blocks the caller: a full queue drops the event with a logged warning rather than stalling the request path. Per-target filtering happens at delivery. A nil Dispatcher (webhooks disabled) is a no-op.
type Emitter ¶
Emitter is the narrow interface handlers depend on. *Dispatcher implements it; a nil *Dispatcher Emit is a no-op.
type Event ¶
type Event struct {
ID string `json:"id"`
Type string `json:"type"`
CreatedAt time.Time `json:"created_at"`
Data map[string]any `json:"data"`
}
Event is the envelope POSTed to a subscriber. Data carries the event-type-specific payload.
type StoreSource ¶
type StoreSource struct {
// contains filtered or unexported fields
}
StoreSource resolves managed subscriptions from the store, decrypting each subscription's HMAC secret under the master key at delivery time. It satisfies SubscriptionSource.
func NewStoreSource ¶
NewStoreSource builds a store-backed subscription source. master may be nil (subscriptions with secrets are then skipped with a logged error).
func (*StoreSource) RecordDelivery ¶
RecordDelivery persists a delivery outcome against the subscription.
func (*StoreSource) TargetsFor ¶
TargetsFor returns active subscriptions wanting eventType, secrets decrypted.
type SubStore ¶
type SubStore interface {
ListActiveWebhookSubscriptions(ctx context.Context) ([]*models.WebhookSubscription, error)
RecordWebhookDelivery(ctx context.Context, id string, ok bool, errMsg string, at time.Time) error
}
SubStore is the store surface a StoreSource needs.
type SubscriptionSource ¶
type SubscriptionSource interface {
TargetsFor(ctx context.Context, eventType string) ([]Target, error)
RecordDelivery(ctx context.Context, targetID string, ok bool, errMsg string)
}
SubscriptionSource yields managed subscriptions for an event and records the outcome of each delivery.